ThemeService.php 35 KB

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