GoodsController.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <?php
  2. namespace api\modules\v1\controllers\goods;
  3. use addons\Yunmeng\common\models\YunmengStoreGoods;
  4. use api\controllers\OnAuthController;
  5. use common\enums\AddonsEnum;
  6. use common\enums\GoodsTypeEnum;
  7. use common\enums\OrderCommentEnum;
  8. use common\enums\StatusEnum;
  9. use common\events\census\ViewsEvent;
  10. use common\globals\GlobalInvoke;
  11. use common\helpers\ApiCode;
  12. use common\listeners\goods\GoodsListener;
  13. use common\logic\common\GoodsLogic;
  14. use common\models\cart\Cart;
  15. use common\models\goods\Goods;
  16. use common\models\goods\GoodsAssociation;
  17. use common\models\goods\GoodsAttr;
  18. use common\models\goods\GoodsCate;
  19. use common\models\goods\GoodsCateRelate;
  20. use common\models\goods\GoodsCollect;
  21. use common\models\goods\GoodsExtra;
  22. use common\models\goods\GoodsReserve;
  23. use common\models\goods\GoodsReserveSku;
  24. use common\models\goods\GoodsReserveTime;
  25. use common\models\goods\GoodsSearchAddress;
  26. use common\models\goods\GoodsService;
  27. use common\models\mall\MallAddons;
  28. use common\models\order\Order;
  29. use common\models\order\OrderComments;
  30. use common\models\user\User;
  31. use common\models\user\UserLevel;
  32. use common\models\user\UserPartitionRelationship;
  33. use Yii;
  34. /**
  35. * Class GoodsController
  36. * @package api\modules\goods\controllers
  37. */
  38. class GoodsController extends OnAuthController
  39. {
  40. public $modelClass = '';
  41. /**
  42. *
  43. * 不用进行登录验证的方法
  44. *
  45. * 例如: ['index', 'update', 'create', 'view', 'delete']
  46. * 默认全部需要验证
  47. *
  48. * @var array
  49. */
  50. protected $authOptional = ['index', 'detail', 'cate-goods-list', 'list', 'recommend', 'comments-list', 'get-cate-list'];
  51. /**
  52. * 分类商品列表(选到哪个分类就获取哪个分类的商品,不包括子级分类)
  53. * @return mixed|void
  54. */
  55. public function actionCateGoodsList()
  56. {
  57. $params = \Yii::$app->request->get();
  58. $where[] = ['g.mall_id' => $this->mall_id, 'g.is_on_sale' => 1, 'g.is_show' => 1, 'status' => StatusEnum::ENABLED];
  59. if (!empty($params['type']) && $params['type'] == 'all') {
  60. //查询三级的所有
  61. $goods_cate_list = GoodsCate::findAll(['parent_id' => $params['cate_id'], 'mall_id' => $this->mall_id, 'is_show' => 1]);
  62. $cate_id_arr = array_column($goods_cate_list, 'id');
  63. $cate_id_arr[] = $params['cate_id'];
  64. } else {
  65. if (empty($params['cate_id'])) { //顶级
  66. //$goods_cate_list = GoodsCate::findAll(['parent_id' => 0, 'mall_id' => $this->mall_id, 'is_show' => 1]);
  67. //查询所有分类的商品
  68. $goods_cate_list = GoodsCate::findAll(['mall_id' => $this->mall_id, 'is_show' => 1]);
  69. $cate_id_arr = array_column($goods_cate_list, 'id');
  70. } else {
  71. $goods_cate = GoodsCate::findOne(['id' => $params['cate_id'], 'mall_id' => $this->mall_id, 'is_show' => 1]);
  72. $c = [$params['cate_id']];
  73. $cate_id_arr = [];
  74. $cate_id_arr1 = [];
  75. GoodsCate::getAllCate($this->mall_id, $c, $cate_id_arr1);
  76. if (!empty($cate_id_arr1)) {
  77. foreach ($cate_id_arr1 as $item) {
  78. if (!empty($item)) {
  79. $cats = explode(",", $item);
  80. array_push($cate_id_arr, ...$cats);
  81. }
  82. }
  83. }
  84. if (!empty($goods_cate)) {
  85. if ($goods_cate['parent_id'] == 0) {
  86. $goods_cate_list = GoodsCate::findAll(['parent_id' => $params['cate_id'], 'mall_id' => $this->mall_id, 'is_show' => 1]);
  87. $cid_arr2 = array_column($goods_cate_list, 'id');
  88. $goods_cate_list = GoodsCate::findAll(['parent_id' => $cid_arr2, 'mall_id' => $this->mall_id, 'is_show' => 1]);
  89. $cid_arr3 = array_column($goods_cate_list, 'id');
  90. $cate_id_arr = array_merge($cate_id_arr, $cid_arr2, $cid_arr3);
  91. }
  92. }
  93. }
  94. }
  95. //$goods_cate_relate_list = GoodsCateRelate::findAll(['cate_id' => $cate_id_arr]);
  96. //$goods_id_arr = array_column($goods_cate_relate_list, 'goods_id');
  97. $goods_id_arr = GoodsCateRelate::find()->where(['cate_id' => $cate_id_arr])->groupBy('goods_id')->select('goods_id')->column();
  98. $invoke_goods_ids_arr = GlobalInvoke::exec(GlobalInvoke::CATEGORY_LIST_FILTER_GOODS_ID, $this->mall_id, [
  99. 'mall_id' => $this->mall_id, 'location_style' => $params['location_style'] ?? 1, 'goods_id' => $goods_id_arr, 'user_id' => $this->user ? $this->user->id : 0
  100. ]);
  101. if ($invoke_goods_ids_arr) {
  102. $where[] = ['g.id' => $invoke_goods_ids_arr['goods_ids']];
  103. } else {
  104. $where[] = ['g.id' => $goods_id_arr];
  105. }
  106. $order = 'sort asc';
  107. // pages/menu/index
  108. if (!empty($params['sort_type']) && in_array($params['sort_order'], ['desc', 'asc'])) {
  109. switch ($params['sort_type']) {
  110. case 'price':
  111. $order = 'price ' . $params['sort_order'];
  112. break;
  113. case 'sales':
  114. $order = 'sales_num ' . $params['sort_order'];
  115. break;
  116. case 'score':
  117. $order = 'comment_score ' . $params['sort_order'];
  118. }
  119. }
  120. // plugins4/Housekeeping/index
  121. if (!empty($params['sort'])) {
  122. switch ($params['sort']) {
  123. case 'price':
  124. $order = 'price asc';
  125. break;
  126. case 'sales':
  127. $order = 'sales_num desc';
  128. break;
  129. case 'score':
  130. $order = 'comment_score desc';
  131. }
  132. }
  133. $params['where'] = $where;
  134. $params['alias'] = 'g';
  135. //$params['select'] = 'g.id,g.goods_name,g.cover_pic,g.price,g.stock,g.attr_groups,g.attr_groups_format,g.is_attr,g.is_show_stock,g.unit,g.goods_source,g.original_price';
  136. //$params['order'] = 'sort asc, g.id asc';
  137. $params['select'] = 'g.id,g.goods_name,g.cover_pic,g.price,g.stock,g.attr_groups,g.attr_groups_format,g.is_attr,g.is_show_stock,g.unit,g.goods_source,g.original_price,g.goods_type';
  138. $params['order'] = $order;
  139. $params['with'] = ['attr', 'extra'];
  140. $params['limit'] = 10;
  141. $goods_list = Goods::listPage($params);
  142. $list = Cart::getCartList($this->user_id);
  143. $goods_num_arr = [];
  144. foreach ($list as $v) {
  145. $row = json_decode($v, true);
  146. if (isset($goods_num_arr[$row['goods_id']])) {
  147. $goods_num_arr[$row['goods_id']] += $row['num'];
  148. } else {
  149. $goods_num_arr[$row['goods_id']] = $row['num'];
  150. }
  151. }
  152. if (!empty($goods_list['list'])) {
  153. $user_level = null;
  154. if (!empty($this->user)) {
  155. //基础会员等级折扣
  156. $user_level = UserLevel::findOne(['mall_id' => $this->mall_id, 'level' => $this->user['level'], 'status' => StatusEnum::ENABLED]);
  157. }
  158. foreach ($goods_list['list'] as &$item) {
  159. $item['member_buy_limit_setting'] = empty($item['extra']['member_buy_limit_setting']) ? '' : json_decode($item['extra']['member_buy_limit_setting'], true);
  160. unset($item['extra']);
  161. $item['commission'] = 0; //最高可赚钱的佣金,预留字段
  162. $item['num'] = !empty($goods_num_arr[$item['id']]) ? $goods_num_arr[$item['id']] : 0;
  163. $item['status'] = $item['goods_type'] == GoodsTypeEnum::GoodsTypeReserved ? 1 : (empty($item['stock']) ? 0 : 1);
  164. $item['attr_id'] = 0;
  165. foreach($item['attr'] as $val){
  166. if($val['is_show'] == StatusEnum::ENABLED){
  167. $item['attr_id'] = $val['id'];
  168. break;
  169. }
  170. }
  171. $smart_form_template = GlobalInvoke::exec(GlobalInvoke::GOODS_NEED_SMARTFORM, $this->mall_id, ['user_id' => $this->user_id, 'mall_id' => $this->mall_id, 'goods_id' => $item['id']]);
  172. if (!empty($smart_form_template)) $item = array_merge($item, $smart_form_template);
  173. //额外会员设置
  174. if ($user_level && !empty($user_level['member_price_is_show'])) {
  175. $item['price'] = GoodsLogic::getMemberPriceList($this->mall_id, $item, $this->user, true);
  176. }
  177. if (!empty($item['goods_source'])) {
  178. $t_class = "\\addons\\{$item['goods_source']}\\common\\service\\ShoppingCartService";
  179. if (is_callable([$t_class, "getCanAddToCart"])) {
  180. $item = $t_class::getCanAddToCart($item, $this->mall_id);
  181. }
  182. }
  183. }
  184. }
  185. return $this->success('操作成功', $goods_list);
  186. }
  187. /**
  188. * 商品搜索
  189. * @return mixed|void
  190. */
  191. public function actionList()
  192. {
  193. $params = \Yii::$app->request->get();
  194. $res = \Yii::$app->services->validate->validate($params, [
  195. [['limit', 'page', 'cate_id', 'sort_type', 'sort_price', 'keyword','province_id', 'city_id', 'district_id', 'town_id'], 'safe']
  196. ]);
  197. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  198. $where[] = ['g.mall_id' => $this->mall_id];
  199. $where[] = ['g.status' => [StatusEnum::ENABLED]];
  200. $where[] = ['g.is_on_sale' => 1];
  201. $where[] = ['g.is_show' => 1];
  202. if (isset($params['keyword'])) {
  203. $where[] = ['like', 'g.goods_name', trim($params['keyword'])];
  204. }
  205. if (!empty($params['cate_id'])) {
  206. $goods_cate_relate_list = GoodsCateRelate::findAll(['cate_id' => $params['cate_id']]);
  207. $goods_id_arr = array_column($goods_cate_relate_list, 'goods_id');
  208. $where[] = ['g.id' => $goods_id_arr];
  209. }
  210. if(isset($params['province_id']) || isset($params['city_id']) || isset($params['district_id']) || isset($params['town_id'])){
  211. $goods_id_arr = GoodsSearchAddress::getGoodsIdByAddressIds($this->mall_id, $params);
  212. if($goods_id_arr !== false){
  213. $where[] = ['g.id' => $goods_id_arr];
  214. }
  215. }
  216. $params['where'] = $where;
  217. $params['alias'] = 'g';
  218. $params['select'] = 'g.id,g.goods_name,g.cover_pic,g.price,g.original_price,g.virtual_sales,g.sales_num,is_show_sales,g.original_price,g.goods_type,g.mch_id,g.check_status, g.stock,freight_type';
  219. $params['order'] = 'g.id ASC'; // 默认按id来升序排序
  220. if (isset($params['sort_type']) && $params['sort_type'] == 'sales') {
  221. $params['order'] = 'g.sales_num DESC';
  222. }
  223. if (isset($params['sort_type']) && $params['sort_type'] == 'new') {
  224. $params['order'] = 'g.id DESC';
  225. }
  226. if (isset($params['sort_type']) && $params['sort_type'] == 'price') {
  227. if (isset($params['sort_price']) && $params['sort_price'] === 'false') {
  228. $params['order'] = 'g.price DESC';
  229. } else {
  230. $params['order'] = 'g.price';
  231. }
  232. }
  233. // 查询商城隐藏分类
  234. $hidden_cate_ids = GoodsCate::getAllEnabledSubCateIds(GoodsCate::getHiddenIds($this->mall_id));
  235. if (!empty($hidden_cate_ids)) {
  236. // 获取隐藏分类下的商品ID
  237. $goods_ids = GoodsCateRelate::getGoodsIdByCateIds($hidden_cate_ids);
  238. // 如果有商品ID,则添加到查询条件中,查询时排除这些商品
  239. $params['where'][] = ['not in', 'g.id', $goods_ids];
  240. }
  241. $goods_list = Goods::listPage($params);
  242. if (!empty($goods_list['list'])) {
  243. $user_level = null;
  244. if (!empty($this->user)) {
  245. //基础会员等级折扣
  246. $user_level = UserLevel::findOne(['mall_id' => $this->mall_id, 'level' => $this->user['level'], 'status' => StatusEnum::ENABLED]);
  247. }
  248. foreach ($goods_list['list'] as $key => &$item) {
  249. $item['sales_num'] += $item['virtual_sales'];
  250. unset($item['virtual_sales']);
  251. //额外会员设置
  252. if ($user_level && !empty($user_level['member_price_is_show'])) {
  253. $item['price'] = GoodsLogic::getMemberPriceList($this->mall_id, $item, $this->user, true);
  254. }
  255. // 判断是否售盘
  256. $item['status'] = $item['goods_type'] == GoodsTypeEnum::GoodsTypeReserved ? 1 : (empty($item['stock']) ? 0 : 1);
  257. // 删除多商户未审核商品
  258. if ($item['mch_id'] > 0 && $item['check_status'] != 1) {
  259. unset($goods_list['list'][$key]);
  260. }
  261. if (!empty($item['goods_source'])) {
  262. $t_class = "\\addons\\{$item['goods_source']}\\common\\service\\ShoppingCartService";
  263. if (is_callable([$t_class, "getCanAddToCart"])) {
  264. $item = $t_class::getCanAddToCart($item, $this->mall_id);
  265. }
  266. }
  267. $item['freight_type'] = explode(',', $item['freight_type']);
  268. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_YUNMENG) && (in_array(2, $item['freight_type']) || in_array(3, $item['freight_type']))) {
  269. $configs = \Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_YUNMENG, 'basic');
  270. if ($configs['is_enable'] == 1) {
  271. $info = YunmengStoreGoods::getOne([
  272. ['mall_id' => $this->mall_id],
  273. ['goods_id' => $item['id']],
  274. ['status' => StatusEnum::ENABLED],
  275. ['is_on_sale' => 1],
  276. ['>', 'stock', 0]
  277. ], true);
  278. if (!empty($info)) {
  279. $item['stock'] = $info['stock'];
  280. $item['status'] = 1;
  281. }
  282. }
  283. }
  284. }
  285. }
  286. return $this->success('操作成功', $goods_list);
  287. }
  288. /**
  289. * 商品详情
  290. * @return mixed|void
  291. */
  292. public function actionDetail()
  293. {
  294. $params = \Yii::$app->request->get();
  295. $res = \Yii::$app->services->validate->validate($params, [
  296. [['goods_id'], 'integer'],
  297. [['scene'], 'string'],
  298. [['addonsFields','latitude','longitude'], 'safe']
  299. ]);
  300. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  301. $goods = GoodsLogic::GetDetail($this->mall_id, $params, $this->user);
  302. if (empty($goods)) return $this->error('商品不存在');
  303. if ($params['addonsFields']) {
  304. if($this->platform == User::PLATFORM_MP_WX){
  305. is_string($params['addonsFields']) && $params['addonsFields'] = json_decode($params['addonsFields'], true);
  306. }else{
  307. $params['addonsFields'] = is_string($params['addonsFields']) ? explode(',', $params['addonsFields']) : $params['addonsFields'];
  308. }
  309. $goods = Goods::getAddonsGoodsSetting($this->mall_id, $params['addonsFields'], $goods, 'detail');
  310. }
  311. $goods['is_bind_popups'] = UserPartitionRelationship::getIsNeedPopups($this->mall_id, $this->user_id ?? 0);
  312. //浏览
  313. if ($goods) {
  314. $event = new ViewsEvent($this->mall_id);
  315. $data['mall_id'] = $this->mall_id;
  316. $data['user_id'] = $this->user_id;
  317. $data['goods_id'] = $params['goods_id'];
  318. \Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  319. $smart_form_template = GlobalInvoke::exec(GlobalInvoke::GOODS_NEED_SMARTFORM, $this->mall_id, ['user_id' => $this->user_id, 'mall_id' => $this->mall_id, 'goods_id' => $params['goods_id']]);
  320. if (!empty($smart_form_template)) $goods = array_merge($goods, $smart_form_template);
  321. // 商品详情公共调用
  322. $invoke_data = GlobalInvoke::exec(
  323. GlobalInvoke::API_GOODS_DETAIL,
  324. $this->mall_id,
  325. ['mall_id' => $this->mall_id, 'goods' => $goods, 'user' => $this->user,'latitude'=>$params['latitude']??0,'longitude'=>$params['longitude']??0]
  326. );
  327. if (!empty($invoke_data['goods'])) $goods = $invoke_data['goods'];
  328. }
  329. // 首页文本命名
  330. $home_text = Yii::$app->services->setting->mall->get($this->mall_id, "goodsdetail.home_text");
  331. $goods['home_text'] = !empty($home_text) ? $home_text : '首页';
  332. $res = GoodsLogic::getGoodsAssociationList($this->mall_id,$params['goods_id']);
  333. $goods['extra1_goods_list'] = $res['extra1_goods_list']??[];
  334. $goods['extra2_goods_list'] = $res['extra2_goods_list']??[];
  335. return $this->success('获取成功', $goods);
  336. }
  337. /**
  338. * 获取预约商品时间
  339. * @return mixed|void
  340. */
  341. public function actionGetReserveTime()
  342. {
  343. $params = \Yii::$app->request->get();
  344. $res = \Yii::$app->services->validate->validate($params, [
  345. [['goods_id','sku_id'], 'required'],
  346. [['goods_id','sku_id'], 'integer'],
  347. ]);
  348. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  349. $reserve = GoodsReserve::findOne(['goods_id' => $params['goods_id']]);
  350. if (empty($reserve)) return $this->error('该预约商品不存在');
  351. // $timeInfo = GoodsReserveSku::find()
  352. // ->select('id,mall_id,mch_id,name,sign_id,pic_url,goods_id,reserve_time_range_type')
  353. // ->where(['goods_id' => $params['goods_id'], 'mall_id' => $this->mall_id,'id' => $params['sku_id']])
  354. // ->with(['reserve','times', 'times.timeSpec'])
  355. // ->asArray()
  356. // ->one();
  357. $sku = GoodsReserveSku::getOne([['goods_id' => $params['goods_id'],'id' => $params['sku_id']]]);
  358. if (empty($sku)) return $this->error('该预约商品不存在');
  359. $timeInfo = GoodsReserveTime::getSkuTime($this->mall_id,$sku);
  360. return $this->success('获取成功', $timeInfo);
  361. }
  362. /**
  363. * 推荐商品
  364. * @return mixed|void
  365. */
  366. public function actionRecommend()
  367. {
  368. $params = \Yii::$app->request->get();
  369. $res = \Yii::$app->services->validate->validate($params, [
  370. [['type'], 'required', 'message' => 'type必传'],
  371. ]);
  372. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  373. $goods_list = [];
  374. $result = \Yii::$app->services->setting->mall->get($this->mall_id, $params['type'] . '.goods_list');
  375. if (empty($result)) {
  376. return $this->success('操作成功', $goods_list);
  377. } else {
  378. $goods_list = json_decode($result, true);
  379. $gids = array_column($goods_list, 'id');
  380. $goods_list = Goods::find()->select("id,goods_name,cover_pic,price")
  381. ->where(['id' => $gids, 'status' => StatusEnum::ENABLED, 'is_on_sale' => StatusEnum::ENABLED, 'is_show' => 1])->asArray()->all();
  382. }
  383. return $this->success('操作成功', $goods_list);
  384. }
  385. /**
  386. * 商品评价列表
  387. * @return mixed|void
  388. */
  389. public function actionCommentsList()
  390. {
  391. $params = \Yii::$app->request->get();
  392. $res = \Yii::$app->services->validate->validate($params, [
  393. [['goods_id'], 'required', 'message' => 'goods_id必传'],
  394. [['limit', 'page', 'type', 'store_id'], 'safe']
  395. ]);
  396. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  397. $data['comments'] = [];
  398. $data['good_rate'] = 0; //满意度
  399. $where = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'store_id' => $params['store_id'] ?? 0, 'goods_id' => $params['goods_id']];
  400. $total = OrderComments::find()->where($where)->count();
  401. $data['comment_count'][0] = ['name' => OrderCommentEnum::OC_ALL, 'count' => $total ?? 0];
  402. $good_num = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_PRAISE_SCORES])->count();
  403. $data['comment_count'][1] = ['name' => OrderCommentEnum::OC_PRAISE, 'count' => $good_num ?? 0];
  404. $count = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_MIDDLE_SCORES])->count();
  405. $data['comment_count'][2] = ['name' => OrderCommentEnum::OC_MIDDLE, 'count' => $count ?? 0];
  406. $count = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_NEGATIVE_SCORES])->count();
  407. $data['comment_count'][3] = ['name' => OrderCommentEnum::OC_NEGATIVE, 'count' => $count ?? 0];
  408. $where = [];
  409. $where[] = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'store_id' => $params['store_id'] ?? 0];
  410. $where[] = ['goods_id' => $params['goods_id']];
  411. if (!empty($params['type'])) {
  412. switch ($params['type']) {
  413. case OrderCommentEnum::TYPE1: //差评
  414. $where[] = ['in', 'score', OrderCommentEnum::OC_NEGATIVE_SCORES];
  415. break;
  416. case OrderCommentEnum::TYPE2: //中评
  417. $where[] = ['in', 'score', OrderCommentEnum::OC_MIDDLE_SCORES];
  418. break;
  419. case OrderCommentEnum::TYPE4: //好评
  420. $where[] = ['in', 'score', OrderCommentEnum::OC_PRAISE_SCORES];
  421. break;
  422. }
  423. }
  424. $params['where'] = $where;
  425. $params['select'] = '*';
  426. $params['order'] = 'is_top desc, virtual_time desc,id desc';
  427. $order_comments_list = OrderComments::listPage($params);
  428. if (!empty($order_comments_list['list'])) {
  429. $user_id_arr = array_column($order_comments_list['list'], 'user_id');
  430. $user_list = User::findAll(['id' => $user_id_arr]);
  431. $user_arr = [];
  432. foreach ($user_list as $v) {
  433. $user_arr[$v['id']] = ['nickname' => $v['nickname'], 'avatar_url' => $v['avatar_url'], 'level' => $v['level']];
  434. }
  435. foreach ($order_comments_list['list'] as &$v) {
  436. $v['pic_url'] = !empty($v['pic_url']) ? json_decode($v['pic_url'], true) : [];
  437. $comment['nickname'] = $comment['avatar_url'] = '';
  438. if (isset($user_arr[$v['user_id']])) {
  439. $user = $user_arr[$v['user_id']];
  440. $v['nickname'] = $user['nickname'];
  441. $v['avatar_url'] = $user['avatar_url'];
  442. $v['level'] = $user['level'];
  443. }
  444. if ($v['virtual_time'] > 0) $v['created_at'] = $v['virtual_time'];
  445. }
  446. unset($v);
  447. $data['comments'] = $order_comments_list;
  448. }
  449. // 获取会员等级
  450. $data['level_arr'] = UserLevel::getUserLevelArr($this->mall_id);
  451. if ($total) $data['good_rate'] = number_format($good_num / $total, 2) * 100;
  452. return $this->success('操作成功', $data);
  453. }
  454. /**
  455. * 商品搜索-es
  456. * @return mixed|void
  457. */
  458. public function actionListEs()
  459. {
  460. $params = \Yii::$app->request->get();
  461. $res = \Yii::$app->services->validate->validate($params, [
  462. [['keyword'], 'required'],
  463. [['limit', 'page', 'cate_id'], 'safe']
  464. ]);
  465. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  466. $params['mall_id'] = $this->mall_id;
  467. $goods_list = \common\models\elasticsearch\goods\Goods::getGoodsList($params);
  468. return $this->success('操作成功', $goods_list);
  469. }
  470. /**
  471. * @desc:商品收藏
  472. * @Author: hua
  473. * @Date: 2021/11/9
  474. * @Time: 9:12
  475. * @Copyright: copyright (c) 2021 广东七件事集团
  476. * @return mixed|void
  477. */
  478. public function actionCollectAdd()
  479. {
  480. $params = \Yii::$app->request->get();
  481. $res = \Yii::$app->services->validate->validate($params, [
  482. [['goods_id', 'type'], 'required'],
  483. [['type'], 'in', 'range' => [0, 1]],
  484. ]);
  485. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  486. $params['mall_id'] = $this->mall_id;
  487. $params['user_id'] = $this->user_id;
  488. $params['status'] = $params['type'];
  489. $res = GoodsCollect::setData($params);
  490. if ($res === false) return $this->error(GoodsCollect::getStaticError());
  491. if ($params['type'] == StatusEnum::ENABLED) {
  492. $msg = "收藏成功";
  493. } else {
  494. $msg = "取消收藏";
  495. }
  496. return $this->success($msg, []);
  497. }
  498. /**
  499. * @name:
  500. * @msg: 根据分类获取商品列表,包括所有子级分类的所有商品
  501. * @param {*}
  502. * @return {*}
  503. */
  504. public function actionCategorysGoodList()
  505. {
  506. if (!\Yii::$app->request->isGet) {
  507. return $this->error('请求方式错误');
  508. }
  509. $page = \Yii::$app->request->get('page', 1);
  510. $limit = \Yii::$app->request->get('limit', $this->pageSize);
  511. $cate_id = \Yii::$app->request->get('cate_id');
  512. $wheres[] = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'is_on_sale' => 1];
  513. if (!empty($cate_id)) {
  514. $second_level_cate_ids = GoodsCate::find()
  515. ->select('id')
  516. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'parent_id' => $cate_id, 'is_show' => 1])
  517. ->asArray()
  518. ->column();
  519. $third_level_cate_ids = GoodsCate::find()
  520. ->select('id')
  521. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'parent_id' => $second_level_cate_ids, 'is_show' => 1])
  522. ->asArray()
  523. ->column();
  524. $cate_ids = array_merge($second_level_cate_ids, $third_level_cate_ids);
  525. $cate_ids[] = $cate_id;
  526. $good_ids = GoodsCateRelate::find()
  527. ->select('goods_id')
  528. ->where(['cate_id' => $cate_ids])
  529. ->asArray()
  530. ->column();
  531. $wheres[] = ['id' => $good_ids];
  532. }
  533. $params = [
  534. 'select' => 'id,goods_name,cover_pic,price,original_price,goods_type',
  535. 'where' => $wheres,
  536. 'order' => 'sort asc,created_at desc',
  537. 'page' => $page,
  538. 'limit' => $limit,
  539. ];
  540. $goods = Goods::listPage($params);
  541. return $this->success('success', $goods);
  542. }
  543. /**
  544. * @Description:
  545. * 1.获取指定分类数据,如果存在上下级关系,下级被包含在上级里面
  546. * 2.获取分类以及子分类
  547. * @Author: zsan
  548. * @DateTime 2023-10-26 18:17:54
  549. * @return \yii\web\Response
  550. */
  551. public function actionGetCateList()
  552. {
  553. if (!\Yii::$app->request->isGet) {
  554. return $this->error('请求方式错误');
  555. }
  556. $params = \Yii::$app->request->get();
  557. $res = \Yii::$app->services->validate->validate($params, [
  558. [['cate_id'], 'required', 'message' => 'cate_id必传'],
  559. [['is_diy'], 'integer']
  560. ]);
  561. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  562. $is_diy = $params['is_diy'] ?? 0;
  563. if ($is_diy) {
  564. $params['cate_id'] = explode(',', $params['cate_id']);
  565. $cate_list = GoodsCate::lists([
  566. 'where' => [['mall_id' => $this->mall_id], ['status' => StatusEnum::ENABLED], ['id' => $params['cate_id']]],
  567. 'select' => 'id, name, parent_id, mch_id, pic',
  568. 'order' => 'sort ASC',
  569. 'with' => [
  570. 'child' => function ($query) {
  571. return $query->select('id, name, parent_id, mch_id, pic');
  572. }
  573. ]
  574. ]);
  575. $cate_list = array_column($cate_list, null, 'id');
  576. $third_cate = [];
  577. foreach ($cate_list as $key => $val) {
  578. if (empty($val['child'])) {
  579. !isset($third_cate[$val['parent_id']]) && $third_cate[$val['parent_id']] = [];
  580. array_push($third_cate[$val['parent_id']], $val);
  581. if (isset($cate_list[$val['parent_id']])) {
  582. // 删除三级
  583. unset($cate_list[$key]);
  584. if (!empty($cate_list[$val['parent_id']]['child'])) {
  585. // 置空二级下三级
  586. $cate_list[$val['parent_id']]['child'] = [];
  587. }
  588. }
  589. }
  590. }
  591. if(!empty($third_cate)){
  592. foreach($cate_list as $key => $val){
  593. if(isset($third_cate[$val['id']])){
  594. $cate_list[$key]['child'] = $third_cate[$val['id']];
  595. }
  596. }
  597. }
  598. $cate_list = array_values($cate_list);
  599. } else {
  600. $cate_list = GoodsCate::lists([
  601. 'where' => [['mall_id' => $this->mall_id], ['status' => StatusEnum::ENABLED], ['parent_id' => $params['cate_id']]],
  602. 'select' => 'id, name, parent_id, mch_id, pic',
  603. 'order' => 'sort ASC',
  604. 'with' => [
  605. 'child' => function ($query) {
  606. return $query->select('id, name, parent_id, mch_id, pic');
  607. }
  608. ]
  609. ]);
  610. }
  611. return $this->success('success', $cate_list);
  612. }
  613. public function actionReserveDetail()
  614. {
  615. $params = \Yii::$app->request->get();
  616. $res = \Yii::$app->services->validate->validate($params, [
  617. [['goods_id'], 'required'],
  618. [['goods_id'], 'integer'],
  619. ]);
  620. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  621. $data = GoodsReserve::getOne([
  622. ['goods_id' => $params['goods_id']],
  623. ['mall_id' => $this->mall_id],
  624. ], true, [], 'id desc', 'ordering_information, information_detail');
  625. return $this->success('获取成功', $data);
  626. }
  627. }