// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\CartModel; use App\Models\GoodsModel; use App\Services\BaseService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 购物车管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services\Api */ class CartService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 */ public function __construct() { $this->model = new CartModel(); } /** * 静态入口 */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } /** * 列表数据 * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 15) { $userId = isset($params['user_id']) ? intval($params['user_id']) : 0; $cacheKey = "caches:goods:cartList_{$userId}_{$pageSize}_" . ($params ? md5(json_encode($params)) : 0); $datas = RedisService::get($cacheKey); if (empty($datas)) { $query = $this->getQuery($params) ->orderBy('a.create_time', 'desc') ->orderBy('a.id', 'desc'); $field = ["a.id",'a.goods_id','a.user_id','a.store_id','a.num','a.sk_key','a.sku_id']; $list = $query->select($field) ->groupBy('a.store_id') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { $datas = [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'count' => $this->getCount($userId), 'list' => isset($list['data']) ? $list['data'] : [] ]; RedisService::set($cacheKey, $datas, rand(3, 5)); } } return $datas; } /** * 查询条件 * @param $params * @return mixed */ public function getQuery($params) { $where = ['a.status' => 1, 'a.mark' => 1]; $status = isset($params['status']) ? $params['status'] : 1; if ($status > 0) { $where['a.status'] = $status; } else { unset($where['a.status']); } $model = $this->model->with(['store','cartGoods']) ->from('carts as a') ->leftJoin('goods as b', 'b.id', '=', 'a.goods_id') ->where($where) ->where(function ($query) use ($params) { // 商品 $goodsId = isset($params['goods_id']) ? intval($params['goods_id']) : 0; if ($goodsId > 0) { $query->where('a.goods_id', $goodsId); } $userId = isset($params['user_id']) ? intval($params['user_id']) : 0; if ($userId > 0) { $query->where('a.user_id', $userId); } // 店铺 $storeId = isset($params['store_id']) ? intval($params['store_id']) : 0; if ($storeId > 0) { $query->where('a.store_id', $storeId); } $keyword = isset($params['keyword']) ? trim($params['keyword']) : ''; if ($keyword) { $query->where(function ($query) use ($keyword) { $query->where('b.goods_name', 'like', "%{$keyword}%") ->orWhere('b.tags', 'like', "%{$keyword}%"); }); } }); return $model; } /** * 添加购物车 * @param $userId * @param $goodsId * @param int $skuId * @return array|false */ public function add($userId, $goodsId, $skuId=0, $num=1) { $cacheKey = "caches:goods:addCart:{$userId}_{$goodsId}_{$skuId}"; if(RedisService::get($cacheKey.'_lock')){ $this->error = '处理中~'; return false; } RedisService::set($cacheKey.'_lock', ['goods_id'=>$goodsId,'sku_id'=>$skuId], rand(3,5)); $goodsInfo = GoodsModel::with(['skus']) ->where(['id' => $goodsId, 'status' => 1, 'mark' => 1]) ->select(['id', 'sku_type', 'store_id']) ->first(); $storeId = isset($goodsInfo['store_id']) ? $goodsInfo['store_id'] : 0; $skuType = isset($goodsInfo['sku_type']) ? $goodsInfo['sku_type'] : 0; $skus = isset($goodsInfo['skus']) ? $goodsInfo['skus'] : []; $skuId = $skuId? $skuId : (isset($skus[0]) ? $skus[0]['id'] : 0); if (empty($goodsInfo)) { RedisService::clear($cacheKey.'_lock'); $this->error = '商品已下架'; return false; } // 去除其他店铺购物车 $this->model->where(['user_id' => $userId, 'mark' => 1])->whereNotIn('store_id', [$storeId])->update(['mark' => 0, 'update_time' => time()]); // 添加购物型 if ($id = $this->model->where(['user_id' => $userId,'sku_id'=>$skuId, 'goods_id' => $goodsId])->value('id')) { $this->model->where(['id' => $id])->update(['store_id' => $storeId,'num'=> DB::raw("num+{$num}"),'sk_key'=>"{$userId}-{$storeId}", 'sku_id' => $skuType == 1 ? 0 : $skuId, 'status' => 1, 'mark' => 1, 'create_time' => time()]); } else { $data = [ 'user_id' => $userId, 'goods_id' => $goodsId, 'store_id' => $storeId, 'num'=> $num, 'sk_key'=>"{$userId}-{$storeId}", 'sku_id' => $skuType == 1 ? 0 : $skuId, 'create_time' => time(), 'status' => 1, 'mark' => 1, ]; $id = $this->model->insertGetId($data); } $this->error = '添加成功'; RedisService::clear($cacheKey.'_lock'); RedisService::clear("caches:goods:cartCount:{$userId}"); RedisService::keyDel("caches:goods:cartList_{$userId}*"); return ['id' => $id,'sku_id'=>$skuId, 'count' => $this->getCount($userId)]; } /** * 更新购物车 * @param $userId * @param $cartId * @return array|false */ public function update($userId, $cartId, $num=1) { $cacheKey = "caches:goods:updateCart:{$userId}_{$cartId}"; if(RedisService::get($cacheKey.'_lock')){ $this->error = '处理中~'; return false; } RedisService::set($cacheKey.'_lock', ['cart_id'=>$cartId], rand(3,5)); // 去除其他店铺购物车 $info = $this->model->where(['id'=>$cartId, 'user_id' => $userId, 'mark' => 1])->first(); if(empty($info)){ RedisService::clear($cacheKey.'_lock'); $this->error = '数据不存在'; return false; } if($num<=0){ $this->model->where(['id' => $cartId])->update(['mark'=>0,'num'=>0,'update_time'=>time()]); }else{ $this->model->where(['id' => $cartId])->update(['num' => $num,'update_time' => time()]); } RedisService::clear($cacheKey.'_lock'); RedisService::clear("caches:goods:cartCount:{$userId}"); return ['id' => $cartId, 'count' => $this->getCount($userId)]; } /** * 删除购物车 * @param $userId * @param $cartId * @return array|false */ public function deleteCart($userId, $ids=[]) { if($ids){ $this->model->where(['user_id'=>$userId,'mark'=>1])->whereIn('id', $ids)->update(['mark'=>0,'num'=>0,'update_time'=>time()]); }else{ $this->model->where(['user_id'=>$userId,'mark'=>1])->update(['mark' => 0,'num'=>0,'update_time' => time()]); } $this->error = '删除成功'; RedisService::clear("caches:goods:cartCount:{$userId}"); return ['ids' => $ids, 'count' => $this->getCount($userId)]; } /** * 购物车数量 * @param $userId * @return array|mixed */ public function getCount($userId) { $cacheKey ="caches:goods:cartCount:{$userId}"; $data = RedisService::get($cacheKey); if($data){ return $data; } $count = $this->model->where(['user_id' => $userId, 'status' => 1, 'mark' => 1])->count('id'); if($count){ RedisService::set($cacheKey, $count, 300); } return $count; } }