From aa32728f6eb6a1f99ee9eaf97bcbde1b4dfaa4fd Mon Sep 17 00:00:00 2001 From: chenlin Date: Thu, 9 Nov 2023 18:26:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=95=86=E5=93=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E3=80=81=E5=95=86=E5=93=81=E8=B5=84=E6=96=99=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 8 +- app/admin/apis/basic/category.go | 79 +++++++++ app/admin/apis/basic/commodity.go | 46 +++++- app/admin/models/commodity.go | 34 ++-- app/admin/models/file.go | 264 ++++++++++++++++++++++++++++++ app/admin/models/model.go | 14 +- app/admin/router/category.go | 2 + app/admin/router/commodity.go | 1 + app/admin/router/router.go | 2 - app/admin/router/sysrouter.go | 1 + docs/docs.go | 230 +++++++++++++++++++++++++- docs/swagger.json | 230 +++++++++++++++++++++++++- docs/swagger.yaml | 181 +++++++++++++++++++- static/导分类.xlsx | Bin 0 -> 10530 bytes static/导商品.xlsx | Bin 0 -> 11539 bytes 15 files changed, 1052 insertions(+), 40 deletions(-) create mode 100644 app/admin/models/file.go create mode 100644 static/导分类.xlsx create mode 100644 static/导商品.xlsx diff --git a/Makefile b/Makefile index eaf1380..7705906 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,12 @@ build-sqlite: # docker build . -t go-admin:latest -build dev: - GOOS=linux GOARCH=amd64 go build -o dev-go-admin main.go +build-dev: + set GOARCH=amd64 + set GOOS=linux + go build -o dev-go-admin main.go + + build: GOOS=linux GOARCH=amd64 go build -o go-admin main.go diff --git a/app/admin/apis/basic/category.go b/app/admin/apis/basic/category.go index a20fcae..722c063 100644 --- a/app/admin/apis/basic/category.go +++ b/app/admin/apis/basic/category.go @@ -9,6 +9,7 @@ import ( "go-admin/logger" "go-admin/tools" "go-admin/tools/app" + "io" "net/http" ) @@ -210,3 +211,81 @@ func CategoryDisplay(c *gin.Context) { app.OK(c, nil, "ok") } + +// CategoryImportView 导入商品分类预览 +// @Summary 导入商品分类预览 +// @Tags 商品分类 +// @Produce json +// @Accept json +// @Param file body string true "上传excel文件" +// @Success 200 {array} models.CategoryExcel +// @Router /api/v1/category/import_category_view [post] +func CategoryImportView(c *gin.Context) { + file, header, err := c.Request.FormFile("file") + if err != nil { + //logger.Error("form file err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + readAll, err := io.ReadAll(file) + if err != nil { + //logger.Error("read all err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + fmt.Println("header:", header.Filename) + _, colsMap, err := models.FileExcelImport([]byte(readAll), nil) + if err != nil { + //logger.Error("file excel reader err:", err) + app.Error(c, http.StatusInternalServerError, err, err.Error()) + return + } + fmt.Println("colsMap:", colsMap) + if len(colsMap) != 0 { + colsMap = colsMap[1:] + } + + app.OK(c, &colsMap, "") + return +} + +// CategoryImport 导入商品分类 +// @Summary 导入商品分类 +// @Tags 商品分类 +// @Produce json +// @Accept json +// @Param file body string true "上传excel文件" +// @Success 200 {object} app.Response +// @Router /api/v1/category/import_category [post] +func CategoryImport(c *gin.Context) { + file, header, err := c.Request.FormFile("file") + if err != nil { + //logger.Error("form file err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + readAll, err := io.ReadAll(file) + if err != nil { + //logger.Error("read all err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + fmt.Println("header:", header.Filename) + _, colsMap, err := models.FileExcelReader([]byte(readAll), nil) + if err != nil { + //logger.Error("file excel reader err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + fmt.Println("colsMap:", colsMap) + if len(colsMap) != 0 { + colsMap = colsMap[1:] + } + + app.OK(c, &colsMap, "") + return +} diff --git a/app/admin/apis/basic/commodity.go b/app/admin/apis/basic/commodity.go index dd446f7..a88871a 100644 --- a/app/admin/apis/basic/commodity.go +++ b/app/admin/apis/basic/commodity.go @@ -7,6 +7,7 @@ import ( "go-admin/app/admin/models" orm "go-admin/common/global" "go-admin/tools/app" + "io" "net/http" "strconv" ) @@ -14,7 +15,7 @@ import ( type CommodityCreateRequest struct { Name string `json:"name" binding:"required"` // 商品名称 ErpCategoryId uint32 `json:"erp_category_id" binding:"required"` // 商品分类id - IMEIType uint32 `json:"imei_type" binding:"required"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type" binding:"required"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) ErpSupplierId uint32 `json:"erp_supplier_id" binding:"required"` // 主供应商 RetailPrice uint32 `json:"retail_price" binding:"required"` // 指导零售价 MinRetailPrice uint32 `json:"min_retail_price" binding:"required"` // 最低零售价 @@ -184,13 +185,13 @@ type CommodityEditRequest struct { Id uint32 `json:"id" binding:"required"` // 商品id Name string `json:"name" binding:"required"` // 商品名称 ErpCategoryId uint32 `json:"erp_category_id" binding:"required"` // 商品分类id - IMEIType uint32 `json:"imei_type" binding:"required"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type" binding:"required"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) ErpSupplierId uint32 `json:"erp_supplier_id" binding:"required"` // 主供应商id RetailPrice uint32 `json:"retail_price" binding:"required"` // 指导零售价 MinRetailPrice uint32 `json:"min_retail_price" binding:"required"` // 最低零售价 StaffCostPrice uint32 `json:"staff_cost_price" binding:"required"` // 员工成本价加价 WholesalePrice uint32 `json:"wholesale_price" binding:"required"` // 指导采购价 - Brokerage1 float64 `json:"brokerage_1" binding:"required"` // 销售毛利提成 + Brokerage1 float64 `json:"brokerage_1"` // 销售毛利提成 Brokerage2 float64 `json:"brokerage_2"` // 员工毛利提成 MemberDiscount float64 `json:"member_discount"` // 会员优惠 Origin string `json:"origin"` // 产地 @@ -314,3 +315,42 @@ func CommodityDel(c *gin.Context) { app.OK(c, nil, "删除成功") return } + +// BatchImportView 导入商品资料预览 +// @Summary 导入商品资料预览 +// @Tags 商品资料 +// @Produce json +// @Accept json +// @Param file body string true "上传excel文件" +// @Success 200 {array} models.CommodityExcel +// @Router /api/v1/commodity/import_commodity_view [post] +func CommodityImportView(c *gin.Context) { + file, header, err := c.Request.FormFile("file") + if err != nil { + //logger.Error("form file err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + readAll, err := io.ReadAll(file) + if err != nil { + //logger.Error("read all err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + + fmt.Println("header:", header.Filename) + _, colsMap, err := models.FileExcelReader([]byte(readAll), nil) + if err != nil { + //logger.Error("file excel reader err:", err) + app.Error(c, http.StatusInternalServerError, err, "预览失败") + return + } + fmt.Println("colsMap:", colsMap) + if len(colsMap) != 0 { + colsMap = colsMap[1:] + } + + app.OK(c, &colsMap, "") + return +} diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index 264dbc8..3f9628e 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -27,7 +27,7 @@ type ErpStock struct { ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` ErpCategoryName string `json:"erp_category_name"` CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` - IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) RetailPrice uint32 `json:"retail_price"` MinRetailPrice uint32 `json:"min_retail_price"` Count uint32 `json:"count"` @@ -56,7 +56,7 @@ type ErpStockCommodity struct { CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` ErpCategoryName string `json:"erp_category_name"` - IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) IMEI string `json:"imei"` ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` ErpSupplierName string `json:"erp_supplier_name"` @@ -87,7 +87,7 @@ type ErpCommodity struct { Name string `json:"name"` // 商品名称 ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 商品分类id ErpCategoryName string `json:"erp_category_name"` // 商品分类名称 - IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) IMEI string `json:"imei"` // 串码 ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 主供应商id ErpSupplierName string `json:"erp_supplier_name"` // 主供应商名称 @@ -152,7 +152,7 @@ type ErpInventoryStock struct { ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` ErpCategoryName string `json:"erp_category_name"` CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` - IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) RetailPrice uint32 `json:"retail_price"` MinRetailPrice uint32 `json:"min_retail_price"` Count uint32 `json:"count"` @@ -174,7 +174,7 @@ type ErpInventoryStockCommodity struct { ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` ErpCommodityName string `json:"erp_commodity_name"` CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` - IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 + IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加) IMEI string `json:"imei"` ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` ErpSupplierName string `json:"erp_supplier_name"` @@ -250,21 +250,21 @@ func (c *ErpCommodity) SetErpCategory() error { } type ErpCommodityListReq struct { - SerialNumber string `json:"serial_number"` - ErpCommodityName string `json:"erp_commodity_name"` - ErpCategoryId uint32 `json:"erp_category_id"` - IMEI string `json:"imei"` - ErpSupplierId uint32 `json:"erp_supplier_id"` - PageNum int `json:"page_num"` - PageSize int `json:"page_size"` - IsExport uint32 `json:"is_export"` // 1-导出 + SerialNumber string `json:"serial_number"` // 商品编号 + ErpCommodityName string `json:"erp_commodity_name"` // 商品名称 + ErpCategoryId uint32 `json:"erp_category_id"` // 商品分类id + IMEI string `json:"imei"` // 串码 + ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id + PageNum int `json:"page_num"` // 页码 + PageSize int `json:"page_size"` // 每页展示数据条数 + IsExport uint32 `json:"is_export"` // 1-导出 } type ErpCommodityListResp struct { List []ErpCommodity `json:"list"` - Total int `json:"total"` - PageNum int `json:"page_num"` - PageSize int `json:"page_size"` - ExportUrl string `json:"export_url"` + Total int `json:"total"` // 总页数 + PageNum int `json:"page_num"` // 页码 + PageSize int `json:"page_size"` // 每页展示数据条数 + ExportUrl string `json:"export_url"` // 1-导出 } func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) { diff --git a/app/admin/models/file.go b/app/admin/models/file.go new file mode 100644 index 0000000..0032daa --- /dev/null +++ b/app/admin/models/file.go @@ -0,0 +1,264 @@ +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 +} diff --git a/app/admin/models/model.go b/app/admin/models/model.go index 51ed954..c1801f0 100644 --- a/app/admin/models/model.go +++ b/app/admin/models/model.go @@ -8,16 +8,16 @@ import ( var RecordNotFound = gorm.ErrRecordNotFound type BaseModel struct { - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` + CreatedAt time.Time `json:"createdAt"` // 创建时间 + UpdatedAt time.Time `json:"updatedAt"` // 更新时间 + DeletedAt *time.Time `json:"deletedAt"` // 删除时间 } type Model struct { - ID uint32 `json:"id" gorm:"primary_key;AUTO_INCREMENT"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"-"` - DeletedAt *time.Time `json:"-" sql:"index"` + ID uint32 `json:"id" gorm:"primary_key;AUTO_INCREMENT"` // 数据库记录编号 + CreatedAt time.Time `json:"createdAt"` // 创建时间 + UpdatedAt time.Time `json:"-"` // 更新时间 + DeletedAt *time.Time `json:"-" sql:"index"` // 删除时间 } type Unix struct { diff --git a/app/admin/router/category.go b/app/admin/router/category.go index 6b8c15e..f7bce7d 100644 --- a/app/admin/router/category.go +++ b/app/admin/router/category.go @@ -14,4 +14,6 @@ func registerCategoryRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddl r.POST("delete", basic.DeleteCategory) r.POST("list", basic.CategoryList) r.POST("display", basic.CategoryDisplay) + r.POST("import_category_view", basic.CategoryImportView) + r.POST("import_category", basic.CategoryImport) } diff --git a/app/admin/router/commodity.go b/app/admin/router/commodity.go index eeb27d7..f0435e3 100644 --- a/app/admin/router/commodity.go +++ b/app/admin/router/commodity.go @@ -14,4 +14,5 @@ func registerCommodityRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd r.POST("delete", basic.CommodityDel) r.POST("list", basic.CommodityList) r.POST("detail", basic.CommodityDetail) + r.POST("import_commodity_view", basic.CommodityImportView) } diff --git a/app/admin/router/router.go b/app/admin/router/router.go index d41bb63..9e46087 100644 --- a/app/admin/router/router.go +++ b/app/admin/router/router.go @@ -96,10 +96,8 @@ func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddle //供应商 registerSupplierRouter(v1, authMiddleware) - //商品分类 registerCategoryRouter(v1, authMiddleware) - //商品资料 registerCommodityRouter(v1, authMiddleware) } diff --git a/app/admin/router/sysrouter.go b/app/admin/router/sysrouter.go index 6d4018f..ba48f68 100644 --- a/app/admin/router/sysrouter.go +++ b/app/admin/router/sysrouter.go @@ -47,6 +47,7 @@ func sysBaseRouter(r *gin.RouterGroup) { func sysStaticFileRouter(r *gin.RouterGroup) { mime.AddExtensionType(".js", "application/javascript") r.Static("/static", "./static") + //r.StaticFile("/importCategory.xlsx", "/static/导分类.xlsx") r.Static("/form-generator", "./static/form-generator") } diff --git a/docs/docs.go b/docs/docs.go index b09b0fe..ed587e2 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -310,6 +310,78 @@ const docTemplate = `{ } } }, + "/api/v1/commodity/import_category_view": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "商品分类" + ], + "summary": "导入商品分类预览", + "parameters": [ + { + "description": "上传excel文件", + "name": "file", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.CategoryExcel" + } + } + } + } + } + }, + "/api/v1/commodity/import_commodity_view": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "商品资料" + ], + "summary": "导入商品资料预览", + "parameters": [ + { + "description": "上传excel文件", + "name": "file", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.CommodityExcel" + } + } + } + } + } + }, "/api/v1/commodity/list": { "post": { "consumes": [ @@ -3050,7 +3122,7 @@ const docTemplate = `{ "type": "integer" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3148,7 +3220,7 @@ const docTemplate = `{ "type": "integer" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3412,6 +3484,7 @@ const docTemplate = `{ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "display": { @@ -3419,6 +3492,7 @@ const docTemplate = `{ "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "name": { @@ -3435,6 +3509,26 @@ const docTemplate = `{ } } }, + "models.CategoryExcel": { + "type": "object", + "required": [ + "first_category" + ], + "properties": { + "first_category": { + "description": "一级分类", + "type": "string" + }, + "second_category": { + "description": "二级分类", + "type": "string" + }, + "three_category": { + "description": "三级分类", + "type": "string" + } + } + }, "models.CategoryModel": { "type": "object", "properties": { @@ -3443,6 +3537,7 @@ const docTemplate = `{ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "display": { @@ -3450,6 +3545,7 @@ const docTemplate = `{ "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "name": { @@ -3473,6 +3569,81 @@ const docTemplate = `{ } } }, + "models.CommodityExcel": { + "type": "object", + "required": [ + "category", + "imei_type", + "member_discount", + "min_retail_price", + "name", + "retail_price", + "sell_brokerage", + "staff_brokerage", + "staff_cost_price", + "supplier_name", + "sys_generate", + "wholesale_price" + ], + "properties": { + "category": { + "description": "商品所属分类", + "type": "string" + }, + "imei_type": { + "description": "是否串码 1-无串码 2-串码(系统生成) 3-串码(手动添加)", + "type": "string" + }, + "member_discount": { + "description": "会员优惠", + "type": "string" + }, + "min_retail_price": { + "description": "最低零售价", + "type": "string" + }, + "name": { + "description": "商品名称", + "type": "string" + }, + "origin": { + "description": "产地", + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "retail_price": { + "description": "指导零售价", + "type": "string" + }, + "sell_brokerage": { + "description": "销售毛利提成", + "type": "string" + }, + "staff_brokerage": { + "description": "员工毛利提成", + "type": "string" + }, + "staff_cost_price": { + "description": "员工成本价加价", + "type": "string" + }, + "supplier_name": { + "description": "供应商名称", + "type": "string" + }, + "sys_generate": { + "description": "系统生成串码", + "type": "string" + }, + "wholesale_price": { + "description": "指导采购价", + "type": "string" + } + } + }, "models.DictType": { "type": "object", "properties": { @@ -3481,12 +3652,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "dictId": { @@ -3516,6 +3689,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -3524,12 +3698,14 @@ const docTemplate = `{ "type": "object", "properties": { "createdAt": { + "description": "创建时间", "type": "string" }, "full_num": { "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "level": { @@ -3578,6 +3754,7 @@ const docTemplate = `{ "type": "number" }, "createdAt": { + "description": "创建时间", "type": "string" }, "erp_category": { @@ -3600,6 +3777,7 @@ const docTemplate = `{ "type": "string" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "imei": { @@ -3607,7 +3785,7 @@ const docTemplate = `{ "type": "string" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3656,15 +3834,19 @@ const docTemplate = `{ "type": "object", "properties": { "erp_category_id": { + "description": "商品分类id", "type": "integer" }, "erp_commodity_name": { + "description": "商品名称", "type": "string" }, "erp_supplier_id": { + "description": "供应商id", "type": "integer" }, "imei": { + "description": "串码", "type": "string" }, "is_export": { @@ -3672,12 +3854,15 @@ const docTemplate = `{ "type": "integer" }, "page_num": { + "description": "页码", "type": "integer" }, "page_size": { + "description": "每页展示数据条数", "type": "integer" }, "serial_number": { + "description": "商品编号", "type": "string" } } @@ -3686,6 +3871,7 @@ const docTemplate = `{ "type": "object", "properties": { "export_url": { + "description": "1-导出", "type": "string" }, "list": { @@ -3695,12 +3881,15 @@ const docTemplate = `{ } }, "page_num": { + "description": "页码", "type": "integer" }, "page_size": { + "description": "每页展示数据条数", "type": "integer" }, "total": { + "description": "总页数", "type": "integer" } } @@ -3745,6 +3934,7 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { @@ -3752,6 +3942,7 @@ const docTemplate = `{ "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "infoId": { @@ -3797,6 +3988,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "username": { @@ -3827,12 +4019,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "icon": { @@ -3884,6 +4078,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "visible": { @@ -3898,12 +4093,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "params": { @@ -3937,6 +4134,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -3977,6 +4175,7 @@ const docTemplate = `{ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "email": { @@ -3984,6 +4183,7 @@ const docTemplate = `{ "type": "string" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "landline": { @@ -4028,12 +4228,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4068,6 +4270,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4099,12 +4302,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "params": { @@ -4118,6 +4323,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4138,12 +4344,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4178,6 +4386,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4195,12 +4404,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptId": { @@ -4245,6 +4456,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4263,12 +4475,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4297,6 +4511,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4316,6 +4531,7 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { @@ -4323,6 +4539,7 @@ const docTemplate = `{ "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptName": { @@ -4398,6 +4615,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "userAgent": { @@ -4416,12 +4634,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptIds": { @@ -4469,6 +4689,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4495,12 +4716,14 @@ const docTemplate = `{ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptId": { @@ -4561,6 +4784,7 @@ const docTemplate = `{ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "userId": { diff --git a/docs/swagger.json b/docs/swagger.json index e78189c..43002be 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -302,6 +302,78 @@ } } }, + "/api/v1/commodity/import_category_view": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "商品分类" + ], + "summary": "导入商品分类预览", + "parameters": [ + { + "description": "上传excel文件", + "name": "file", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.CategoryExcel" + } + } + } + } + } + }, + "/api/v1/commodity/import_commodity_view": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "商品资料" + ], + "summary": "导入商品资料预览", + "parameters": [ + { + "description": "上传excel文件", + "name": "file", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.CommodityExcel" + } + } + } + } + } + }, "/api/v1/commodity/list": { "post": { "consumes": [ @@ -3042,7 +3114,7 @@ "type": "integer" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3140,7 +3212,7 @@ "type": "integer" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3404,6 +3476,7 @@ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "display": { @@ -3411,6 +3484,7 @@ "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "name": { @@ -3427,6 +3501,26 @@ } } }, + "models.CategoryExcel": { + "type": "object", + "required": [ + "first_category" + ], + "properties": { + "first_category": { + "description": "一级分类", + "type": "string" + }, + "second_category": { + "description": "二级分类", + "type": "string" + }, + "three_category": { + "description": "三级分类", + "type": "string" + } + } + }, "models.CategoryModel": { "type": "object", "properties": { @@ -3435,6 +3529,7 @@ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "display": { @@ -3442,6 +3537,7 @@ "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "name": { @@ -3465,6 +3561,81 @@ } } }, + "models.CommodityExcel": { + "type": "object", + "required": [ + "category", + "imei_type", + "member_discount", + "min_retail_price", + "name", + "retail_price", + "sell_brokerage", + "staff_brokerage", + "staff_cost_price", + "supplier_name", + "sys_generate", + "wholesale_price" + ], + "properties": { + "category": { + "description": "商品所属分类", + "type": "string" + }, + "imei_type": { + "description": "是否串码 1-无串码 2-串码(系统生成) 3-串码(手动添加)", + "type": "string" + }, + "member_discount": { + "description": "会员优惠", + "type": "string" + }, + "min_retail_price": { + "description": "最低零售价", + "type": "string" + }, + "name": { + "description": "商品名称", + "type": "string" + }, + "origin": { + "description": "产地", + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "retail_price": { + "description": "指导零售价", + "type": "string" + }, + "sell_brokerage": { + "description": "销售毛利提成", + "type": "string" + }, + "staff_brokerage": { + "description": "员工毛利提成", + "type": "string" + }, + "staff_cost_price": { + "description": "员工成本价加价", + "type": "string" + }, + "supplier_name": { + "description": "供应商名称", + "type": "string" + }, + "sys_generate": { + "description": "系统生成串码", + "type": "string" + }, + "wholesale_price": { + "description": "指导采购价", + "type": "string" + } + } + }, "models.DictType": { "type": "object", "properties": { @@ -3473,12 +3644,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "dictId": { @@ -3508,6 +3681,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -3516,12 +3690,14 @@ "type": "object", "properties": { "createdAt": { + "description": "创建时间", "type": "string" }, "full_num": { "type": "integer" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "level": { @@ -3570,6 +3746,7 @@ "type": "number" }, "createdAt": { + "description": "创建时间", "type": "string" }, "erp_category": { @@ -3592,6 +3769,7 @@ "type": "string" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "imei": { @@ -3599,7 +3777,7 @@ "type": "string" }, "imei_type": { - "description": "1-无串码 2-串码", + "description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)", "type": "integer" }, "member_discount": { @@ -3648,15 +3826,19 @@ "type": "object", "properties": { "erp_category_id": { + "description": "商品分类id", "type": "integer" }, "erp_commodity_name": { + "description": "商品名称", "type": "string" }, "erp_supplier_id": { + "description": "供应商id", "type": "integer" }, "imei": { + "description": "串码", "type": "string" }, "is_export": { @@ -3664,12 +3846,15 @@ "type": "integer" }, "page_num": { + "description": "页码", "type": "integer" }, "page_size": { + "description": "每页展示数据条数", "type": "integer" }, "serial_number": { + "description": "商品编号", "type": "string" } } @@ -3678,6 +3863,7 @@ "type": "object", "properties": { "export_url": { + "description": "1-导出", "type": "string" }, "list": { @@ -3687,12 +3873,15 @@ } }, "page_num": { + "description": "页码", "type": "integer" }, "page_size": { + "description": "每页展示数据条数", "type": "integer" }, "total": { + "description": "总页数", "type": "integer" } } @@ -3737,6 +3926,7 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { @@ -3744,6 +3934,7 @@ "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "infoId": { @@ -3789,6 +3980,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "username": { @@ -3819,12 +4011,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "icon": { @@ -3876,6 +4070,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "visible": { @@ -3890,12 +4085,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "params": { @@ -3929,6 +4126,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -3969,6 +4167,7 @@ "type": "integer" }, "createdAt": { + "description": "创建时间", "type": "string" }, "email": { @@ -3976,6 +4175,7 @@ "type": "string" }, "id": { + "description": "数据库记录编号", "type": "integer" }, "landline": { @@ -4020,12 +4220,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4060,6 +4262,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4091,12 +4294,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "params": { @@ -4110,6 +4315,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4130,12 +4336,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4170,6 +4378,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4187,12 +4396,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptId": { @@ -4237,6 +4448,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4255,12 +4467,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "id": { @@ -4289,6 +4503,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4308,6 +4523,7 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { @@ -4315,6 +4531,7 @@ "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptName": { @@ -4390,6 +4607,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "userAgent": { @@ -4408,12 +4626,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptIds": { @@ -4461,6 +4681,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" } } @@ -4487,12 +4708,14 @@ "type": "string" }, "createdAt": { + "description": "创建时间", "type": "string" }, "dataScope": { "type": "string" }, "deletedAt": { + "description": "删除时间", "type": "string" }, "deptId": { @@ -4553,6 +4776,7 @@ "type": "string" }, "updatedAt": { + "description": "更新时间", "type": "string" }, "userId": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f2fac5a..2d19cb6 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -53,7 +53,7 @@ definitions: description: 主供应商 type: integer imei_type: - description: 1-无串码 2-串码 + description: 1-无串码 2-串码(系统生成) 3-串码(手动添加) type: integer member_discount: description: 会员优惠 @@ -125,7 +125,7 @@ definitions: description: 商品id type: integer imei_type: - description: 1-无串码 2-串码 + description: 1-无串码 2-串码(系统生成) 3-串码(手动添加) type: integer member_discount: description: 会员优惠 @@ -332,11 +332,13 @@ definitions: description: 合作商id type: integer createdAt: + description: 创建时间 type: string display: description: 1 展示 0 隐藏 type: integer id: + description: 数据库记录编号 type: integer name: description: 分类名称 @@ -348,17 +350,33 @@ definitions: description: 父分类的编号 type: integer type: object + models.CategoryExcel: + properties: + first_category: + description: 一级分类 + type: string + second_category: + description: 二级分类 + type: string + three_category: + description: 三级分类 + type: string + required: + - first_category + type: object models.CategoryModel: properties: cooperative_business_id: description: 合作商id type: integer createdAt: + description: 创建时间 type: string display: description: 1 展示 0 隐藏 type: integer id: + description: 数据库记录编号 type: integer name: description: 分类名称 @@ -375,16 +393,76 @@ definitions: $ref: '#/definitions/models.CategoryModel' type: array type: object + models.CommodityExcel: + properties: + category: + description: 商品所属分类 + type: string + imei_type: + description: 是否串码 1-无串码 2-串码(系统生成) 3-串码(手动添加) + type: string + member_discount: + description: 会员优惠 + type: string + min_retail_price: + description: 最低零售价 + type: string + name: + description: 商品名称 + type: string + origin: + description: 产地 + type: string + remark: + description: 备注 + type: string + retail_price: + description: 指导零售价 + type: string + sell_brokerage: + description: 销售毛利提成 + type: string + staff_brokerage: + description: 员工毛利提成 + type: string + staff_cost_price: + description: 员工成本价加价 + type: string + supplier_name: + description: 供应商名称 + type: string + sys_generate: + description: 系统生成串码 + type: string + wholesale_price: + description: 指导采购价 + type: string + required: + - category + - imei_type + - member_discount + - min_retail_price + - name + - retail_price + - sell_brokerage + - staff_brokerage + - staff_cost_price + - supplier_name + - sys_generate + - wholesale_price + type: object models.DictType: properties: createBy: description: 创建者 type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string dictId: type: integer @@ -406,15 +484,18 @@ definitions: description: 更新者 type: string updatedAt: + description: 更新时间 type: string type: object models.ErpCategory: properties: createdAt: + description: 创建时间 type: string full_num: type: integer id: + description: 数据库记录编号 type: integer level: description: 分类层级 @@ -449,6 +530,7 @@ definitions: description: 员工毛利提成 type: number createdAt: + description: 创建时间 type: string erp_category: $ref: '#/definitions/models.ErpCategory' @@ -465,12 +547,13 @@ definitions: description: 主供应商名称 type: string id: + description: 数据库记录编号 type: integer imei: description: 串码 type: string imei_type: - description: 1-无串码 2-串码 + description: 1-无串码 2-串码(系统生成) 3-串码(手动添加) type: integer member_discount: description: 会员优惠 @@ -506,36 +589,47 @@ definitions: models.ErpCommodityListReq: properties: erp_category_id: + description: 商品分类id type: integer erp_commodity_name: + description: 商品名称 type: string erp_supplier_id: + description: 供应商id type: integer imei: + description: 串码 type: string is_export: description: 1-导出 type: integer page_num: + description: 页码 type: integer page_size: + description: 每页展示数据条数 type: integer serial_number: + description: 商品编号 type: string type: object models.ErpCommodityListResp: properties: export_url: + description: 1-导出 type: string list: items: $ref: '#/definitions/models.ErpCommodity' type: array page_num: + description: 页码 type: integer page_size: + description: 每页展示数据条数 type: integer total: + description: 总页数 type: integer type: object models.Login: @@ -567,11 +661,13 @@ definitions: description: 创建人 type: string createdAt: + description: 创建时间 type: string dataScope: description: 数据 type: string deletedAt: + description: 删除时间 type: string infoId: description: 主键 @@ -605,6 +701,7 @@ definitions: description: 更新者 type: string updatedAt: + description: 更新时间 type: string username: description: 用户名 @@ -625,10 +722,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string icon: type: string @@ -663,6 +762,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string visible: type: string @@ -672,10 +772,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string params: type: string @@ -700,6 +802,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string type: object models.Supplier: @@ -729,11 +832,13 @@ definitions: description: 合作商id type: integer createdAt: + description: 创建时间 type: string email: description: 邮件 type: string id: + description: 数据库记录编号 type: integer landline: description: 固定电话 @@ -766,10 +871,12 @@ definitions: description: 创建者 type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string id: description: 分类Id @@ -795,6 +902,7 @@ definitions: description: 更新者 type: string updatedAt: + description: 更新时间 type: string type: object models.SysConfig: @@ -817,10 +925,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string params: type: string @@ -830,6 +940,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string type: object models.SysContent: @@ -844,10 +955,12 @@ definitions: description: 创建者 type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string id: description: id @@ -873,6 +986,7 @@ definitions: description: 更新者 type: string updatedAt: + description: 更新时间 type: string type: object models.SysDept: @@ -884,10 +998,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string deptId: description: 部门编码 @@ -920,6 +1036,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string type: object models.SysFileDir: @@ -932,10 +1049,12 @@ definitions: description: 创建人 type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string id: type: integer @@ -956,6 +1075,7 @@ definitions: description: 编辑人 type: string updatedAt: + description: 更新时间 type: string type: object models.SysOperLog: @@ -969,11 +1089,13 @@ definitions: description: 创建人 type: string createdAt: + description: 创建时间 type: string dataScope: description: 数据 type: string deletedAt: + description: 删除时间 type: string deptName: description: 部门名称 @@ -1030,6 +1152,7 @@ definitions: description: 更新者 type: string updatedAt: + description: 更新时间 type: string userAgent: description: ua @@ -1042,10 +1165,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string deptIds: items: @@ -1079,6 +1204,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string type: object models.SysUser: @@ -1097,10 +1223,12 @@ definitions: createBy: type: string createdAt: + description: 创建时间 type: string dataScope: type: string deletedAt: + description: 删除时间 type: string deptId: description: 部门编码 @@ -1145,6 +1273,7 @@ definitions: updateBy: type: string updatedAt: + description: 更新时间 type: string userId: description: 编码 @@ -1523,6 +1652,52 @@ paths: summary: 编辑商品 tags: - 商品资料 + /api/v1/commodity/import_category_view: + post: + consumes: + - application/json + parameters: + - description: 上传excel文件 + in: body + name: file + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.CategoryExcel' + type: array + summary: 导入商品分类预览 + tags: + - 商品分类 + /api/v1/commodity/import_commodity_view: + post: + consumes: + - application/json + parameters: + - description: 上传excel文件 + in: body + name: file + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.CommodityExcel' + type: array + summary: 导入商品资料预览 + tags: + - 商品资料 /api/v1/commodity/list: post: consumes: diff --git a/static/导分类.xlsx b/static/导分类.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..831c59a888540b5b1fa674006c98dd299a6f0174 GIT binary patch literal 10530 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 literal 0 HcmV?d00001 diff --git a/static/导商品.xlsx b/static/导商品.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..239e61bf6460220da1d6aaf1e54542a7f91f7257 GIT binary patch literal 11539 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