Product.php 8.6 KB

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