571 lines
21 KiB
PHP
571 lines
21 KiB
PHP
<?php
|
||
namespace app\common\model\food;
|
||
|
||
use Endroid\QrCode\QrCode as CodeMode;
|
||
use Endroid\QrCode\Writer\PngWriter;
|
||
use hema\alipay\Driver as Alipay;
|
||
use hema\wechat\Driver as Wechat;
|
||
use hema\wechat\Map;
|
||
use think\facade\Db;
|
||
/**
|
||
* 门店模型
|
||
*/
|
||
class Shop extends BaseModel
|
||
{
|
||
// 定义表名
|
||
protected $name = 'food_shop';
|
||
// 定义主键
|
||
protected $pk = 'shop_id';
|
||
// 追加字段
|
||
protected $append = [
|
||
'qrcode',
|
||
'wifi',
|
||
'paybill'
|
||
];
|
||
|
||
/**
|
||
* 获取门店码
|
||
*/
|
||
public function getQrcodeAttr($value,$data)
|
||
{
|
||
$qrcode = [
|
||
'h5' => '',
|
||
'weixin' => '',
|
||
'alipay' => '',
|
||
'qrcode' => '',
|
||
];
|
||
//生成存储路径
|
||
if(!file_exists('./temp/food')){
|
||
mkdir('./temp/food',0777,true);
|
||
}
|
||
//生成微信小程序码
|
||
$wechat_path = '/temp/food/wechat-shop-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $wechat_path)){
|
||
$wx = new Wechat;
|
||
if($wx->getUnlimitedQRCode($data['applet_id'],$wechat_path,'shop-'.$data['shop_id'])){
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
}else{
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
//如果已经发布H5端代码
|
||
if(is_file('./h5/food/index.html')){
|
||
$h5_path = '/temp/food/h5-shop-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $h5_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'h5/food/#/?applet_id=' . $data['applet_id'] . '&q=shop-' . $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $h5_path);
|
||
}
|
||
$qrcode['h5'] = $h5_path;
|
||
}
|
||
//生成支付宝小程序码
|
||
$alipay_path = '/temp/food/alipay-shop-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $alipay_path)){
|
||
$alipay = new Alipay($data['applet_id']);
|
||
if($alipay->openAppQrcodeCreate('shop-'.$data['shop_id'],$alipay_path)){
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
}else{
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
//生成小程序聚合码
|
||
$qrcode_path = '/temp/food/qrcode-shop-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $qrcode_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'food/' . $data['applet_id'] . '/shop-'. $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $qrcode_path);
|
||
}
|
||
$qrcode['qrcode'] = $qrcode_path;
|
||
return $qrcode;
|
||
}
|
||
|
||
/**
|
||
* 获取买单码
|
||
*/
|
||
public function getPaybillAttr($value,$data)
|
||
{
|
||
$qrcode = [
|
||
'h5' => '',
|
||
'weixin' => '',
|
||
'alipay' => '',
|
||
'qrcode' => '',
|
||
];
|
||
//生成存储路径
|
||
if(!file_exists('./temp/food')){
|
||
mkdir('./temp/food',0777,true);
|
||
}
|
||
//生成微信小程序码
|
||
$wechat_path = '/temp/food/wechat-paybill-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $wechat_path)){
|
||
$wx = new Wechat;
|
||
if($wx->getUnlimitedQRCode($data['applet_id'],$wechat_path,'paybill-'.$data['shop_id'])){
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
}else{
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
//如果已经发布H5端代码
|
||
if(is_file('./h5/food/index.html')){
|
||
$h5_path = '/temp/food/h5-paybill-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $h5_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'h5/food/#/?applet_id=' . $data['applet_id'] . '&q=paybill-' . $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $h5_path);
|
||
}
|
||
$qrcode['h5'] = $h5_path;
|
||
}
|
||
//生成支付宝小程序码
|
||
$alipay_path = '/temp/food/alipay-paybill-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $alipay_path)){
|
||
$alipay = new Alipay($data['applet_id']);
|
||
if($alipay->openAppQrcodeCreate('paybill-'.$data['shop_id'],$alipay_path)){
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
}else{
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
//生成小程序聚合码
|
||
$qrcode_path = '/temp/food/qrcode-paybill-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $qrcode_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'food/' . $data['applet_id'] . '/paybill-'. $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $qrcode_path);
|
||
}
|
||
$qrcode['qrcode'] = $qrcode_path;
|
||
return $qrcode;
|
||
}
|
||
|
||
/**
|
||
* 获取WIFI码
|
||
*/
|
||
public function getWifiAttr($value,$data)
|
||
{
|
||
$qrcode = [
|
||
'h5' => '',
|
||
'weixin' => '',
|
||
'alipay' => '',
|
||
'qrcode' => '',
|
||
];
|
||
//生成存储路径
|
||
if(!file_exists('./temp/food')){
|
||
mkdir('./temp/food',0777,true);
|
||
}
|
||
//生成微信小程序码
|
||
$wechat_path = '/temp/food/wechat-wifi-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $wechat_path)){
|
||
$wx = new Wechat;
|
||
if($wx->getUnlimitedQRCode($data['applet_id'],$wechat_path,'wifi-'.$data['shop_id'])){
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
}else{
|
||
$qrcode['weixin'] = $wechat_path;
|
||
}
|
||
//如果已经发布H5端代码
|
||
if(is_file('./h5/food/index.html')){
|
||
$h5_path = '/temp/food/h5-wifi-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $h5_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'h5/food/#/?applet_id=' . $data['applet_id'] . '&q=wifi-' . $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $h5_path);
|
||
}
|
||
$qrcode['h5'] = $h5_path;
|
||
}
|
||
//生成支付宝小程序码
|
||
$alipay_path = '/temp/food/alipay-wifi-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $alipay_path)){
|
||
$alipay = new Alipay($data['applet_id']);
|
||
if($alipay->openAppQrcodeCreate('wifi-'.$data['shop_id'],$alipay_path)){
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
}else{
|
||
$qrcode['alipay'] = $alipay_path;
|
||
}
|
||
//生成小程序聚合码
|
||
$qrcode_path = '/temp/food/qrcode-wifi-' . $data['shop_id'] . '.png';
|
||
if(!is_file('.' . $qrcode_path)){
|
||
$writer = new PngWriter();
|
||
$code = CodeMode::create(base_url() . 'food/' . $data['applet_id'] . '/wifi-'. $data['shop_id'])->setSize(500);
|
||
$result = $writer->write($code);
|
||
$result->saveToFile('.' . $qrcode_path);
|
||
}
|
||
$qrcode['qrcode'] = $qrcode_path;
|
||
return $qrcode;
|
||
}
|
||
|
||
/**
|
||
* 格式化页面数据(读取的时候对数据转换)
|
||
*/
|
||
public function getFoodModeAttr($value)
|
||
{
|
||
$value = json_decode($value, true);
|
||
$tab = [];
|
||
$tmp = [
|
||
10 => [
|
||
'text' => '堂食',
|
||
'value' => '10',
|
||
'status' => '0'
|
||
],
|
||
20 => [
|
||
'text' => '外卖',
|
||
'value' => '20',
|
||
'status' => '0'
|
||
],
|
||
30 => [
|
||
'text' => '自取',
|
||
'value' => '30',
|
||
'status' => '0'
|
||
]
|
||
];
|
||
foreach ($value as $item){
|
||
$tmp[$item]['status'] = '1';
|
||
$tab[] = $tmp[$item];
|
||
}
|
||
return [
|
||
'tab' => $tab, //小程序端选项卡
|
||
'value' => $tmp
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 自动转换data为json格式(修改器,保存de时候操作)
|
||
*/
|
||
public function setFoodModeAttr($value)
|
||
{
|
||
return json_encode($value);
|
||
}
|
||
/**
|
||
* 门店状态
|
||
*/
|
||
public function getStatusAttr($value,$data)
|
||
{
|
||
$value2 = $value;
|
||
$status = ['歇业中', '营业中'];
|
||
if($value == 1){
|
||
$time = explode('-',$data['shop_hours']);
|
||
$start_time = trim($time[0]);
|
||
$end_time = trim($time[1]);
|
||
//判断起始时间和结束时间是否一致,如一致为24小时营业
|
||
if($start_time != $end_time){
|
||
$time = time();
|
||
$now = date('Y-m-d',$time);
|
||
$start = strtotime($now . ' ' . $start_time . ':00');
|
||
$end = strtotime($now . ' ' . $end_time . ':00');
|
||
//判断是否不再营业时间
|
||
if(!($start < $time AND $end > $time)){
|
||
$value = 0;
|
||
}
|
||
}
|
||
}
|
||
return ['text' => $status[$value], 'value' => $value,'status' => $value2];
|
||
}
|
||
|
||
/**
|
||
* 是否开启自动配送
|
||
*/
|
||
public function getIsDeliveryAttr($value)
|
||
{
|
||
$status = ['关闭', '开启'];
|
||
return ['text' => $status[$value], 'value' => $value];
|
||
}
|
||
/**
|
||
* 是否开启骑手自动抢单
|
||
*/
|
||
public function getIsGrabAttr($value)
|
||
{
|
||
$status = ['关闭', '开启'];
|
||
return ['text' => $status[$value], 'value' => $value];
|
||
}
|
||
/**
|
||
* 是否开启自动接单
|
||
*/
|
||
public function getIsOrderAttr($value)
|
||
{
|
||
$status = ['关闭', '开启'];
|
||
return ['text' => $status[$value], 'value' => $value];
|
||
}
|
||
/**
|
||
* 是否开启自动配送
|
||
*/
|
||
public function getOutShowAttr($value)
|
||
{
|
||
$status = ['隐藏', '显示'];
|
||
return ['text' => $status[$value], 'value' => $value];
|
||
}
|
||
/**
|
||
* 获取列表
|
||
* @param [type] $district 区域
|
||
* @param [type] $location 位置坐标
|
||
* @param [type] $type 类型 0=所有,10=堂食,20=外卖,30=打包,80=订桌,90排号
|
||
* @param [type] $sortType 门店排序 all=所有 range=距离最近 sales=销量最高 score=评分最高
|
||
*/
|
||
public function getList($page = true,$page_n = 15, string $location = '',$shop_id = 0)
|
||
{
|
||
$filter = [];
|
||
$shop_id > 0 && $filter['shop_id'] = $shop_id;
|
||
// 执行查询
|
||
if($page){
|
||
$list = $this->where($filter)->order(['sort' => 'asc'])->paginate(['list_rows'=>$page_n,'query' => request()->param()]);
|
||
}else{
|
||
$list = $this->where($filter)->order(['sort' => 'asc'])->select()->toArray();
|
||
}
|
||
//是否计算距离
|
||
if(!empty($location)){
|
||
$to = $this->order(['sort' => 'asc'])->column('coordinate');
|
||
$to = implode(';',$to);
|
||
$map = new Map;
|
||
if($result = $map->getDistance($location,$to)){
|
||
for($n=0;$n<sizeof($list);$n++){
|
||
$distance = $result[$n]['distance'];
|
||
if(self::$applet_id > 0) {
|
||
//获取派送设置
|
||
$delivery =Setting::getItem('delivery');
|
||
$list[$n]['range'] = 0; //1为超出派送范围
|
||
if($delivery['delivery_range'] < $distance){
|
||
$list[$n]['range'] = 1; //1为超出派送范围
|
||
}
|
||
}
|
||
if($distance >= 1000){
|
||
$location = sprintf("%.2f", $distance/1000) . 'km';
|
||
}else{
|
||
$location = $distance . 'm';
|
||
}
|
||
$list[$n]['distance'] = $distance;
|
||
$list[$n]['location'] = $location;
|
||
}
|
||
$list = arr_sort($list,'distance','asc');
|
||
}else{
|
||
for($n=0;$n<sizeof($list);$n++){
|
||
$list[$n]['location'] = '未知距离';
|
||
$list[$n]['distance'] = 0;
|
||
}
|
||
}
|
||
}
|
||
return $list;
|
||
}
|
||
/**
|
||
* 获取详情
|
||
*/
|
||
public static function detail($shop_id = 0, string $location = '')
|
||
{
|
||
if($shop_id > 0){
|
||
$detail = self::find($shop_id);
|
||
if(!empty($location)){
|
||
$map = new Map;
|
||
if(!$result = $map->getDistance($location,$detail['coordinate'])){
|
||
$detail['location'] = '未知距离';
|
||
$detail['distance'] = 0;
|
||
}else{
|
||
$distance = $result[0]['distance'];
|
||
if(self::$applet_id > 0) {
|
||
//获取派送设置
|
||
$delivery =Setting::getItem('delivery');
|
||
$detail['range'] = 0; //1为超出派送范围
|
||
if($delivery['delivery_range'] < $distance){
|
||
$detail['range'] = 1; //1为超出派送范围
|
||
}
|
||
}
|
||
if($distance >= 1000){
|
||
$location = sprintf("%.2f", $distance/1000) . 'km';
|
||
}else{
|
||
$location = $distance . 'm';
|
||
}
|
||
$detail['distance'] = $distance;
|
||
$detail['location'] = $location;
|
||
}
|
||
}
|
||
return $detail;
|
||
}else{
|
||
$list = self::order(['sort' => 'asc'])->select()->toArray();
|
||
//是否计算距离
|
||
if(!empty($location)){
|
||
$to = self::order(['sort' => 'asc'])->column('coordinate');
|
||
$to = implode(';',$to);
|
||
$map = new Map;
|
||
if($result = $map->getDistance($location,$to)){
|
||
for($n=0;$n<sizeof($list);$n++){
|
||
$distance = $result[$n]['distance'];
|
||
if(self::$applet_id > 0) {
|
||
//获取派送设置
|
||
$delivery =Setting::getItem('delivery');
|
||
$list[$n]['range'] = 0; //1为超出派送范围
|
||
if($delivery['delivery_range'] < $distance){
|
||
$list[$n]['range'] = 1; //1为超出派送范围
|
||
}
|
||
}
|
||
if($distance >= 1000){
|
||
$location = sprintf("%.2f", $distance/1000) . 'km';
|
||
}else{
|
||
$location = $distance . 'm';
|
||
}
|
||
$list[$n]['distance'] = $distance;
|
||
$list[$n]['location'] = $location;
|
||
}
|
||
$list = arr_sort($list,'distance','asc');
|
||
}else{
|
||
$list[0]['location'] = '未知距离';
|
||
$list[0]['distance'] = 0;
|
||
}
|
||
}
|
||
return $list[0];
|
||
}
|
||
}
|
||
/**
|
||
* 获取详情
|
||
*/
|
||
public static function getShop()
|
||
{
|
||
return self::order(['shop_id' => 'desc'])->find();
|
||
}
|
||
/**
|
||
* 添加
|
||
*/
|
||
public function add(array $data)
|
||
{
|
||
if(!isset($data['logo']) or empty($data['logo'])){
|
||
$this->error = '请上传门店图标';
|
||
return false;
|
||
}
|
||
$map = new Map;
|
||
if(!$location = $map->getLocation($data['coordinate'])){
|
||
$this->error = $map->getError();
|
||
return false;
|
||
}
|
||
$data['province'] = $location['province'];
|
||
$data['city'] = $location['city'];
|
||
$data['district'] = $location['district'];
|
||
$data['poi_id'] = $location['poi_id'];
|
||
$data['applet_id'] = self::$applet_id;
|
||
return $this->save($data);
|
||
}
|
||
|
||
|
||
/**
|
||
* 编辑
|
||
*/
|
||
public function edit(array $data)
|
||
{
|
||
if(!isset($data['logo']) or empty($data['logo'])){
|
||
$this->error = '请上传门店图标';
|
||
return false;
|
||
}
|
||
$map = new Map;
|
||
if(!$location = $map->getLocation($data['coordinate'])){
|
||
$this->error = $map->getError();
|
||
return false;
|
||
}
|
||
$data['province'] = $location['province'];
|
||
$data['city'] = $location['city'];
|
||
$data['district'] = $location['district'];
|
||
$data['poi_id'] = $location['poi_id'];
|
||
return $this->save($data);
|
||
}
|
||
/**
|
||
* 删除门店
|
||
* $clear_all 是否全部清除
|
||
*/
|
||
public function remove($shop_id)
|
||
{
|
||
if($this->count() == 1){
|
||
$this->error = '至少保留一个门店';
|
||
return false;
|
||
}
|
||
$filter['shop_id'] = $shop_id;
|
||
// 开启事务
|
||
Db::startTrans();
|
||
try {
|
||
$this->withoutGlobalScope()->where($filter)->delete();
|
||
Device::withoutGlobalScope()->where($filter)->delete();
|
||
CouponLog::withoutGlobalScope()->where($filter)->delete();
|
||
CouponUser::withoutGlobalScope()->where($filter)->delete();
|
||
Pact::withoutGlobalScope()->where($filter)->delete();
|
||
Comment::withoutGlobalScope()->where($filter)->delete();
|
||
Record::withoutGlobalScope()->where($filter)->delete();
|
||
Table::withoutGlobalScope()->where($filter)->delete();
|
||
ShopClerk::withoutGlobalScope()->where($filter)->delete();
|
||
Category::withoutGlobalScope()->where($filter)->delete();
|
||
//清除商品记录
|
||
$goodsId = (new Goods)->withoutGlobalScope()->where($filter)->column('goods_id');
|
||
for($n=0;$n<sizeof($goodsId);$n++){
|
||
(new Goods)->remove($goodsId[$n]);
|
||
}
|
||
//清除订单记录
|
||
$orderId = (new Order)->withoutGlobalScope()->where($filter)->column('order_id');
|
||
for($n=0;$n<sizeof($orderId);$n++){
|
||
(new Order)->remove($orderId[$n]);
|
||
}
|
||
Db::commit();
|
||
return true;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* 新增默认门店
|
||
*/
|
||
public function insertDefault($applet_id,$data)
|
||
{
|
||
// 开启事务
|
||
Db::startTrans();
|
||
try {
|
||
// 添加默认门店
|
||
$this->save([
|
||
'shop_name' => $data['shop_name'],
|
||
'linkman' => $data['linkman'],
|
||
'shop_hours' => '08:00 - 21:00',
|
||
'phone' => $data['phone'],
|
||
'applet_id' => $applet_id,
|
||
]);
|
||
// 新增默认店长
|
||
$clerk = new ShopClerk;
|
||
$clerk->insertDefault($this->shop_id,$data,$applet_id);
|
||
Db::commit();
|
||
return true;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 获取所有 - api组件接口
|
||
*/
|
||
public static function getAll($location='')
|
||
{
|
||
$filter['status'] = 1;
|
||
$sort = ['sort', 'shop_id' => 'desc'];
|
||
$list = self::where($filter)->order($sort)->select();
|
||
//是否计算距离
|
||
if($location){
|
||
for($n=0;$n<sizeof($list);$n++){
|
||
$result = getDistance($location,$list[$n]['coordinate']);
|
||
if($result){
|
||
$distance = $result[0]['distance'];//获取距离计算结果
|
||
if(self::$applet_id > 0) {
|
||
//获取派送设置
|
||
$delivery =(new Setting)->getItem('delivery');
|
||
$list[$n]['range'] = 0; //1为超出派送范围
|
||
if($delivery['delivery_range'] < $distance){
|
||
$list[$n]['range'] = 1; //1为超出派送范围
|
||
}
|
||
}
|
||
$list[$n]['minute'] = round($result[0]['distance']/100);
|
||
if($distance>=1000){
|
||
$distance = sprintf("%.2f", $result[0]['distance']/1000).'km';
|
||
}else{
|
||
$distance = $result[0]['distance'].'m';
|
||
}
|
||
$list[$n]['location'] = $distance;
|
||
}else{
|
||
$list[$n]['location'] = '未知距离';
|
||
}
|
||
}
|
||
}
|
||
return $list;
|
||
}
|
||
} |