assign('breadcrumb1','基础信息'); $this->assign('breadcrumb2','产品管理'); } /** * 首页列表 * * */ public function index(Model $Model,City $City,ProductCity $ProductCity,OrdersProduct $OrdersProduct,AdminHistory $AdminHistory,Business $Business){ // 接受参数 $code = request('product_code',''); $name = request('name',''); $status = request('status'); $startTime = request('start_time',''); $businessId = request('business_id',''); $cityIds = request('city_ids',[]); // 编码转ID $id = $code ? $Model->codeToId($code) : 0; // 查询条件 $map = []; // 编码ID if( $id ) $map[] = ['product.id','=',$id]; if( $businessId ) $map[] = ['product.business_id','=',$businessId]; if( $name ) $map[] = ['product.name','like','%'.$name.'%']; if( $startTime ) $map[] = ['product.insert_time','>=',Carbon::createFromFormat('Y-m-d',$startTime)->startOfDay()->getTimestamp()]; if( $startTime ) $map[] = ['product.insert_time','<=',Carbon::createFromFormat('Y-m-d',$startTime)->endOfDay()->getTimestamp()]; if( !is_null($status) ) $map[] = ['product.status','=',$status]; // 当前登录的角色数据 $session = session('userRule') ? session('userRule') : ['business_id'=>0,'menu_type'=>0,'data_type'=>0]; // 是否存在对应的商业公司ID if ( $session['business_id'] ) $map[] = ['product.business_id','=',$session['business_id']]; // 数据类型 $shopIds = ($session['menu_type'] == 1 && $session['data_type'] == 2) ? Business::query()->where('leader_uid',$session['admin_uid'])->pluck('id')->toArray() : []; // 查询数据 $list = $Model->query()->join('product_city','product_city.product_id','=','product.id'); if( $cityIds ) $list = $list->whereIn('product_city.city_id',$cityIds); if( $shopIds ) $list = $list->whereIn('product.business_id',$shopIds); $list = $list->groupBy('product.id') ->where($map) ->orderBy('product.sort') ->orderByDesc('product.id') ->select(['product.*']) ->paginate(request('limit',config('page_num',10)))->appends(request()->all()); // 统计销量 $salesList = $OrdersProduct->query()->where([['status','<>',4]])->whereIn('product_id',array_column($list->items(),'id'))->groupBy('product_id')->select([DB::raw('sum(`buy_num`) as sales_total'),'product_id'])->pluck('sales_total','product_id')->toArray(); // 循环处理数据 foreach ($list as $key => $value) { // 判断总库存 if( !$value['stock_total'] ) { // 以首次添加时的为准 $value['stock_total']= (int) $AdminHistory->query()->where([['table_name','=','product'],['primary_id','=',$value['id']],['notes_type','=',1],['column_name','=','stock']])->orderBy('update_time')->value('after_value'); // 修改库存 $Model->edit($value['id'],['stock_total'=>$value['stock_total']]); } // id转编号 $value['product_code'] = $Model->idToCode($value['id']); $value['business_name']= Business::query()->where('id',$value['business_id'])->value('name'); // id转编号 $cityName = []; // 获取城市列表 $cityIds = $ProductCity->query()->where([['product_id','=',$value['id']]])->pluck('city_id'); // 如果有的话 if( $cityIds ) { // 返回结果 foreach ($cityIds as $cityId) { // 城市ID if( $cityId == 1 ) continue; // 获取城市名 $cityName[] = $City->getOne($cityId,'name'); } } // 销量统计 $value['sales_total'] = isset($salesList[$value['id']])?$salesList[$value['id']]:0; // 城市 $value['city_name'] = implode('、',$cityName); // 重组 $list[$key] = $value; } // 获取列表 $cityList = $City->getCityList(); $businessList = $Business->getListByAdmin(); // 分配数据 $this->assign('empty', '~~暂无数据'); $this->assign('cityList',$cityList); $this->assign('businessList',$businessList); $this->assign('list', $list); // 加载模板 return $this->fetch(); } /** * 获取小程序海报 * */ public function get_poster(Model $Model){ // 接收参数 $id = request('id',0); // // 查询用户 $oldData = $Model->where(['id'=>$id])->first(); // // 错误告知 if( !$oldData ) return $this->error('查无数据'); // url有效期 $urlLink = '';//$this->getUrlLink($id); // 获取分享海报图片 $result = $this->getShareImage('id='.$id,$oldData); // 错误提示 if( isset($result['error']) ) return $this->error($result['error']); // 分配数据 $this->assign('image',$result); $this->assign('urlLink',$urlLink); $this->assign('oldData',$oldData); $this->assign('crumbs','海报'); // 加载模板 return $this->fetch(); } /** * 获取小程序链接 * */ private function getUrlLink($id){ // 结果数据 $link = cache('admin:product:urllink:product_id'.$id); // 不存在数据 if ( is_null($link) ) { // 从数据库获取数据 $link = Mini::getUrlLink('pages/product/index','product_id='.$id); // 存起来 cache(['admin:product:urllink:product_id'.$id=>$link],$link ? now()->addDays(23) : now()->addMinutes(3)); } // 返回结果 return $link; } /** * 获取分享海报图片 * @param int $scene 场景值 * */ private function getShareImage($scene,$oldData){ // 尝试执行 try { // 加载图片 $image = Image::make(public_path('uploads/images/poster/').'product.png'); // 产品缩略图 $thumb = Image::make(path_compat($oldData['thumb']))->resize(1000,1000); // 设置文字样式(字体、大小、颜色等) $fontPath = public_path().'/fonts/msyh14.ttf';// 指定字体文件路径 // 生成小程序二维码 $qrcode = Mini::getUnlimit($scene,['page'=>'pages/product/index','width'=>280,'is_hyaline'=>true]); // 错误提示 if( isset($qrcode['error']) ) return $qrcode; // 加载图片 $qrcode = Image::make($qrcode)->resize(250,250); // 插入图片 $image->insert($thumb,'top-center',0,130); // 插入图片 $image->insert($qrcode,'bottom-left',120,120); // 给图片写入文字 $image->text('¥'.$oldData['price'], 360,1280,function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(88); // 字体大小 $font->color('#333333'); $font->align('left'); }); // 给图片写入文字 $image->text($oldData['name'], 120,1380,function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(48); // 字体大小 $font->color('#333333'); $font->align('left'); }); // 转码成字符串 $image = $image->encode('jpg', 90)->__toString(); // 转base64 $base64 = 'data:image/jpg;base64,' . base64_encode($image); // 返回结果 return $base64; } catch (\Throwable $th) { // 错误提示 return ['error'=>$th->getMessage()]; } } /** * 添加 * * */ public function add(Request $request, Model $Model, WeiBanTags $WeiBanTags, ProductPhoto $ProductPhoto, Producer $Producer, Business $Business, ProductType $ProductType, ProductSpec $ProductSpec, ProductAttr $ProductAttr, ProductSkus $ProductSkus, City $City, ProductCity $ProductCity){ if( request()->isMethod('post') ){ // 验证参数 $request->scene('add')->validate(); // 组合数据 $data['name'] = request('name',''); $data['thumb'] = request('thumb',''); $data['poster'] = request('poster',''); $data['spec'] = request('spec',''); $data['price'] = request('price',0); $data['market_price'] = request('market_price',0); $data['producer_id'] = request('producer_id',0); $data['business_id'] = request('business_id',0); $data['quota'] = request('quota',0); $data['min_quota'] = request('min_quota',0); $data['quota_start'] = request('quota_start',''); $data['quota_end'] = request('quota_end',''); $data['puton_time'] = request('puton_time',''); $data['putoff_time'] = request('putoff_time',''); $data['stock'] = request('stock',0); $data['status'] = 1; $data['admin_uid'] = admin('uid'); $description = request('description',''); $attr = request('attr',[]); $skuList = request('sku',[]); $cityIds = request('city_ids',[]); $photoList = request('photo_list',[]); $tagScope = request('tag_scope',[]); $data['tag_scope'] = implode(',',$tagScope); $tagExclude = request('tag_exclude',[]); $data['tag_exclude'] = implode(',',$tagExclude); // 循环 foreach ($photoList as $key => $value) { if( !$value ) unset($photoList[$key]); } $photoList = array_values($photoList); // 如果没有选择,则意味着全部 $cityIds = $cityIds ? $cityIds : [1]; $data['quota_start'] = $data['quota_start'] ? strtotime($data['quota_start']) : 0; $data['quota_end'] = $data['quota_end'] ? strtotime($data['quota_end']) : 0; $data['puton_time'] = $data['puton_time'] ? strtotime($data['puton_time']) : 0; $data['putoff_time'] = $data['putoff_time'] ? strtotime($data['putoff_time']) : 0; // 限购提示 if( !$data['thumb'] ) return json_send(['code'=>'error','msg'=>'请上传产品主图','data'=>['error'=>'请上传产品主图']]); // 限购提示 if( $attr && !$skuList ) return json_send(['code'=>'error','msg'=>'规格属性存在时,请填写SKU','data'=>['error'=>'规格属性存在时,请填写SKU']]); // 限购提示 if( $data['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'限购必填限购时间','data'=>['error'=>'限购必填限购时间']]); // 限购提示 if( $data['quota'] && $data['min_quota'] > $data['quota'] ) return json_send(['code'=>'error','msg'=>'起购数量请勿大于限购数量','data'=>['error'=>'起购数量请勿大于限购数量']]); // SKU存在的时候,判断限购数量 if( $skuList ) { // 循环处理 foreach ($skuList as $attrNames => $value) { // SKU限购,所以限购时间也必须填 if( $value['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'SKU限购时,请填限购时间','data'=>['error'=>'SKU限购时,请填限购时间']]); // 限购提示 if( $value['quota'] && $value['min_quota'] > $value['quota'] ) return json_send(['code'=>'error','msg'=>$attrNames.'起购数量请勿大于限购数量','data'=>['error'=>$attrNames.'起购数量请勿大于限购数量']]); // 提示起购数量异常,如果总起购数量小于SKU起购数量,提示 if( $value['min_quota'] && $value['min_quota'] < $data['min_quota'] ) return json_send(['code'=>'error','msg'=>'SKU的起购数量不能小于总起购数量','data'=>['error'=>'SKU的起购数量不能小于总起购数量']]); } // 限购数量 $quota = array_sum(array_column($skuList,'quota')); // 提示限购数量异常 if( $data['quota']&& $data['quota'] < $quota ) return json_send(['code'=>'error','msg'=>'总限购数量不能小于SKU的限购数量','data'=>['error'=>'总限购数量不能小于SKU的限购数量']]); } // 上下架 if( $data['puton_time'] ) { // 下架时间必填 if( !$data['putoff_time'] ) return json_send(['code'=>'error','msg'=>'请填写自动下架时间','data'=>['error'=>'自动上架请填写下架时间']]); // 下架时间必填 if( $data['putoff_time'] <= $data['puton_time'] ) return json_send(['code'=>'error','msg'=>'下架时间请晚于上架时间','data'=>['error'=>'下架时间请晚于上架时间']]); } // 总库存 if( $skuList ) $data['stock'] = array_sum(array_column($skuList,'stock')); // 总库存 $data['stock_total'] = $data['stock']; // 总库存提醒 if( $data['stock_total'] <= 0 ) return json_send(['code'=>'error','msg'=>'请设置库存','data'=>['error'=>'请设置库存']]); // 获取规格属性 $specAttr = $this->getSpecAttr($attr,$ProductSpec,true); // 开启事务 DB::beginTransaction(); try { // 写入 $id = $Model->add($data); // 提示新增失败 if( !$id ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'新增失败']); } // 组合数据 foreach ($specAttr as $key => $value) { // 查询结果 $value['id'] = $ProductAttr->upsertByName($value,$id); // 提示新增失败 if( !$value['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'商品属性新增失败']); } // 重组 $specAttr[$key] = $value; } // 图册 foreach ($photoList as $key => $value) { // 整理数据 $value = ['sort'=>$key,'thumb'=>$value,'product_id'=>$id,'insert_time'=>time(),'update_time'=>time()]; // 重新整理 $photoList[$key] = $value; } // 存在图册 if( $photoList ) { // 写入失败 $result = $ProductPhoto->query()->insert($photoList); // 提示新增失败 if( !$result ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'商品图册写入失败']); } } // 循环SKU foreach ($skuList as $attrNames => $value) { // 属性ID值 $value['attr_ids'] = []; // 规格属性值组合 $value['attr_names']= $attrNames; // 切割成数据 $names = explode(',',$attrNames); // 循环处理 foreach ($names as $name) { foreach ($specAttr as $vv) { if( $name == $vv['name'] ) { // 提示新增失败 if( !$vv['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'属性SKU匹配失败']); } $value['attr_ids'][] = $vv['id']; } } } // 转成好存储的数据 $value['attr_ids'] = implode(',',$value['attr_ids']); // 转成好存储的数据 $value['product_id'] = $id; // 转成好存储的数据 $value['sku_thumb'] = (string)$value['sku_thumb']; // 转成好存储的数据 $value['stock_total']= $value['stock']; // 转成好存储的数据 $value['insert_time']= time(); // 转成好存储的数据 $value['update_time']= time(); // SKU结果 $skuList[$attrNames] = $value; } // 循环城市范围 foreach ($cityIds as $key => $value) { // 重组数据 $cityIds[$key] = ['city_id'=>$value,'product_id'=>$id,'insert_time'=>time(),'update_time'=>time()]; } // 写入城市范围 $ProductCity->query()->insert($cityIds); // 返回结果 $result = $ProductSkus->insert($skuList); // 提示新增失败 if( !$result ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'SKU插入失败']); } // 更新内容 $Model->updateDesc($id,$description); // 提交 DB::commit(); // 记录行为 $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data); // 告知结果 return json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']); } catch (\Throwable $th) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'系统异常,写入失败','data'=>$th->getMessage()]); } } // 获取类型数据 $typeList = $ProductType->getList(); $cityList = $City->getCityList(); $businessList = $Business->getListByAdmin(); $producerList = $Producer->getList(); // 标签列表 $tagData = $WeiBanTags->query()->groupBy('group')->groupBy('name')->get(['group','name'])->toArray(); // 标签列表 $tagList = []; // 循环数据 foreach ($tagData as $value) { $tagList[$value['group']][] = $value['name']; } // 分配数据 $this->assign('crumbs','新增'); $this->assign('tagList',$tagList); $this->assign('typeList',$typeList); $this->assign('cityList',$cityList); $this->assign('businessList',$businessList); $this->assign('producerList',$producerList); // 加载模板 return $this->fetch(); } /** * 编辑 * * */ public function edit(Request $request, Model $Model, WeiBanTags $WeiBanTags, ProductPhoto $ProductPhoto, Producer $Producer, Business $Business, ProductType $ProductType, ProductSpec $ProductSpec, ProductAttr $ProductAttr, ProductSkus $ProductSkus, City $City, ProductCity $ProductCity){ // 接收参数 $id = request('id',0); // 查询数据 $oldData = $Model->where(['id'=>$id])->first(); // 修改 if(request()->isMethod('post')){ // 验证参数 $request->scene('edit')->validate(); // 组合数据 $id = request('id',0); $data['name'] = request('name',''); $data['thumb'] = request('thumb',''); $data['poster'] = request('poster',''); $data['spec'] = request('spec',''); $data['price'] = request('price',0); $data['market_price'] = request('market_price',0); $data['quota'] = request('quota',0); $data['min_quota'] = request('min_quota',0); $data['quota_start'] = request('quota_start',''); $data['quota_end'] = request('quota_end',''); $data['puton_time'] = request('puton_time',''); $data['putoff_time'] = request('putoff_time',''); $data['producer_id'] = request('producer_id',0); $data['business_id'] = request('business_id',0); $data['stock'] = request('stock',0); $data['status'] = 1; $description = request('description',''); $attr = request('attr',[]); $skuList = request('sku',[]); $cityIds = request('city_ids',[]); $photoList = request('photo_list',[]); $tagScope = request('tag_scope',[]); $data['tag_scope'] = implode(',',$tagScope); $tagExclude = request('tag_exclude',[]); $data['tag_exclude'] = implode(',',$tagExclude); // 循环 foreach ($photoList as $key => $value) { if( !$value ) unset($photoList[$key]); } $photoList = array_values($photoList); // 如果没有选择,则意味着全部 $cityIds = $cityIds ? $cityIds : [1]; $data['quota_start'] = $data['quota_start'] ? strtotime($data['quota_start']) : 0; $data['quota_end'] = $data['quota_end'] ? strtotime($data['quota_end']) : 0; $data['puton_time'] = $data['puton_time'] ? strtotime($data['puton_time']) : 0; $data['putoff_time'] = $data['putoff_time'] ? strtotime($data['putoff_time']) : 0; // 限购提示 if( !$data['thumb'] ) return json_send(['code'=>'error','msg'=>'请上传产品主图','data'=>['error'=>'请上传产品主图']]); // 限购提示 if( $attr && !$skuList ) return json_send(['code'=>'error','msg'=>'规格属性存在时,请填写SKU','data'=>['error'=>'规格属性存在时,请填写SKU']]); // 限购提示 if( $data['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'限购必填限购时间','data'=>['error'=>'限购必填限购时间']]); // 限购提示 if( $data['quota'] && $data['min_quota'] > $data['quota'] ) return json_send(['code'=>'error','msg'=>'起购数量请勿大于限购数量','data'=>['error'=>'起购数量请勿大于限购数量']]); // SKU存在的时候,判断限购数量 if( $skuList ) { // 循环处理 foreach ($skuList as $attrNames => $value) { // SKU限购,所以限购时间也必须填 if( $value['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'SKU限购时,请填限购时间','data'=>['error'=>'SKU限购时,请填限购时间']]); // 限购提示 if( $value['quota'] && $value['min_quota'] > $value['quota'] ) return json_send(['code'=>'error','msg'=>$attrNames.'起购数量请勿大于限购数量','data'=>['error'=>$attrNames.'起购数量请勿大于限购数量']]); // 提示起购数量异常,如果总起购数量小于SKU起购数量,提示 if( $value['min_quota'] && $value['min_quota'] < $data['min_quota'] ) return json_send(['code'=>'error','msg'=>'SKU的起购数量不能小于总起购数量','data'=>['error'=>'SKU的起购数量不能小于总起购数量']]); } // 限购数量 $quota = array_sum(array_column($skuList,'quota')); // 提示限购数量异常 if( $data['quota']&& $data['quota'] < $quota ) return json_send(['code'=>'error','msg'=>'总限购数量不能小于SKU的限购数量','data'=>['error'=>'总限购数量不能小于SKU的限购数量']]); } // 上下架 if( $data['puton_time'] ) { // 下架时间必填 if( !$data['putoff_time'] ) return json_send(['code'=>'error','msg'=>'请填写自动下架时间','data'=>['error'=>'自动上架请填写下架时间']]); // 下架时间必填 if( $data['putoff_time'] <= $data['puton_time'] ) return json_send(['code'=>'error','msg'=>'下架时间请晚于上架时间','data'=>['error'=>'下架时间请晚于上架时间']]); } // 总库存 if( $skuList ) $data['stock'] = array_sum(array_column($skuList,'stock')); // 总库存 $data['stock_total'] = $data['stock']; // 总库存提醒 if( $data['stock_total'] <= 0 ) return json_send(['code'=>'error','msg'=>'请设置库存','data'=>['error'=>'请设置库存']]); // 获取规格属性 $specAttr = $this->getSpecAttr($attr,$ProductSpec,true); // 开启事务 DB::beginTransaction(); try { // 写入 $result = $Model->edit($id,$data); // 提示新增失败 if( !$result ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'修改失败']); } // 获取旧图册 $oldPhoto = $ProductPhoto->getListByProductId($id); // 循环个数 for ($i=0; $i < 4; $i++) { // 如果存在旧数据与新数据,修改 if( isset($oldPhoto[$i]) && isset($photoList[$i]) ) $ProductPhoto->query()->where([['product_id','=',$id],['sort','=',$i]])->update(['thumb'=>(string)$photoList[$i],'update_time'=>time()]); // 如果存在旧数据,不存在新数据,删除 if( isset($oldPhoto[$i]) && !isset($photoList[$i]) ) $ProductPhoto->query()->where([['product_id','=',$id],['sort','=',$i]])->delete(); // 如果不存在旧数据,存在新数据,新增 if( !isset($oldPhoto[$i]) && isset($photoList[$i]) ) $ProductPhoto->add(['sort'=>$i,'product_id'=>$id,'thumb'=>(string)$photoList[$i],'insert_time'=>time(),'update_time'=>time()]); } // 组合数据 foreach ($specAttr as $key => $value) { // 查询结果 $value['id'] = $ProductAttr->upsertByName($value,$id); // 提示新增失败 if( !$value['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'商品属性新增失败']); } // 重组 $specAttr[$key] = $value; } // 如果不在这个属性列表中的数据删除 $ProductAttr->query()->where([['product_id','=',$id]])->whereNotIn('id',array_column($specAttr,'id'))->delete(); // 循环SKU foreach ($skuList as $attrNames => $value) { // 属性ID值 $value['attr_ids'] = []; // 规格属性值组合 $value['attr_names']= $attrNames; // 切割成数据 $names = explode(',',$attrNames); // 循环处理 foreach ($names as $name) { foreach ($specAttr as $vv) { if( $name == $vv['name'] ) { // 提示新增失败 if( !$vv['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'属性SKU匹配失败']); } $value['attr_ids'][] = $vv['id']; } } } // 转成好存储的数据 $value['attr_ids'] = implode(',',$value['attr_ids']); // 转成好存储的数据 $value['sku_thumb'] = (string)$value['sku_thumb']; // 转成好存储的数据 $value['stock_total']= $value['stock']; // 转成好存储的数据 $value['product_id']= $id; // 查询 $oldSkuId = $ProductSkus->query()->where([['product_id','=',$id],['attr_ids','=',$value['attr_ids']]])->value('id'); // 判断是否存在ID $value['id'] = $oldSkuId ? $ProductSkus->edit($oldSkuId,$value) : $ProductSkus->add($value); // SKU结果 $skuList[$attrNames]= $value; } // 如果不在这个属性列表中的数据删除 $ProductSkus->query()->where([['product_id','=',$id]])->whereNotIn('id',array_column($skuList,'id'))->delete(); // 获取之前的城市ID $oldCityIds = $ProductCity->getListByProductId($id); // 循环城市范围 foreach ($cityIds as $key => $value) { // 不存在则新增 if( !in_array($value,$oldCityIds) ) $ProductCity->add(['city_id'=>$value,'product_id'=>$id]); } // 不存在的城市删除 $ProductCity->query()->where([['product_id','=',$id]])->whereNotIn('city_id',$cityIds)->delete(); // 更新内容 $Model->updateDesc($id,$description); // 提交 DB::commit(); // 记录行为 $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$oldData,$data); // 告知结果 return json_send(['code'=>'success','msg'=>'修改成功','action'=>'edit']); } catch (\Throwable $th) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'系统异常,写入失败','data'=>$th->getMessage() .'=>'.$th->getLine()]); } } // 如果是没有数据 if( !$oldData ) return $this->error('查无数据'); // 产品信息转格式 $oldData = $oldData->toArray(); $oldData['description'] = $Model->getDesc($id); $oldData['city_ids'] = $ProductCity->getListByProductId($id); $oldData['tag_scope'] = explode(',',$oldData['tag_scope']); $oldData['tag_exclude'] = explode(',',$oldData['tag_exclude']); $photoList = $ProductPhoto->getListByProductId($id); // 获取产品属性 $attrList = $ProductAttr->getListByProductId($id); // 规格属性 $specList = []; // 获取数据 foreach ($attrList as $value) { $value['active'] = 0; if( !isset($specList[$value['spec_id']]) ) $specList[$value['spec_id']] = $ProductSpec->getOne($value['spec_id']); $specList[$value['spec_id']]['attr_list'][] = $value; } // 产品类型 $skuList = $ProductSkus->getListByProductId($id); // 循环处理 foreach ($skuList as $key => $value) { // 数据解析 $value['attr_ids'] = explode(',',$value['attr_ids']); // 循环处理 foreach ( $value['attr_ids'] as $k=>$attrId ) { // 获取ids对应的name $value['attr_ids'][$k] = $ProductAttr->getValueById($attrId,'name'); } // 数据合并 $value['attr_ids'] = implode(',',$value['attr_ids']); // 重组 $skuList[$key] = $value; } // 获取类型数据 $typeList = $ProductType->getList(); $cityList = $City->getCityList(); $businessList = $Business->getListByAdmin(); $producerList = $Producer->getList(); // 标签列表 $tagData = $WeiBanTags->query()->groupBy('group')->groupBy('name')->get(['group','name'])->toArray(); // 标签列表 $tagList = []; // 循环数据 foreach ($tagData as $value) { $tagList[$value['group']][] = $value['name']; } // 分配数据 $this->assign('tagList',$tagList); $this->assign('typeList',$typeList); $this->assign('cityList',$cityList); $this->assign('businessList',$businessList); $this->assign('producerList',$producerList); $this->assign('oldData',$oldData); $this->assign('photoList',$photoList); $this->assign('skuList',$skuList); $this->assign('specList',$specList); $this->assign('crumbs','修改'); // 加载模板 return $this->fetch(); } /** * 编辑 * * */ public function copy(Request $request, Model $Model, WeiBanTags $WeiBanTags, ProductPhoto $ProductPhoto, Producer $Producer, Business $Business, ProductType $ProductType, ProductSpec $ProductSpec, ProductAttr $ProductAttr, ProductSkus $ProductSkus, City $City, ProductCity $ProductCity){ if( request()->isMethod('post') ){ // 验证参数 $request->scene('add')->validate(); // 组合数据 $data['name'] = request('name',''); $data['thumb'] = request('thumb',''); $data['poster'] = request('poster',''); $data['spec'] = request('spec',''); $data['price'] = request('price',0); $data['market_price'] = request('market_price',0); $data['producer_id'] = request('producer_id',0); $data['business_id'] = request('business_id',0); $data['quota'] = request('quota',0); $data['min_quota'] = request('min_quota',0); $data['quota_start'] = request('quota_start',''); $data['quota_end'] = request('quota_end',''); $data['puton_time'] = request('puton_time',''); $data['putoff_time'] = request('putoff_time',''); $data['stock'] = request('stock',0); $data['status'] = 1; $data['admin_uid'] = admin('uid'); $description = request('description',''); $attr = request('attr',[]); $skuList = request('sku',[]); $cityIds = request('city_ids',[]); $photoList = request('photo_list',[]); $tagScope = request('tag_scope',[]); $data['tag_scope'] = implode(',',$tagScope); $tagExclude = request('tag_exclude',[]); $data['tag_exclude'] = implode(',',$tagExclude); // 循环 foreach ($photoList as $key => $value) { if( !$value ) unset($photoList[$key]); } $photoList = array_values($photoList); // 如果没有选择,则意味着全部 $cityIds = $cityIds ? $cityIds : [1]; $data['quota_start'] = $data['quota_start'] ? strtotime($data['quota_start']) : 0; $data['quota_end'] = $data['quota_end'] ? strtotime($data['quota_end']) : 0; // 限购提示 if( !$data['thumb'] ) return json_send(['code'=>'error','msg'=>'请上传产品主图','data'=>['error'=>'请上传产品主图']]); // 限购提示 if( $attr && !$skuList ) return json_send(['code'=>'error','msg'=>'规格属性存在时,请填写SKU','data'=>['error'=>'规格属性存在时,请填写SKU']]); // 限购提示 if( $data['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'限购必填限购时间','data'=>['error'=>'限购必填限购时间']]); // 限购提示 if($data['quota'] && $data['min_quota'] > $data['quota'] ) return json_send(['code'=>'error','msg'=>'起购数量请勿大于限购数量','data'=>['error'=>'起购数量请勿大于限购数量']]); // 总库存 if( $skuList ) $data['stock'] = array_sum(array_column($skuList,'stock')); // SKU存在的时候,判断限购数量 if( $skuList ) { // 循环处理 foreach ($skuList as $attrNames => $value) { // SKU限购,所以限购时间也必须填 if( $value['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) return json_send(['code'=>'error','msg'=>'SKU限购时,请填限购时间','data'=>['error'=>'SKU限购时,请填限购时间']]); // 限购提示 if( $value['quota'] && $value['min_quota'] > $value['quota'] ) return json_send(['code'=>'error','msg'=>$attrNames.'起购数量请勿大于限购数量','data'=>['error'=>$attrNames.'起购数量请勿大于限购数量']]); // 提示起购数量异常,如果总起购数量小于SKU起购数量,提示 if( $value['min_quota'] && $value['min_quota'] < $data['min_quota'] ) return json_send(['code'=>'error','msg'=>'SKU的起购数量不能小于总起购数量','data'=>['error'=>'SKU的起购数量不能小于总起购数量']]); } // 限购数量 $quota = array_sum(array_column($skuList,'quota')); // 提示限购数量异常 if( $data['quota'] && $data['quota'] < $quota ) return json_send(['code'=>'error','msg'=>'总限购数量不能小于SKU的限购数量','data'=>['error'=>'总限购数量不能小于SKU的限购数量']]); } // 总库存 $data['stock_total'] = $data['stock']; // 总库存提醒 if( $data['stock_total'] <= 0 ) return json_send(['code'=>'error','msg'=>'请设置库存','data'=>['error'=>'请设置库存']]); // 获取规格属性 $specAttr = $this->getSpecAttr($attr,$ProductSpec,true); // 开启事务 DB::beginTransaction(); try { // 写入 $id = $Model->add($data); // 提示新增失败 if( !$id ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'新增失败']); } // 图册 foreach ($photoList as $key => $value) { // 整理数据 $value = ['sort'=>$key,'thumb'=>$value,'product_id'=>$id,'insert_time'=>time(),'update_time'=>time()]; // 重新整理 $photoList[$key] = $value; } // 存在图册 if( $photoList ) { // 写入失败 $result = $ProductPhoto->query()->insert($photoList); // 提示新增失败 if( !$result ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'商品图册写入失败']); } } // 组合数据 foreach ($specAttr as $key => $value) { // 查询结果 $value['id'] = $ProductAttr->upsertByName($value,$id); // 提示新增失败 if( !$value['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'商品属性新增失败']); } // 重组 $specAttr[$key] = $value; } // 循环SKU foreach ($skuList as $attrNames => $value) { // 属性ID值 $value['attr_ids'] = []; // 规格属性值组合 $value['attr_names']= $attrNames; // 切割成数据 $names = explode(',',$attrNames); // 循环处理 foreach ($names as $name) { foreach ($specAttr as $vv) { if( $name == $vv['name'] ) { // 提示新增失败 if( !$vv['id'] ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'属性SKU匹配失败']); } $value['attr_ids'][] = $vv['id']; } } } // 转成好存储的数据 $value['attr_ids'] = implode(',',$value['attr_ids']); // 转成好存储的数据 $value['product_id']= $id; // 转成好存储的数据 $value['sku_thumb'] = (string) $value['sku_thumb']; // 转成好存储的数据 $value['stock_total']= $value['stock']; // 转成好存储的数据 $value['insert_time']= time(); // 转成好存储的数据 $value['update_time']= time(); // SKU结果 $skuList[$attrNames] = $value; } // 循环城市范围 foreach ($cityIds as $key => $value) { // 重组数据 $cityIds[$key] = ['city_id'=>$value,'product_id'=>$id,'insert_time'=>time(),'update_time'=>time()]; } // 写入城市范围 $ProductCity->query()->insert($cityIds); // 返回结果 $result = $ProductSkus->insert($skuList); // 提示新增失败 if( !$result ) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'SKU插入失败']); } // 更新内容 $Model->updateDesc($id,$description); // 提交 DB::commit(); // 记录行为 $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data); // 告知结果 return json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']); } catch (\Throwable $th) { // 回滚 DB::rollBack(); // 提示 return json_send(['code'=>'error','msg'=>'系统异常,写入失败','data'=>$th->getMessage()]); } } // 接收参数 $id = request('id',0); // 查询数据 $oldData = $Model->where(['id'=>$id])->first(); // 如果是没有数据 if( !$oldData ) return $this->error('查无数据'); // 产品信息转格式 $oldData = $oldData->toArray(); $oldData['description'] = $Model->getDesc($id); $oldData['city_ids'] = $ProductCity->getListByProductId($id); $oldData['tag_scope'] = explode(',',$oldData['tag_scope']); $oldData['tag_exclude'] = explode(',',$oldData['tag_exclude']); $photoList = $ProductPhoto->getListByProductId($id); // 获取产品属性 $attrList = $ProductAttr->getListByProductId($id); // 规格属性 $specList = []; // 获取数据 foreach ($attrList as $value) { $value['active'] = 0; if( !isset($specList[$value['spec_id']]) ) $specList[$value['spec_id']] = $ProductSpec->getOne($value['spec_id']); $specList[$value['spec_id']]['attr_list'][] = $value; } // 产品类型 $skuList = $ProductSkus->getListByProductId($id); // 循环处理 foreach ($skuList as $key => $value) { // 数据解析 $value['attr_ids'] = explode(',',$value['attr_ids']); // 循环处理 foreach ( $value['attr_ids'] as $k=>$attrId ) { // 获取ids对应的name $value['attr_ids'][$k] = $ProductAttr->getValueById($attrId,'name'); } // 数据合并 $value['attr_ids'] = implode(',',$value['attr_ids']); // 重组 $skuList[$key] = $value; } // 标签列表 $tagData = $WeiBanTags->query()->groupBy('group')->groupBy('name')->get(['group','name'])->toArray(); // 标签列表 $tagList = []; // 循环数据 foreach ($tagData as $value) { $tagList[$value['group']][] = $value['name']; } // 获取类型数据 $typeList = $ProductType->getList(); $cityList = $City->getCityList(); $businessList = $Business->getListByAdmin(); $producerList = $Producer->getList(); // 分配数据 $this->assign('tagList',$tagList); $this->assign('typeList',$typeList); $this->assign('cityList',$cityList); $this->assign('businessList',$businessList); $this->assign('producerList',$producerList); $this->assign('oldData',$oldData); $this->assign('photoList',$photoList); $this->assign('skuList',$skuList); $this->assign('specList',$specList); $this->assign('crumbs','复制'); // 加载模板 return $this->fetch(); } /** * 状态 * * */ public function set_status( Request $request, Model $Model ){ // 验证参数 $request->scene('set_status')->validate(); // 接收参数 $id = request('id',0); $status = request('status',0); // 查询数据 $result = $Model->edit($id,['status'=>$status]); // 提示新增失败 if( !$result ) return json_send(['code'=>'error','msg'=>'设置失败']); // 记录行为 $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,[],['status'=>$status]); // 告知结果 return json_send(['code'=>'success','msg'=>'设置成功','path'=>'']); } /** * 获取某个类目下的规格 * */ public function get_spec_html( ProductSpec $ProductSpec){ // 接收参数 $typeId = request('type_id',0); // 查询数据 $specList = $ProductSpec->getList(); // 循环处理 foreach ($specList as $key => $value) { if( $value['type_id'] != $typeId ) unset($specList[$key]); } // 分配数据 $this->assign('specList',$specList); // 加载模板 return $this->fetch(); } /** * 获取某个类目下的规格 * */ public function get_sku_html( ProductSpec $ProductSpec,ProductSkus $ProductSkus){ // 接收参数 $attr = request('attr',[]); $id = request('product_id',0); // 产品类型 $oldSkus = $id ? $ProductSkus->getListByProductId($id) : []; // 获取规格属性 $specAttr = $this->getSpecAttr($attr,$ProductSpec); // 组合SKU $brushList = []; // 循环规格属性 foreach ($specAttr as $specId => $value) { // 获取SKU组合 $brushList[$specId] = array_column($value['attr_list'],'name'); } // sku列表 $skuList = $this->brush([],$brushList); // 循环规格属性 foreach ($skuList as $newKey => $new) { // 获取新数据 $new = ['attr_names'=>$new,'price'=>0,'market_price'=>0,'stock'=>0,'min_quota'=>0,'quota'=>0,'status'=>0,'sku_thumb'=>'']; // 循环旧的sku foreach ($oldSkus as $old) { // 如果有相等的规格 if( $old['attr_names'] == $new['attr_names']) { $new['sku_thumb'] = $old['sku_thumb']; $new['market_price']= $old['market_price']; $new['price'] = $old['price']; $new['stock'] = $old['stock']; $new['status'] = $old['status']; $new['min_quota'] = $old['min_quota']; $new['quota'] = $old['quota']; } } $skuList[$newKey] = $new; } // 分配数据 $this->assign('specAttr',$specAttr); $this->assign('skuList',$skuList); // 加载模板 return $this->fetch(); } /** * 获取规格属性 * @param ProductSpec $ProductSpec * */ private function getSpecAttr($attr,$ProductSpec,$onlyList=false){ // 组合参数 $specAttr = []; // 循环处理数据 foreach ($attr as $specId => $value) { $specAttr[$specId]['spec_id'] = $specId; $specAttr[$specId]['spec_name'] = $ProductSpec->getOne($specId,'name'); $specAttr[$specId]['attr_list'] = []; foreach ($value['name'] as $key => $name) { // 如果没有名称的,跳过 if( !$name ) continue; // 结果 $temp = ['id'=>0,'spec_id'=>$specId,'thumb'=>'','name'=>'','remark'=>'']; // 获取名称 $temp['name'] = str_ireplace(',','',$name); // 获取对应的备注信息 if( !empty($value['remark'][$key]) ) $temp['remark'] = $value['remark'][$key]; if( !empty($value['thumb'][$key]) ) $temp['thumb'] = $value['thumb'][$key]; // 获取对应的数据 $specAttr[$specId]['attr_list'][]= $temp; } // 没有属性的规格,移除 if( !$specAttr[$specId]['attr_list'] ) unset($specAttr[$specId]); } // 仅获取属性列表 if( $onlyList ) { // 属性列表 $attrList = []; // 判断结果 foreach ($specAttr as $value) { // 获取数据 array_push($attrList,...$value['attr_list']); } // 返回结果 $specAttr = $attrList; } // 返回结果 return $specAttr; } /** * 组合SKU * */ private function brush($res = [], $arr = []){ // 获取第一个规格的属性 if (empty($res)) $res = (array) array_shift($arr); // 如果只有一个规格,返回该规格的属性即可 if (empty($arr)) return $res; // 接下来要参与计算的一组属性 $current = array_shift($arr); // 计算的列表 $last = []; // 循环上一次已经算出的集合 foreach ($res as $attr) { foreach ($current as $col_val) { $last[] = $attr . ',' . $col_val; } } return $this->brush($last,$arr); # 递归处理, 直到$arr滚到最后一组属性 } /** * 排序 * * */ public function set_sort( Request $request, Model $Model ){ // 验证参数 $request->scene('set_sort')->validate(); // 接收参数 $id = request('id',0); $sort = request('sort',0); // 查询数据 $result = $Model->edit($id,['sort'=>$sort]); // 提示新增失败 if( !$result ) return json_send(['code'=>'error','msg'=>'设置失败']); // 记录行为 $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,[],['sort'=>$sort]); // 告知结果 return json_send(['code'=>'success','msg'=>'设置成功','path'=>'']); } }