StoreProduct.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\controller\api\store\product;
  12. use app\common\repositories\store\PriceRuleRepository;
  13. use app\common\repositories\store\product\ProductAttrRepository;
  14. use app\common\repositories\store\product\ProductAttrValueRepository;
  15. use app\common\repositories\store\product\SpuRepository;
  16. use app\common\repositories\store\StoreCategoryRepository;
  17. use app\common\repositories\system\groupData\GroupDataRepository;
  18. use app\common\repositories\user\UserMerchantRepository;
  19. use app\common\repositories\user\UserVisitRepository;
  20. use think\App;
  21. use crmeb\basic\BaseController;
  22. use app\common\repositories\store\product\ProductRepository as repository;
  23. use think\facade\Cache;
  24. use app\common\repositories\system\CacheRepository;
  25. class StoreProduct extends BaseController
  26. {
  27. use BindSpreadTrait;
  28. /**
  29. * @var repository
  30. */
  31. protected $repository;
  32. protected $userInfo = null;
  33. /**
  34. * StoreProduct constructor.
  35. * @param App $app
  36. * @param repository $repository
  37. */
  38. public function __construct(App $app, repository $repository)
  39. {
  40. parent::__construct($app);
  41. $this->repository = $repository;
  42. $this->userInfo = $this->request->isLogin() ? $this->request->userInfo() : null;
  43. }
  44. /**
  45. * 列出搜索结果
  46. *
  47. * 本函数用于根据用户请求的参数,从仓库中获取搜索结果的列表。搜索结果可以根据关键字、类别、价格范围、品牌、评级等条件进行筛选。
  48. * 接口返回搜索结果的分页数据。
  49. *
  50. * @return \think\response\Json 成功时返回的JSON格式数据,包含搜索结果信息。
  51. */
  52. public function lst()
  53. {
  54. // 解包分页信息
  55. [$page, $limit] = $this->getPage();
  56. // 获取请求中的搜索参数
  57. $where = $this->request->params(['keyword', 'cate_id', 'order', 'price_on', 'price_off', 'brand_id', 'pid', 'star']);
  58. // 从仓库中根据搜索条件获取搜索结果的分页数据
  59. $data = $this->repository->getApiSearch(null, $where, $page, $limit, $this->userInfo);
  60. // 返回成功的JSON响应,包含搜索结果数据
  61. return app('json')->success($data);
  62. }
  63. /**
  64. * 获取商品详情
  65. *
  66. * 本函数用于根据提供的ID获取商品的详细信息。如果商品不存在或已下架,则将商品状态设置为下架并返回相应信息。
  67. * 如果用户已登录,更新用户在商家处的最后活动时间。
  68. *
  69. * @param int $id 商品ID
  70. * @return json 返回商品详情数据或错误信息
  71. */
  72. public function detail($id)
  73. {
  74. $this->bindSpread($this->userInfo);
  75. //通过ID和用户信息获取商品详情
  76. $data = $this->repository->detail((int)$id, $this->userInfo);
  77. // 如果商品不存在,则将商品状态设置为下架并返回错误信息
  78. if (!$data) {
  79. app()->make(SpuRepository::class)->changeStatus($id, 0);
  80. return app('json')->fail('商品已下架');
  81. }
  82. // 如果用户已登录,更新用户在该商品所属商家的最后活动时间
  83. if ($this->request->isLogin()) {
  84. app()->make(UserMerchantRepository::class)->updateLastTime($this->request->uid(), $data['mer_id']);
  85. }
  86. // 返回商品详情数据
  87. return app('json')->success($data);
  88. }
  89. /**
  90. * 根据产品ID展示产品信息。
  91. *
  92. * 本函数用于获取指定产品ID的产品展示信息。如果用户已登录,将结合用户的ID来获取个性化展示信息。
  93. * 未登录用户将获取默认的展示信息。通过依赖注入的方式,使用JSON工具类来返回处理结果。
  94. *
  95. * @param int $id 产品ID,用于查询特定产品信息。
  96. * @return json 返回包含产品展示信息的JSON对象。
  97. */
  98. public function show($id)
  99. {
  100. // 检查用户是否已登录,已登录则获取用户ID,否则设置为0
  101. $uid = $this->request->isLogin() ? $this->request->uid() : 0;
  102. // 从仓库中获取指定ID的产品展示信息,如果用户已登录,则结合用户ID来获取信息
  103. $data = $this->repository->getProductShow($id, [], null, $uid);
  104. // 使用JSON工具类返回获取的产品展示信息
  105. return app('json')->success($data);
  106. }
  107. /**
  108. * 根据产品ID获取产品属性值
  109. *
  110. * 本函数通过产品ID获取相应产品的属性及其值,包括产品属性的详细信息和属性值信息。
  111. * 这对于展示产品详细信息或进行产品管理操作时非常有用。
  112. *
  113. * @param int $id 产品ID
  114. * @return json 返回包含产品属性和属性值的数据
  115. */
  116. public function getAttrValue($id)
  117. {
  118. // 创建产品属性仓库实例
  119. $productAttrRepository = app()->make(ProductAttrRepository::class);
  120. // 创建产品属性值仓库实例
  121. $productAttrValueRepository = app()->make(ProductAttrValueRepository::class);
  122. // 查询指定产品ID的所有属性信息
  123. $attr = $productAttrRepository->getSearch([])->where('product_id', $id)->select();
  124. // 处理属性信息,获取详细属性数据
  125. $data['attr'] = $this->repository->detailAttr($attr);
  126. // 查询指定产品ID的所有属性值信息
  127. $data['attrValue'] = $productAttrValueRepository->getSearch([])->where('product_id', $id)->select();
  128. // 返回处理后的数据,以JSON格式响应
  129. return app('json')->success($data);
  130. }
  131. /**
  132. * 获取推荐列表
  133. *
  134. * 本函数用于获取用户推荐内容的列表。它利用分页机制,返回指定页码和每页数量的推荐内容。
  135. * 推荐内容是基于用户信息和特定算法生成的,旨在为用户提供个性化的内容推荐。
  136. *
  137. * @return \Illuminate\Http\JsonResponse 推荐内容的JSON响应,包含成功状态和推荐数据。
  138. */
  139. public function recommendList()
  140. {
  141. // 解包获取当前请求的页码和每页数量
  142. [$page, $limit] = $this->getPage();
  143. // 调用repository中的recommend方法获取推荐内容,并包装在成功的JSON响应中返回
  144. return app('json')->success($this->repository->recommend($this->userInfo, null, $page, $limit));
  145. }
  146. /**
  147. * 生成商品二维码
  148. *
  149. * 本函数用于根据请求参数生成特定类型的商品二维码。支持常规商品二维码和小程序商品二维码。
  150. * 通过请求中的$id$获取商品信息,并根据请求中的类型参数决定生成哪种类型的二维码。
  151. * 如果商品不存在或请求参数有误,将返回错误信息。成功生成二维码后,返回二维码的链接。
  152. *
  153. * @param int $id 商品ID,用于查询商品信息。
  154. * @return json 返回包含二维码链接的JSON对象,如果生成失败则返回错误信息。
  155. */
  156. public function qrcode($id)
  157. {
  158. // 将ID转换为整数类型,确保数据类型的一致性和安全性
  159. $id = (int)$id;
  160. // 获取请求中的类型参数,以及默认的产品类型参数
  161. $param = $this->request->params(['type', ['product_type', 0]]);
  162. // 将产品类型参数转换为整数类型
  163. $param['product_type'] = (int)$param['product_type'];
  164. // 检查ID和产品类型是否有效,如果无效则返回错误信息
  165. if (!$id || !$product = $this->repository->existsProduct($id, $param['product_type']))
  166. return app('json')->fail('商品不存在');
  167. // 根据请求中的类型参数决定生成哪种类型的二维码
  168. if ($param['type'] == 'routine') {
  169. // 生成小程序商品二维码
  170. $url = $this->repository->routineQrCode($id, $param['product_type'], $this->userInfo);
  171. } else {
  172. // 生成常规商品二维码
  173. $url = $this->repository->wxQrCode($id, $param['product_type'], $this->userInfo);
  174. }
  175. // 检查二维码生成是否成功,如果失败则返回错误信息
  176. if (!$url) return app('json')->fail('二维码生成失败');
  177. // 返回生成的二维码链接
  178. return app('json')->success(compact('url'));
  179. }
  180. /**
  181. * 获取礼包列表
  182. *
  183. * 本方法用于获取符合特定条件的礼包列表。首先,它会检查系统配置是否启用了扩展功能,
  184. * 如果未开启,则返回一个表示失败的JSON响应,提示活动未开启。然后,它获取当前的分页信息,
  185. * 并构造一个查询条件。最后,它使用这些条件来获取礼包列表,并返回一个表示成功的JSON响应,
  186. * 其中包含礼包列表数据。
  187. *
  188. * @return \Illuminate\Http\JsonResponse 返回一个JSON响应,包含礼包列表数据或错误信息。
  189. */
  190. public function getBagList()
  191. {
  192. // 检查系统配置,如果扩展功能未开启,则返回失败的JSON响应
  193. if (!systemConfig('extension_status')) return app('json')->fail('活动未开启');
  194. // 获取当前的分页信息
  195. [$page, $limit] = $this->getPage();
  196. // 构造查询条件
  197. $where = $this->repository->bagShow();
  198. // 使用查询条件和分页信息获取礼包列表,并返回成功的JSON响应
  199. return app('json')->success($this->repository->getBagList($where, $page, $limit));
  200. }
  201. /**
  202. * 获取推荐商品包
  203. *
  204. * 本函数用于查询并返回被标记为最佳的商品包信息。它首先从仓库层获取所有展示中的商品包条件,
  205. * 然后特定地筛选出标记为最佳的商品包,并附加商家信息返回。
  206. *
  207. * @return \Illuminate\Http\JsonResponse 推荐商品包的信息,包括商家信息。
  208. */
  209. public function getBagrecomm()
  210. {
  211. // 从仓库层获取所有展示中的商品包的条件
  212. $where = $this->repository->bagShow();
  213. // 将条件限定为只包含标记为最佳的商品包
  214. $where['is_best'] = 1;
  215. // 返回查询结果,附加商家信息,并以JSON格式响应
  216. return app('json')->success($this->repository->selectWhere($where)->append(['merchant']));
  217. }
  218. /**
  219. * 获取推广员礼包说明
  220. *
  221. * 本函数用于获取推广员礼包的详细说明信息,包括推广员计划的介绍和配置数据。
  222. * 如果系统配置中推广员功能未开启,则返回错误信息。否则,从系统配置中获取推广员计划的介绍文本,
  223. * 并通过GroupDataRepository获取推广员配置的相关数据,最后将这些信息封装成JSON格式返回。
  224. *
  225. * @return \Illuminate\Http\JsonResponse 返回包含推广员计划说明和配置数据的JSON对象。
  226. */
  227. public function getBagExplain()
  228. {
  229. // 检查推广员功能是否开启,如果没有开启,则返回错误信息
  230. if (!systemConfig('extension_status')) return app('json')->fail('活动未开启');
  231. // 组装返回的数据,包括推广员计划的介绍和配置数据
  232. $data = [
  233. 'explain' => app()->make(CacheRepository::class)->getResult('promoter_explain'),
  234. 'data' => app()->make(GroupDataRepository::class)->groupData('promoter_config', 0),
  235. ];
  236. // 返回包含推广员计划说明和配置数据的JSON对象
  237. return app('json')->success($data);
  238. }
  239. /**
  240. * 获取热门商品
  241. *
  242. * 本函数用于根据指定的热门类型,获取相应的热门商品列表。此列表是基于用户的浏览或购买行为进行热门程度排序的。
  243. * 主要用于在前端展示热门推荐商品,以引导用户浏览或购买。
  244. *
  245. * @param string $type 热门类型标识,用于区分不同类型的热门商品。例如,可以是'bestseller'表示畅销商品,'new'表示新品等。
  246. * @return \Illuminate\Http\JsonResponse 返回一个JSON响应,其中包含获取的热门商品列表及其相关信息。
  247. */
  248. public function hot($type)
  249. {
  250. // 分解并获取当前请求的页码和每页数量
  251. [$page, $limit] = $this->getPage();
  252. // 调用repository的getApiSearch方法获取热门商品列表,并包装成成功响应返回
  253. return app('json')->success($this->repository->getApiSearch(null, ['hot_type' => $type, 'is_gift_bag' => 0, 'is_used' => 1], $page, $limit, $this->userInfo));
  254. }
  255. /**
  256. * 根据模板ID保证获取模板信息
  257. *
  258. * 本函数旨在通过指定的模板ID,从数据库中检索对应的保证模板信息。
  259. * 它确保了只返回状态为有效的模板数据。
  260. *
  261. * @param int $id 保证模板的唯一标识ID
  262. * @return \Illuminate\Http\JsonResponse 成功获取数据时返回的JSON响应,包含模板信息
  263. */
  264. public function guaranteeTemplate($id)
  265. {
  266. // 定义查询条件,确保只查询状态为有效的模板
  267. $where = [
  268. 'guarantee_template_id' => $id,
  269. 'status' => 1,
  270. ];
  271. // 通过仓库接口查询并获取满足条件的保证模板数据
  272. $data = $this->repository->GuaranteeTemplate($where);
  273. // 返回成功的JSON响应,包含查询到的模板数据
  274. return app('json')->success($data);
  275. }
  276. /**
  277. * 设置增加领取数量
  278. *
  279. * 本函数用于处理增加领取数量的请求。它首先从请求中获取必要的参数,
  280. * 然后检查用户是否已绑定手机号(当类型为1时),最后调用仓库接口增加领取数量。
  281. * 如果用户未绑定手机号且类型为1,函数将返回错误消息;否则,返回成功消息。
  282. *
  283. * @return \think\response\Json 成功时返回订阅成功的Json响应,失败时返回错误的Json响应。
  284. */
  285. public function setIncreaseTake()
  286. {
  287. // 从请求中获取产品ID、唯一标识和类型
  288. $product_id = $this->request->param('product_id');
  289. $unique = $this->request->param('unique');
  290. $type = $this->request->param('type');
  291. // 检查类型为1时用户是否已绑定手机号
  292. if ($type == 1 && !$this->userInfo['phone']) {
  293. return app('json')->fail('请先绑定手机号');
  294. }
  295. // 调用仓库接口增加领取数量
  296. $this->repository->increaseTake($this->request->uid(), $unique, $type, $product_id);
  297. // 返回订阅成功的响应
  298. return app('json')->success('订阅成功');
  299. }
  300. /**
  301. * 预览数据。
  302. * 该方法用于获取预览数据,支持通过键名或ID进行获取。如果通过键名获取,首先尝试从缓存中读取数据,
  303. * 然后删除该缓存条目,以防止重复使用过期数据。如果通过ID获取,直接从数据仓库中检索数据。
  304. *
  305. * @return \think\response\Json 成功时返回数据,失败时返回错误信息。
  306. * @throws \Exception 如果发生任何异常,将返回异常信息。
  307. */
  308. public function preview()
  309. {
  310. try {
  311. // 从请求中获取必要的参数:键名、ID和产品类型。
  312. $param = $this->request->params(['key', 'id', 'product_type']);
  313. $data = [];
  314. // 如果提供了键名参数,尝试从缓存中获取数据并删除该缓存项。
  315. if ($param['key']) {
  316. $data = Cache::get($param['key']);
  317. Cache::delete($param['key']);
  318. // 如果提供了ID参数,从数据仓库中获取预览数据。
  319. } elseif ($param['id']) {
  320. $data = $this->repository->getPreview($param);
  321. }
  322. // 如果没有获取到数据,返回错误信息。
  323. if (!$data) return app('json')->fail('数据不存在');
  324. } catch (\Exception $e) {
  325. // 如果捕获到异常,返回异常信息。
  326. return app('json')->fail($e->getMessage());
  327. }
  328. // 如果一切正常,返回获取到的数据。
  329. return app('json')->success($data);
  330. }
  331. /**
  332. * 根据分类ID获取价格规则
  333. * 该方法用于根据给定的分类ID查询并返回相应的价格规则。如果规则存在缓存,则直接从缓存中获取;
  334. * 否则,通过查询数据库获取规则,并将结果缓存起来。
  335. *
  336. * @param int $id 分类ID
  337. * @return json 返回价格规则的JSON格式数据;如果规则不存在,则返回错误信息。
  338. */
  339. public function priceRule($id)
  340. {
  341. // 生成缓存的唯一标识
  342. $cache_unique = md5('get_product_rule_' . $id);
  343. // 尝试从缓存中获取规则数据
  344. $res = Cache::get($cache_unique);
  345. // 如果缓存中没有规则数据
  346. if (!$res) {
  347. // 查询分类路径
  348. $path = app()->make(StoreCategoryRepository::class)->query(['store_category_id' => $id, 'mer_id' => 0])->value('path');
  349. // 如果路径存在且不为根路径
  350. if ($path && $path !== '/') {
  351. // 将分类路径和当前分类ID分解为数组
  352. $ids = explode('/', trim($path, '/'));
  353. // 将当前分类ID添加到数组中
  354. $ids[] = $id;
  355. } else {
  356. // 如果路径不存在或为根路径,直接使用当前分类ID
  357. $ids[] = $id;
  358. }
  359. // 查询有效的价格规则,按排序降序,规则ID降序
  360. $rule = app()->make(PriceRuleRepository::class)->search(['cate_id' => $ids, 'is_show' => 1])
  361. ->order('sort DESC,rule_id DESC')->find();
  362. // 如果查询到规则
  363. if ($rule) {
  364. // 将规则数据转为JSON字符串并缓存,缓存有效期为1小时
  365. $res = json_encode($rule->toArray());
  366. Cache::tag('get_product')->set($cache_unique, $res, 3600);
  367. }
  368. }
  369. // 如果有缓存数据或查询到规则
  370. if ($res) {
  371. // 返回成功的JSON响应,包含规则数据
  372. return app('json')->success(json_decode($res, true));
  373. }
  374. // 如果没有缓存数据且查询不到规则,返回失败的JSON响应
  375. return app('json')->fail('规则不存在');
  376. }
  377. /**
  378. * 热门搜索第一个列表
  379. * @return \think\response\Json
  380. * @author Qinii
  381. * @day 2023/10/23
  382. */
  383. public function getHotList()
  384. {
  385. /**
  386. * 热门搜索第一列
  387. * 根据搜索记录查前10
  388. * 根据搜索记录查询出前10的商品
  389. */
  390. $keyword = app()->make(UserVisitRepository::class)->getHotList();
  391. $data = $this->repository->getHotSearchList(compact('keyword'));
  392. return app('json')->success($data);
  393. }
  394. /**
  395. * 获取热门分类排行榜
  396. * 本函数通过查询配置和数据库,获取指定数量的热门分类及其对应的SPU列表。
  397. * 主要用于展示热门商品分类,引导用户浏览或购买。
  398. *
  399. * @param SpuRepository $spuRepository SPU仓库对象,用于查询热门SPU。
  400. * @return json 返回包含热门分类及其SPU列表的数据。
  401. */
  402. public function getHotTop(SpuRepository $spuRepository)
  403. {
  404. // 获取请求参数中的limit值,用于限制返回的分类数量,默认为10。
  405. $limit = $this->request->param('limit', 10);
  406. // 从系统配置中获取热门排行榜开关和级别。
  407. $hot = systemConfig(['hot_ranking_switch', 'hot_ranking_lv']);
  408. // 如果热门排行榜开关关闭,则直接返回空数据。
  409. if (!$hot['hot_ranking_switch']) return app('json')->success([]);
  410. // 根据配置的级别查询符合条件的分类,限制结果数量并按排序降序和创建时间降序排列。
  411. $cateId = app()->make(StoreCategoryRepository::class)->getSearch([
  412. 'level' => $hot['hot_ranking_lv'],
  413. 'mer_id' => 0,
  414. 'is_show' => 1,
  415. 'type' => 0
  416. ])->limit($limit)->order('sort DESC,create_time DESC')->column('cate_name,store_category_id');
  417. // 初始化数据数组,用于存储最终的分类及其SPU列表。
  418. $data = [];
  419. // 遍历分类列表,为每个分类查询其热门SPU。
  420. foreach ($cateId as $cate) {
  421. // 获取该分类的热门SPU列表。
  422. $list = $spuRepository->getHotRanking($cate['store_category_id'], $limit);
  423. // 如果有热点SPU数据,则添加到结果数据数组中。
  424. if ($list) {
  425. $data[] = [
  426. 'cate_id' => $cate['store_category_id'] ?? 0,
  427. 'cate_name' => $cate['cate_name'] ?? '总榜',
  428. 'list' => $list,
  429. ];
  430. }
  431. }
  432. // 返回最终的热门分类及其SPU列表数据。
  433. return app('json')->success($data);
  434. }
  435. /**
  436. * 获取店铺商品推荐
  437. * @param $id
  438. * @return mixed
  439. * @throws \think\db\exception\DataNotFoundException
  440. * @throws \think\db\exception\DbException
  441. * @throws \think\db\exception\ModelNotFoundException
  442. */
  443. public function getGoodList($id)
  444. {
  445. $uid = $this->request->isLogin() ? $this->request->uid() : 0 ;
  446. return app('json')->success($this->repository->getGoodList($id, $uid));
  447. }
  448. /**
  449. * 商品大图推荐列表
  450. * @return void
  451. * @author Qinii
  452. */
  453. public function cateHotList()
  454. {
  455. /**
  456. * 当第一个商品的商户,只查询当前商品,
  457. * 同时在次请求,商品分类ID,返回通分类的商品列表
  458. * 1. 商品 id
  459. * 2. 商品的三级分类
  460. * 3. 商品的一级分类
  461. */
  462. [$page, $limit] = $this->getPage();
  463. $params = $this->request->params(['product_id','cate_id','cate_pid',['filter','']]);
  464. $merId = $this->request->param('mer_id' , 0);
  465. $not = $params['product_id'];
  466. if ($params['cate_id']) {
  467. $where['cate_id'] = $params['cate_id'];
  468. } else if ($params['cate_pid']) {
  469. $where['cate_pid'] = $params['cate_pid'];
  470. } else {
  471. $where['product_id'] = $params['product_id'];
  472. $not = 0;
  473. }
  474. $data = $this->repository->cateHotList($where, $merId, $page, $limit, $this->userInfo,$not);
  475. return app('json')->success($data);
  476. }
  477. /**
  478. * 根据商品的 spuId,获取商品的规格信息
  479. * @param $id
  480. * @return \think\response\Json
  481. * @author Qinii
  482. */
  483. public function getSpec($id)
  484. {
  485. $data = $this->repository->getSpec($id, $this->userInfo);
  486. return app('json')->success($data);
  487. }
  488. /**
  489. * 推荐商品列表
  490. *
  491. * @return void
  492. */
  493. public function recommendProduct()
  494. {
  495. $params = $this->request->params([['recommend_num', 1], 'product_id']);
  496. if(!$params['product_id']) {
  497. return app('json')->fail('商品ID不能为空');
  498. }
  499. if(!isset($params['recommend_num'])) {
  500. return app('json')->fail('推荐数量不能为空');
  501. }
  502. $data = $this->repository->recommendProduct($params);
  503. return app('json')->success($data);
  504. }
  505. }