model = new ShopGoodsModel(); } /** * 静态化入口 * @return static|null */ public static function make() { if(!self::$instance){ self::$instance = new static(); } return self::$instance; } /** * 获取列表 * @param $map 分组 * @param $pageSize 分页大小 * @param $field 返回字段 * @param $cache 是否缓存数据,默认是 * @return array|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getList($map, $pageSize=10, $field='', $cache=true) { $page = request()->post('page', 1); $cacheKey = "caches:goods:list_{$page}_{$pageSize}_".md5(json_encode($map, 256).$field); $list = RedisCache::get($cacheKey); if($list && $cache){ return $list; } $where = ['on_sale'=> 1]; $menuId = isset($map['menu_id'])? intval($map['menu_id']) : 0; if ($menuId>0){ $where['menu_id'] = $menuId; } $keywords = isset($map['keywords'])? trim($map['keywords']) : ''; if (!empty($keywords)) { $where['goods_name|hot_keywords'] = "%{$map['keywords']}%"; } $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'; $order = isset($map['sort']) && $map['sort']? $map['sort'] : 'sort desc,goods_id desc'; $list = $this->model->where($where) ->where(function($query) use($map){ $cls = isset($map['cls'])? trim($map['cls']) : 0; if (!empty($cls)) { $query->where('give_vip','>', 0); } }) ->field($field) ->order($order) ->paginate($pageSize); $list = $list? $list->toArray():[]; if($list){ RedisCache::set($cacheKey, $list, rand(10,20)); } return $list; } /** * 获取商品详情 * @param $map * @return array|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getDetail($map) { $where = []; $goodsSn = isset($map['goods_sn'])? trim($map['goods_sn']) : 0; $goodsId = isset($map['goods_id'])? intval($map['goods_id']) : 0; if($goodsSn){ $where['goods_sn'] = $goodsSn; } if($goodsId){ $where['goods_id'] = $goodsId; } $isCache = false; $cacheKey = "caches:goods:detail_sn{$goodsSn}_g{$goodsId}"; $info = RedisCache::get($cacheKey); if(empty($info)){ $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'; $info = $this->model->where($where)->field($field)->withAttr('goods_img_banner', function ($value) { return json_decode($value, true) ?: []; })->withAttr('goods_remark', function ($value) { return htmlspecialchars_decode($value); })->withAttr('buyNote', function ($value) { return htmlspecialchars_decode($value); })->findOrEmpty()->toArray(); }else{ $isCache = true; } if($info){ $specRelation = ShopGoodsSpecRelationService::make()->getDataByGoods($info['goods_id']); $goodsExpress = ExpressDeliveryService::make()->getDataByTemplate($info['post_template_id']); $goodsSpec = ShopGoodsSpecService::make()->getListByGoods($info['goods_id']); $info['expressNote'] = $goodsExpress['remake'] ?: ''; $info['spec_relation'] = $specRelation; $info['goods_spec'] = $goodsSpec; $attensionCount = RedisCache::get("caches:goods:attension:{$info['goods_id']}"); if($isCache && $attensionCount>0){ $info['attension_count'] = $attensionCount; } RedisCache::set($cacheKey, $info, rand(3,5)); } return $info; } /** * 更新商品浏览量 * @param $goodsId * @return false */ public function updateScanCount($goodsId) { return $goodsId?$this->model->where(['goods_id'=> $goodsId])->inc('scan_count',1)->update():false; } /** * 商品收藏 * @param $uid 用户 * @param $goodsId * @return bool * @throws Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function goodsAttension($uid, $goodsId) { $info = $this->model->where(['goods_id'=> $goodsId])->field('goods_id,attension_count')->find(); if(!$info){ throw new Exception('商品不存在'); } // 是否收藏过 if(GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id')){ return true; }else{ $data = [ 'uid'=> $uid, 'goods_id'=> $goodsId, 'create_time'=>sr_getcurtime(time()) ]; Db::startTrans(); if(!GoodsAttensionModel::insertGetId($data)){ Db::rollback(); throw new Exception('收藏失败'); } if(!$this->model->where(['goods_id'=> $goodsId])->inc('attension_count')->update()){ Db::rollback(); throw new Exception('收藏失败'); } $attenSionCount = isset($info['attension_count'])? $info['attension_count'] : 0; RedisCache::set("caches:goods:attension:{$goodsId}", $attenSionCount+1, rand(5, 10)); RedisCache::keyDel('caches:goods:list_*'); Db::commit(); return true; } } /** * 取消收藏 * @param $uid 用户 * @param $goodsId 商品ID * @return bool */ public function cancelAttension($uid, $goodsId) { if(!GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id')){ return true; } Db::startTrans(); if(GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->delete()){ RedisCache::keyDel('caches:goods:list_*'); if(!$this->model->where(['goods_id'=> $goodsId])->dec('attension_count')->update()){ Db::rollback(); return false; } Db::commit(); RedisCache::keyDel("caches:goods:attension:{$goodsId}"); return true; }else{ Db::rollback(); return false; } } /** * 是否收藏过该商品 * @param $uid 用户 * @param $goodsId 商品 * @return bool|mixed */ public function checkAttension($uid, $goodsId) { $cacheKey = "caches:goods:attensionUser:u_{$uid}_g{$goodsId}"; if(RedisCache::get($cacheKey)){ return true; } $data = GoodsAttensionModel::where(['uid'=> $uid,'goods_id'=> $goodsId])->value('id'); if($data){ RedisCache::set($cacheKey, $data, rand(5, 10)); } return $data? true : false; } /** * 获取商品缓存信息 * @param $goodsSn * @param string $field * @return array|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getCacheInfo($goodsSn, $field='', $cache=true) { $cacheKey = "caches:goods:info_sn{$goodsSn}".($field? '_'.md5($field) : ''); $info = RedisCache::get($cacheKey); if($info && $cache){ return $info; } $field? $field : 'id,goods_type,restrictions_num'; $info = $this->model->where(['goods_sn'=> $goodsSn])->field($field)->find(); $info = $info? $info->toArray() : []; if($info && $cache){ RedisCache::set($cacheKey, $info, rand(5, 10)); } return $info; } }