Product.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <?php
  2. namespace app\api\model\product;
  3. use app\common\model\product\Product as ProductModel;
  4. use app\common\service\product\BaseProductService;
  5. use app\common\library\helper;
  6. use app\api\model\supplier\Supplier as SupplierModel;
  7. use app\api\model\supplier\ServiceApply;
  8. use app\common\model\supplier\User as SupplierUserModel;
  9. /**
  10. * 商品模型
  11. */
  12. class Product extends ProductModel
  13. {
  14. /**
  15. * 隐藏字段
  16. */
  17. protected $hidden = [
  18. 'spec_rel',
  19. 'delivery',
  20. 'sales_initial',
  21. 'sales_actual',
  22. 'is_delete',
  23. 'app_id',
  24. 'create_time',
  25. 'update_time'
  26. ];
  27. /**
  28. * 商品详情:HTML实体转换回普通字符
  29. */
  30. public function getContentAttr($value)
  31. {
  32. return htmlspecialchars_decode($value);
  33. }
  34. /**
  35. * 获取商品列表
  36. */
  37. public function getList($param, $userInfo = false)
  38. {
  39. // 获取商品列表
  40. $data = (new ProductModel())->getList($param);
  41. // 隐藏api属性
  42. !$data->isEmpty() && $data->hidden(['category', 'content', 'image', 'sku']);
  43. // 整理列表数据并返回
  44. return $this->setProductListDataFromApi($data, true, ['userInfo' => $userInfo]);
  45. }
  46. /**
  47. * 商品详情
  48. */
  49. public static function detail($product_id)
  50. {
  51. // 商品详情
  52. $detail = parent::detail($product_id);
  53. // 多规格商品sku信息
  54. $detail['product_multi_spec'] = BaseProductService::getSpecData($detail);
  55. return $detail;
  56. }
  57. /**
  58. * 获取商品详情页面
  59. */
  60. public function getDetails($productId, $userInfo = false)
  61. {
  62. // 获取商品详情
  63. $detail = $this->with([
  64. 'category',
  65. 'image' => ['file'],
  66. 'contentImage' => ['file'],
  67. 'sku' => ['image'],
  68. 'spec_rel' => ['spec'],
  69. 'delivery' => ['rule'],
  70. 'commentData' => function ($query) {
  71. $query->with('user')->where(['is_delete' => 0, 'status' => 1])->limit(2);
  72. },
  73. 'video',
  74. 'poster'
  75. ])->withCount(['commentData' => function ($query) {
  76. $query->where(['is_delete' => 0, 'status' => 1]);
  77. }])
  78. ->where('product_id', '=', $productId)
  79. ->find();
  80. // 判断商品的状态
  81. if (empty($detail) || $detail['is_delete'] || $detail['product_status']['value'] != 10) {
  82. $this->error = '很抱歉,商品信息不存在或已下架';
  83. return false;
  84. }
  85. $SupplierModel = new SupplierModel;
  86. if ($detail['shop_supplier_id']) {
  87. $supplier = $SupplierModel::detail($detail['shop_supplier_id'], ['logo', 'category']);
  88. $supplier['logos'] = $supplier['logo']['file_path'];
  89. unset($supplier['logo']);
  90. $supplier['category_name'] = $supplier['category']['name'];
  91. unset($supplier['category']);
  92. $supplier['supplier_user_id'] = (new SupplierUserModel())->where('shop_supplier_id', '=', $detail['shop_supplier_id'])->value('supplier_user_id');
  93. $supplier->visible(['logos', 'category_name', 'name', 'shop_supplier_id', 'product_sales', 'server_score', 'store_type', 'user_id', 'supplier_user_id']);
  94. $server = (new ServiceApply())->getList($detail['shop_supplier_id']);
  95. } else {
  96. $supplier = [];
  97. $server = [];
  98. }
  99. $detail['supplier'] = $supplier;
  100. $detail['server'] = $server;
  101. // 更新访问数据
  102. $this->where('product_id', '=', $detail['product_id'])->inc('view_times')->update();
  103. // 设置商品展示的数据
  104. $detail = $this->setProductListDataFromApi($detail, false, ['userInfo' => $userInfo]);
  105. // 多规格商品sku信息
  106. $detail['product_multi_spec'] = BaseProductService::getSpecData($detail);
  107. return $detail;
  108. }
  109. /**
  110. * 根据商品id集获取商品列表
  111. */
  112. public function getListByIdsFromApi($productIds, $userInfo = false)
  113. {
  114. // 获取商品列表
  115. $data = (new ProductModel())->getListByIds($productIds, 10);
  116. // 整理列表数据并返回
  117. return $this->setProductListDataFromApi($data, true, ['userInfo' => $userInfo]);
  118. }
  119. /**
  120. * 设置商品展示的数据 api模块
  121. */
  122. private function setProductListDataFromApi(&$data, $isMultiple, $param)
  123. {
  124. return parent::setProductListData($data, $isMultiple, function ($product) use ($param) {
  125. // 计算并设置商品会员价
  126. $this->setProductGradeMoney($param['userInfo'], $product);
  127. });
  128. }
  129. /**
  130. * 设置商品的会员价
  131. */
  132. public function setProductGradeMoney($user, &$product)
  133. {
  134. // 会员等级状态
  135. $gradeStatus = (!empty($user) && $user['grade_id'] > 0 && !empty($user['grade']))
  136. && (!$user['grade']['is_delete']);
  137. // 判断商品是否参与会员折扣
  138. if (!$gradeStatus || !$product['is_enable_grade']) {
  139. $product['is_user_grade'] = false;
  140. return;
  141. }
  142. $alone_grade_type = 10;
  143. // 商品单独设置了会员折扣
  144. if ($product['is_alone_grade'] && isset($product['alone_grade_equity'][$user['grade_id']])) {
  145. if ($product['alone_grade_type'] == 10) {
  146. // 折扣比例
  147. $discountRatio = helper::bcdiv($product['alone_grade_equity'][$user['grade_id']], 100);
  148. } else {
  149. $alone_grade_type = 20;
  150. $discountRatio = helper::bcdiv($product['alone_grade_equity'][$user['grade_id']], $product['product_price'], 2);
  151. }
  152. } else {
  153. // 折扣比例
  154. $discountRatio = helper::bcdiv($user['grade']['equity'], 100);
  155. }
  156. if ($discountRatio < 1) {
  157. // 标记参与会员折扣
  158. $product['is_user_grade'] = true;
  159. // 会员折扣后的商品总金额
  160. if ($alone_grade_type == 20) {
  161. $product['product_price'] = $product['alone_grade_equity'][$user['grade_id']];
  162. } else {
  163. $product['product_price'] = helper::number2(helper::bcmul($product['product_price'], $discountRatio), true);
  164. }
  165. // 会员折扣价
  166. foreach ($product['sku'] as &$skuItem) {
  167. if ($alone_grade_type == 20) {
  168. $skuItem['product_price'] = $product['alone_grade_equity'][$user['grade_id']];
  169. } else {
  170. $skuItem['product_price'] = helper::number2(helper::bcmul($skuItem['product_price'], $discountRatio), true);
  171. }
  172. }
  173. } else {
  174. $product['is_user_grade'] = false;
  175. }
  176. }
  177. /**
  178. * 为你推荐
  179. */
  180. public function getRecommendProduct($params)
  181. {
  182. $model = $this;
  183. // 手动
  184. if ($params['choice'] == 1) {
  185. $product_id = array_column($params['product'], 'product_id');
  186. $model = $model->where('product_id', 'IN', $product_id);
  187. $list = $model->with(['category', 'image.file'])
  188. ->where('product_status', '=', 10)
  189. ->where('audit_status', '=', 10)
  190. ->where('is_delete', '=', 0)
  191. ->select();
  192. // 整理列表数据并返回
  193. return $this->setProductListData($list, true);
  194. } else {
  195. $sort = ['create_time' => 'desc'];
  196. if ($params['type'] == 10) {
  197. $sort = ['sales_actual' => 'desc'];
  198. } else if ($params['type'] == 30) {
  199. $sort = ['view_times' => 'desc'];
  200. }
  201. // 自动
  202. $sort = $params['type'] == 20 ? ['create_time' => 'desc'] : ['product_sales' => 'desc'];
  203. $list = $model->field(['*', '(sales_initial + sales_actual) as product_sales'])->with(['category', 'image.file'])
  204. ->where('product_status', '=', 10)
  205. ->where('audit_status', '=', 10)
  206. ->where('is_delete', '=', 0)
  207. ->limit($params['num'])
  208. ->order($sort)
  209. ->select();
  210. return $this->setProductListData($list, true);
  211. }
  212. }
  213. //商品上下架
  214. public function editStatus($data)
  215. {
  216. return $this->save(['product_status' => $data['product_status']]);
  217. }
  218. }