ThemeService.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeshop100%开源免费商用商城系统
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | 商业版本务必购买商业授权,以免引起法律纠纷
  8. // | 禁止对系统程序代码以任何目的,任何形式的再发布
  9. // | gitee下载:https://gitee.com/likeshop_gitee
  10. // | github下载:https://github.com/likeshop-github
  11. // | 访问官网:https://www.likeshop.cn
  12. // | 访问社区:https://home.likeshop.cn
  13. // | 访问手册:http://doc.likeshop.cn
  14. // | 微信公众号:likeshop技术社区
  15. // | likeshop团队 版权所有 拥有最终解释权
  16. // +----------------------------------------------------------------------
  17. // | author: likeshopTeam
  18. // +----------------------------------------------------------------------
  19. namespace app\common\service;
  20. use app\common\{enum\ActivityEnum,
  21. enum\GoodsEnum,
  22. enum\LiveEnum,
  23. enum\PresellEnum,
  24. enum\SeckillEnum,
  25. enum\TeamEnum,
  26. model\Cart,
  27. model\CouponList,
  28. model\Goods,
  29. model\GoodsItem,
  30. model\Order,
  31. model\Coupon,
  32. enum\CouponEnum,
  33. model\Presell,
  34. model\PresellGoods,
  35. model\PresellGoodsItem,
  36. model\SeckillActivity,
  37. model\SeckillGoodsItem,
  38. model\ShopNotice,
  39. enum\ThemePageEnum,
  40. model\GoodsCategoryIndex,
  41. model\TeamActivity,
  42. model\TeamGoodsItem};
  43. use function JmesPath\search;
  44. /**
  45. * 主题功能类
  46. * Class ThemeService
  47. * @package app\common\service
  48. */
  49. class ThemeService
  50. {
  51. public static array $params = [];
  52. /**
  53. * @notes 替换组件内容
  54. * @param array $content
  55. * @return array
  56. * @author cjhao
  57. * @date 2021/8/19 18:52
  58. */
  59. public static function getModuleData(array $content,array $config = []):array
  60. {
  61. self::$params = $config;
  62. $isDistribution = self::$params['is_distribution'] ?? false; //是否分销
  63. $isVerifier = self::$params['is_verifier'] ?? false; //是否核销员
  64. $source = self::$params['source'] ?? 'shop'; //后台组件替换或商城组件替换
  65. $userId = self::$params['user_id'] ?? '';
  66. $moduleList = array_column($content,'name');
  67. return $moduleList;
  68. foreach ($moduleList as $moduleKey => $moduleName) {
  69. //需要拼接数据的组件
  70. switch ($moduleName) {
  71. //商品组件
  72. case ThemePageEnum::GOODS:
  73. $goods_type = $content[$moduleKey]['content']['goods_type'] ?? 2;
  74. //商品分类
  75. $limit = false;
  76. if(2 == $goods_type){
  77. if('admin' == $source){
  78. $content[$moduleKey]['content']['data'] = [];
  79. break;
  80. }
  81. $categoryId = $content[$moduleKey]['content']['category']['id'] ?? 0;
  82. $limit = $content[$moduleKey]['content']['category']['num'] ?? false;
  83. $goodsIds = GoodsCategoryIndex::where(['category_id'=>$categoryId])->column('goods_id');
  84. }else{
  85. $goodsIds = array_column($content[$moduleKey]['content']['data'], 'id');
  86. }
  87. //如果id都是空,直接返回数组
  88. if (empty($goodsIds)) {
  89. $content[$moduleKey]['content']['data'] = [];
  90. break;
  91. // $goods_info = Goods::where(['status'=>1])->field('id')->select()->toArray();
  92. // $goods_id_arr = array_column($goods_info,'id');
  93. // $goodsIds = array_rand($goods_id_arr,1);
  94. }
  95. //todo 商品需要根据顺序排序
  96. $orderField = implode(',', $goodsIds);
  97. $goodsList = Goods::where(['id' => $goodsIds,'status'=>GoodsEnum::STATUS_SELL])
  98. ->field('id,name,image,virtual_sales_num+sales_num as sales_num,min_price as sell_price,min_lineation_price as lineation_price,0 as is_multi_gauge')
  99. ->orderRaw("field(id,$orderField)")
  100. ->limit($limit)
  101. ->order('sort desc')
  102. ->select()
  103. ->toArray();
  104. // foreach($goodsList as &$gv){
  105. // $goods_item_count = GoodsItem::where(['goods_id'=>$gv['id']])->count();
  106. // if($goods_item_count > 1){
  107. // $gv['is_multi_gauge'] = 1;
  108. // }else{
  109. // $gv['is_multi_gauge'] = 0;
  110. // }
  111. // }
  112. //是否显示划线加
  113. $showPrice = ConfigService::get('goods_set', 'show_price', 1);
  114. if(0 == $showPrice){
  115. foreach ($goodsList as $goodsKey => $goodsVal){
  116. $goodsList[$goodsKey]['lineation_price'] = 0;
  117. }
  118. }
  119. $content[$moduleKey]['content']['data'] = $goodsList;
  120. break;
  121. //选项卡组件 todo 选项卡的data是多维数据
  122. case ThemePageEnum::TABS:
  123. $dataList = $content[$moduleKey]['content']['data'];
  124. foreach ($dataList as $dataKey => $dataVal){
  125. $goods_type = $dataVal['goods_type'] ?? 1;
  126. $limit = false;
  127. if(2 == $goods_type){
  128. if('admin' == $source){
  129. $content[$moduleKey]['content']['data'][$dataKey]['data'] = [];
  130. break;
  131. }
  132. $categoryId = $dataVal['category']['id'] ?? 0;
  133. $limit = $dataVal['category']['num'] ?? false;
  134. $goodsIds = GoodsCategoryIndex::where(['category_id'=>$categoryId])->column('goods_id');
  135. }else{
  136. $goodsIds = array_column($dataVal['data'], 'id');
  137. }
  138. //如果id都是空,直接返回数组
  139. if (empty($goodsIds)) {
  140. $content[$moduleKey]['content']['data'][$dataKey]['data'] = [];
  141. break;
  142. // $goods_info = Goods::where(['status'=>1])->field('id')->select()->toArray();
  143. // $goods_id_arr = array_column($goods_info,'id');
  144. // $goodsIds = array_rand($goods_id_arr,1);
  145. }
  146. //todo 商品需要根据顺序排序
  147. $orderField = implode(',', $goodsIds);
  148. $goodsList = Goods::where(['id' => $goodsIds,'status'=>GoodsEnum::STATUS_SELL])
  149. ->field('id,name,image,virtual_sales_num+sales_num as sales_num,min_price as sell_price,min_lineation_price as lineation_price,0 as is_multi_gauge')
  150. ->orderRaw("field(id,$orderField)")
  151. ->limit($limit)
  152. ->select()
  153. ->toArray();
  154. // foreach($goodsList as &$gv){
  155. // $goods_item_count = GoodsItem::where(['goods_id'=>$gv['id']])->count();
  156. // if($goods_item_count > 1){
  157. // $gv['is_multi_gauge'] = 1;
  158. // }else{
  159. // $gv['is_multi_gauge'] = 0;
  160. // }
  161. // }
  162. //是否显示划线加
  163. $showPrice = ConfigService::get('goods_set', 'show_price', 1);
  164. if(0 == $showPrice){
  165. foreach ($goodsList as $goodsKey => $goodsVal){
  166. $goodsList[$goodsKey]['lineation_price'] = 0;
  167. }
  168. }
  169. $content[$moduleKey]['content']['data'][$dataKey]['data'] = $goodsList;
  170. }
  171. break;
  172. //优惠券组件
  173. case ThemePageEnum::COUPON:
  174. $couponIds = array_column($content[$moduleKey]['content']['data'], 'id');
  175. //如果id都是空,直接返回数组
  176. if (empty($couponIds)) {
  177. $content[$moduleKey]['content']['data'] = [];
  178. break;
  179. }
  180. //todo 优惠券需要根据顺序排序
  181. $orderField = implode(',', $couponIds);
  182. $couponList = Coupon::where(['id' => $couponIds,'status'=>[CouponEnum::COUPON_STATUS_NOT,CouponEnum::COUPON_STATUS_CONDUCT]])
  183. ->append([ 'use_type', 'discount_content', 'status_desc', 'condition' ])
  184. ->field('id,name,money,discount_ratio,condition_type,get_num_type,condition_money,use_goods_type,get_num,status')
  185. ->orderRaw("field(id,$orderField)")
  186. ->select();
  187. $myCouponIds = [];
  188. if($couponList && $userId){
  189. $myCouponIds = CouponList::where(['user_id'=>$userId,'status'=>CouponEnum::USE_STATUS_NOT])
  190. ->column('coupon_id');
  191. }
  192. $list = [];
  193. foreach ($couponList as $coupon) {
  194. //是否已领取
  195. $isReceive = 0;
  196. if(in_array($coupon->id,$myCouponIds)){
  197. $isReceive = 1;
  198. }
  199. $isAvailable = 0;
  200. //是否可领取
  201. switch ($coupon->get_num_type) {
  202. case CouponEnum::GET_NUM_TYPE_LIMIT:
  203. $total = CouponList::where(['coupon_id' => $coupon->id])
  204. ->where(['user_id' => $userId])
  205. ->count();
  206. $isAvailable = $total >= $coupon->get_num ? 1 : 0;
  207. break;
  208. case CouponEnum::GET_NUM_TYPE_DAY:
  209. $total = CouponList::where(['coupon_id' => $coupon->id])
  210. ->where(['user_id' =>$userId])
  211. ->where('create_time', '>=', TimeService::today()[0])
  212. ->where('create_time', '<=', TimeService::today()[1])
  213. ->count();
  214. $isAvailable = $total >= $coupon->get_num ? 1 : 0;
  215. break;
  216. }
  217. $coupon->is_receive = $isReceive;
  218. $coupon->is_available = $isAvailable;
  219. $list[] = $coupon->toArray();
  220. }
  221. $content[$moduleKey]['content']['data'] = $list;
  222. break;
  223. //公告组件
  224. case ThemePageEnum::NOTICE:
  225. $limit = $content[$moduleKey]['content']['num'] ?? 1;//默认拿一条
  226. $noticeList = ShopNotice::field('id,name')
  227. ->where(['status'=>1])
  228. ->limit($limit)
  229. ->order('sort asc,id desc')
  230. ->select()
  231. ->toArray();
  232. $content[$moduleKey]['content']['data'] = $noticeList;
  233. break;
  234. //会员中心-我的服务组件、微页面-导航组件
  235. case ThemePageEnum::USERSERVE:
  236. case ThemePageEnum::NAVIGATION:
  237. if('admin' == $source){
  238. break;
  239. }
  240. $linksData = $content[$moduleKey]['content']['data'];
  241. foreach ($linksData as $linkKey => $link){
  242. // 非分销用户,屏蔽分销菜单,index == 17时分销菜单,
  243. if(false === $isDistribution && isset($link['link']['index']) && 17 == $link['link']['index']){
  244. unset($linksData[$linkKey]);
  245. }
  246. //非核销用户,屏蔽分销菜单
  247. if(false === $isVerifier && isset($link['link']['index']) && 19 == $link['link']['index']){
  248. unset($linksData[$linkKey]);
  249. }
  250. }
  251. $content[$moduleKey]['content']['data'] = array_values($linksData);
  252. break;
  253. //商品拼团
  254. case ThemePageEnum::SPELLGROUP:
  255. if('admin' == $source){
  256. break;
  257. }
  258. $dataType = $content[$moduleKey]['content']['data_type'];
  259. $data = $content[$moduleKey]['content']['data'];
  260. $limit = false;
  261. $where = [];
  262. if(1 == $dataType) {
  263. //获取数量
  264. $limit = $content[$moduleKey]['content']['num'];
  265. $orderField = 'TA.id desc';
  266. }else{
  267. if(empty($data)){
  268. break;
  269. }
  270. $goods_ids = array_column($data,'goods_id');
  271. $where = ['goods_id'=>$goods_ids];
  272. $goodsIds = implode(',',array_column($data,'goods_id'));
  273. $orderField = "field(goods_id,$goodsIds)";
  274. }
  275. $goodsList = TeamActivity::alias('TA')
  276. ->join('team_goods TG','TA.id = TG.team_id')
  277. ->join('goods G','TG.goods_id = G.id')
  278. ->where([
  279. ['TA.status','=',TeamEnum::TEAM_STATUS_CONDUCT],
  280. ['start_time', '<=', time()],
  281. ['end_time', '>=', time()],
  282. ])
  283. ->where($where)
  284. ->field('TA.id as activity_id,TG.id,goods_id,goods_snap,min_team_price,people_num,G.image')
  285. ->limit($limit)
  286. ->orderRaw($orderField)
  287. ->select()
  288. ->toArray();
  289. if(empty($goodsList)){
  290. $content[$moduleKey]['content']['data'] = [];
  291. break;
  292. }
  293. // foreach($goodsList as &$gv){
  294. // $goods_item_count = GoodsItem::where(['goods_id'=>$gv['id']])->count();
  295. // if($goods_item_count > 1){
  296. // $gv['is_multi_gauge'] = 1;
  297. // }else{
  298. // $gv['is_multi_gauge'] = 0;
  299. // }
  300. // }
  301. $activityIds = array_column($goodsList,'activity_id');
  302. $goodsIds = array_column($goodsList,'goods_id');
  303. $salesList = TeamGoodsItem::where(['team_id'=>$activityIds,'goods_id'=>$goodsIds])
  304. ->group('goods_id')
  305. ->column('sum(sales_volume)','goods_id');
  306. $data = [];
  307. foreach ($goodsList as $goods){
  308. $goods_snap = json_decode($goods['goods_snap'],true);
  309. $data[] = [
  310. 'id' => $goods['id'],
  311. 'activity_id' => $goods['activity_id'],
  312. 'activity_type' => ActivityEnum::TEAM,
  313. 'goods_id' => $goods['goods_id'],
  314. 'name' => $goods_snap['name'],
  315. 'image' => FileService::getFileUrl($goods['image']),
  316. 'people_num' => $goods['people_num'],
  317. 'sell_price' => $goods_snap['min_price'],
  318. 'activity_price' => $goods['min_team_price'],
  319. 'activity_sales' => $salesList[$goods['goods_id']] ?? 0,
  320. ];
  321. }
  322. $content[$moduleKey]['content']['data'] = $data;
  323. break;
  324. //商品秒杀
  325. case ThemePageEnum::SECKILL:
  326. if('admin' == $source){
  327. break;
  328. }
  329. $dataType = $content[$moduleKey]['content']['data_type'];
  330. $data = $content[$moduleKey]['content']['data'];
  331. $limit = false;
  332. $where = [];
  333. //自动获取商品
  334. if(1 == $dataType) {
  335. //获取数量
  336. $limit = $content[$moduleKey]['content']['num'];
  337. $orderField = 'SA.id desc';
  338. }else{
  339. if(empty($data)){
  340. break;
  341. }
  342. $goods_ids = array_column($data,'goods_id');
  343. $where = ['goods_id'=>$goods_ids];
  344. $goodsIds = implode(',',array_column($data,'goods_id'));
  345. $orderField = "field(goods_id,$goodsIds)";
  346. }
  347. $goodsList = SeckillActivity::alias('SA')
  348. ->join('seckill_goods SG','SA.id = SG.seckill_id')
  349. ->join('goods G','SG.goods_id = G.id')
  350. ->where([
  351. ['SA.status','=',SeckillEnum::SECKILL_STATUS_CONDUCT],
  352. ['start_time', '<=', time()],
  353. ['end_time', '>=', time()],
  354. ])
  355. ->where($where)
  356. ->field('SA.id as activity_id,SG.id,goods_id,goods_snap,min_seckill_price,G.image')
  357. ->limit($limit)
  358. ->orderRaw($orderField)
  359. ->select()
  360. ->toArray();
  361. if(empty($goodsList)){
  362. $content[$moduleKey]['content']['data'] = [];
  363. break;
  364. }
  365. // foreach($goodsList as &$gv){
  366. // $goods_item_count = GoodsItem::where(['goods_id'=>$gv['id']])->count();
  367. // if($goods_item_count > 1){
  368. // $gv['is_multi_gauge'] = 1;
  369. // }else{
  370. // $gv['is_multi_gauge'] = 0;
  371. // }
  372. // }
  373. //销量
  374. $activityIds = array_column($goodsList,'activity_id');
  375. $goodsIds = array_column($goodsList,'goods_id');
  376. $salesList = SeckillGoodsItem::where(['seckill_id'=>$activityIds,'goods_id'=>$goodsIds])
  377. ->group('goods_id')
  378. ->column('sum(sales_volume)','goods_id');
  379. $data = [];
  380. foreach ($goodsList as $goods){
  381. $goodsSnap = json_decode($goods['goods_snap'],true);
  382. $data[] = [
  383. 'id' => $goods['id'],
  384. 'activity_id' => $goods['activity_id'],
  385. 'activity_type' => ActivityEnum::SECKILL,
  386. 'goods_id' => $goods['goods_id'],
  387. 'name' => $goodsSnap['name'],
  388. 'image' => FileService::getFileUrl($goods['image']),
  389. 'sell_price' => $goodsSnap['min_price'],
  390. 'activity_price' => $goods['min_seckill_price'],
  391. 'activity_sales' => $salesList[$goods['goods_id']] ?? 0,
  392. ];
  393. }
  394. $content[$moduleKey]['content']['data'] = $data;
  395. break;
  396. // 预售
  397. case ThemePageEnum::PRESELL:
  398. if('admin' == $source){
  399. break;
  400. }
  401. $dataType = $content[$moduleKey]['content']['data_type'];
  402. $data = $content[$moduleKey]['content']['data'];
  403. $limit = false;
  404. $where = [];
  405. //自动获取商品
  406. if(1 == $dataType) {
  407. //获取数量
  408. $limit = $content[$moduleKey]['content']['num'];
  409. $orderField = 'pg.id desc';
  410. }else{
  411. if(empty($data)){
  412. break;
  413. }
  414. $goods_ids = array_column($data,'goods_id');
  415. $where = ['pg.goods_id'=>$goods_ids];
  416. $goodsIds = implode(',',array_column($data,'goods_id'));
  417. $orderField = "field(goods_id,$goodsIds)";
  418. }
  419. $lists = PresellGoods::alias('pg')
  420. ->join('presell p', 'p.id=pg.presell_id')
  421. ->where('p.status', PresellEnum::STATUS_START)
  422. ->where('p.start_time', '<=', time())
  423. ->where('p.end_time', '>=', time())
  424. ->where($where)
  425. ->limit($limit)
  426. ->orderRaw($orderField)
  427. ->field([
  428. 'pg.id',
  429. 'p.id as presell_id', 'p.name', 'p.type',
  430. 'p.start_time', 'p.end_time', 'p.remark',
  431. 'p.send_type', 'p.send_type_day', 'p.buy_limit', 'p.buy_limit_num',
  432. 'p.status',
  433. 'pg.goods_id',
  434. 'pg.content',
  435. 'pg.min_price',
  436. 'pg.virtual_sale',
  437. ])
  438. ->with([
  439. 'items' => function ($query) {
  440. $query->field([ 'presell_goods_id', 'sale_nums' ]);
  441. }
  442. ])
  443. ->select()
  444. ->toArray();
  445. $data = [];
  446. foreach ($lists as $presell) {
  447. $data[] = [
  448. 'id' => $presell['goods_id'],
  449. 'activity_id' => $presell['presell_id'],
  450. 'activity_type' => ActivityEnum::PRESELL,
  451. 'goods_id' => $presell['goods_id'],
  452. 'name' => $presell['content']['name'],
  453. 'image' => FileService::getFileUrl($presell['content']['image']),
  454. 'sell_price' => $presell['content']['min_price'],
  455. 'activity_price' => $presell['min_price'],
  456. 'activity_sales' => array_sum(array_column($presell['items'], 'sale_nums')) + ($presell['virtual_sale']),
  457. ];
  458. }
  459. $content[$moduleKey]['content']['data'] = $data;
  460. break;
  461. //商品推荐
  462. case ThemePageEnum::GOODSRECOM:
  463. $show = $content[$moduleKey]['show'];
  464. if('admin' == $source || 0 == $show){
  465. break;
  466. }
  467. $content[$moduleKey]['content']['data'] = self::recommend();
  468. break;
  469. //小程序直播
  470. case ThemePageEnum::MNPLIVE:
  471. if('admin' == $source){
  472. break;
  473. }
  474. $num = $content[$moduleKey]['content']['num'] ?? 1;
  475. $result = WeChatService::getLiveRoom(0,$num);
  476. if (!is_array($result)) {
  477. break;
  478. }
  479. $data = [];
  480. foreach ($result['room_info'] as $item) {
  481. $data[] = [
  482. 'name' => $item['name'],
  483. 'room_id' => $item['roomid'],
  484. 'cover_img' => $item['cover_img'],
  485. 'anchor_name' => $item['anchor_name'],
  486. 'status' => $item['live_status'],
  487. 'live_status' => LiveEnum::getLiveStatus($item['live_status']),
  488. 'goods' => count($item['goods']),
  489. 'start_time' => date('Y-m-d H:i:s', $item['start_time']),
  490. 'end_time' => date('Y-m-d H:i:s', $item['end_time'])
  491. ];
  492. }
  493. $content[$moduleKey]['content']['data'] = $data;
  494. break;
  495. }
  496. }
  497. return $content;
  498. }
  499. public static function getPCModuleData(array $content,array $config = []):array
  500. {
  501. self::$params = $config;
  502. $isDistribution = self::$params['is_distribution'] ?? false; //是否分销
  503. $isVerifier = self::$params['is_verifier'] ?? false; //是否核销员
  504. $source = self::$params['source'] ?? 'shop'; //后台组件替换或商城组件替换
  505. $userId = self::$params['user_id'] ?? '';
  506. $moduleList = array_column($content,'name');
  507. foreach ($moduleList as $moduleKey => $moduleName){
  508. //需要拼接数据的组件
  509. switch ($moduleName) {
  510. case ThemePageEnum::GOODS:
  511. $goods_type = $content[$moduleKey]['content']['goods_type'] ?? 2;
  512. //商品分类
  513. $limit = false;
  514. if(2 == $goods_type){
  515. if('admin' == $source){
  516. $content[$moduleKey]['content']['data'] = [];
  517. break;
  518. }
  519. $categoryId = $content[$moduleKey]['content']['category']['id'] ?? 0;
  520. $limit = $content[$moduleKey]['content']['category']['num'] ?? false;
  521. $goodsIds = GoodsCategoryIndex::where(['category_id'=>$categoryId])->column('goods_id');
  522. }else{
  523. $goodsIds = array_column($content[$moduleKey]['content']['data'], 'id');
  524. }
  525. //如果id都是空,直接返回数组
  526. if (empty($goodsIds)) {
  527. $content[$moduleKey]['content']['data'] = [];
  528. break;
  529. }
  530. //todo 商品需要根据顺序排序
  531. $orderField = implode(',', $goodsIds);
  532. $goodsList = Goods::where(['id' => $goodsIds,'status'=>GoodsEnum::STATUS_SELL])
  533. ->field('id,name,image,virtual_sales_num+sales_num as sales_num,min_price as sell_price,min_lineation_price as lineation_price')
  534. ->orderRaw("field(id,$orderField)")
  535. ->limit($limit)
  536. ->select()
  537. ->toArray();
  538. //是否显示划线加
  539. $showPrice = ConfigService::get('goods_set', 'show_price', 1);
  540. if(0 == $showPrice){
  541. foreach ($goodsList as $goodsKey => $goodsVal){
  542. $goodsList[$goodsKey]['lineation_price'] = 0;
  543. }
  544. }
  545. $content[$moduleKey]['content']['data'] = $goodsList;
  546. break;
  547. case ThemePageEnum::SECKILL:
  548. if('admin' == $source){
  549. break;
  550. }
  551. $dataType = $content[$moduleKey]['content']['data_type'];
  552. $data = $content[$moduleKey]['content']['data'];
  553. $limit = false;
  554. $where = [];
  555. //自动获取商品
  556. if(1 == $dataType) {
  557. //获取数量
  558. $limit = $content[$moduleKey]['content']['num'];
  559. $orderField = 'SA.id desc';
  560. }else{
  561. if(empty($data)){
  562. break;
  563. }
  564. $goods_ids = array_column($data,'goods_id');
  565. $where = ['goods_id'=>$goods_ids];
  566. $goodsIds = implode(',',array_column($data,'goods_id'));
  567. $orderField = "field(goods_id,$goodsIds)";
  568. }
  569. $goodsList = SeckillActivity::alias('SA')
  570. ->join('seckill_goods SG','SA.id = SG.seckill_id')
  571. ->where([
  572. ['status','=',SeckillEnum::SECKILL_STATUS_CONDUCT],
  573. ['start_time', '<=', time()],
  574. ['end_time', '>=', time()],
  575. ])
  576. ->where($where)
  577. ->field('SA.id as activity_id,SG.id,goods_id,goods_snap,min_seckill_price')
  578. ->limit($limit)
  579. ->orderRaw($orderField)
  580. ->select()
  581. ->toArray();
  582. if(empty($goodsList)){
  583. $content[$moduleKey]['content']['data'] = [];
  584. break;
  585. }
  586. //销量
  587. $activityIds = array_column($goodsList,'activity_id');
  588. $goodsIds = array_column($goodsList,'goods_id');
  589. $salesList = SeckillGoodsItem::where(['seckill_id'=>$activityIds,'goods_id'=>$goodsIds])
  590. ->group('goods_id')
  591. ->column('sum(sales_volume)','goods_id');
  592. $data = [];
  593. foreach ($goodsList as $goods){
  594. $goodsSnap = json_decode($goods['goods_snap'],true);
  595. $data[] = [
  596. 'id' => $goods['id'],
  597. 'activity_id' => $goods['activity_id'],
  598. 'activity_type' => ActivityEnum::SECKILL,
  599. 'goods_id' => $goods['goods_id'],
  600. 'name' => $goodsSnap['name'],
  601. 'image' => FileService::getFileUrl($goodsSnap['image']),
  602. 'sell_price' => $goodsSnap['min_price'],
  603. 'activity_price' => $goods['min_seckill_price'],
  604. 'activity_sales' => $salesList[$goods['goods_id']] ?? 0,
  605. ];
  606. }
  607. $content[$moduleKey]['content']['data'] = $data;
  608. break;
  609. }
  610. }
  611. return $content;
  612. }
  613. /**
  614. * @notes 获取推荐商品
  615. * @param string $orderRaw 推荐商品排序;默认按销量和排序,传空则随机排序
  616. * @return array $type 页面类型
  617. * @return array $goodsIds 排除的商品id
  618. * @author cjhao
  619. * @date 2021/8/23 11:07
  620. */
  621. public static function recommend(string $orderRaw = 'virtual_sales_num+sales_num desc,sort desc',int $type=0,array $goodsIds = []):array
  622. {
  623. $pageType = self::$params['page_type'] ?? $type; //页面类型
  624. $goodsList = [];
  625. $categoryIds = [];
  626. $notGoodsIds = self::$params['goods_id'] ?? $goodsIds;
  627. //如果传空,则使用随机排序
  628. if(empty($orderRaw)){
  629. $orderRaw = 'rand()';
  630. }
  631. //获取推荐商品:
  632. switch ($pageType){
  633. case ThemePageEnum::TYPE_GOODS_DETAIL://商品详情推荐商品
  634. $goodsId = self::$params['goods_id'] ?? '';
  635. $categoryIds = GoodsCategoryIndex::where(['goods_id'=>$goodsId])->column('category_id');
  636. break;
  637. case ThemePageEnum::TYPE_CART: //购物车推荐商品
  638. $userId = self::$params['user_id'] ?? '';
  639. //购物车商品的分类
  640. $cartList = Cart::alias('C')
  641. ->join('goods_category_index GCI','C.goods_id = GCI.goods_id')
  642. ->where(['user_id'=>$userId])
  643. ->column('C.goods_id,category_id');
  644. $notGoodsIds = array_unique(array_column($cartList,'goods_id'));
  645. $categoryIds = array_unique(array_column($cartList,'category_id'));
  646. if(empty($notGoodsIds) || empty($categoryIds)){
  647. $goods_info = Goods::alias('g')->leftJoin('goods_category_index gci','g.id=gci.goods_id')->field('g.id,gci.category_id')->where('g.status = 1')->select()->toArray();
  648. $key_Arr = array_keys($goods_info);
  649. $gc_key = array_rand($key_Arr,1);
  650. $goods_card_info = $goods_info[$gc_key];
  651. $notGoodsIds[] = $goods_card_info['id'];
  652. if((count($goods_card_info['category_id'])>1)){
  653. $key_Arr1 = array_keys($goods_card_info['category_id']);
  654. $gc_key1 = array_rand($key_Arr1,1);
  655. $categoryIds[]=$goods_card_info['category_id'][$gc_key1];
  656. }else{
  657. $categoryIds[]=$goods_card_info['category_id'][0];
  658. }
  659. }
  660. break;
  661. case ThemePageEnum::TYPE_MEMBER_CENTRE://个人中心推荐商品
  662. $userId = self::$params['user_id'] ?? '';
  663. //订单商品的分类
  664. $orderList = Order::alias('O')
  665. ->join('order_goods OG','O.id = OG.order_id')
  666. ->join('goods_category_index GCI','OG.goods_id = GCI.goods_id')
  667. ->where(['user_id'=>$userId])
  668. ->column('OG.goods_id,category_id');
  669. $notGoodsIds = array_unique(array_column($orderList,'goods_id'));
  670. $categoryIds = array_unique(array_column($orderList,'category_id'));
  671. break;
  672. }
  673. if($categoryIds){
  674. $where[] = ['status','=',GoodsEnum::STATUS_SELL];
  675. $where[] = ['category_id','in',$categoryIds];
  676. if($notGoodsIds){
  677. $where[] = ['G.id','not in',$notGoodsIds];
  678. }
  679. //找到推荐商品
  680. $goodsList = Goods::alias('G')
  681. ->join('goods_category_index GCI','G.id = GCI.goods_id')
  682. ->where($where)
  683. ->field('G.id,name,image,min_price as sell_price,min_lineation_price as lineation_price')
  684. ->group("G.id")
  685. ->orderRaw($orderRaw)
  686. ->limit(9)
  687. ->select()->toarray();
  688. //是否显示划线加
  689. $showPrice = ConfigService::get('goods_set', 'show_price', 1);
  690. if(0 == $showPrice){
  691. foreach ($goodsList as $goodsKey => $goodsVal){
  692. $goodsList[$goodsKey]['lineation_price'] = 0;
  693. }
  694. }
  695. }
  696. if(empty($goodsList)){
  697. $goodsList = [];
  698. $goodsLists = Goods::alias('G')
  699. ->join('goods_category_index GCI','G.id = GCI.goods_id')
  700. ->where('G.status = 1')
  701. ->field('G.id,name,image,min_price as sell_price,min_lineation_price as lineation_price')
  702. ->group("G.id")
  703. ->orderRaw($orderRaw)
  704. ->limit(20)
  705. ->select()->toarray();
  706. $key_Arr = array_keys($goodsLists);
  707. if(count($goodsLists)>4){
  708. $gc_key = array_rand($key_Arr,4);
  709. }else{
  710. $gc_key = $key_Arr;
  711. }
  712. foreach ($goodsLists as $k=>$v){
  713. foreach($gc_key as $gk=>$gv){
  714. if($k==$gk){
  715. $goodsList[]=$v;
  716. }
  717. }
  718. }
  719. }
  720. return $goodsList;
  721. }
  722. }