package models import ( "bytes" "encoding/json" "errors" "fmt" "github.com/codinl/go-logger" "github.com/xuri/excelize/v2" "reflect" ) type CategoryExcel struct { FirstCategory string `json:"first_category" binding:"required"` // 一级分类 SecondCategory string `json:"second_category"` // 二级分类 ThreeCategory string `json:"three_category"` // 三级分类 } type CommodityExcel struct { Category string `json:"category" binding:"required"` // 商品所属分类 Name string `json:"name" binding:"required"` // 商品名称 IMEIType string `json:"imei_type" binding:"required"` // 是否串码 1-无串码 2-串码(系统生成) 3-串码(手动添加) SysGenerate string `json:"sys_generate" binding:"required"` // 系统生成串码 SupplierName string `json:"supplier_name" binding:"required"` // 供应商名称 SellBrokerage string `json:"sell_brokerage" binding:"required"` // 销售毛利提成 StaffBrokerage string `json:"staff_brokerage" binding:"required"` // 员工毛利提成 MemberDiscount string `json:"member_discount" binding:"required"` // 会员优惠 RetailPrice string `json:"retail_price" binding:"required"` // 指导零售价 MinRetailPrice string `json:"min_retail_price" binding:"required"` // 最低零售价 WholesalePrice string `json:"wholesale_price" binding:"required"` // 指导采购价 StaffCostPrice string `json:"staff_cost_price" binding:"required"` // 员工成本价加价 Origin string `json:"origin"` // 产地 Remark string `json:"remark"` // 备注 } // 获取struct的tag标签,匹配excel导入数据 func getJSONTagNames(s interface{}) []string { valueType := reflect.TypeOf(s) if valueType.Kind() != reflect.Struct { fmt.Println("传入的不是结构体") return nil } var tagNames []string for i := 0; i < valueType.NumField(); i++ { field := valueType.Field(i) tag := field.Tag.Get("json") if tag != "" { tagNames = append(tagNames, tag) } } return tagNames } // 预览excel数据(不做必填项校验) func FileExcelReader(d []byte, cols []string) ([]byte, []map[string]interface{}, error) { reader, err := excelize.OpenReader(bytes.NewReader(d)) if err != nil { logger.Error("open reader err:", err) return nil, nil, err } sheetList := reader.GetSheetList() if len(sheetList) == 0 { logger.Error("sheet list nil") return nil, nil, err } rows, err := reader.Rows(sheetList[0]) if err != nil { logger.Error("reader rows err:", err) return nil, nil, err } sheetCols, err := reader.GetCols(sheetList[0]) if err != nil { logger.Error("reader get cols err:", err) return nil, nil, err } if len(sheetCols) == 0 { logger.Error("get cols null err") return nil, nil, err } colsMap := make([]map[string]interface{}, 0) if len(cols) == 0 { if sheetList[0] == "导分类" { cols = getJSONTagNames(CategoryExcel{}) } else if sheetList[0] == "导商品" { cols = getJSONTagNames(CommodityExcel{}) } else { cols = make([]string, len(sheetCols)) for i := 0; i < len(sheetCols); i++ { cols[i] = fmt.Sprintf("c%02d", i) } } } else { fmt.Println("cols", len(cols)) fmt.Println("sheetCols", len(sheetCols)) if len(cols) != len(sheetCols) { logger.Error("cols length not equal columns") return nil, nil, errors.New("cols length not equal columns") } } for rows.Next() { columns, err := rows.Columns() if err != nil { logger.Error("rows columns err:", err) return nil, nil, err } columnMap := make(map[string]interface{}, 0) for i, _ := range cols { columnMap[cols[i]] = "" } for i, _ := range columns { columnMap[cols[i]] = columns[i] } fmt.Println("columnMap:", columnMap) colsMap = append(colsMap, columnMap) } fmt.Println("colsMap:", colsMap) mCols, err := json.Marshal(colsMap) if err != nil { logger.Error("marshal err:", err) return mCols, nil, err } return mCols, colsMap, nil } // 导入excel数据(校验必填项) func FileExcelImport(d []byte, cols []string) ([]byte, []map[string]interface{}, error) { reader, err := excelize.OpenReader(bytes.NewReader(d)) if err != nil { logger.Error("open reader err:", err) return nil, nil, err } sheetList := reader.GetSheetList() if len(sheetList) == 0 { logger.Error("sheet list nil") return nil, nil, err } rows, err := reader.Rows(sheetList[0]) if err != nil { logger.Error("reader rows err:", err) return nil, nil, err } sheetCols, err := reader.GetCols(sheetList[0]) if err != nil { logger.Error("reader get cols err:", err) return nil, nil, err } if len(sheetCols) == 0 { logger.Error("get cols null err") return nil, nil, err } colsMap := make([]map[string]interface{}, 0) if len(cols) == 0 { if sheetList[0] == "导分类" { //校验商品分类导入规则 err := checkCategoryExcel(sheetCols) if err != nil { return nil, nil, err } cols = getJSONTagNames(CategoryExcel{}) } else if sheetList[0] == "导商品" { //校验商品资料导入规则 err := checkCommodityExcel(sheetCols) if err != nil { return nil, nil, err } cols = getJSONTagNames(CommodityExcel{}) } else { cols = make([]string, len(sheetCols)) for i := 0; i < len(sheetCols); i++ { cols[i] = fmt.Sprintf("c%02d", i) } } } else { fmt.Println("cols", len(cols)) fmt.Println("sheetCols", len(sheetCols)) if len(cols) != len(sheetCols) { logger.Error("cols length not equal columns") return nil, nil, errors.New("cols length not equal columns") } } for rows.Next() { columns, err := rows.Columns() if err != nil { logger.Error("rows columns err:", err) return nil, nil, err } columnMap := make(map[string]interface{}, 0) for i, _ := range cols { columnMap[cols[i]] = "" for j, _ := range columns { columnMap[cols[j]] = columns[j] } } //for i, _ := range columns { // columnMap[cols[i]] = columns[i] //} fmt.Println("columnMap:", columnMap) colsMap = append(colsMap, columnMap) } fmt.Println("colsMap:", colsMap) mCols, err := json.Marshal(colsMap) if err != nil { logger.Error("marshal err:", err) return mCols, nil, err } return mCols, colsMap, nil } // 校验商品分类导入规则 // 导入商品分类校验报错: (1)只有3级,没有2级或1级 (2)有2,3级,但没有1级 func checkCategoryExcel(sheetCols [][]string) error { if len(sheetCols) != 3 { return errors.New("模版错误,请检查文件") } if len(sheetCols[0]) < len(sheetCols[1]) || len(sheetCols[0]) < len(sheetCols[2]) { return errors.New("格式错误,缺少一级分类") } else if len(sheetCols[1]) < len(sheetCols[2]) { return errors.New("格式错误,缺少二级分类") } for i := 1; i < len(sheetCols[2]); i++ { if sheetCols[0][i] == "" && (sheetCols[1][i] != "" || sheetCols[2][i] != "") { return errors.New("格式错误,缺少一级分类") } else if sheetCols[2][i] != "" && sheetCols[1][i] == "" { return errors.New("格式错误,缺少二级分类") } } return nil } // 校验商品资料导入规则 // 导入商品资料校验报错:必填项缺少数据(除了产地、备注,其他都是必填项) func checkCommodityExcel(sheetCols [][]string) error { if len(sheetCols) != 14 { return errors.New("模版错误,请检查文件") } for i := 0; i < len(sheetCols)-2; i++ { if len(sheetCols[i]) < len(sheetCols[i+1]) { return errors.New("格式错误,有必填项未录入") } for _, v := range sheetCols[i] { if v == "" { return errors.New("格式错误,有必填项未录入") } } } return nil }