1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package controllers
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/xuri/excelize/v2"
    "gorm.io/gorm"
    "strings"
    "wms/constvar"
    "wms/extend/code"
    "wms/extend/util"
    "wms/models"
    "wms/pkg/logx"
    "wms/utils/upload"
)
 
type OtherController struct{}
 
type saveProductImagesFromExcelRequest struct {
    ExcelFilePath        string `json:"excelFilePath"`        //excel路径 用docker cp传到容器里
    SheetIndex           int    `json:"sheetIndex"`           //第几个sheet
    ProductIdColumnIndex int    `json:"productIdColumnIndex"` //产品ID是第几列(从0开始)
    ImageColumn          string `json:"imageColumn"`          //图片所在列名
}
 
// SaveProductImagesFromExcel
// @Tags      其他
// @Summary   从excel中获取产品图片并保存
// @Produce   application/json
// @Param     object  body  saveProductImagesFromExcelRequest true  "属性信息"
// @Param     Authorization    header string true "token"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/other/saveProductImagesFromExcel [post]
func (slf OtherController) SaveProductImagesFromExcel(c *gin.Context) {
    var params saveProductImagesFromExcelRequest
    if err := c.BindJSON(&params); err != nil {
        util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误:"+err.Error())
        return
    }
    if params.ExcelFilePath == "" || params.ImageColumn == "" {
        util.ResponseFormat(c, code.RequestParamError, "参数缺失")
        return
    }
 
    productImageMap, err := UploadProductImagesFromExcel(params.ExcelFilePath, params.SheetIndex, params.ProductIdColumnIndex, params.ImageColumn)
    if err != nil {
        logx.Errorf("SaveProductImagesFromExcel err:%v", err)
        util.ResponseFormat(c, code.SaveFail, "操作失败")
        return
    }
 
    for productId, urls := range productImageMap {
        if len(urls) == 0 {
            continue
        }
        attachmentList := make([]*models.Attachment, 0)
        materialAttachmentList := make([]*models.MaterialAttachment, 0)
        for _, url := range urls {
            attachmentList = append(attachmentList, &models.Attachment{
                FileUrl:  url,
                FileType: constvar.FileType_Picture,
            })
        }
 
        err = models.WithTransaction(func(db *gorm.DB) error {
            //保存附件
            if attachmentList, err = models.NewAttachmentSearch().CreateBatchWithResp(attachmentList); err != nil {
                logx.Errorf("attachment create err: %v", err)
                return err
            }
 
            //保存物料和附件映射
            for _, v := range attachmentList {
                ma := &models.MaterialAttachment{MaterialID: productId, AttachmentID: v.Id}
                materialAttachmentList = append(materialAttachmentList, ma)
            }
            if err := models.NewMaterialAttachmentSearch().SetOrm(db).CreateBatch(materialAttachmentList); err != nil {
                return err
            }
            return nil
        })
        if err != nil {
            logx.Errorf("SaveProductImagesFromExcel save db  err:%v, productId:%v, urls:%v", err, productId, urls)
        }
    }
 
    util.ResponseFormat(c, code.Success, "保存成功")
}
 
// UploadProductImagesFromExcel 从Excel文件中上传产品图片
func UploadProductImagesFromExcel(filePath string, sheetIndex int, productIdColumn int, imageColumn string) (productImageMap map[string][]string, err error) {
    productImageMap = make(map[string][]string)
    // 加载Excel文件
    f, err := excelize.OpenFile(filePath)
    if err != nil {
        logx.Errorf("Failed to open Excel file: %v", err)
        return
    }
    defer f.Close()
 
    // 获取工作表名称
    sheetName := f.GetSheetName(sheetIndex)
    // 读取工作表中的所有行
    rows, err := f.GetRows(sheetName)
    if err != nil {
        logx.Errorf("Failed to get rows from sheet:%v", err)
        return
    }
 
    // 获取指定列的合并单元格信息
    mergedCells, err := getColumnMergeCells(f, sheetName, imageColumn)
    if err != nil {
        logx.Errorf("Failed to get merged cells:%v", err)
        return
    }
 
    mergeCellMap := make(map[string]excelize.MergeCell)
    for _, cell := range mergedCells {
        mergeCellMap[cell.GetStartAxis()] = cell
    }
 
    var imagePaths []string
    // 遍历Excel行,读取数据
    for rowIndex, row := range rows[1:] { // 假设第一行是标题行,跳过
        if len(row) < 1 {
            continue
        }
        productId := row[productIdColumn]
        currentCell := fmt.Sprintf("%s%d", imageColumn, rowIndex+2)
 
        // 检查当前单元格是否在合并单元格中
        if mergeCell, ok := mergeCellMap[currentCell]; ok {
            imagePaths = make([]string, 0)
            imageCell := mergeCell.GetStartAxis()
 
            // 获取图片
            pictures, err := f.GetPictures(sheetName, imageCell)
            if err != nil {
                logx.Errorf("Failed to get picture for cell %s: %v", imageCell, err)
                continue
            }
 
            if len(pictures) == 0 {
                logx.Errorf("No picture found for cell %s", imageCell)
                continue
            }
 
            for k, picture := range pictures {
                fileBytes := picture.File
                fileName := fmt.Sprintf("image_%s_%d.png", imageCell, k+1)
 
                // 保存图片到本地并获取路径
                imagePath, err := upload.UploadFileToSeaWeed(string(constvar.FileType_Picture), fileName, fileBytes)
                if err != nil {
                    logx.Errorf("Failed to save image for product %s: %v\n", productId, err)
                    continue
                }
                imagePaths = append(imagePaths, imagePath)
            }
        }
 
        if productId == "" {
            continue
        }
 
        // imagePaths
        productImageMap[productId] = imagePaths
        logx.Infof("UploadProductImagesFromExcel Product ID: %s, Image Urls: %s\n", productId, imagePaths)
    }
    return productImageMap, nil
}
 
// getColumnMergeCells 获取指定列的合并单元格
func getColumnMergeCells(f *excelize.File, sheetName string, targetColumn string) ([]excelize.MergeCell, error) {
    // 获取所有合并单元格
    mergeCells, err := f.GetMergeCells(sheetName)
    if err != nil {
        return nil, err
    }
 
    var columnMergeCells []excelize.MergeCell
    for _, mergeCell := range mergeCells {
        if strings.HasPrefix(mergeCell.GetStartAxis(), targetColumn) {
            columnMergeCells = append(columnMergeCells, mergeCell)
        }
    }
    return columnMergeCells, nil
}