// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\AgentModel; use App\Models\GoodsModel; use App\Models\MemberModel; use App\Models\MerchantModel; use App\Models\OrderModel; use App\Models\ShopModel; use App\Models\TradeModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 商品管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class GoodsService * @package App\Services\Api */ class GoodsService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * GoodsService constructor. */ public function __construct() { $this->model = new GoodsModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 列表数据 * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 15, $field = '', $userId=0) { $where = ['a.mark' => 1,'c.status'=>2,'c.mark'=>1,'d.mark'=>1]; $field = $field? $field : 'lev_a.id,lev_a.user_id,lev_a.merch_id,lev_a.goods_name,lev_a.attr,lev_a.sales,lev_a.service_type,lev_a.intro_effect,lev_a.thumb,lev_a.intro_albums,lev_a.intro_process_albums,lev_a.intro_other_albums,lev_a.buy_notice,lev_a.cate_id,lev_a.type,lev_a.service_fee,lev_a.price,lev_a.discount,lev_a.unit,lev_a.sku,lev_a.sales,lev_a.intro_effect,lev_a.status,lev_b.name as cate_name,lev_c.lat,lev_c.lng,lev_c.trade_status,lev_c.name as merch_name'; $lat = isset($params['lat']) ? $params['lat'] : 0.00; $lng = isset($params['lng']) ? $params['lng'] : 0.00; $sortType = isset($params['sort_type']) ? $params['sort_type'] : 0; $order = 'id desc'; if($sortType == 1){ $order = $lng&&$lat? 'lev_c.trade_status asc,distance asc, lev_a.id desc':'lev_c.trade_status asc,lev_a.id desc'; }else if($sortType == 2){ $order = 'lev_a.sales desc, lev_a.id desc'; } $distanceField = ''; if ($lat && $lng) { $distanceField = "ROUND( 6378.138 * 2 * ASIN( SQRT( POW( SIN( ( {$lat} * PI() / 180 - `lev_c`.`lat` * PI() / 180 ) / 2 ), 2 ) + COS({$lat} * PI() / 180) * COS(`lev_c`.`lat` * PI() / 180) * POW( SIN( ( {$lng} * PI() / 180 - `lev_c`.`lng` * PI() / 180 ) / 2 ), 2 ) ) ) * 1000 )"; $field .= ", {$distanceField} AS distance"; } $distanceLimit = ConfigService::make()->getConfigByCode('distance_limit'); $distanceLimit = $distanceLimit? $distanceLimit : 0; $model = $this->model->from('goods as a') ->leftJoin('goods_category as b', 'a.cate_id', '=', 'b.id') ->leftJoin('merchant as c', 'a.merch_id', '=', 'c.id') ->leftJoin('member as d', 'd.id', '=', 'c.user_id') ->where($where) ->where(function ($query) use ($params,$distanceField,$distanceLimit) { $type = isset($params['type']) ? $params['type'] : 0; if ($type > 0) { $query->where('a.type', $type); } // 商户 $merchId = isset($params['merch_id']) ? $params['merch_id'] : 0; if ($merchId > 0) { $query->where('a.merch_id', $merchId); } $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId > 0) { $query->where('a.user_id', $userId); } // 推荐 $isRecommend = isset($params['is_recommend']) ? $params['is_recommend'] : 0; if ($isRecommend > 0) { $query->where('a.is_recommend', $isRecommend); } // 首页展示 $isHome = isset($params['is_home']) ? $params['is_home'] : 0; if ($isHome > 0) { $query->where('a.is_home', $isHome); } // 分类 $cateId = isset($params['cate_id']) ? $params['cate_id'] : 0; if ($cateId > 0) { $query->where('a.cate_id', $cateId); } $lat = isset($params['lat']) ? $params['lat'] : 0.00; $lng = isset($params['lng']) ? $params['lng'] : 0.00; if($lat>0 && $lng>0 && $distanceLimit>0 && $distanceField) { $query->whereRaw("{$distanceField} <= {$distanceLimit}"); } $agentId = isset($params['agent_id'])? intval($params['agent_id']) : 0; if($agentId>0){ $agentCity = AgentModel::where(['id'=>$agentId,'status'=>2,'mark'=>1])->value('city'); $agentCity = $agentCity? $agentCity : '不存在'; $query->where('c.city', $agentCity); } }) ->where(function ($query) use ($params) { $keyword = isset($params['kw']) ? $params['kw'] : ''; if ($keyword) { $query->where('a.goods_name', 'like', "%{$keyword}%")->orWhere('b.name', 'like', "%{$keyword}%")->orWhere('c.name', 'like', "%{$keyword}%"); } }); $countModel = clone $model; $countModel1 = clone $model; $countModel2 = clone $model; $counts = [ 'status1'=> $countModel->where(['a.status'=>2])->count('a.id'), 'status2'=> $countModel1->where(['a.status'=>1])->count('a.id'), 'status3'=> $countModel2->whereIn('a.status',[0,3])->count('a.id'), ]; $list = $model->where(function ($query) use ($params) { $status = isset($params['status']) ? $params['status'] : 0; $tabType = isset($params['tab_type']) ? $params['tab_type'] : 0; $status = $status > 0 ? $status : 2; if ($status > 0 && $tabType<=0) { $query->where('a.status', $status); } if ($tabType == 1) { $query->where('a.status', 2); }else if($tabType == 2){ $query->where('a.status', 1); }else if($tabType == 3){ $query->whereIn('a.status', [0,3]); } })->selectRaw($field) ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list && $list['data']) { foreach ($list['data'] as &$item) { $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : ''; $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : ''; $item['sales'] = isset($item['sales'])? ($item['sales']>1000? '1000+': $item['sales']):0; if(isset($item['distance'])){ $item['distance_text'] = $item['lat']>0? formatDistance($item['distance']) : ''; } if(isset($item['albums'])){ $albums = $item['albums']? json_decode($item['albums'], true):[]; $item['albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['video'])){ $item['video'] = $item['video']? get_image_url($item['video']) : ''; } if(isset($item['intro_albums'])){ $albums = $item['intro_albums']? json_decode($item['intro_albums'], true):[]; $item['intro_albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['intro_process_albums'])){ $albums = $item['intro_process_albums']? json_decode($item['intro_process_albums'], true):[]; $item['intro_process_albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['intro_other_albums'])){ $albums = $item['intro_other_albums']? json_decode($item['intro_other_albums'], true):[]; $item['intro_other_albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['service_type']) && $item['service_type']){ $item['service_type'] = explode(',', $item['service_type']); } $item['service_type'] = $item['service_type']? $item['service_type'] : [2,3]; $price = isset($item['price'])? moneyFormat($item['price'],2) : 0; $discount = isset($item['discount'])? floatval($item['discount']) : 0; $item['price'] = $discount>0 && $discount<10? moneyFormat($price * $discount/10, 2) : $price; $item['original_price'] = $price; $showType = isset($params['show_type'])? $params['show_type'] : 0; if($showType){ $item['num'] = CartService::make()->getGoodsCartNum($userId, $item['id']); } } } return [ 'pageSize' => $pageSize, 'counts' => $counts, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 列表数据 * @param $params * @param int $pageSize * @return array */ public function getIndexList($params, $pageSize = 6) { $where = ['a.is_home'=>1,'a.status'=>2]; $field = 'lev_a.id,lev_a.user_id,lev_a.merch_id,lev_a.goods_name,lev_a.thumb,lev_a.type,lev_a.sales,lev_a.price,lev_a.unit,lev_a.sku,lev_c.lat,lev_c.lng,lev_c.trade_status,lev_c.name as merch_name'; $lat = isset($params['lat']) ? $params['lat'] : 0.00; $lng = isset($params['lng']) ? $params['lng'] : 0.00; $sortType = isset($params['sort_type']) ? $params['sort_type'] : 0; $order = 'lev_a.id desc,lev_a.create_time desc'; if($sortType == 1){ $order = $lng&&$lat? 'lev_c.trade_status asc,distance asc, lev_a.id desc':'lev_c.trade_status asc,lev_a.id desc'; }else if($sortType == 2){ $order = 'lev_c.trade_status asc,lev_a.sales desc, lev_a.id desc'; } $distanceField = ''; if ($lat && $lng) { $distanceField = "ROUND( 6378.138 * 2 * ASIN( SQRT( POW( SIN( ( {$lat} * PI() / 180 - `lev_c`.`lat` * PI() / 180 ) / 2 ), 2 ) + COS({$lat} * PI() / 180) * COS(`lev_c`.`lat` * PI() / 180) * POW( SIN( ( {$lng} * PI() / 180 - `lev_c`.`lng` * PI() / 180 ) / 2 ), 2 ) ) ) * 1000 )"; $field .= ", {$distanceField} AS distance"; } $type = isset($params['type']) ? $params['type'] : 0; if($type){ $where['a.type'] = $type; } $where['a.mark'] = 1; $where['c.status'] = 2; $where['c.mark'] = 1; $where['b.mark'] = 1; $distanceLimit = ConfigService::make()->getConfigByCode('distance_limit'); $distanceLimit = $distanceLimit? $distanceLimit : 0; $list = $this->model->from('goods as a') ->leftJoin('merchant as c', 'a.merch_id', '=', 'c.id') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where($where) ->where(function ($query) use ($params,$distanceField,$distanceLimit) { // 商户 $merchId = isset($params['merch_id']) ? $params['merch_id'] : 0; if ($merchId > 0) { $query->where('a.merch_id', $merchId); } $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId > 0) { $query->where('a.user_id', $userId); } // 推荐 $isRecommend = isset($params['is_recommend']) ? $params['is_recommend'] : 0; if ($isRecommend > 0) { $query->where('a.is_recommend', $isRecommend); } // 分类 $cateId = isset($params['cate_id']) ? $params['cate_id'] : 0; if ($cateId > 0) { $query->where('a.cate_id', $cateId); } $lat = isset($params['lat']) ? $params['lat'] : 0.00; $lng = isset($params['lng']) ? $params['lng'] : 0.00; if($lat>0 && $lng>0 && $distanceLimit>0 && $distanceField) { $query->whereRaw("{$distanceField} <= {$distanceLimit}"); } }) ->selectRaw($field) ->orderByRaw($order) ->limit($pageSize) ->get(); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list as &$item) { $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : ''; $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : ''; $item['sales'] = isset($item['sales'])? ($item['sales']>1000? '1000+': $item['sales']):0; if(isset($item['distance'])){ $item['distance_text'] = $item['lat']>0? formatDistance($item['distance']) : ''; } $price = isset($item['price'])? moneyFormat($item['price'],2) : 0; $discount = isset($item['discount'])? floatval($item['discount']) : 0; $item['price'] = $discount>0 && $discount<10? moneyFormat($price * $discount/10, 2) : $price; $item['original_price'] = $price; } } return $list; } /** * 详情 * @param $id * @return array */ public function getInfo($id, $userId=0) { $field = ['a.id','a.goods_name','a.user_id','a.merch_id','a.type','a.service_type','a.thumb','a.cate_id','a.views','a.intro_albums','a.intro_process_albums','a.intro_other_albums','a.intro_other','a.buy_notice','a.unit','a.sku','a.price','a.attr','a.detail_img','a.service_fee','a.albums','a.sales','a.discount','a.status','a.stock','a.intro_effect','a.intro_people','a.video','a.intro_unsuitable','a.intro_service','a.intro_process','a.content','b.name as merch_name','b.type as merch_type','b.logo','b.category as merch_cate','b.service_time','b.trade_status','c.type as merch_cate_type']; $info = $this->model->from('goods as a')->with(['category']) ->leftJoin('merchant as b','b.id','=','a.merch_id') ->leftJoin('merchant_category as c','c.id','=','b.category') ->where(['a.id'=> $id,'a.mark'=>1,'b.mark'=>1]) ->select($field) ->first(); $info = $info? $info->toArray() : []; if($info){ if(isset($info['logo'])){ $info['logo'] = $info['logo']? get_image_url($info['logo']) : ''; } if(isset($info['thumb'])){ $info['thumb'] = $info['thumb']? get_image_url($info['thumb']) : ''; } if(isset($info['detail_img'])){ $info['detail_img'] = $info['detail_img']? get_image_url($info['detail_img']) : ''; } if(isset($info['video'])){ $info['video'] = $info['video']? get_image_url($info['video']) : ''; } if(isset($info['intro_albums'])){ $info['intro_albums'] = $info['intro_albums']? json_decode($info['intro_albums'], true) : []; $info['intro_albums'] = $info['intro_albums']? get_images_preview($info['intro_albums']) : []; } if(isset($info['intro_process_albums'])){ $info['intro_process_albums'] = $info['intro_process_albums']? json_decode($info['intro_process_albums'], true) : []; $info['intro_process_albums'] = $info['intro_process_albums']? get_images_preview($info['intro_process_albums']) : []; } if(isset($info['intro_other_albums'])){ $info['intro_other_albums'] = $info['intro_other_albums']? json_decode($info['intro_other_albums'], true) : []; $info['intro_other_albums'] = $info['intro_other_albums']? get_images_preview($info['intro_other_albums']) : []; } if(isset($info['albums'])){ $info['albums'] = $info['albums']? json_decode($info['albums'], true) : []; $info['albums'] = $info['albums']? get_images_preview($info['albums']) : []; } $price = isset($info['price'])? moneyFormat($info['price'],2) : 0; $discount = isset($info['discount'])? floatval($info['discount']) : 0; $info['price'] = $discount>0 && $discount<10? moneyFormat($price * $discount/10, 2) : $price; $info['original_price'] = $price; if(isset($info['service_type']) && $info['service_type']){ $info['service_type'] = explode(',', $info['service_type']); } $info['service_type'] = $info['service_type']? $info['service_type'] : [2,3]; $info['coupon_num'] = CouponService::make()->getCountByMerch($info['merch_id']); $info['service_status'] = 2; $info['service_time'] = isset($info['service_time']) && $info['service_time']? $info['service_time']:'08点~22点'; $serviceTime = $info['service_time']? str_replace('~','~',$info['service_time']):''; $times = $serviceTime? explode('~',$serviceTime) : []; $times[0] = isset($times[0]) && !empty($times[0])? $times[0] : '08点'; $times[1] = isset($times[1]) && $times[1]? $times[1] : '22点'; if($times && date('H点')>= $times[0] && date('H点')<=$times[1]){ $info['service_status'] = 1; } if($info['trade_status'] != 1){ $info['service_status'] = 2; } $time1 = isset($times[0]) && !empty($times[0])? str_replace('点','',$times[0]) : '08'; $time2 = isset($times[1]) && $times[1]? intval(str_replace('点','',$times[1])) : 22; $info['minDate'] = strtotime(date("Y-m-d"))*1000; $info['maxDate'] = (strtotime(date("Y-m-d")) + 30*86400)*1000; $info['minHour'] = intval($time1); $info['maxHour'] = intval($time2>1?$time2-1:$time2); $info['maxHour'] = $info['maxHour']<= $info['minHour']? 23: $info['maxHour']; $this->updateView($userId, $id); } return $info; } /** * 更新浏览量 * @param $userId * @param $dynamicId * @return array|mixed */ public function updateView($userId, $id) { $cacheKey = "caches:articles:views:u{$userId}_d{$id}"; $data = RedisService::get($cacheKey); if($data){ return false; } $data = $this->model->where(['id'=> $id])->update(['views'=>DB::raw('views + 1'),'update_time'=>time()]); RedisService::set($cacheKey, $id, rand(1,3)*7200); return $data; } /** * \获取技师服务列表 * @param $ids * @return mixed */ public function getListByIds($ids) { $field = 'lev_a.id,lev_a.user_id,lev_a.merch_id,lev_a.goods_name,lev_a.attr,lev_a.sales,lev_a.intro_effect,lev_a.thumb,lev_a.cate_id,lev_a.type,lev_a.service_fee,lev_a.price,lev_a.discount,lev_a.unit,lev_a.sku,lev_a.sales,lev_a.intro_effect,lev_a.status,lev_b.name as cate_name,lev_c.lat,lev_c.lng,lev_c.name as merch_name,lev_c.type as merch_type'; $datas = $this->model->from('goods as a') ->leftJoin('goods_category as b', 'a.cate_id', '=', 'b.id') ->leftJoin('merchant as c', 'a.merch_id', '=', 'c.id') ->whereIn('a.id', $ids) ->where(['a.status'=>2,'a.type'=>2,'a.mark'=>1,'c.status'=>2,'c.mark'=>1]) ->selectRaw($field) ->get(); if($datas){ foreach ($datas as &$item) { $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : ''; $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : ''; $item['sales'] = isset($item['sales'])? ($item['sales']>1000? '1000+': $item['sales']):0; if(isset($item['distance'])){ $item['distance_text'] = $item['lat']>0? formatDistance($item['distance']) : ''; } $price = isset($item['price'])? moneyFormat($item['price'],2) : 0; $discount = isset($item['discount'])? floatval($item['discount']) : 0; $item['price'] = $discount>0 && $discount<10? moneyFormat($price * $discount/10, 2) : $price; $item['original_price'] = $price; } } return $datas; } /** * 发布/编辑商品信息 * @param $goodsId * @return bool */ public function submit($userId, $params) { $id = isset($params['id'])? intval($params['id']) : 0; $merchId = isset($params['merch_id'])? intval($params['merch_id']) : 0; $type = isset($params['type'])? intval($params['type']) : 2; $checkType = isset($params['check_type'])? intval($params['check_type']) : 1; $status = isset($params['status'])? intval($params['status']) : 1; $merchInfo = MerchantModel::where(['id'=> $merchId,'mark'=>1]) ->select(['id','name','status']) ->first(); $status = isset($merchInfo['status'])? $merchInfo['status'] : 0; if(empty($merchInfo) || $status != 2){ $this->error = 2982; return false; } if ($id && !$this->model->where(['id' => $id, 'mark' => 1])->value('id')) { $this->error = 2981; return false; } $thumb = isset($params['thumb'][0])? get_image_path($params['thumb'][0]['url']) : ''; $video = isset($params['video'][0])? get_image_path($params['video'][0]['url']) : ''; $albums = isset($params['albums'])? get_format_images($params['albums']) : ''; $introProcessAlbums = isset($params['intro_process_albums'])? get_format_images($params['intro_process_albums']) : ''; $introOtherAlbums = isset($params['intro_other_albums'])? get_format_images($params['intro_other_albums']) : ''; $introAlbums = isset($params['intro_albums'])? get_format_images($params['intro_albums']) : ''; $discount = isset($params['discount']) ? floatval($params['discount']) : 0; $goodsPublish = ConfigService::make()->getConfigByCode('goods_publish'); $goodsPublish = $goodsPublish==1? $goodsPublish : 2; $goodsName = isset($params['goods_name']) ? trim($params['goods_name']) : ''; $goodsName = MessageService::make()->filterMessage($goodsName,4); $data = [ 'user_id' => $userId, 'merch_id' => $merchId, 'type' => $type, 'goods_name' => $goodsName, 'cate_id' => isset($params['cate_id']) ? intval($params['cate_id']) : 0, 'price' => isset($params['price']) ? floatval($params['price']) : 0.00, 'unit' => isset($params['unit']) ? trim($params['unit']) : '项', 'sku' => isset($params['sku']) ? trim($params['sku']) : '', 'attr' => isset($params['attr']) ? MessageService::make()->filterMessage($params['attr'],4) : '', 'weight' => isset($params['weight']) ? trim($params['weight']) : '', 'stock' => isset($params['stock']) && $params['stock']>0? intval($params['stock']) : 9999, 'buy_notice' => isset($params['buy_notice']) ? MessageService::make()->filterMessage($params['buy_notice'],4) : '', 'intro_effect' => isset($params['intro_effect']) ? MessageService::make()->filterMessage($params['intro_effect'],4) : '', 'intro_people' => isset($params['intro_people']) ? MessageService::make()->filterMessage($params['intro_people'],4) : '', 'intro_unsuitable' => isset($params['intro_unsuitable']) ? MessageService::make()->filterMessage($params['intro_unsuitable'],4) : '', 'intro_service' => isset($params['intro_service']) ? MessageService::make()->filterMessage($params['intro_service'],4) : '', 'intro_process' => isset($params['intro_process']) ? MessageService::make()->filterMessage($params['intro_process'],4) : '', 'content' => isset($params['content']) ? MessageService::make()->filterMessage($params['content'],4) : '', 'service_fee' => isset($params['service_fee']) ? floatval($params['service_fee']) : 0.00, 'is_recommend' => isset($params['is_recommend']) && $params['is_recommend']? intval($params['is_recommend']) : 2, 'is_home' => isset($params['is_home']) && $params['is_home']? intval($params['is_home']) : 1, 'sort' => isset($params['sort']) && $params['sort']? intval($params['sort']) : 0, 'service_type' => isset($params['service_type']) && $params['service_type']? trim($params['service_type']) : '2,3', 'discount' => $discount>0&&$discount<10?$discount:0, 'thumb' => $thumb, 'video' => $video, 'albums' => $albums, 'intro_albums' => $introAlbums, 'intro_process_albums' => $introProcessAlbums, 'intro_other_albums' => $introOtherAlbums, 'status' => $checkType==2? $status : ($goodsPublish==1? 0 : 1), 'mark' => 1, 'update_time' => time(), ]; if($id>0){ if($this->model->where(['id'=> $id,'mark'=>1])->update($data)){ $this->error = 1008; return true; } }else{ $data['create_time'] = time(); if($this->model->insertGetId($data)){ $this->error = 1023; return true; } } $this->error = $id? 1007 : 1024; return false; } /** * 上下架 * @return bool */ public function status() { $id = request()->post('id', 0); $status = request()->post('status', 1); if ($id && !$this->model->where(['id' => $id, 'mark' => 1])->value('id')) { $this->error = 2981; return false; } if($this->model->where(['id'=> $id,'mark'=>1])->update(['status'=>$status, 'update_time'=> time()])){ $this->error = 1002; return true; } $this->error = 1003; return true; } /** * 删除 * @return array */ public function delete() { // 参数 $param = request()->all(); $ids = getter($param, "id"); if (empty($ids)) { return message("请选择操作选项", false); } DB::beginTransaction(); $result = parent::delete(); // TODO: Change the autogenerated stub $code = isset($result['success']) ? $result['success'] : ''; if (!$code) { DB::rollBack(); return $result; } DB::commit(); return $result; } }