ShopGoodsService.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | EasyAdmin
  4. // +----------------------------------------------------------------------
  5. // | PHP交流群: 763822524
  6. // +----------------------------------------------------------------------
  7. // | 开源协议 https://mit-license.org
  8. // +----------------------------------------------------------------------
  9. // | github开源项目:https://github.com/zhongshaofa/EasyAdmin
  10. // +----------------------------------------------------------------------
  11. namespace app\common\service;
  12. use app\common\model\GoodsAttensionModel;
  13. use app\common\model\ShopGoodsModel;
  14. use think\Exception;
  15. use think\facade\Db;
  16. use utils\RedisCache;
  17. /**
  18. * 商品服务 by wes
  19. * Class ShopGoodsService
  20. * @package app\common\service
  21. */
  22. class ShopGoodsService
  23. {
  24. protected static $instance = null;
  25. protected $model = null;
  26. public function __construct()
  27. {
  28. $this->model = new ShopGoodsModel();
  29. }
  30. /**
  31. * 静态化入口
  32. * @return static|null
  33. */
  34. public static function make()
  35. {
  36. if(!self::$instance){
  37. self::$instance = new static();
  38. }
  39. return self::$instance;
  40. }
  41. /**
  42. * 获取列表
  43. * @param $map 分组
  44. * @param $pageSize 分页大小
  45. * @param $field 返回字段
  46. * @param $cache 是否缓存数据,默认是
  47. * @return array|mixed
  48. * @throws \think\db\exception\DataNotFoundException
  49. * @throws \think\db\exception\DbException
  50. * @throws \think\db\exception\ModelNotFoundException
  51. */
  52. public function getList($map, $pageSize=10, $field='', $cache=true)
  53. {
  54. $page = request()->post('page', 1);
  55. $cacheKey = "caches:goods:list_{$page}_{$pageSize}_".md5(json_encode($map, 256).$field);
  56. $list = RedisCache::get($cacheKey);
  57. if($list && $cache){
  58. return $list;
  59. }
  60. $where = ['on_sale'=> 1];
  61. $menuId = isset($map['menu_id'])? intval($map['menu_id']) : 0;
  62. if ($menuId>0){
  63. $where['menu_id'] = $menuId;
  64. }
  65. $keywords = isset($map['keywords'])? trim($map['keywords']) : '';
  66. if (!empty($keywords)) {
  67. $where['goods_name|hot_keywords'] = "%{$map['keywords']}%";
  68. }
  69. $field = $field? $field : 'sort,category,goods_sn,goods_name,goods_img,min_original_price as original_price,min_price as price,rebate_score,sales_volume,inventory,attension_count,restrictions_num';
  70. $order = isset($map['sort']) && $map['sort']? $map['sort'] : 'sort desc,goods_id desc';
  71. $list = $this->model->where($where)
  72. ->where(function($query) use($map){
  73. $cls = isset($map['cls'])? trim($map['cls']) : 0;
  74. if (!empty($cls)) {
  75. $query->where('give_vip','>', 0);
  76. }
  77. })
  78. ->field($field)
  79. ->order($order)
  80. ->paginate($pageSize);
  81. $list = $list? $list->toArray():[];
  82. if($list){
  83. RedisCache::set($cacheKey, $list, rand(10,20));
  84. }
  85. return $list;
  86. }
  87. /**
  88. * 获取商品详情
  89. * @param $map
  90. * @return array|mixed
  91. * @throws \think\db\exception\DataNotFoundException
  92. * @throws \think\db\exception\DbException
  93. * @throws \think\db\exception\ModelNotFoundException
  94. */
  95. public function getDetail($map)
  96. {
  97. $where = [];
  98. $goodsSn = isset($map['goods_sn'])? trim($map['goods_sn']) : 0;
  99. $goodsId = isset($map['goods_id'])? intval($map['goods_id']) : 0;
  100. if($goodsSn){
  101. $where['goods_sn'] = $goodsSn;
  102. }
  103. if($goodsId){
  104. $where['goods_id'] = $goodsId;
  105. }
  106. $isCache = false;
  107. $cacheKey = "caches:goods:detail_sn{$goodsSn}_g{$goodsId}";
  108. $info = RedisCache::get($cacheKey);
  109. if(empty($info)){
  110. $field = 'menu_id,spec_name,goods_id,category,goods_sn,goods_name,goods_img,goods_img_banner,goods_remark,min_original_price as original_price,min_price as price,note,inventory,rebate_score,sales_volume,restrictions,rush_buy,buynote_template as buyNote,post_template_id,restrictions_num';
  111. $info = $this->model->where($where)->field($field)->withAttr('goods_img_banner', function ($value) {
  112. return json_decode($value, true) ?: [];
  113. })->withAttr('goods_remark', function ($value) {
  114. return htmlspecialchars_decode($value);
  115. })->withAttr('buyNote', function ($value) {
  116. return htmlspecialchars_decode($value);
  117. })->findOrEmpty()->toArray();
  118. }else{
  119. $isCache = true;
  120. }
  121. if($info){
  122. $specRelation = ShopGoodsSpecRelationService::make()->getDataByGoods($info['goods_id']);
  123. $goodsExpress = ExpressDeliveryService::make()->getDataByTemplate($info['post_template_id']);
  124. $goodsSpec = ShopGoodsSpecService::make()->getListByGoods($info['goods_id']);
  125. $info['expressNote'] = $goodsExpress['remake'] ?: '';
  126. $info['spec_relation'] = $specRelation;
  127. $info['goods_spec'] = $goodsSpec;
  128. $attensionCount = RedisCache::get("caches:goods:attension:{$info['goods_id']}");
  129. if($isCache && $attensionCount>0){
  130. $info['attension_count'] = $attensionCount;
  131. }
  132. RedisCache::set($cacheKey, $info, rand(3,5));
  133. }
  134. return $info;
  135. }
  136. /**
  137. * 更新商品浏览量
  138. * @param $goodsId
  139. * @return false
  140. */
  141. public function updateScanCount($goodsId)
  142. {
  143. return $goodsId?$this->model->where(['goods_id'=> $goodsId])->inc('scan_count',1)->update():false;
  144. }
  145. /**
  146. * 商品收藏
  147. * @param $uid 用户
  148. * @param $goodsId
  149. * @return bool
  150. * @throws Exception
  151. * @throws \think\db\exception\DataNotFoundException
  152. * @throws \think\db\exception\DbException
  153. * @throws \think\db\exception\ModelNotFoundException
  154. */
  155. public function goodsAttension($uid, $goodsId)
  156. {
  157. $info = $this->model->where(['goods_id'=> $goodsId])->field('goods_id,attension_count')->find();
  158. if(!$info){
  159. throw new Exception('商品不存在');
  160. }
  161. // 是否收藏过
  162. if(GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id')){
  163. return true;
  164. }else{
  165. $data = [
  166. 'uid'=> $uid,
  167. 'goods_id'=> $goodsId,
  168. 'create_time'=>sr_getcurtime(time())
  169. ];
  170. Db::startTrans();
  171. if(!GoodsAttensionModel::insertGetId($data)){
  172. Db::rollback();
  173. throw new Exception('收藏失败');
  174. }
  175. if(!$this->model->where(['goods_id'=> $goodsId])->inc('attension_count')->update()){
  176. Db::rollback();
  177. throw new Exception('收藏失败');
  178. }
  179. $attenSionCount = isset($info['attension_count'])? $info['attension_count'] : 0;
  180. RedisCache::set("caches:goods:attension:{$goodsId}", $attenSionCount+1, rand(5, 10));
  181. RedisCache::keyDel('caches:goods:list_*');
  182. Db::commit();
  183. return true;
  184. }
  185. }
  186. /**
  187. * 取消收藏
  188. * @param $uid 用户
  189. * @param $goodsId 商品ID
  190. * @return bool
  191. */
  192. public function cancelAttension($uid, $goodsId)
  193. {
  194. if(!GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id')){
  195. return true;
  196. }
  197. Db::startTrans();
  198. if(GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->delete()){
  199. RedisCache::keyDel('caches:goods:list_*');
  200. if(!$this->model->where(['goods_id'=> $goodsId])->dec('attension_count')->update()){
  201. Db::rollback();
  202. return false;
  203. }
  204. Db::commit();
  205. RedisCache::keyDel("caches:goods:attension:{$goodsId}");
  206. return true;
  207. }else{
  208. Db::rollback();
  209. return false;
  210. }
  211. }
  212. /**
  213. * 是否收藏过该商品
  214. * @param $uid 用户
  215. * @param $goodsId 商品
  216. * @return bool|mixed
  217. */
  218. public function checkAttension($uid, $goodsId)
  219. {
  220. $cacheKey = "caches:goods:attensionUser:u_{$uid}_g{$goodsId}";
  221. if(RedisCache::get($cacheKey)){
  222. return true;
  223. }
  224. $data = GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id');
  225. if($data){
  226. RedisCache::set($cacheKey, $data, rand(5, 10));
  227. }
  228. return $data? true : false;
  229. }
  230. /**
  231. * 获取商品缓存信息
  232. * @param $goodsSn
  233. * @param string $field
  234. * @return array|mixed
  235. * @throws \think\db\exception\DataNotFoundException
  236. * @throws \think\db\exception\DbException
  237. * @throws \think\db\exception\ModelNotFoundException
  238. */
  239. public function getCacheInfo($goodsSn, $field='', $cache=true)
  240. {
  241. $cacheKey = "caches:goods:info_sn{$goodsSn}".($field? '_'.md5($field) : '');
  242. $info = RedisCache::get($cacheKey);
  243. if($info && $cache){
  244. return $info;
  245. }
  246. $field? $field : 'id,goods_type,restrictions_num';
  247. $info = $this->model->where(['goods_sn'=> $goodsSn])->field($field)->find();
  248. $info = $info? $info->toArray() : [];
  249. if($info && $cache){
  250. RedisCache::set($cacheKey, $info, rand(5, 10));
  251. }
  252. return $info;
  253. }
  254. }