repository = $repository; $this->userInfo =$this->request->isLogin() ? $this->request->userInfo():null; $this->source = $this->request->header('source'); $this->merId = $this->request->header('merId'); } /** * @Author:Qinii * @Date: 2020/5/27 * @return mixed */ public function lst() { [$page, $limit] = $this->getPage(); $where = $this->request->params(['keyword','order','category_id']); return json_encode($where); return app('json')->success($this->repository->getList($where, $page,$limit,$this->userInfo)); } /** * @Author:Qinii * @Date: 2020/5/29 * @param $id * @return mixed */ public function detail($id) { if(!$this->repository->apiGetOne($id)) return app('json')->fail('店铺不存在'); $lat=$this->request->param('lat',''); $lng=$this->request->param('lng',''); return app('json')->success($this->repository->detail($id,$this->userInfo,$lat, $lng)); } /** * @Author:Qinii * @Date: 2020/5/29 * @param $id * @return mixed */ public function productList($id) { [$page, $limit] = $this->getPage(); $where = $this->request->params(['keyword','order','mer_cate_id','price_on', 'price_off','brand_id']); $where['is_gift_bag'] = 0; $where['is_used'] = 1; $where['product_type'] = 0; $where['is_hide'] = 0; if($id==324){ $where['mer_type']=1; } if($this->source=='yhc' && $this->merId==496){ return app('json')->success($this->repository->productList_yhc($id,$where, $page, $limit,$this->userInfo)); } return app('json')->success($this->repository->productList($id,$where, $page, $limit,$this->userInfo)); } public function productTypeList() { $params= $this->request->params(['type','mer_cate_id','pageNum','pageSize','mer_id']); $name=$params['type']; $domain = $this->request->domain(); $id=0; $type439=true; $is_commercetrade = 0; if($name=='dingsheng'){ $id=486; }else if($name=='jingpin'){ $id=439; $type439=false; }else if($name=='jifen'){ $id=148; }else if($name=='gongchang'){ if(strpos($domain, 'test.hebeiyhc.com') !== false) { // 域名中包含 "test.hebeiyhc.com'" 字符串 $id=486;//测试环境工厂直供 }else{ $id=497;//生产环境工厂直供 } }else if($name=='fugou'){ $id=491; }// 商贸区 else if($name=='commercetrade'){ if (empty($params['mer_id'])) return app('json')->fail('店铺不存在'); $id=$this->merId = $params['mer_id']; $is_commercetrade = 1; } else if ($name == 'sharedProsperity') { $id = 3447; } [$page, $limit] = $this->getPage(); if($params['pageNum']!=''){ $page=$params['pageNum']; } if($params['pageSize']!=''){ $limit=$params['pageSize']; } $where = $this->request->params(['keyword','order','mer_cate_id', 'cate_id','price_on', 'price_off','brand_id']); $where['is_gift_bag'] = 0; $where['is_used'] = 1; $where['product_type'] = 0; $where['is_hide'] = 0; // log::info("====={$params['mer_cate_id']}==="); if($params['mer_cate_id']){ $where['cate_id'] = $params['mer_cate_id']; } $result = $this->repository->productList($id,$where, $page, $limit,$this->userInfo,$type439,$is_commercetrade); // ===== sort 相同则随机打乱顺序 ===== // 默认排序为 sort DESC, create_time DESC。当多条商品 sort 值相同时, // 按 sort 分组,同组内随机打乱,使相同权重的商品每次展示顺序不同 if (!empty($result['list'])) { try { $grouped = []; // 按 sort 值分组 foreach ($result['list'] as $item) { $sortVal = $item['sort'] ?? 0; $grouped[$sortVal][] = $item; } // 同 sort 组内随机打乱 $shuffled = []; foreach ($grouped as $sortVal => $group) { if (count($group) > 1) { shuffle($group); } $shuffled = array_merge($shuffled, $group); } $result['list'] = $shuffled; } catch (\Throwable $e) { Log::info('productTypeList sort 随机打乱失败: ' . $e->getMessage()); } } // ===== sort 随机打乱结束 ===== // ===== 混入推荐商品逻辑(每页3-5个,跨页不重复,随机插入) ===== // 用户已登录且没有主动搜索时,将搜索关键词匹配的商品随机混入列表,保持每页商品数量不变 // 跨页去重方案:一次性查询所有匹配商品形成"推荐池",按页码切片取不同子集 $hasKeyword = !empty($params['keyword'] ?? '') || !empty($this->request->param('keyword', '')); if (!is_null($this->userInfo) && !empty($result['list']) && !$hasKeyword) { try { // 1. 获取用户最近的搜索关键词(SQL 层去重) $searchKeywords = Db::name('user_visit') ->where('uid', $this->userInfo['uid']) ->where('type', 'searchProduct') ->where('content', '<>', '') ->group('content') ->order('create_time', 'DESC') ->limit(5) ->column('content'); $searchKeywords = array_filter($searchKeywords); if (!empty($searchKeywords)) { // 2. 查询所有匹配的商品ID(不 limit,形成推荐池),排除已在当前列表中的 $existIds = array_column($result['list'], 'product_id'); $matchQuery = Db::name('store_product') ->where('mer_id', $id) ->where('is_show', 1) ->where('status', 1) ->where('is_del', 0) ->where('is_gift_bag', 0) ->where('product_type', 0) ->where('price', '>', 0); // 关键词 LIKE 条件 $matchQuery->where(function ($q) use ($searchKeywords) { foreach ($searchKeywords as $kw) { $q->whereOr('store_name', 'like', "%{$kw}%"); } }); if (!empty($existIds)) { $matchQuery->whereNotIn('product_id', $existIds); } // 查出所有匹配商品ID(推荐池),按 ID 排序保证跨页顺序一致 $allMatchProductIds = $matchQuery->order('product_id', 'ASC')->column('product_id'); if (!empty($allMatchProductIds)) { // 3. 根据页码切片:每页取 mixCount 个,不同页取不同区间 $mixCount = min(5, $limit); // 每页混入3-5个,取上限5 $totalPool = count($allMatchProductIds); // 如果推荐池足够大,按页码切片;否则循环复用但保证同一页内不重复 if ($totalPool <= $mixCount) { // 池子太小:全部使用,但不同页之间可能重复(资源有限) $pageMatchIds = $allMatchProductIds; } else { // 池子足够:按页码取不同切片 // 计算当前页的起始偏移量,确保不同页取不同区间 $offset = (($page - 1) * $mixCount) % $totalPool; $pageMatchIds = array_slice($allMatchProductIds, $offset, $mixCount); // 如果切片不够 mixCount,从头部补足(环形取) if (count($pageMatchIds) < $mixCount) { $remainder = array_slice($allMatchProductIds, 0, $mixCount - count($pageMatchIds)); $pageMatchIds = array_merge($pageMatchIds, $remainder); } } if (!empty($pageMatchIds)) { // 4. 直接用 pageMatchIds 查询 store_product 表获取基础数据 // 再通过 pvParm 补充 yanglao/pv/jifen/gongxian 等格式化字段 $baseProducts = Db::name('store_product') ->where('mer_id', $id) ->whereIn('product_id', $pageMatchIds) ->where('is_show', 1) ->where('status', 1) ->where('is_del', 0) ->select(); $baseProducts = $baseProducts->toArray(); $matchList = []; if (!empty($baseProducts)) { foreach ($baseProducts as $bp) { // 补充 pv/yanglao/jifen/gongxian 等字段 $pvData = app()->make(ProductRepository::class)->pvParm($bp['product_id']); $bp['yanglao'] = $pvData['yanglao'] ?? ''; $bp['pv'] = $pvData['pv'] ?? ''; $bp['jifen'] = $pvData['jifen'] ?? ''; $bp['gongxian'] = $pvData['gongxian'] ?? ''; $bp['jfduihuan'] = $pvData['jfduihuan'] ?? ''; $bp['jdduihuan'] = $pvData['jdduihuan'] ?? ''; $bp['fzone_paytype'] = $pvData['fzone_paytype'] ?? ''; $matchList[] = $bp; } } // 5. 随机混入:从原列表中随机移除同等数量商品,再随机插入推荐商品 $actualMixCount = min(count($matchList), $mixCount, $limit); if ($actualMixCount > 0) { $matchList = array_slice($matchList, 0, $actualMixCount); // 随机选择要移除的商品位置 $removeKeys = array_rand($result['list'], $actualMixCount); if (!is_array($removeKeys)) { $removeKeys = [$removeKeys]; } // 从大到小排序,避免删除时索引错乱 rsort($removeKeys); foreach ($removeKeys as $rk) { array_splice($result['list'], $rk, 1); } // 随机插入推荐商品 foreach ($matchList as $ml) { $insertPos = rand(0, count($result['list'])); array_splice($result['list'], $insertPos, 0, [$ml]); } } } } } } catch (\Throwable $e) { Log::info('productTypeList 混入推荐商品失败: ' . $e->getMessage()); } } // ===== 混入推荐商品逻辑结束 ===== return app('json')->success($result); } /** * 获取商户上架的商品列表 * @return mixed */ public function getProductList() { $params = request()->only(['pageNum', 'pageSize', 'mer_id']); $merId = $params['mer_id'] ?? 0; [$page, $limit] = $this->getPage(); $where = request()->only(['keyword']); $where['is_gift_bag'] = 0; $where['is_used'] = 1; $where['product_type'] = 0; $where['is_hide'] = 0; $result = $this->repository->productList($merId, $where, $page, $limit, $this->userInfo); $formatList = []; foreach ($result['list'] as $productInfo) { $formatList[] = [ 'type' => 0,//京东商品 'merId' => $productInfo['mer_id'], 'skuId' => '',//itemId 京东官方 已不返回skuId , 使用 联盟商品ID 代替skuId 'id' => $productInfo['product_id'] ?? '', //id 'name' => $productInfo['store_name'],//名称 'thumb' => $productInfo['image'] ?? '',//商品缩略图 'pv' => $productInfo['pv'],//PV金额 'gongxian' => $productInfo['gongxian'], 'jifen' => $productInfo['jifen'], 'yanglaojin' => $productInfo['yanglao'], 'commission' => $productInfo['concession_pri'],//佣金 'commission_rate' => null,//佣金比例 'coupon_money' => [], 'coupon_link' => '', 'lowestCouponPrice' => $productInfo['price'], 'price' => $productInfo['ot_price'], //价格 'imageList' => $productInfo['slider_image'], //图片合集 'materialUrl' => '' ]; } return app('json')->success($formatList); } /** * 商贸区店铺商品列表 * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function commerceProductList() { $params= $this->request->params(['pageNum','pageSize','category_id']); $mer_id_unset = [496,486,439,148,491]; $domain = $this->request->domain(); if(strpos($domain, 'test.hebeiyhc.com') !== false) { // 域名中包含 "test.hebeiyhc.com'" 字符串 array_push($mer_id_unset, 486); }else{ array_push($mer_id_unset, 497); } $is_commercetrade = 1; [$page, $limit] = $this->getPage(); if($params['pageNum']!=''){ $page=$params['pageNum']; } if($params['pageSize']!=''){ $limit=$params['pageSize']; } $category_id = $params['category_id']?:0; $where['is_del'] = 0; $where['status'] = 1; $category_id && $where['category_id'] = $category_id; $hasProductMerIdList = Db::name('store_product') ->where('status', '=', 1) ->where('is_show', '=', 1) ->where('is_del', '=', 0) ->group('mer_id') ->field('mer_id') ->select(); if ($hasProductMerIdList) { $hasProductMerIdList = array_column($hasProductMerIdList->toArray(), 'mer_id'); } $query = Db::name('merchant')->where($where); if (!empty($hasProductMerIdList) && is_array($hasProductMerIdList)) { $query->whereIn('mer_id', $hasProductMerIdList); } $mer_list = $query->page($page)->limit($limit)->select(); $where['is_gift_bag'] = 0; $where['is_used'] = 1; $where['product_type'] = 0; $where['is_hide'] = 0; $return_list = []; if($mer_list) { $mer_list = $mer_list->toArray(); foreach ($mer_list as $mer) { if(in_array($mer['mer_id'],$mer_id_unset)) continue; $goods = $this->repository->productList($mer['mer_id'],$where, 1, 3,$this->userInfo,false,$is_commercetrade); if(empty($goods['list'])) continue; $mer['goods_list'] = $goods['list']; if (mb_strlen($mer['mer_name']) > 8) { $mer['mer_name'] = mb_substr($mer['mer_name'], 0, 8) . '...'; } $return_list[] = $mer; } } return app('json')->success(['list'=>$return_list]); } /** * 查询代理人商品 * @param $type * @return mixed */ public function areaProductList() { [$page, $limit] = $this->getPage(); $where = $this->request->params(['keyword','order','mer_cate_id','price_on', 'price_off','brand_id']); $where['is_gift_bag'] = 0; $where['is_used'] = 1; $where['product_type'] = 0; $where['is_hide'] = 0; $type = $this->request->param('type'); Log::info('查询代理人商品请求参数,type:'.$type); $type = $type == 'district' ? 13 : ($type == 'town' ? 12 : ($type == 'village' ? 11 : -1)); // $where['web_type'] = $type; $id = 324; $data = $this->repository->productList($id,$where, $page, $limit,$this->userInfo); Log::info('查询代理人商品返回'.json_encode($data,true)); return app('json')->success($data); } /** * @Author:Qinii * @Date: 2020/5/29 * @param int $id * @return mixed */ public function categoryList($id) { if(!$this->repository->merExists($id)) return app('json')->fail('店铺不存在'); return app('json')->success($this->repository->categoryList($id)); } public function qrcode($id) { $mer = \app\common\model\system\merchant\Merchant::getInstance()->where('mer_id', $id)->find(); if(!$mer) return app('json')->fail('店铺不存在'); $type = $this->request->param('type'); $is_payment = $this->request->param('is_payment', 0); switch ($type) { case 'routine': if ($is_payment) { $url = $this->repository->routineQrcode(intval($id), '/h5payment/index.html','_store_routine_payment.jpg'); } else { $url = $this->repository->routineQrcode(intval($id)); } break; default: if ($is_payment) { $url = $this->repository->wxQrcode(intval($id), '/h5payment/index.html', '_store_wap_payment.jpg', $mer->mer_avatar); } else { $url = $this->repository->wxQrcode(intval($id)); } } return app('json')->success(compact('url')); } public function payQrCode($id){ $mer = \app\common\model\system\merchant\Merchant::getInstance()->where('mer_id', $id)->find(); if(!$mer) return app('json')->fail('店铺不存在'); $res = $this -> repository -> getQrCode($mer); return app('json') -> success($res); } /** * @Date: 2020/10/10 * 店铺列表 :首页 最多十个 * @return mixed */ public function listindex() { // [$page, $limit] = $this->getPage(); $page=input("page/d",1); $limit=input("limit/d",10); $keyword=input("keyword",""); $order=input("order",0); $type=input("type",2); $lat=input("lat",1); $lng=input("lng",1); $data=[ "lat"=>$lat, "lng"=>$lng, "keyword"=>$keyword, "order"=>$order ]; return app('json')->success($this->repository->getLists($data,$page,$limit,$type)); } /** * @Date: 2020/10/10 * 店铺列表: * @param $keyword //搜索 * @param $order //排序 * @param $category_id //分类id * @return mixed */ public function list() { $category_id=input("category_id",0); $page=input("page/d",1); $limit=input("limit/d",10); $keyword=input("keyword",""); $order=input("order",0); $type=input("type",0); $lat=input("lat",'113.643636'); $lng=input("lng",'34.73841'); $city_name=input("city_name",''); if ($type==2){ $data=[ "lat"=>empty($lat)?"113.643636":$lat, "lng"=>empty($lng)?"34.73841":$lng, "keyword"=>$keyword, "order"=>$order ]; return app('json')->success($this->repository->getLists($data,$page,$limit,$type)); } $where=[]; if ($category_id){ $where["category_id"]=$category_id; } $data=[ "lat"=>empty($lat)?"34.73841":$lat, "lng"=>empty($lng)?"113.643636":$lng, ]; if ($city_name){ $data["city_name"]=$city_name; } return app('json')->success($this->repository->getLists($data,1,10,1,$where)); // return app('json')->success(['count'=>0,'list'=>[],'where'=>[]]); } /** * @Date: 2020/10/10 * 店铺分类 */ public function merchantcategory() { [$page, $limit] = $this->getPage(); return app('json')->success($this->repository->merchantcategory()); } /** * 附近页面商家分类 * @day 2020/10/30 */ public function mercat() { [$page, $limit] = $this->getPage(); return app('json')->success($this->repository->mercat($page, $limit)); } /* *分类下的商家列表 * @author cabbage * @day 2020/10/30 * */ public function mercatStore(){ [$page, $limit] = $this->getPage(); $data = $this->request->params([ 'order', //人气 'distance', //距离 'lat', //经度 'lng', //纬度 'user_id' ]); $where = $this->request->params([ 'category_id', //商铺分类id 'keyword', //商铺名称 ]); return app('json')->success($this->repository->getLst($data,$page,$limit,$where)); // return app('json')->success([]); } /** * @param $id * @return mixed * @throws \think\db\exception\DbException * 店铺置顶 */ public function shop_topping($id) { if($id!=0){ $res=Db::name('user')->where('uid',$this->request->uid())->update(['mer_topping'=>$id]); if($res!==false) $message='置顶成功'; else $message='置顶失败'; return app('json')->success($message); }else{ $res=Db::name('user')->where('uid',$this->request->uid())->update(['mer_topping'=>0]); if($res!==false) $message='取消置顶成功'; else $message='取消置顶失败'; return app('json')->success($message); } } /** * @param $id * @return mixed * @throws \think\db\exception\DbException * 店铺点赞 or 店铺取消点赞 */ public function shop_fabulous($id) { $uid=$this->request->uid(); $user_like=Db::name('store_fabulous')->where('uid',$uid)->where('mer_id',$id)->value('status'); if($user_like=='0'){ $res=Db::name('store_fabulous')->where('uid',$uid)->where('mer_id',$id)->update(['status'=>1]); if($res!==false) $message='点赞成功'; else $message='点赞失败'; }elseif ($user_like=='1'){ $res=Db::name('store_fabulous')->where('uid',$uid)->where('mer_id',$id)->update(['status'=>0]); if($res!==false) $message='取消点赞成功'; else $message='取消点赞失败'; }else{ $inser_data=[ 'uid'=>$uid, 'mer_id'=>$id, 'ctime'=>time(), 'status'=>1 ]; $res=Db::name('store_fabulous')->insert($inser_data); if($res!==false) $message='点赞成功'; else $message='点赞失败'; } return app('json')->success($message); } }