235 lines
6.9 KiB
Markdown
235 lines
6.9 KiB
Markdown
异步excel导入
|
||
|
||
|
||
|
||
## 安装
|
||
|
||
```bash
|
||
$ go get -u gitea.cdlsxd.cn/self-tools/l_excel_import
|
||
```
|
||
|
||
|
||
## 使用
|
||
```go
|
||
importExcel, err := excel.NewImportExcel("goods_import",
|
||
excel.WithHeader([]string{"条码", "分类名称", "货品名称", "货品编号", "商品货号", "品牌", "单位", "规格参数", "货品说明", "保质期", "保质期单位", "链接", "货品图片", "电商销售价格", "销售价", "供应商报价", "税率", "默认供应商", "默认存放仓库", "备注", "长", "宽", "高", "重量"}),
|
||
excel.WithTrimFiled([]string{"分类名称", "默认供应商", "默认存放仓库", "货品编号", "商品货号"}),
|
||
excel.WithFiledRegex(map[string]*excel.Regex{
|
||
"货品编号": {
|
||
Rule: "[\\u4e00-\\u9fa5]",
|
||
MatchBool: true,
|
||
Desc: "不能包含中文",
|
||
},
|
||
}),
|
||
excel.WithSpeedMod(true),
|
||
excel.WithRowPicHandle(func(pic *excel.Pic) (url string, err2 error) {
|
||
ossConf := s.c.GetOss()
|
||
businessMap, exist := ossConf.BusinessMap["goods"]
|
||
if !exist {
|
||
return "", errors.New("oss配置不存在")
|
||
}
|
||
//"physicalGoodsSystems/images/goods"
|
||
url = s.GoodsBiz.OssPathFile(businessMap.Folder, pic.PicInfos.Format.AltText, pic.PicInfos.Extension)
|
||
// 判断endpoint字段中是否存在internal的字段,如果存在则替换为internal
|
||
urlEndpoint := businessMap.Endpoint
|
||
if strings.Contains(businessMap.Endpoint, "-internal") {
|
||
urlEndpoint = strings.Replace(businessMap.Endpoint, "-internal", "", 1)
|
||
}
|
||
return fmt.Sprintf("https://%s.%s/%s", businessMap.Bucket, urlEndpoint, url), oss.NewOss(ossConf.AccessKeyId, ossConf.AccessKeySecret).UploadBase64Byte(
|
||
ctx,
|
||
businessMap.Endpoint,
|
||
businessMap.Bucket,
|
||
url,
|
||
pic.PicInfos.File)
|
||
}),
|
||
excel.WithDeleteOssHandle(func(ObjectName []string) (err error) {
|
||
ossConf := s.c.GetOss()
|
||
businessMap, exist := ossConf.BusinessMap["goods"]
|
||
if !exist {
|
||
return errors.New("oss配置不存在")
|
||
}
|
||
return oss.NewOss(ossConf.AccessKeyId, ossConf.AccessKeySecret).DeleteBatch(ctx, businessMap.Endpoint, businessMap.Bucket, ObjectName)
|
||
}),
|
||
excel.WithGetFileObject(func(fileObjectUrl string) (body io.ReadCloser, err error) {
|
||
ossConf := s.c.GetOss()
|
||
businessMap, exist := ossConf.BusinessMap["goods"]
|
||
if !exist {
|
||
return nil, errors.New("oss配置不存在")
|
||
}
|
||
return oss.NewOss(ossConf.AccessKeyId, ossConf.AccessKeySecret).GetObject(ctx, businessMap.Endpoint, businessMap.Bucket, fileObjectUrl)
|
||
}),
|
||
).Init(ctx, func(excel *excel.ImportExcel, rows []map[string]string) {
|
||
var sellByData int
|
||
//创建子上下文,防止父ctx取消导致无法请求rpc
|
||
subCtx, cancel := context.WithCancel(context.Background())
|
||
//协程结束后释放掉子上下文
|
||
defer cancel()
|
||
for k, v := range rows {
|
||
var (
|
||
supId int32
|
||
WareHouseId int32
|
||
CateId int32
|
||
webPrice float64
|
||
price float64
|
||
costPrice float64
|
||
)
|
||
//这里用中文作key是为了方便,如果用英文key或者数字作key,需要做映射关系,而且还要考虑key可能是任意类型,而且开发的时候出现excel插入删除也很麻烦
|
||
//分类
|
||
if len(v["分类名称"]) > 30 {
|
||
excel.AddErr("条码过长,请检查", k+1, v)
|
||
continue
|
||
}
|
||
if v["分类名称"] != "" {
|
||
if _, exist := cateMap[v["分类名称"]]; !exist {
|
||
excel.AddErr("商品分类不存在", k+1, v)
|
||
continue
|
||
}
|
||
CateId = cateMap[v["分类名称"]].Id
|
||
}
|
||
//供应商
|
||
if v["默认供应商"] != "" {
|
||
if _, exist := supplierMap[v["默认供应商"]]; !exist {
|
||
excel.AddErr("供应商不存在", k+1, v)
|
||
continue
|
||
}
|
||
supId = supplierMap[v["默认供应商"]].Id
|
||
}
|
||
//仓库
|
||
if v["默认存放仓库"] != "" {
|
||
if _, exist := wareHouseMap[v["默认存放仓库"]]; !exist {
|
||
excel.AddErr("仓库不存在", k+1, v)
|
||
continue
|
||
}
|
||
WareHouseId = int32(wareHouseMap[v["默认存放仓库"]].Id)
|
||
}
|
||
//电商价
|
||
if v["电商销售价格"] != "" {
|
||
webPrice, err = strconv.ParseFloat(v["电商销售价格"], 64)
|
||
if err != nil {
|
||
excel.AddErr("电商销售价格格式不正确", k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
if v["销售价"] != "" {
|
||
price, err = strconv.ParseFloat(v["销售价"], 64)
|
||
if err != nil {
|
||
excel.AddErr("销售价格式不正确", k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
if v["供应商报价"] != "" {
|
||
costPrice, err = strconv.ParseFloat(v["供应商报价"], 64)
|
||
if err != nil {
|
||
excel.AddErr("供应商报价格式不正确", k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
|
||
//保质期
|
||
if v["保质期"] == "" {
|
||
sellByData = 0
|
||
} else {
|
||
sellByData, err = strconv.Atoi(v["保质期"])
|
||
if err != nil {
|
||
excel.AddErr("保质期格式不正确", k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
|
||
//税率
|
||
tax := util.RemovePercentSignsWithBuilder(v["税率"])
|
||
taxRate, err := strconv.ParseFloat(tax, 64)
|
||
if err != nil {
|
||
excel.AddErr("税率格式不正确", k+1, v)
|
||
continue
|
||
}
|
||
//"条码", "分类名称", "货品名称", "货品编号", "品牌", "单位", "规格参数", "货品说明", "保质期", "保质期单位", "链接", "货品图片", "电商销售价格", "代发含税运价格", "税率", "默认供应商", "默认存放仓库", "备注"}
|
||
goodsInfo := &pb.AddGoodsReqs{
|
||
//商品标题
|
||
Title: v["货品名称"],
|
||
//商品品牌
|
||
Brand: v["品牌"],
|
||
//商品简介、卖点
|
||
Introduction: v["货品说明"],
|
||
|
||
//商品编码
|
||
GoodsNum: v["货品编号"],
|
||
//商品货号
|
||
GoodsCode: v["商品货号"],
|
||
//商品条形码
|
||
GoodsBarCode: v["条码"],
|
||
//是否组合商品
|
||
IsComposeGoods: 2,
|
||
//市场价,单位分
|
||
Price: float32(price),
|
||
//单位
|
||
Unit: v["单位"],
|
||
//保质期
|
||
SellByDate: int32(sellByData),
|
||
//保质期单位
|
||
SellByDateUnit: v["保质期单位"],
|
||
//外部平台链接
|
||
ExternalUrl: v["链接"],
|
||
//电商平台价格
|
||
ExternalPrice: float32(webPrice),
|
||
//销售价
|
||
SalesPrice: float32(price),
|
||
//税率
|
||
TaxRate: float32(taxRate),
|
||
//商品参数
|
||
GoodsAttributes: v["规格参数"],
|
||
//商品说明
|
||
GoodsIllustration: v["货品说明"],
|
||
//备注
|
||
Remark: v["备注"],
|
||
Status: pojo.STATUS_ENABLE,
|
||
IsHot: 2,
|
||
}
|
||
|
||
goodsAdd, err := goods.NewGoodsBiz(types.ToTmplConf(s.c)).Add(subCtx, goodsInfo)
|
||
if err != nil {
|
||
excel.AddErr(fmt.Sprintf("添加商品失败:%s", err), k+1, v)
|
||
continue
|
||
}
|
||
if CateId != 0 {
|
||
_, err = goods.NewGoodsCateGoryRelationBiz(types.ToTmplConf(s.c)).Add(subCtx, &api.AddGoodsCategoryRelationReqs{
|
||
GoodsId: goodsAdd.Id,
|
||
CategoryIds: []int32{CateId},
|
||
})
|
||
if err != nil {
|
||
excel.AddErr(fmt.Sprintf("添加商品分类失败:%s", err), k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
if WareHouseId != 0 && supId != 0 && costPrice != 0 {
|
||
_, err = goods.NewGoodsSupplierRelationBiz(types.ToTmplConf(s.c)).Add(subCtx, &pb.AddGoodsSupplierRelationReqs{
|
||
SupplierId: supId,
|
||
GoodsId: goodsAdd.Id,
|
||
WarehouseId: WareHouseId,
|
||
IsDefaultWarehouse: pojo.IS_DEFAULT_WAREHOUSE,
|
||
SupplierGoodsPrice: float32(costPrice),
|
||
Sort: 1,
|
||
})
|
||
if err != nil {
|
||
excel.AddErr(fmt.Sprintf("添加供应商商品关系失败:%s", err), k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
if v["货品图片"] != "" { //商品图片
|
||
for key, media := range strings.Split(v["货品图片"], ",") {
|
||
_, _err := goods.NewGoodsMediaBiz(types.ToTmplConf(s.c)).Add(subCtx, &pb.AddGoodsMediaReqs{
|
||
GoodsId: goodsAdd.Id,
|
||
Url: media,
|
||
Sort: int32(key + 1),
|
||
Type: pojo.GOODS_MEDIA_TYPE_IMAGE,
|
||
})
|
||
if _err != nil {
|
||
excel.AddErr(fmt.Sprintf("添加商品图片失败:%s", err), k+1, v)
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
excel.Next()
|
||
}
|
||
})
|
||
``` |