setBase($params); $this->addGoodsItem($goods,$params); Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); return $e->getMessage(); } } /** * @notes 编辑商品 * @param array $params * @return array|bool[] * @author cjhao * @date 2021/7/14 18:09 */ public function edit(array $params) { Db::startTrans(); try { $oldItemIds = GoodsItem::where('goods_id', $params['id'])->column('id'); $goods = $this->setBase($params); $this->editGoodsItem($goods,$params); $newItemIds = GoodsItem::where('goods_id', $params['id'])->column('id'); //todo 其他业务逻辑 $isDistributionGoods = false; $distributionGoods = DistributionGoods::where('goods_id', $params['id'])->findOrEmpty()->toArray(); // 存在分销 且sku已经变更 则清除分销信息 if ($distributionGoods && $oldItemIds != $newItemIds) { // 编辑商品时清除已设置好的分销比例,商家须重新设置 $deleteIds = DistributionGoods::where('goods_id', $params['id'])->column('id'); DistributionGoods::destroy($deleteIds); $isDistributionGoods = true; } Db::commit(); return [ 'status' => true, 'is_distribution_goods' => $isDistributionGoods, ]; } catch (\Exception $e) { Db::rollback(); return [ 'status' => false, 'err' => $e->getMessage() ]; } } /** * @notes 商品基础信息 * @param array $params * @return Goods|array|\think\Model|null * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author cjhao * @date 2021/7/22 14:01 */ public function setBase(array $params){ $goods = new Goods(); $goodsImage = $params['goods_image']; $goodsCategory = $params['category_id']; //总库存 $totalStock = array_sum(array_column($params['spec_value_list'],'stock')); //售价数组 $specPriceArray = array_column($params['spec_value_list'],'sell_price'); //划线价数组 $specLineationPriceArray = array_column($params['spec_value_list'],'lineation_price'); //编辑操作 if(isset($params['id'])){ $goods = $goods::find($params['id']); //删除轮播图 GoodsImage::where(['goods_id'=>$goods->id])->delete(); //删除商品分类 GoodsCategoryIndex::where(['goods_id'=>$goods->id])->delete(); //保存改变前的规格类型 $goods->oldSpecType = $goods->spec_type; } $isExpress = GoodsEnum::GOODS_REALITY == $params['type'] ? $params['is_express'] : 0 ; //快递 $isSelffetch = GoodsEnum::GOODS_REALITY == $params['type'] ? $params['is_selffetch'] : 0 ; //自提 $isVirtualdelivery = GoodsEnum::GOODS_VIRTUAL == $params['type'] ? 1 : 0; //虚拟发货 $afterPay = 0; $afterDelivery = 0; switch ($params['type']){ case 1: $isExpress = $params['is_express']; $isSelffetch = $params['is_selffetch']; break; case 2: $isVirtualdelivery = 1; $afterPay = $params['after_pay']; $afterDelivery = $params['after_delivery']; break; } //更新商品基础信息 $goods->name = $params['name']; $goods->code = $params['code']; $goods->type = $goods['type'] ?? $params['type']; //编辑不允许修改类型 $goods->brand_id = $params['brand_id']; $goods->supplier_id = $params['supplier_id']; $goods->unit_id = $params['unit_id']; $goods->image = array_shift($goodsImage); //弹出第一张图片,设为商品主图; $goods->spec_type = $params['spec_type']; $goods->video_source = $params['video_source']; $goods->video_cover = $params['video_cover']; $goods->video = $params['video']; $goods->poster = $params['poster']; $goods->total_stock = $totalStock; $goods->min_price = min($specPriceArray); $goods->max_price = max($specPriceArray); $goods->min_lineation_price = min($specLineationPriceArray); $goods->max_lineation_price = max($specLineationPriceArray); $goods->express_type = $params['express_type']; $goods->express_money = $params['express_money']; $goods->express_template_id = $params['express_template_id']; $goods->stock_warning = $params['stock_warning']; $goods->virtual_sales_num = $params['virtual_sales_num']; $goods->virtual_click_num = $params['virtual_click_num'] ?? 0; $goods->sort = $params['sort'] ?? DefaultEnum::SORT; $goods->status = $params['status']; $goods->content = $params['content']; $goods->is_express = $isExpress; //快递配送 $goods->is_selffetch = $isSelffetch; //上门自提 $goods->is_virtualdelivery = $isVirtualdelivery; //虚拟发货 $goods->after_pay = $afterPay; //买家付款后:1-自动发货,2-手动发货 $goods->after_delivery = $afterDelivery; //发货后:1-自动完成订单,2-需要买家确认 $goods->delivery_content = $params['delivery_content'] ?? ''; //发货内容 $goods->delivery_type = $params['delivery_type'] ?? 0;// 发货类型 $goods->delivery_template_id= $params['delivery_template_id'] ?? 0;// 发货模版 $goods->is_address = $params['is_address'] ?? 0; $goods->limit_type = $params['limit_type']; $goods->limit_value = $params['limit_value']; $goods->service_guarantee_ids = $params['service_guarantee_ids'] ?? []; $goods->save(); //添加商品轮播图 if ($goodsImage) { array_walk($goodsImage, function (&$image){ $image = ['uri' => $image]; }); $goods->imageList()->saveAll($goodsImage); } //添加商品分类关联表 if($goodsCategory){ array_walk($goodsCategory, function (&$category_id){ $category_id = ['category_id' => $category_id]; }); $goods->goodsCategoryIndex()->saveAll($goodsCategory); } return $goods; } /** * @notes 添加商品规格信息 * @param Goods $goods * @param array $params * @author cjhao * @date 2021/7/22 14:37 */ public function addGoodsItem(Goods $goods,array $params) { $specType = $params['spec_type']; //添加商品规格 if (GoodsEnum::SEPC_TYPE_SIGNLE == $specType) { //单规格商品 $specValueList = $params['spec_value_list']; foreach ($specValueList as $spec) { $goodsSpec = new GoodsSpec(); $goodsSpec->goods_id = $goods->id; $goodsSpec->name = '默认'; $goodsSpec->save(); $goodsSpecValue = new GoodsSpecValue(); $goodsSpecValue->save([ 'goods_id' => $goodsSpec->goods_id, 'spec_id' => $goodsSpec->id, 'value' => '默认', ]); $specValueData = [ 'goods_id' => $goods->id, 'spec_value_ids' => $goodsSpecValue->id, 'spec_value_str' => '默认', 'image' => $spec['image'], 'sell_price' => $spec['sell_price'], 'lineation_price' => $spec['lineation_price'], 'cost_price' => $spec['cost_price'], 'stock' => $spec['stock'], 'volume' => $spec['volume'], 'weight' => $spec['weight'], 'bar_code' => $spec['bar_code'], ]; (new GoodsItem())->save($specValueData); } } else { //添加规格项 $postSpecValue = $params['spec_value']; $specData = []; foreach ($postSpecValue as $sepcKey => $specVal) { $goodsSpec = new GoodsSpec(); $goodsSpec->goods_id = $goods->id; $goodsSpec->name = $specVal['name']; $goodsSpec->save(); //处理规格值 array_walk($specVal['spec_list'], function ($spec) use ($goodsSpec,&$specData){ $specData[] = ['spec_id'=>$goodsSpec->id,'value'=>$spec['value']]; }); } $goods->specValueSpec()->saveAll($specData); //添加规格信息 $serverSpecValueList = $params['server_spec_value_list']; //改变数据结构,ids为索引 $postSpecValueList = array_column($params['spec_value_list'], null, 'ids'); // $goodsSpecValueList = GoodsSpecValue::where(['goods_id'=>$goods->id]) // ->group('spec_id') // ->column(' GROUP_CONCAT(value Separator \',\') as spec_values,GROUP_CONCAT(id Separator \',\') as spec_ids'); //GROUP_CONCAT函数有长度限制,替换成下面的方法 $goodsSpecValue = GoodsSpecValue::where(['goods_id'=>$goods->id]) ->column('id,spec_id,value'); $goodsSpecValueList = []; foreach ($goodsSpecValue as $goodsSpecValue_val) { $goodsSpecValueList[$goodsSpecValue_val['spec_id']][] = $goodsSpecValue_val; } foreach ($goodsSpecValueList as $goodsSpecValueList_key=>$goodsSpecValueList_val) { $spec_values = array_column($goodsSpecValueList_val,'value'); $spec_values = implode(',',$spec_values); $spec_ids = array_column($goodsSpecValueList_val,'id'); $spec_ids = implode(',',$spec_ids); $goodsSpecValueList[$goodsSpecValueList_key] = []; $goodsSpecValueList[$goodsSpecValueList_key]['spec_values'] = $spec_values; $goodsSpecValueList[$goodsSpecValueList_key]['spec_ids'] = $spec_ids; } $goodsSpecValueList = array_values($goodsSpecValueList); $specValueData = []; foreach ($serverSpecValueList as $serverValue) { $specValueList = $postSpecValueList[$serverValue['ids']]; $specValue = explode(GoodsEnum::SPEC_SEPARATOR, $serverValue['spec_value']); $specIds = []; //获取规格值对应的id foreach ($specValue as $specIndex => $specVal){ $specListValues = explode(',',$goodsSpecValueList[$specIndex]['spec_values']); $specListIds = explode(',',$goodsSpecValueList[$specIndex]['spec_ids']); $specValueIds = array_combine($specListValues,$specListIds); $specIds[] = $specValueIds[$specVal]; } $specValueData[] = [ 'spec_value_ids' => implode(GoodsEnum::SPEC_SEPARATOR, $specIds), 'spec_value_str' => $serverValue['spec_value'], 'image' => $specValueList['image'], 'sell_price' => $specValueList['sell_price'], 'lineation_price' => $specValueList['lineation_price'], 'cost_price' => $specValueList['cost_price'], 'stock' => $specValueList['stock'], 'volume' => $specValueList['volume'], 'weight' => $specValueList['weight'], 'bar_code' => $specValueList['bar_code'], ]; } $goods->specValueList()->saveAll($specValueData); } } /** * @notes 编辑商品规格信息 * @param Goods $goods * @param array $params * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author cjhao * @date 2021/7/22 14:46 */ public function editGoodsItem(Goods $goods,array $params) { $specType = $params['spec_type']; //编辑后的规格类型 $oldSpecType = $goods->oldSpecType; //原来的规格类型 //编辑商品规格 if(GoodsEnum::SEPC_TYPE_SIGNLE == $specType){ //原来单规格,更新规格信息 $specValueList = $params['spec_value_list'][0]; if(GoodsEnum::SEPC_TYPE_SIGNLE == $oldSpecType){ GoodsItem::update([ 'id' => $specValueList['id'], 'sell_price' => $specValueList['sell_price'], 'lineation_price' => $specValueList['lineation_price'], 'cost_price' => $specValueList['cost_price'], 'stock' => $specValueList['stock'], 'volume' => $specValueList['volume'], 'weight' => $specValueList['weight'], 'bar_code' => $specValueList['bar_code'], ]); }else{ //原来多规格,删除多规格数据 GoodsSpec::where(['goods_id'=>$goods->id])->delete(); GoodsSpecValue::where(['goods_id'=>$goods->id])->delete(); GoodsItem::where(['goods_id'=>$goods->id])->delete(); //写入单规格数据 $goodsSpec = new GoodsSpec(); $goodsSpec->goods_id = $goods->id; $goodsSpec->name = '默认'; $goodsSpec->save(); $goodsSpecValue = new GoodsSpecValue(); $goodsSpecValue->save([ 'goods_id' => $goodsSpec->goods_id, 'spec_id' => $goodsSpec->id, 'value' => '默认', ]); $specValueData = [ 'goods_id' => $goods->id, 'spec_value_ids' => $goodsSpecValue->id, 'spec_value_str' => '默认', 'image' => $specValueList['image'], 'sell_price' => $specValueList['sell_price'], 'lineation_price' => $specValueList['lineation_price'], 'cost_price' => $specValueList['cost_price'], 'stock' => $specValueList['stock'], 'volume' => $specValueList['volume'], 'weight' => $specValueList['weight'], 'bar_code' => $specValueList['bar_code'], ]; (new GoodsItem())->save($specValueData); } }else{ //原单规格 if(GoodsEnum::SEPC_TYPE_SIGNLE == $oldSpecType){ //原来单规格,删除单规格数据 GoodsSpec::where(['goods_id'=>$goods->id])->delete(); GoodsSpecValue::where(['goods_id'=>$goods->id])->delete(); GoodsItem::where(['goods_id'=>$goods->id])->delete(); //添加规格项 $postSpecValue = $params['spec_value']; $specData = []; foreach ($postSpecValue as $specVal) { $goodsSpec = new GoodsSpec(); $goodsSpec->goods_id = $goods->id; $goodsSpec->name = $specVal['name']; $goodsSpec->save(); //处理规格值 array_walk($specVal['spec_list'], function ($spec) use ($goodsSpec,&$specData){ $specData[] = ['spec_id'=>$goodsSpec->id,'value'=>$spec['value']]; }); } $goods->specValueSpec()->saveAll($specData); //添加规格信息 $serverSpecValueList = $params['server_spec_value_list']; //改变数据结构,ids为索引 $postSpecValueList = array_column($params['spec_value_list'], null, 'ids'); // $goodsSpecValueList = GoodsSpecValue::where(['goods_id'=>$goods->id]) // ->group('spec_id') // ->column(' GROUP_CONCAT(value Separator \',\') as spec_values,GROUP_CONCAT(id Separator \',\') as spec_ids'); //GROUP_CONCAT函数有长度限制,替换成下面的方法 $goodsSpecValue = GoodsSpecValue::where(['goods_id'=>$goods->id]) ->column('id,spec_id,value'); $goodsSpecValueList = []; foreach ($goodsSpecValue as $goodsSpecValue_val) { $goodsSpecValueList[$goodsSpecValue_val['spec_id']][] = $goodsSpecValue_val; } foreach ($goodsSpecValueList as $goodsSpecValueList_key=>$goodsSpecValueList_val) { $spec_values = array_column($goodsSpecValueList_val,'value'); $spec_values = implode(',',$spec_values); $spec_ids = array_column($goodsSpecValueList_val,'id'); $spec_ids = implode(',',$spec_ids); $goodsSpecValueList[$goodsSpecValueList_key] = []; $goodsSpecValueList[$goodsSpecValueList_key]['spec_values'] = $spec_values; $goodsSpecValueList[$goodsSpecValueList_key]['spec_ids'] = $spec_ids; } $goodsSpecValueList = array_values($goodsSpecValueList); $specValueData = []; foreach ($serverSpecValueList as $serverValue) { $specValueList = $postSpecValueList[$serverValue['ids']]; $specValue = explode(GoodsEnum::SPEC_SEPARATOR, $serverValue['spec_value']); $specIds = []; //获取规格值对应的id foreach ($specValue as $specIndex => $specVal){ $specListValues = explode(',',$goodsSpecValueList[$specIndex]['spec_values']); $specListIds = explode(',',$goodsSpecValueList[$specIndex]['spec_ids']); $specValueIds = array_combine($specListValues,$specListIds); $specIds[] = $specValueIds[$specVal]; } $specValueData[] = [ 'spec_value_ids' => implode(GoodsEnum::SPEC_SEPARATOR, $specIds), 'spec_value_str' => $serverValue['spec_value'], 'image' => $specValueList['image'], 'sell_price' => $specValueList['sell_price'], 'lineation_price' => $specValueList['lineation_price'], 'cost_price' => $specValueList['cost_price'], 'stock' => $specValueList['stock'], 'volume' => $specValueList['volume'], 'weight' => $specValueList['weight'], 'bar_code' => $specValueList['bar_code'], ]; } $goods->specValueList()->saveAll($specValueData); }else{ //原来多规格,改变后还是多规格 $goodsSpecIds = GoodsSpec::where(['goods_id'=>$goods->id])->column('id'); $goodsSpecValueIds = GoodsSpecValue::where(['goods_id'=>$goods->id])->column('id'); $goodsItemIds = GoodsItem::where(['goods_id'=>$goods->id])->column('id'); $postSpecValue = $params['spec_value']; $postGoodsSpecValueIds = []; foreach ($postSpecValue as $spec) { $goodsSpec = new GoodsSpec(); //存在规格id,进行更新操作 if($spec['id'] > 0){ $goodsSpec = $goodsSpec->find($spec['id']); } $goodsSpec->goods_id = $goods->id; $goodsSpec->name = $spec['name']; $goodsSpec->save(); //合并规格值id $postGoodsSpecValueIds = array_merge($postGoodsSpecValueIds,array_column($spec['spec_list'],'id')); //写入规格,存在则更新 array_walk($spec['spec_list'], function ($specVal) use ($goodsSpec, &$specList) { $goodsSpecValue = new GoodsSpecValue(); //存在规格值id,进行更新操作 if($specVal['id'] > 0){ $goodsSpecValue = $goodsSpecValue->find($specVal['id']); } $goodsSpecValue->save([ 'goods_id' => $goodsSpec->goods_id, 'spec_id' => $goodsSpec->id, 'value' => $specVal['value'], ]); }); } //添加规格信息 $serverSpecValueList = $params['server_spec_value_list']; //改变数据结构,ids为索引 $postSpecValueList = array_column($params['spec_value_list'], null, 'ids'); $specValues = array_column($serverSpecValueList, 'spec_value'); $specValues = implode(',',$specValues); // $goodsSpecValueList = GoodsSpecValue::where(['goods_id'=>$goods->id]) // ->where('value','in',$specValues) // ->group('spec_id') // ->column(' GROUP_CONCAT(value Separator \',\') as spec_values,GROUP_CONCAT(id Separator \',\') as spec_ids'); //GROUP_CONCAT函数有长度限制,替换成下面的方法 $goodsSpecValue = GoodsSpecValue::where(['goods_id'=>$goods->id]) ->where('value','in',$specValues) ->column('id,spec_id,value'); $goodsSpecValueList = []; foreach ($goodsSpecValue as $goodsSpecValue_val) { $goodsSpecValueList[$goodsSpecValue_val['spec_id']][] = $goodsSpecValue_val; } foreach ($goodsSpecValueList as $goodsSpecValueList_key=>$goodsSpecValueList_val) { $spec_values = array_column($goodsSpecValueList_val,'value'); $spec_values = implode(',',$spec_values); $spec_ids = array_column($goodsSpecValueList_val,'id'); $spec_ids = implode(',',$spec_ids); $goodsSpecValueList[$goodsSpecValueList_key] = []; $goodsSpecValueList[$goodsSpecValueList_key]['spec_values'] = $spec_values; $goodsSpecValueList[$goodsSpecValueList_key]['spec_ids'] = $spec_ids; } $goodsSpecValueList = array_values($goodsSpecValueList); $specValueData = []; foreach ($serverSpecValueList as $serverValue) { $specValueList = $postSpecValueList[$serverValue['ids']]; $specValue = explode(GoodsEnum::SPEC_SEPARATOR, $serverValue['spec_value']); $specIds = []; //获取规格值对应的id foreach ($specValue as $specIndex => $specVal){ $specListValues = explode(',',$goodsSpecValueList[$specIndex]['spec_values']); $specListIds = explode(',',$goodsSpecValueList[$specIndex]['spec_ids']); $specValueIds = array_combine($specListValues,$specListIds); $specIds[] = $specValueIds[$specVal]; } //添加的数据 $itemData = [ 'spec_value_ids' => implode(GoodsEnum::SPEC_SEPARATOR, $specIds), 'spec_value_str' => $serverValue['spec_value'], 'image' => $specValueList['image'], 'sell_price' => $specValueList['sell_price'], 'lineation_price' => $specValueList['lineation_price'], 'cost_price' => $specValueList['cost_price'], 'stock' => $specValueList['stock'], 'volume' => $specValueList['volume'], 'weight' => $specValueList['weight'], 'bar_code' => $specValueList['bar_code'], ]; //更新规格 if($specValueList['id'] > 0){ $itemData['id'] = $specValueList['id']; } $specValueData[] = $itemData; } $goods->specValueList()->saveAll($specValueData); $postSpecIds = array_column($postSpecValue,'id'); $postItemIds = array_column($params['spec_value_list'],'id'); //对比规格是否需要删除 $delSpecIds = array_diff($goodsSpecIds, $postSpecIds); $delSpecValyeIds = array_diff($goodsSpecValueIds, $postGoodsSpecValueIds); $delItemIds = array_diff($goodsItemIds, $postItemIds); //需要删除规格名 if($delSpecIds){ GoodsSpec::where(['id'=>array_values($delSpecIds)])->delete(); } //删除规格值 if($delSpecValyeIds){ GoodsSpecValue::where(['id'=>array_values($delSpecValyeIds)])->delete(); } //删除规格信息 if($delItemIds){ GoodsItem::where(['id'=>array_values($delItemIds)])->delete(); } } } } /** * @notes 商品其他列表 * @param string $type * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author cjhao * @date 2021/7/22 15:47 */ public function otherList(string $type) { $supplierList = GoodsSupplier::field('id,name')->order('sort','asc')->select(); $categoryList = GoodsCategory::field('id,pid,name')->order('sort','asc')->select()->toArray(); $categoryList = linear_to_tree($categoryList,'sons'); if('all' !== $type){ $activityLists = ActivityEnum::getActivityDesc(); $activityLists = [0=>'未参与'] + $activityLists; return [ 'supplier_list' => $supplierList, 'category_list' => $categoryList, 'type_list' => GoodsEnum::getGoodsTypeDesc(), 'activity_list' => $activityLists, ]; } $unitList = GoodsUnit::field('id,name')->order('sort','asc')->select(); $brandList = GoodsBrand::field('id,name')->order('sort','asc')->select(); $freightList = Freight::field('id,name')->select(); $list = [ 'supplier_list' => $supplierList, 'category_list' => $categoryList, 'brand_list' => $brandList, 'unit_list' => $unitList, 'freight_list' => $freightList, ]; return $list; } /** * @notes 商品详情 * @param int $id 商品id * @return array|\think\Model|null * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author cjhao * @date 2021/7/15 15:49 */ public function detail(int $id) { $goods = Goods::with(['spec_value.spec_list','spec_value_list']) ->withoutField('create_time,update_time') ->append(['goods_image','category_id']) ->find($id) ->toArray(); return $goods; } /** * @notes 商品上下架 * @param array $params * @return Goods * @author cjhao * @date 2021/7/17 17:10 */ public function status(array $params) { $status = YesNoEnum::YES == $params['status'] ? 1 : 0; return Goods::update(['status'=>$status],['id'=>$params['ids']]); } /** * @notes 设置商品上下架 * @param array $params * @return Goods * @author cjhao * @date 2021/7/22 9:51 */ public function sort(array $params) { return Goods::update(['id'=>$params['id'],'sort'=>(int)$params['sort']]); } /** * @notes 删除商品 todo 删除接口需要考虑商品的其他状态 * @param array $ids * @return bool * @author cjhao * @date 2021/7/17 17:23 */ public function del(array $ids) { Db::startTrans(); try { Goods::destroy(['id'=>$ids]); // 删除商品时清除已设置好的分销比例 $deleteIds = DistributionGoods::where('goods_id', 'in', $ids)->column('id'); DistributionGoods::destroy($deleteIds); // 删掉用户购物车商品 Cart::where(['goods_id'=>$ids])->delete(); Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); return false; } } /** * @notes 修改商品名称 * @param array $params * @return Goods * @author cjhao * @date 2021/7/29 16:11 */ public function rename(array $params) { return Goods::update(['id'=>$params['id'],'name'=>$params['name']]); } /** * @notes 移动分类 * @param array $params * @throws \Exception * @author ljj * @date 2023/5/6 2:24 下午 */ public function changeCategory(array $params) { //删除旧的商品分类 GoodsCategoryIndex::where(['goods_id'=>$params['ids']])->delete(); //创建新的商品分类 $data = []; foreach ($params['ids'] as $id) { foreach ($params['category_id'] as $category_id) { $data[] = ['goods_id'=>$id,'category_id'=>$category_id]; } } (new GoodsCategoryIndex())->saveAll($data); return true; } /** * @notes 商品规格价格导入 * @param array $params * @return bool|string * @author * @date 2024/01/01 00:00 */ public function importSpecPrice(array $params) { if (empty($params['file'])) { return '请上传导入文件'; } Db::startTrans(); try { // 处理上传的Excel文件 $file = $params['file']; $data = $this->parseExcelFile($file); if (empty($data)) { return '导入文件为空或格式错误'; } $successCount = 0; $errorMessages = []; foreach ($data as $row => $item) { try { // 验证必要字段 if (empty($item['item_id']) || empty($item['goods_id'])) { $errorMessages[] = "第{$row}行:商品ID或规格ID不能为空"; continue; } // 检查商品是否存在 $goods = Goods::find($item['goods_id']); if (!$goods) { $errorMessages[] = "第{$row}行:商品ID {$item['goods_id']} 不存在"; continue; } // 检查规格是否存在 $goodsItem = GoodsItem::where('id', $item['item_id']) ->where('goods_id', $item['goods_id']) ->find(); if (!$goodsItem) { $errorMessages[] = "第{$row}行:规格ID {$item['item_id']} 不存在或不属于该商品"; continue; } // 更新规格价格信息 $updateData = []; if (isset($item['sell_price']) && is_numeric($item['sell_price'])) { $updateData['sell_price'] = $item['sell_price']; } if (isset($item['lineation_price']) && is_numeric($item['lineation_price'])) { $updateData['lineation_price'] = $item['lineation_price']; } if (isset($item['cost_price']) && is_numeric($item['cost_price'])) { $updateData['cost_price'] = $item['cost_price']; } if (isset($item['stock']) && is_numeric($item['stock'])) { $updateData['stock'] = $item['stock']; } if (isset($item['weight']) && is_numeric($item['weight'])) { $updateData['weight'] = $item['weight']; } if (isset($item['volume']) && is_numeric($item['volume'])) { $updateData['volume'] = $item['volume']; } if (!empty($updateData)) { GoodsItem::where('id', $item['item_id'])->update($updateData); $successCount++; } } catch (\Exception $e) { $errorMessages[] = "第{$row}行:" . $e->getMessage(); } } Db::commit(); if (!empty($errorMessages)) { return "导入完成,成功{$successCount}条,失败" . count($errorMessages) . "条。错误信息:" . implode(';', array_slice($errorMessages, 0, 5)); } return true; } catch (\Exception $e) { Db::rollback(); return '导入失败:' . $e->getMessage(); } } /** * @notes 解析Excel文件 * @param string $file * @return array * @author * @date 2024/01/01 00:00 */ private function parseExcelFile($file) { try { // 使用PhpSpreadsheet处理Excel文件 if (is_array($file)) { return $file; } // 检查文件是否存在 if (!file_exists($file)) { throw new \Exception('文件不存在'); } // 加载Excel文件 $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file); $worksheet = $spreadsheet->getActiveSheet(); $data = $worksheet->toArray(); if (empty($data)) { throw new \Exception('Excel文件为空'); } // 获取表头 $headers = array_shift($data); $result = []; // 将表头映射为字段名 $fieldMap = [ '商品ID' => 'goods_id', '商品编码' => 'goods_code', '商品名称' => 'goods_name', '规格ID' => 'item_id', '规格名称' => 'spec_value_str', '销售价格' => 'sell_price', '划线价格' => 'lineation_price', '成本价格' => 'cost_price', '库存数量' => 'stock', '重量(kg)' => 'weight', '体积(m³)' => 'volume' ]; // 创建字段索引映射 $fieldIndexes = []; foreach ($headers as $index => $header) { if (isset($fieldMap[$header])) { $fieldIndexes[$fieldMap[$header]] = $index; } } // 处理数据行 foreach ($data as $rowIndex => $row) { if (empty(array_filter($row))) { continue; // 跳过空行 } $item = []; foreach ($fieldIndexes as $field => $index) { $item[$field] = isset($row[$index]) ? trim($row[$index]) : ''; } if (!empty($item)) { $result[$rowIndex + 2] = $item; // +2 因为表头占一行,数组从0开始 } } return $result; } catch (\Exception $e) { throw new \Exception('Excel文件解析失败:' . $e->getMessage()); } } }