// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\AgentModel; use App\Models\GoodsCategoryModel; use App\Models\GoodsModel; use App\Models\GoodsSkuModel; use App\Models\MemberModel; use App\Models\MerchantModel; use App\Models\OrderModel; use App\Models\ShopModel; use App\Models\TradeModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use App\Services\SupplyService; use App\Services\WalletService; use BN\Red; use Illuminate\Support\Facades\DB; /** * 商品管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class GoodsService * @package App\Services\Api */ class GoodsService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * GoodsService constructor. */ public function __construct() { $this->model = new GoodsModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 商品列表 * @param $params * @param int $pageSize * @param int $userId * @return array */ public function getDataList($params, $pageSize = 12, $userId = 0) { $model = $this->model->with(['skuList'])->from('goods as a') ->where(['a.status' => 1, 'a.mark' => 1]) ->where('a.cost_price', '>', 0) ->where(function ($query) use ($params) { $supplyType = isset($params['supply_type']) ? intval($params['supply_type']) : 0; if ($supplyType > 0) { $query->where('a.supply_type', $supplyType); } $cateId = isset($params['cate_id']) ? intval($params['cate_id']) : 0; if ($cateId > 0) { $subIds = GoodsCategoryModel::where(['pid'=> $cateId,'mark'=>1,'status'=>1])->pluck('cate_id'); $query->where(function($query) use($cateId,$subIds){ if($subIds){ $query->whereIn('a.cate_id', $subIds) ->orWhere('a.cate_id', $cateId); }else{ $query->where('a.cate_id', $cateId); } }); } }) ->where(function ($query) use ($params) { $keyword = isset($params['kw']) ? $params['kw'] : ''; if ($keyword) { $query->where('a.goods_name', 'like', "%{$keyword}%") ->orWhere('a.spu_name', 'like', "%{$keyword}%") ->orWhere('a.tag', 'like', "%{$keyword}%"); } }) ->select(['a.*']); // 排序 $sortType = isset($params['sort_type'])? $params['sort_type'] : 1; if ($sortType == 2){ $model = $model->orderBy('a.is_recommend','asc')->orderBy('a.sales', 'desc'); } $list = $model->orderBy('a.create_time', 'desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { $locale = RedisService::get("caches:locale:lang_{$userId}"); $locale = $locale ? $locale : session('locale_lang'); $locale = $locale ? $locale : 'zh-cn'; $supplyList = config('goods.supplyList'); $usdtPrice = RedisService::get("caches:wallets:usdt_rate"); if($usdtPrice<=0){ $usdtCnyPrice = ConfigService::make()->getConfigByCode('usdt_cny_price', 7.2); $usdtPrice = $usdtCnyPrice>0 && $usdtCnyPrice< 100? $usdtCnyPrice : 0; } $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; foreach ($list['data'] as &$item) { $item['detail_img'] = isset($item['detail_img']) && $item['detail_img'] ? json_decode($item['detail_img'], true) : []; $item['supply_name'] = isset($supplyList[$item['supply_type']]) ? $supplyList[$item['supply_type']] : ''; $item['usdt_price'] = $usdtPrice; $item['xd_price_rate'] = $xdPrice; $item['original_price'] = $item['cost_price']; $item['cost_price'] = $usdtPrice > 0 ? moneyFormat($item['cost_price'] / $usdtPrice * $xdPrice, 2) : $item['cost_price']; } unset($item); } else { $this->updateGoods(); } return [ 'total' => isset($list['total']) ? $list['total'] : 9, 'pageSize' => $pageSize, 'list' => isset($list['data']) ? $list['data'] : [], ]; } /** * 详情 * @param $id * @return array */ public function getInfo($goodsId, $userId=0) { $field = ['a.*']; $info = $this->model->from('goods as a')->with(['category','skuList']) ->where(['a.goods_id'=> $goodsId,'a.status'=>1,'a.mark'=>1]) ->select($field) ->first(); $info = $info? $info->toArray() : []; if($info){ if(isset($info['main_img'])){ $info['main_img'] = $info['main_img']? get_image_url($info['main_img']) : ''; } if(isset($info['detail_img'])){ $info['detail_img'] = $info['detail_img']? json_decode($info['detail_img'], true) : []; } $supplyList = config('goods.supplyList'); $info['supply_name'] = isset($supplyList[$info['supply_type']]) ? $supplyList[$info['supply_type']] : ''; $usdtPrice = RedisService::get("caches:wallets:usdt_rate"); if($usdtPrice<=0){ $usdtCnyPrice = ConfigService::make()->getConfigByCode('usdt_cny_price', 7.2); $usdtPrice = $usdtCnyPrice>0 && $usdtCnyPrice< 100? $usdtCnyPrice : 0; } $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; $info['usdt_price_rate'] = $usdtPrice; $info['xd_price'] = $xdPrice; if(isset($info['cost_price']) && $info['cost_price']){ $info['cost_price'] = moneyFormat($info['cost_price']/$usdtPrice * $xdPrice,2); } if(isset($info['sku_list']) && $info['sku_list']){ foreach ($info['sku_list'] as &$v){ $v['detail_img'] = $v['detail_img']? json_decode($v['detail_img'], true) : []; $v['attr'] = $v['attr']? json_decode($v['attr'], true) : []; $v['main_img'] = $v['main_img']? get_image_url($v['main_img']) : ''; $v['cost_prict'] = $v['retail_price']? moneyFormat($v['retail_price']/$usdtPrice * $xdPrice,2) : $info['cost_price']; } unset($v); } $this->updateView($userId, $goodsId); } return $info; } public function getFreight($userId, $addressId) { $cacheKey = "caches:goods:freight:{$userId}_{$addressId}"; $data = RedisService::get($cacheKey); if($data){ return $data; } $result = SupplyService::make()->getApiData('getFreight',['address_id'=> $addressId]); } /** * 更新浏览量 * @param $userId * @param $dynamicId * @return array|mixed */ public function updateView($userId, $id) { $cacheKey = "caches:goods:views:u{$userId}_d{$id}"; $data = RedisService::get($cacheKey); if($data){ return false; } $data = $this->model->where(['goods_id'=> $id])->update(['views'=>DB::raw('views + 1'),'update_time'=>time()]); RedisService::set($cacheKey, $id, rand(1,3)*7200); return $data; } /** * 更新商品SKU数据到本地 * @param int $pageSize * @param $params 参数 * @return array|false */ public function updateGoodsSku($pageSize = 100, $params = []) { $cacheKey = "caches:supply:goods_sku_update_{$pageSize}"; if (RedisService::get($cacheKey)) { $this->error = 1047; return false; } $page = RedisService::get($cacheKey . '_page'); $page = $page ? $page + 1 : 1; $lastDate = GoodsSkuModel::where(['mark' => 1])->orderBy('last_update_at', 'desc')->value('last_update_at'); $params = [ 'limit' => $pageSize > 0 ? $pageSize : 50, 'page' => $page, 'date' => $lastDate ? $lastDate : '', // 开始时间 ]; $goods = []; $updated = 0; $error = 0; $datas = SupplyService::make()->getApiData('getSkuUpdate', $params); if ($datas && $datas['list']) { foreach ($datas['list'] as &$item) { $goodsId = isset($item['goods_id']) ? $item['goods_id'] : 0; $goodsSkuSn = isset($item['sku_sn']) ? $item['sku_sn'] : ''; $changeType = isset($item['change_type']) ? $item['change_type'] : ''; if ($goodsId && $goodsSkuSn && $changeType) { $skuInfo = SupplyService::make()->getApiData('getSkuDetail', ['sku_sn' => $goodsSkuSn]); if ($skuInfo) { $updateData = ['goods_id'=>$goodsId,'sku_sn'=> $goodsSkuSn,'remark'=>'SKU更新','update_time' => time(),'mark'=>1, 'last_update_at' => $item['update_time']]; if (isset($skuInfo['sku_name']) && $skuInfo['sku_name']) { $updateData['sku_name'] = $skuInfo['sku_name']; } if (isset($skuInfo['main_img']) && $skuInfo['main_img']) { $updateData['main_img'] = $skuInfo['main_img']; } if (isset($skuInfo['spu_sn']) && $skuInfo['spu_sn']) { $updateData['spu_sn'] = $skuInfo['spu_sn']; } if (isset($skuInfo['sku_id']) && $skuInfo['sku_id']) { $updateData['sku_id'] = intval($skuInfo['sku_id']); } if (isset($skuInfo['status']) && $skuInfo['status']) { $updateData['status'] = intval($skuInfo['status']); } if (isset($skuInfo['retail_price']) && $skuInfo['retail_price']) { $updateData['retail_price'] = floatval($skuInfo['retail_price']); } if (isset($skuInfo['plat_price']) && $skuInfo['plat_price']) { $updateData['plat_price'] = floatval($skuInfo['plat_price']); } if (isset($skuInfo['detail_img']) && $skuInfo['detail_img']) { $updateData['detail_img'] = json_encode($skuInfo['detail_img'], 256); } if (isset($skuInfo['attr']) && $skuInfo['attr']) { $updateData['attr'] = json_encode($skuInfo['attr'], 256); } if(GoodsSkuModel::where(['goods_id' => $goodsId])->value('id')){ GoodsSkuModel::where(['goods_id' => $goodsId, 'mark' => 1])->update($updateData); $updated++; }else{ $error++; } } else { $error++; } } else { $error++; } } unset($item); RedisService::set($cacheKey . '_page', $page, rand(300, 600)); }else{ RedisService::set($cacheKey . '_page', 0, rand(300, 600)); } return ['count' => count($goods), 'updated' => $updated, 'errorCount' => $error,'page'=>$page]; } /** * 更新商品 * @param int $pageSize * @param $params 参数 * @return array|false */ public function updateGoods($pageSize = 100, $params = []) { set_time_limit(0); $cacheKey = "caches:supply:goods_list_update_{$pageSize}"; if (RedisService::get($cacheKey)) { $this->error = 1047; return false; } $page = RedisService::get($cacheKey . '_page'); $page = $page ? $page + 1 : 1; $lastTime = $this->model->where(['mark' => 1])->orderBy('create_time', 'desc')->value('create_time'); $params = [ 'limit' => $pageSize > 0 ? $pageSize : 50, 'page' => $page, 'status' => isset($params['status']) ? $params['status'] : 1, // 状态:0-全部,1-上架的,2-下架的 'supply_type' => isset($params['supply_type']) ? $params['supply_type'] : 0, // 渠道商 'title' => isset($params['title']) ? $params['title'] : '', // 标题关键词 'cate_id' => isset($params['cate_id']) ? $params['cate_id'] : '', // 分类ID 'begin_time' => $lastTime ? $lastTime : '', // 开始时间 ]; $goods = []; $skus = []; $updated = 0; $error = 0; $datas = SupplyService::make()->getApiData('getGoodsList', $params); if ($datas && $datas['list']) { foreach ($datas['list'] as &$item) { $goodsId = isset($item['goods_id']) ? $item['goods_id'] : 0; if ($goodsId && !$this->checkGoods($goodsId)) { $info = $this->getApiInfo($goodsId); if ($info) { $skuList = isset($info['sku_list']) ? $info['sku_list'] : []; $goods[] = [ 'goods_id' => $goodsId, 'supply_type' => isset($item['supply_type']) ? $item['supply_type'] : 0, 'spu_sn' => isset($item['spu_sn']) ? $item['spu_sn'] : '', 'spu_name' => isset($info['spu_name']) ? $info['spu_name'] : '', 'main_img' => isset($info['main_img']) ? $info['main_img'] : '', 'detail_img' => isset($info['detail_img']) ? json_encode($info['detail_img'], 256) : '', 'goods_name' => isset($item['goods_name']) ? $item['goods_name'] : '', 'brand_name' => isset($info['brand_name']) ? $info['brand_name'] : '', 'limit_num' => isset($info['limit_num']) ? intval($info['limit_num']) : 0, 'lowest_num' => isset($info['lowest_num']) ? intval($info['lowest_num']) : 1, 'cost_price' => isset($info['cost_price']) ? floatval($info['cost_price']) : 0, 'retail_price' => isset($info['retail_price']) ? floatval($info['retail_price']) : 0, 'profit' => isset($info['profit']) ? floatval($info['profit']) : 0, 'sku_list' => $skuList? json_encode($skuList,256):'', 'sku_total' => isset($info['sku_total']) ? intval($info['sku_total']) : 0, 'tag' => isset($item['tag']) ? json_encode($item['tag'], 256) : '', 'status' => isset($info['status']) ? intval($info['status']) : 1, 'cate_id' => isset($item['cate_id']) ? intval($item['cate_id']) : 0, 'last_update_at' => isset($info['update_time']) ? $info['update_time'] : (isset($item['time']) && $item['time'] ? $item['time'] : date('Y-m-d H:i:s')), 'create_time' => time(), ]; foreach($skuList as $v){ $skus[] = [ 'sku_id'=> isset($v['sku_id'])? $v['sku_id'] : 0, 'goods_id'=> $goodsId, 'spu_sn'=> isset($v['spu_sn'])? $v['spu_sn'] : '', 'sku_sn'=> isset($v['sku_sn'])? $v['sku_sn'] : '', 'sku_name'=> isset($v['sku_name'])? $v['sku_name'] : '', 'main_img'=> isset($v['main_img'])? $v['main_img'] : '', 'status'=> isset($v['status'])? $v['status'] : 1, 'source_type'=> isset($v['source_type'])? $v['source_type'] : 0, 'retail_price'=> isset($v['retail_price'])? floatval($v['retail_price']) : 0, 'plat_price'=> isset($v['plat_price'])? floatval($v['plat_price']) : 0, 'profit'=> isset($v['profit'])? floatval($v['profit']) : 0, 'last_update_at'=> isset($v['update_time'])? $v['update_time'] : date('Y-m-d H:i:s'), 'detail_img'=> isset($v['detail_img'])? json_encode($v['detail_img'],256) : '', 'attr'=> isset($v['attr'])? json_encode($v['attr'],256) : '', 'remark'=>'SKU同步创建', ]; } $updated++; } else { $error++; } } else { $error++; } } unset($item); } else { RedisService::set($cacheKey . '_page', 0, rand(300, 600)); } if ($goods) { RedisService::set($cacheKey . '_page', $page, rand(300, 600)); RedisService::set($cacheKey, $goods, rand(5, 10)); DB::beginTransaction(); try { $this->model->insertAll($goods); if($skus){ GoodsSkuModel::insert($skus); } DB::commit(); }catch (\Exception $exception){ DB::rollBack(); } } return ['count' => count($goods), 'updated' => $updated, 'errorCount' => $error,'page'=>$page]; } /** * 更新商品分类 * @param int $pid 上级ID * @param int $pageSize * @param $params 参数 * @return array|false */ public function updateGoodsCategory($pid=0, $pageSize = 200, $params = []) { set_time_limit(0); $cacheKey = "caches:supply:goods_category_update_{$pid}_{$pageSize}"; if (RedisService::get($cacheKey)) { $this->error = 1047; return false; } $params = [ 'limit' => $pageSize > 0 ? $pageSize : 50, 'page' => 1, 'pid' => $pid, // 上级ID ]; $categorys = []; $updated = 0; $error = 0; $datas = SupplyService::make()->getApiData('getGoodsCategory', $params); if ($datas && $datas['data']) { foreach ($datas['data'] as &$item) { $cateId = isset($item['id']) ? $item['id'] : 0; if ($cateId && !$this->checkCategory($cateId)) { $categorys[] = [ 'cate_id' => $cateId, 'name' => isset($item['name']) ? $item['name'] : '', 'pid' => isset($item['pid']) ? intval($item['pid']) : 0, 'create_time' => time(), ]; $updated++; } else { $error++; } } unset($item); } if ($categorys) { RedisService::set($cacheKey, $categorys, rand(5, 10)); GoodsCategoryModel::insert($categorys); } return ['count' => count($categorys), 'updated' => $updated,'pid'=>$pid, 'errorCount' => $error]; } /** * 验证 * @param $goodsId * @return bool */ public function checkGoods($goodsId) { $cacheKey = "caches:goods:check_{$goodsId}"; if (RedisService::get($cacheKey) || RedisService::exists($cacheKey)) { return true; } $data = $this->model->where(['goods_id' => $goodsId, 'mark' => 1])->value('id'); RedisService::set($cacheKey, $data, rand(30, 60)); return $data; } /** * 验证分类 * @param $cateId * @return bool */ public function checkCategory($cateId) { $cacheKey = "caches:goods:category_check_{$cateId}"; if (RedisService::get($cacheKey) || RedisService::exists($cacheKey)) { return true; } $data = GoodsCategoryModel::where(['cate_id' => $cateId, 'mark' => 1])->value('id'); RedisService::set($cacheKey, $data, rand(30, 60)); return $data; } /** * 接口商品详情 * @param $goodsId 商品ID * @param int $isReal 是否实时数据,0-是,1-否 * @param int $type 数据类型:0-详情,1-仅SKU数据 * @return array|false|mixed|string */ public function getApiInfo($goodsId, $isReal = 0, $type = 0) { $cacheKey = "caches:goods:detail_{$goodsId}_{$isReal}_{$type}"; $info = RedisService::get($cacheKey); if (empty($info)) { $params = [ 'goods_id' => $goodsId, 'is_real' => $isReal, 'type' => $type ]; $info = SupplyService::make()->getApiData('getGoodsDetail', $params); if ($info) { RedisService::set($cacheKey, $info, rand(5, 10)); } } return $info; } public function apiCategory($num) { } }