问题说明:门店端商品导入时模版分类归属不明确,没有根据“是否门店自建分类”去查询分类信息。
1、开启自建分类,门店的分类还是手动一个个选择,
2、门店的二级分类type=0,relation_id =0
修改文件:crmeb/services/FileService.php
修改方法:getVerifyColumns() 、processRowData()
/**
* 获取对应类型的验证列
* @param $import_type
*/
protected function getVerifyColumns($import_type, $firstRowData)
{
switch ($import_type) {
case 'user':
$verifyColumns = [
'openid', 'unionId', 'uid', '手机号', '用户昵称',
'客户姓名', '性别', '生日', '用户等级', '经验值',
'付费会员有效期', '客户积分', '客户余额', '客户标签',
'用户分组', '用户来源', '省', '市', '区', '地址'
];
break;
case 'goods':
$verifyColumns = [
'商品编号', '商品名称', '商品类型', '商品分类(一级)', '商品分类(二级)', '商品分类(三级)', '商品单位',
'商品图片', '商品视频', '商品详情', '已售数量', '规格类型', '规格类型值',
'规格名称', '规格值组合', '规格图片', '售价', '调价区间(最小值)', '调价区间(最大值)', '划线价', '成本价', '库存', '重量',
'体积', '商品编码', '条形码', '商品简介', '商品关键字', '商品口令', '购买送积分'
];
break;
case 'store_goods':
$verifyColumns = [
'商品编号', '商品名称', '商品类型', '平台商品分类(一级)', '平台商品分类(二级)', '平台商品分类(三级)','门店商品分类(一级)', '门店商品分类(二级)', '门店商品分类(三级)', '商品单位',
'商品图片', '商品视频', '商品详情', '已售数量', '规格类型', '规格类型值',
'规格名称', '规格值组合', '规格图片', '售价' , '划线价', '成本价', '库存', '重量',
'体积', '商品编码', '条形码', '商品简介', '商品关键字', '商品口令'
];
break;
case 'supplier_goods':
$verifyColumns = [
'商品编号', '商品名称', '商品类型', '商品分类(一级)', '商品分类(二级)', '商品分类(三级)', '商品单位',
'商品图片', '商品视频', '商品详情', '已售数量', '规格类型', '规格类型值',
'规格名称', '规格值组合', '规格图片', '结算价', '库存', '重量',
'体积', '商品编码', '条形码', '商品简介', '商品关键字', '商品口令'
];
break;
default:
$verifyColumns = [];
}
$firstRowDataSlice = array_slice($firstRowData, 0, count($verifyColumns));
if ($firstRowDataSlice != $verifyColumns) {
throw new ValidateException('导入文件格式不正确');
}
return true;
}
/**
* 根据类型处理每行数据
* @param array $rowData
* @param $type
* @return array
*/
protected function processRowData(array $rowData, $import_type)
{
switch ($import_type) {
case 'user' :
return array_combine(
['openid', 'unionid', 'uid', 'phone', 'nickname', 'real_name', 'sex', 'birthday', 'level', 'exp', 'overdue_time', 'integral',
'now_money', 'label', 'group', 'login_type', 'province', 'city', 'area', 'addres'],
array_map('strval', $rowData)
);
break;
case 'goods':
return array_combine(
[
'id',//商品编号
'store_name',//商品名称
'product_type',//商品类型
'cate_name_one', //商品分类(一级)
'cate_name_two', //商品分类(二级)
'cate_name_three', //商品分类(三级)
'unit_name', //商品单位
'slider_image', //商品图片
'video_link', //商品视频
'description', //商品详情
'ficti',//已售数量
'spec_type', //规格类型
'sku_type_value', //规格类型值
'sku_name', //规格名称
'sku_value', //规格值组合
'pic', //规格图片
'price', //售价
'price_range_min', //调价区间:最小值
'price_range_max', //调价区间:最大值
'ot_price', //划线价
'cost', //成本价
'stock', //库存
'weight', //重量
'volume',//体积
'code',//商品编码
'bar_code',//条形码
'store_info', //商品简介
'keyword', //商品关键字
'command_word', //商品口令
'give_integral',//购买送积分
],
array_map('strval', $rowData)
);
break;
case 'store_goods':
return array_combine(
[
'id',//商品编号
'store_name',//商品名称
'product_type',//商品类型
'cate_name_one', //平台商品分类(一级)
'cate_name_two', //平台商品分类(二级)
'cate_name_three', //平台商品分类(三级)
'store_cate_name_one', //门店商品分类(一级)
'store_cate_name_two', //门店商品分类(二级)
'store_cate_name_three', //门店商品分类(三级)
'unit_name', //商品单位
'slider_image', //商品图片
'video_link', //商品视频
'description', //商品详情
'ficti',//已售数量
'spec_type', //规格类型
'sku_type_value', //规格类型值
'sku_name', //规格名称
'sku_value', //规格值组合
'pic', //规格图片
'price', //售价
'ot_price', //划线价
'cost', //成本价
'stock', //库存
'weight', //重量
'volume',//体积
'code',//商品编码
'bar_code',//条形码
'store_info', //商品简介
'keyword', //商品关键字
'command_word', //商品口令
],
array_map('strval', $rowData)
);
break;
case 'supplier_goods':
return array_combine(
[
'id',//商品编号
'store_name',//商品名称
'product_type',//商品类型
'cate_name_one', //商品分类(一级)
'cate_name_two', //商品分类(二级)
'cate_name_three', //商品分类(三级)
'unit_name', //商品单位
'slider_image', //商品图片
'video_link', //商品视频
'description', //商品详情
'ficti',//已售数量
'spec_type', //规格类型
'sku_type_value', //规格类型值
'sku_name', //规格名称
'sku_value', //规格值组合
'pic', //规格图片
'settle_price', //结算价
'stock', //库存
'weight', //重量
'volume',//体积
'code',//商品编码
'bar_code',//条形码
'store_info', //商品简介
'keyword', //商品关键字
'command_word', //商品口令
],
array_map('strval', $rowData)
);
break;
default:
return [];
}
}修改文件:app/services/product/product/StoreProductServices.php
修改方法:productImport()
/**
* 商品导入
* @param $importData
* @param $impord_id
* @param $end
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function productImport($importData, $impord_id, $end, $type = 0, $relation_id = 0)
{
$productCateServices = app()->make(StoreProductCategoryServices::class);
$storeBrandServices = app()->make(StoreBrandServices::class);
$unitServices = app()->make(StoreProductUnitServices::class);
// 检查门店是否开启自建商品分类
$storeSelfBuildCate = false;
if ($type == 1 && $relation_id > 0) {
/** @var SystemStoreServices $storeServices */
$storeServices = app()->make(SystemStoreServices::class);
$storeSelfBuildCate = (bool)$storeServices->value(
['id' => $relation_id],
'product_category_status'
);
}
$productData = $issetProductArr = [];
$virtualType = ['普通商品' => 0, '卡密/网盘' => 1, '优惠券' => 2, '虚拟商品' => 3, '次卡商品' => 4, '卡项商品' => 5, '预约商品' => 6];
$productAttrValueServices = app()->make(StoreProductAttrValueServices::class);
$barCodeArr = array_unique($productAttrValueServices->getColumn(['type' => 0], 'code', 'id'));
$barCodeNumberArr = array_unique($productAttrValueServices->getColumn(['type' => 0], 'bar_code', 'id'));
$unit = $unitServices->getColumn(['status' => 1, 'is_del' => 0], 'name', 'id');
$error = [];
$jump1 = 0;
foreach ($importData as $sku) {
if ($sku['id'] == null) {
$jump1 += 1;
continue;
}
$error[$sku['id']][] = $sku;
if (!isset($productData[$sku['id']])) {
$productData[$sku['id']]['product_type'] = $virtualType[$sku['product_type']] ?? 0;
// 平台分类:始终使用 Excel 中的平台分类列
$productData[$sku['id']]['cate_id'] = $productCateServices->getCateId(0, 0, $sku['cate_name_one'], $sku['cate_name_two'], $sku['cate_name_three']);
// 门店自建分类处理
if ($type == 1 && $relation_id > 0 && $storeSelfBuildCate) {
// 开启自建分类:优先使用 Excel 中的「门店商品分类」列,未填写则回退到平台分类名
$storeCateOne = $sku['store_cate_name_one'] ?? $sku['cate_name_one'];
$storeCateTwo = $sku['store_cate_name_two'] ?? $sku['cate_name_two'];
$storeCateThree = $sku['store_cate_name_three'] ?? $sku['cate_name_three'];
$productData[$sku['id']]['store_cate_id'] = $productCateServices->getCateId(
$type, $relation_id, $storeCateOne, $storeCateTwo, $storeCateThree
);
} elseif ($type == 1 && $relation_id > 0 && !$storeSelfBuildCate) {
// 未开启自建分类:门店分类留空,后续通过定时任务同步
$productData[$sku['id']]['store_cate_id'] = [];
} else {
$productData[$sku['id']]['store_cate_id'] = [];
}
$productData[$sku['id']]['store_name'] = $sku['store_name'];
$productData[$sku['id']]['brand_id'] = [];
$productData[$sku['id']]['store_info'] = $sku['store_info'];
$productData[$sku['id']]['keyword'] = $sku['keyword'];
$productData[$sku['id']]['unit_name'] = in_array($sku['unit_name'], $unit) ? $sku['unit_name'] : '';
$productData[$sku['id']]['recommend_image'] = '';
$productData[$sku['id']]['slider_image'] = explode(';', $sku['slider_image']);
$productData[$sku['id']]['sort'] = 0;
$productData[$sku['id']]['ficti'] = $sku['ficti'];
$productData[$sku['id']]['give_integral'] = $sku['give_integral'] ?? 0;
$productData[$sku['id']]['is_show'] = 0;
// $productData[$sku['id']]['is_hot'] = 0;
// $productData[$sku['id']]['is_benefit'] = 0;
// $productData[$sku['id']]['is_best'] = 0;
// $productData[$sku['id']]['is_new'] = 0;
$productData[$sku['id']]['is_good'] = 0;
$productData[$sku['id']]['description'] = $this->processDescription($sku['description']);
$productData[$sku['id']]['spec_type'] = $sku['spec_type'] == '多规格' ? 1 : 0;
$productData[$sku['id']]['video_open'] = $sku['video_link'] != '' ? 1 : 0;
$productData[$sku['id']]['video_link'] = $sku['video_link'];
//items
//attrs
//attr
$productData[$sku['id']]['related'] = [];
$productData[$sku['id']]['recommend'] = [];
$productData[$sku['id']]['activity'] = ['默认', '秒杀', '砍价', '拼团'];
$productData[$sku['id']]['coupon_ids'] = [];
$productData[$sku['id']]['label_id'] = [];
$productData[$sku['id']]['command_word'] = $sku['command_word'];
$productData[$sku['id']]['tao_words'] = '';
$productData[$sku['id']]['is_copy'] = 0;
$productData[$sku['id']]['delivery_type'] = [1];
$productData[$sku['id']]['freight'] = 1;
$productData[$sku['id']]['postage'] = 0;
$productData[$sku['id']]['temp_id'] = '';
$productData[$sku['id']]['recommend_list'] = [];
$productData[$sku['id']]['soure_link'] = '';
$productData[$sku['id']]['bar_code'] = '';
$productData[$sku['id']]['code'] = '';
$productData[$sku['id']]['is_support_refund'] = 1;
$productData[$sku['id']]['is_presale_product'] = 0;
$productData[$sku['id']]['presale_time'] = [];
$productData[$sku['id']]['presale_day'] = 0;
$productData[$sku['id']]['is_vip_product'] = 0;
$productData[$sku['id']]['auto_on_time'] = 0;
$productData[$sku['id']]['auto_off_time'] = 0;
$productData[$sku['id']]['custom_form'] = [];
$productData[$sku['id']]['system_form_id'] = 0;
$productData[$sku['id']]['store_label_id'] = [];
$productData[$sku['id']]['ensure_id'] = 0;
$productData[$sku['id']]['specs'] = [];
$productData[$sku['id']]['specs_id'] = 0;
$productData[$sku['id']]['is_limit'] = 0;
$productData[$sku['id']]['limit_type'] = 0;
$productData[$sku['id']]['limit_num'] = 0;
$productData[$sku['id']]['presale_status'] = 0;
}
$detail = [];
$sku_value = explode(';', $sku['sku_value']);
if ($sku_value) {
foreach ($sku_value as $pair) {
if (!$pair) continue;
$pair_arr = explode('=', $pair);
if (count($pair_arr) < 2) throw new AdminException('规格值组合有误!');
list($key, $value) = explode('=', $pair);
$detail[$key] = $value;
}
}
if ($sku['code'] != '' && in_array($sku['code'], $barCodeArr)) {
$issetProductArr[] = $sku['id'];
}
if ($sku['bar_code'] != '' && in_array($sku['bar_code'], $barCodeNumberArr)) {
$issetProductArr[] = $sku['id'];
}
if ($sku['spec_type'] == '多规格') {
$productData[$sku['id']]['attrs'][] = [
'attr_arr' => array_values($detail),
'detail' => $detail,
'price' => $sku['price'] ?? 0,
'price_range_min' => $sku['price_range_min'] ?? 0,
'price_range_max' => $sku['price_range_max'] ?? 0,
'settle_price' => $sku['settle_price'] ?? 0,
'pic' => $sku['pic'],
'ot_price' => $sku['ot_price'] ?? 0,
'cost' => $sku['cost'] ?? 0,
'stock' => $sku['stock'],
'is_show' => 1,
'is_default_select' => 0,
'is_virtual' => 0,
'brokerage' => 0,
'brokerage_two' => 0,
'vip_price' => 0,
'vip_proportion' => 0,
'unique' => '',
'weight' => $sku['weight'],
'volume' => $sku['volume'],
'code' => $sku['code'],
'bar_code' => $sku['bar_code'],
];
} else {
$productData[$sku['id']]['attrs'][] = [];
$productData[$sku['id']]['attr'] = [
'attr_arr' => array_values($detail),
'detail' => $detail,
'price' => $sku['price'] ?? 0,
'price_range_min' => $sku['price_range_min'] ?? 0,
'price_range_max' => $sku['price_range_max'] ?? 0,
'settle_price' => $sku['settle_price'] ?? 0,
'pic' => $sku['pic'],
'ot_price' => $sku['ot_price'] ?? 0,
'cost' => $sku['cost'] ?? 0,
'stock' => $sku['stock'],
'is_show' => 1,
'is_default_select' => 0,
'is_virtual' => 0,
'brokerage' => 0,
'brokerage_two' => 0,
'vip_price' => 0,
'vip_proportion' => 0,
'unique' => '',
'weight' => $sku['weight'],
'volume' => $sku['volume'],
'code' => $sku['code'],
'bar_code' => $sku['bar_code'],
];
}
$items = [];
$pairs = explode(';', $sku['sku_type_value']);
if ($pairs) {
foreach ($pairs as $pair) {
if (!$pair) continue;
$pair_arr1 = explode('=', $pair);
if (count($pair_arr1) < 2) throw new AdminException('规格类型值有误!');
// 将每个部分按等号分割成 key 和 value
list($key, $values) = explode('=', $pair);
// 将 value 部分按逗号分割为数组
$detailArray = explode(',', $values);
$detail = [];
foreach ($detailArray as &$det) {
$detail[] = [
'value' => $det,
'pic' => '',
];
}
// 重新构建原始数组的结构
$items[] = [
'value' => $key,
'detail' => $detail
];
}
}
$productData[$sku['id']]['items'] = $items;
}
$all = count($productData);
foreach (array_unique($issetProductArr) as $issetProduct) {
if (isset($productData[$issetProduct])) {
unset($productData[$issetProduct]);
}
}
$success = count($productData);
$jump = count($issetProductArr);
$jump = $jump + $jump1;
/** @var ImportRecordServices $importServices */
$importServices = app()->make(ImportRecordServices::class);
/** @var ImportRecordErrorServices $errorServices */
$errorServices = app()->make(ImportRecordErrorServices::class);
$error_sum = 0;
foreach ($productData as $k => $info) {
try {
if (!$this->saveData(0, $info, $type, $relation_id)) {
foreach ($error[$k] as $item) {
$errorServices->save([
'record_id' => $impord_id,
'original_data' => json_encode($item),
'fail_msg' => '添加失败,请检测导入数据',
]);
$error_sum += 1;
}
}
} catch (\Throwable $e) {
foreach ($error[$k] as $item) {
$errorServices->save([
'record_id' => $impord_id,
'original_data' => json_encode($item),
'fail_msg' => $e->getMessage(),
]);
$error_sum += 1;
}
}
}
//是否最后一批数据
if ($end) {
$importServices->update($impord_id, ['status' => $error_sum > 0 ? -1 : 1, 'jump_count' => $jump, 'fail_count' => $error_sum]);
} else {
$importServices->update($impord_id, ['status' => -1, 'jump_count' => $jump, 'fail_count' => $error_sum]);
}
return ['error_sum' => $error_sum, 'jump' => $jump];
}修改文件:app/services/product/category/StoreProductCategoryServices.php
修改方法:getCateId()
public function getCateId($type = 0, $relation_id = 0, $cate_name_one = '', $cate_name_two = '', $cate_name_three = '')
{
if ($cate_name_one != '') {
$cate_name_one = explode(',', $cate_name_one)[0];
$cate_id_one = $this->dao->value(['cate_name' => $cate_name_one, 'type'=> $type, 'relation_id'=> $relation_id], 'id');
if (!$cate_id_one) {
$cate_id_one = $this->dao->save(['cate_name' => $cate_name_one, 'add_time' => time(), 'type'=> $type, 'relation_id'=> $relation_id])['id'];
}
if ($cate_name_two != '') {
$cate_name_two = explode(',', $cate_name_two)[0];
$cate_id_two = $this->dao->value(['cate_name' => $cate_name_two, 'pid' => $cate_id_one, 'type'=> $type, 'relation_id'=> $relation_id], 'id');
if (!$cate_id_two) {
$cate_id_two = $this->dao->save(['cate_name' => $cate_name_two, 'pid' => $cate_id_one, 'add_time' => time(), 'type'=> $type, 'relation_id'=> $relation_id])['id'];
}
if ($cate_name_three != '') {
$cate_name_three = explode(',', $cate_name_three)[0];
$cate_id_three = $this->dao->value(['cate_name' => $cate_name_three, 'pid' => $cate_id_two, 'type'=> $type, 'relation_id'=> $relation_id], 'id');
if (!$cate_id_three) {
$cate_id_three = $this->dao->save(['cate_name' => $cate_name_three, 'pid' => $cate_id_two, 'add_time' => time(), 'type'=> $type, 'relation_id'=> $relation_id])['id'];
}
return [$cate_id_one, $cate_id_two, $cate_id_three];
}
return [$cate_id_one, $cate_id_two];
}
return [$cate_id_one];
}
return [];
}注意:修改完成后下载下面模板重新编辑门店导入信息

