l_excel_import/README.md

235 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

异步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()
}
})
```