Goods.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Niucloud-admin 企业快速开发的多应用管理平台
  4. // +----------------------------------------------------------------------
  5. // | 官方网址:https://www.niucloud.com
  6. // +----------------------------------------------------------------------
  7. // | niucloud团队 版权所有 开源版本可自由商用
  8. // +----------------------------------------------------------------------
  9. // | Author: Niucloud Team
  10. // +----------------------------------------------------------------------
  11. namespace addon\mall\app\model\goods;
  12. use addon\mall\app\dict\coupon\CouponDict;
  13. use addon\mall\app\dict\goods\GoodsDict;
  14. use addon\mall\app\model\coupon\Coupon;
  15. use addon\mall\app\model\coupon\CouponGoods;
  16. use app\dict\sys\FileDict;
  17. use app\model\shop\Shop;
  18. use app\model\site\Site;
  19. use core\base\BaseModel;
  20. use think\model\concern\SoftDelete;
  21. use think\model\relation\HasMany;
  22. use think\model\relation\HasOne;
  23. /**
  24. * 商品模型
  25. * Class Goods
  26. * @package addon\mall\app\model\goods
  27. */
  28. class Goods extends BaseModel
  29. {
  30. use SoftDelete;
  31. /**
  32. * 数据表主键
  33. * @var string
  34. */
  35. protected $pk = 'goods_id';
  36. /**
  37. * 模型名称
  38. * @var string
  39. */
  40. protected $name = 'mall_goods';
  41. /**
  42. * 定义软删除标记字段.
  43. * @var string
  44. */
  45. protected $deleteTime = 'delete_time';
  46. /**
  47. * 定义软删除字段的默认值
  48. * @var int
  49. */
  50. protected $defaultSoftDelete = 0;
  51. // 设置json类型字段
  52. protected $json = [ 'goods_category', 'label_ids', 'service_ids', 'delivery_type', 'audit_info', 'attr_format' ];
  53. // 设置JSON数据返回数组
  54. protected $jsonAssoc = true;
  55. /**
  56. * 状态字段转化
  57. * @param $value
  58. * @param $data
  59. * @return mixed
  60. */
  61. public function getGoodsTypeNameAttr($value, $data)
  62. {
  63. if (!empty($data[ 'goods_type' ])) {
  64. return GoodsDict::getType($data[ 'goods_type' ])[ 'name' ] ?? '';
  65. }
  66. return '';
  67. }
  68. /**
  69. * 状态字段转化
  70. * @param $value
  71. * @param $data
  72. * @return mixed
  73. */
  74. public function getGoodsEditPathAttr($value, $data)
  75. {
  76. if (!empty($data[ 'goods_type' ])) {
  77. return GoodsDict::getType($data[ 'goods_type' ])[ 'path' ] ?? '';
  78. }
  79. return '';
  80. }
  81. /**
  82. * 获取封面缩略图(小)
  83. */
  84. public function getGoodsCoverThumbSmallAttr($value, $data)
  85. {
  86. if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
  87. return get_thumb_images($data[ 'site_id' ], $data[ 'goods_cover' ], FileDict::SMALL);
  88. }
  89. return [];
  90. }
  91. /**
  92. * 获取封面缩略图(中)
  93. */
  94. public function getGoodsCoverThumbMidAttr($value, $data)
  95. {
  96. if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
  97. return get_thumb_images($data[ 'site_id' ], $data[ 'goods_cover' ], FileDict::MID);
  98. }
  99. return [];
  100. }
  101. /**
  102. * 获取封面缩略图(大)
  103. */
  104. public function getGoodsCoverThumbBigAttr($value, $data)
  105. {
  106. if (isset($data[ 'goods_cover' ]) && $data[ 'goods_cover' ] != '') {
  107. return get_thumb_images($data[ 'site_id' ], $data[ 'goods_cover' ], FileDict::BIG);
  108. }
  109. return [];
  110. }
  111. /**
  112. * 获取商品图片缩略图(小)
  113. */
  114. public function getGoodsImageThumbSmallAttr($value, $data)
  115. {
  116. if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
  117. $goods_image = explode(',', $data[ 'goods_image' ]);
  118. $img_arr = [];
  119. foreach ($goods_image as $k => $v) {
  120. $img = get_thumb_images($data[ 'site_id' ], $v, FileDict::SMALL);
  121. if (!empty($img)) {
  122. $img_arr[] = $img;
  123. }
  124. }
  125. return $img_arr;
  126. }
  127. return [];
  128. }
  129. /**
  130. * 获取商品图片缩略图(中)
  131. */
  132. public function getGoodsImageThumbMidAttr($value, $data)
  133. {
  134. if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
  135. $goods_image = explode(',', $data[ 'goods_image' ]);
  136. $img_arr = [];
  137. foreach ($goods_image as $k => $v) {
  138. $img = get_thumb_images($data[ 'site_id' ], $v, FileDict::MID);
  139. if (!empty($img)) {
  140. $img_arr[] = $img;
  141. }
  142. }
  143. return $img_arr;
  144. }
  145. return [];
  146. }
  147. /**
  148. * 获取商品图片缩略图(大)
  149. */
  150. public function getGoodsImageThumbBigAttr($value, $data)
  151. {
  152. if (isset($data[ 'goods_image' ]) && $data[ 'goods_image' ] != '') {
  153. $goods_image = explode(',', $data[ 'goods_image' ]);
  154. $img_arr = [];
  155. foreach ($goods_image as $k => $v) {
  156. $img = get_thumb_images($data[ 'site_id' ], $v, FileDict::BIG);
  157. if (!empty($img)) {
  158. $img_arr[] = $img;
  159. }
  160. }
  161. return $img_arr;
  162. }
  163. return [];
  164. }
  165. /**
  166. * 获取商品分类
  167. */
  168. public function getGoodsCategoryAttr($value, $data)
  169. {
  170. if (!is_array($value)) {
  171. $value = json_decode($value, true);
  172. }
  173. if (!empty($value)) {
  174. return array_map(function($item) {
  175. return (int) $item;
  176. }, $value);
  177. }
  178. return [];
  179. }
  180. /**
  181. * 搜索器:商品商品id
  182. * @param $value
  183. * @param $data
  184. */
  185. public function searchGoodsIdAttr($query, $value, $data)
  186. {
  187. if ($value) {
  188. $query->where('goods_id', $value);
  189. }
  190. }
  191. /**
  192. * 搜索器:商品商品名称
  193. * @param $value
  194. * @param $data
  195. */
  196. public function searchGoodsNameAttr($query, $value, $data)
  197. {
  198. if ($value) {
  199. $query->where('goods_name', 'like', '%' . $value . '%');
  200. }
  201. }
  202. /**
  203. * 搜索器:商品副标题
  204. * @param $value
  205. * @param $data
  206. */
  207. public function searchSubTitleAttr($query, $value, $data)
  208. {
  209. if ($value) {
  210. $query->where('sub_title', 'like', '%' . $value . '%');
  211. }
  212. }
  213. /**
  214. * 搜索器:关键词
  215. * @param $value
  216. * @param $data
  217. */
  218. public function searchKeywordAttr($query, $value, $data)
  219. {
  220. if ($value) {
  221. $query->whereLike('goods_name|sub_title', '%' . $value . '%');
  222. }
  223. }
  224. /**
  225. * 搜索器:商品商品类型
  226. * @param $value
  227. * @param $data
  228. */
  229. public function searchGoodsTypeAttr($query, $value, $data)
  230. {
  231. if ($value) {
  232. $query->where('goods_type', $value);
  233. }
  234. }
  235. /**
  236. * 搜索器:商品商品品牌id
  237. * @param $value
  238. * @param $data
  239. */
  240. public function searchBrandIdAttr($query, $value, $data)
  241. {
  242. if ($value) {
  243. $query->where('brand_id', $value);
  244. }
  245. }
  246. /**
  247. * 搜索器:商品商品品牌id(关联查询使用)
  248. * @param $value
  249. * @param $data
  250. */
  251. public function searchSiteIdAttr($query, $value, $data)
  252. {
  253. if ($value) {
  254. $query->where('goods.site_id', $value);
  255. }
  256. }
  257. /**
  258. * 平台商品分类查询
  259. * @param $query
  260. * @param $value
  261. * @param $data
  262. */
  263. public function searchGoodsMallCategoryAttr($query, $value, $data)
  264. {
  265. if ($value) {
  266. if (is_array($value)) {
  267. $value = end($value);
  268. }
  269. //查询分类信息
  270. $goods_category_model = new Category();
  271. $category_info = $goods_category_model->where([ [ 'category_id', '=', $value ] ])->field('category_id,level,pid')->findOrEmpty()->toArray();
  272. if ($category_info[ 'level' ] == 3) {
  273. $query->where('goods_mall_category', $value);
  274. } elseif ($category_info[ 'level' ] == 2) {
  275. $category_ids = $value;
  276. $category_list = $goods_category_model->where([ [ 'pid', '=', $value ] ])->field('category_id,level,pid')->select()->toArray();
  277. if (!empty($category_list)) {
  278. foreach ($category_list as $k => $v) {
  279. $category_ids = $category_ids . ',' . $v[ 'category_id' ];
  280. }
  281. }
  282. $query->where('goods_mall_category', 'in', $category_ids);
  283. } else {
  284. // 一级
  285. $category_ids = $value;
  286. $child_list = $goods_category_model->where([ [ 'pid', '=', $value ] ])->field('category_id,level,pid')->select()->toArray();
  287. if (!empty($child_list)) {
  288. $child_ids = '';
  289. foreach ($child_list as $k => $v) {
  290. $category_ids = $category_ids . ',' . $v[ 'category_id' ];
  291. $child_ids = $child_ids == '' ? $v[ 'category_id' ] : $child_ids . ',' . $v[ 'category_id' ];
  292. }
  293. $grand_child_list = $goods_category_model->where([ [ 'pid', 'in', $child_ids ] ])->field('category_id,level')->select()->toArray();
  294. if (!empty($grand_child_list)) {
  295. foreach ($grand_child_list as $k_child => $v_child) {
  296. $category_ids = $category_ids . ',' . $v_child[ 'category_id' ];
  297. }
  298. }
  299. $query->where('goods_mall_category', 'in', $category_ids);
  300. } else {
  301. $query->where('goods_mall_category', '=', $category_ids);
  302. }
  303. }
  304. }
  305. }
  306. /**
  307. * 搜索器:商品商品分类
  308. * @param $value
  309. * @param $data
  310. */
  311. public function searchGoodsCategoryAttr($query, $value, $data)
  312. {
  313. if ($value) {
  314. if (is_array($value)) {
  315. $temp_where = array_map(function($item) { return '%"' . $item . '"%'; }, $value);
  316. } else {
  317. $temp_where = [ '%"' . $value . '"%' ];
  318. }
  319. $query->where('goods_category', 'like', $temp_where, 'or');
  320. }
  321. }
  322. /**
  323. * 搜索器:商品标签组
  324. * @param $value
  325. * @param $data
  326. */
  327. public function searchLabelIdsAttr($query, $value, $data)
  328. {
  329. if ($value) {
  330. if (is_array($value)) {
  331. $temp_where = array_map(function($item) { return '%"' . $item . '"%'; }, $value);
  332. } else {
  333. $temp_where = [ '%"' . $value . '"%' ];
  334. }
  335. $query->where('label_ids', 'like', $temp_where, 'or');
  336. }
  337. }
  338. /**
  339. * 搜索器:商品服务
  340. * @param $value
  341. * @param $data
  342. */
  343. public function searchServiceIdsAttr($query, $value, $data)
  344. {
  345. if ($value) {
  346. if (is_array($value)) {
  347. $temp_where = array_map(function($item) { return '%"' . $item . '"%'; }, $value);
  348. } else {
  349. $temp_where = [ '%"' . $value . '"%' ];
  350. }
  351. $query->where('service_ids', 'like', $temp_where, 'or');
  352. }
  353. }
  354. /**
  355. * 搜索器:商品销量
  356. * @param $value
  357. * @param $data
  358. */
  359. public function searchSaleNumAttr($query, $value, $data)
  360. {
  361. if (!empty($data[ 'start_sale_num' ]) && !empty($data[ 'end_sale_num' ])) {
  362. $money = [ $data[ 'start_sale_num' ], $data[ 'end_sale_num' ] ];
  363. sort($money);
  364. $query->where('goods.sale_num', 'between', $money);
  365. } elseif (!empty($data[ 'start_sale_num' ])) {
  366. $query->where('goods.sale_num', '>=', $data[ 'start_sale_num' ]);
  367. } elseif (!empty($data[ 'end_sale_num' ])) {
  368. $query->where('goods.sale_num', '<=', $data[ 'end_sale_num' ]);
  369. }
  370. }
  371. /**
  372. * 搜索器:商品sku是否默认
  373. * @param $value
  374. * @param $data
  375. */
  376. public function searchGoodsSkuIsDefaultAttr($query, $value, $data)
  377. {
  378. if ($value) {
  379. $query->where('goodsSku.is_default', $value);
  380. }
  381. }
  382. /**
  383. * 搜索器:商品sku价格
  384. * @param $value
  385. * @param $data
  386. */
  387. public function searchGoodsSkuPriceAttr($query, $value, $data)
  388. {
  389. if (!empty($data[ 'start_price' ]) && !empty($data[ 'end_price' ])) {
  390. $money = [ $data[ 'start_price' ], $data[ 'end_price' ] ];
  391. sort($money);
  392. $query->where('goodsSku.price', 'between', $money);
  393. } elseif (!empty($data[ 'start_price' ])) {
  394. $query->where('goodsSku.price', '>=', $data[ 'start_price' ]);
  395. } elseif (!empty($data[ 'end_price' ])) {
  396. $query->where('goodsSku.price', '<=', $data[ 'end_price' ]);
  397. }
  398. }
  399. /**
  400. * 搜索器:优惠券id(查询适用优惠券的商品列表)
  401. * @param $value
  402. * @param $data
  403. */
  404. public function searchCouponIdAttr($query, $value, $data)
  405. {
  406. if ($value) {
  407. $coupon_goods_model = new CouponGoods();
  408. $coupon = (new Coupon())->where([ [ 'id', '=', $value ] ])->field('site_id, is_all_site_join, join_site_ids')->findOrEmpty()->toArray();
  409. $coupon_list = $coupon_goods_model->where([ [ 'coupon_id', '=', $value ] ])->field('goods_id,category_id,mall_category_id,brand_id')->select()->toArray();
  410. if (!empty($coupon_list)) {
  411. $goods_ids = array_values(array_filter(array_column($coupon_list, 'goods_id')));
  412. $category_ids = array_values(array_filter(array_column($coupon_list, 'category_id')));
  413. $mall_category_ids = array_values(array_filter(array_column($coupon_list, 'mall_category_id')));
  414. $brand_ids = array_values(array_filter(array_column($coupon_list, 'brand_id')));
  415. if (!empty($goods_ids)) {
  416. $query->where('goods.goods_id', 'in', $goods_ids);
  417. } elseif (!empty($category_ids)) {
  418. $like_arr = [];
  419. foreach ($category_ids as $v) {
  420. $like_arr[] = '%' . $v . '%';
  421. }
  422. $query->where('goods_category', 'like', $like_arr, 'or');
  423. } elseif (!empty($mall_category_ids)) {
  424. $query->where('goods_mall_category', 'in', $mall_category_ids);
  425. } elseif (!empty($brand_ids)) {
  426. $query->where('brand_id', 'in', $brand_ids);
  427. }
  428. }
  429. if (!empty($coupon)) {
  430. if ($coupon['site_id']) {
  431. $query->where(function ($query) use ($coupon){
  432. $query->where('goods.site_id', '=', $coupon['site_id']);
  433. });
  434. } else {
  435. if ($coupon['is_all_site_join'] == CouponDict::NOT_ALL_SITE_JOIN) {
  436. $query->where(function ($query) use ($coupon){
  437. $query->where('goods.site_id', 'in', $coupon['join_site_ids']);
  438. });
  439. }
  440. }
  441. }
  442. }
  443. }
  444. /**
  445. * 搜索器:商品商品状态(1.正常0下架)
  446. * @param $value
  447. * @param $data
  448. */
  449. public function searchStatusAttr($query, $value, $data)
  450. {
  451. if ($value !== '') {
  452. $query->where('goods.status', $value);
  453. }
  454. }
  455. /**
  456. * 搜索器:供应商id
  457. * @param $value
  458. * @param $data
  459. */
  460. public function searchSupplierIdAttr($query, $value, $data)
  461. {
  462. if ($value) {
  463. $query->where('supplier_id', $value);
  464. }
  465. }
  466. /**
  467. * 关联默认商品规格
  468. * @return HasOne
  469. */
  470. public function goodsSku()
  471. {
  472. return $this->hasOne(GoodsSku::class, 'goods_id', 'goods_id');
  473. }
  474. /**
  475. * 关联商品规格列表
  476. * @return HasMany
  477. */
  478. public function skuList()
  479. {
  480. return $this->hasMany(GoodsSku::class, 'goods_id', 'goods_id');
  481. }
  482. /**
  483. * 关联站点信息
  484. * @return HasOne
  485. */
  486. public function site()
  487. {
  488. return $this->hasOne(Site::class, 'site_id', 'site_id');
  489. }
  490. /**
  491. * 关联店铺信息
  492. * @return HasOne
  493. */
  494. public function shop()
  495. {
  496. return $this->hasOne(Shop::class, 'site_id', 'site_id');
  497. }
  498. /**
  499. * 关联商品规格列表
  500. * @return HasMany
  501. */
  502. public function goodsSpec()
  503. {
  504. return $this->hasMany(GoodsSpec::class, 'goods_id', 'goods_id');
  505. }
  506. /**
  507. * 关联默认商品规格
  508. * @return HasOne
  509. */
  510. public function brand()
  511. {
  512. return $this->hasOne(Brand::class, 'brand_id', 'brand_id')
  513. ->joinType('left')
  514. ->withField('brand_id, brand_name, logo, desc');
  515. }
  516. }