diff --git a/repository/test.data/DL6850.go b/repository/test.data/DL6850.go new file mode 100644 index 0000000..048849a --- /dev/null +++ b/repository/test.data/DL6850.go @@ -0,0 +1,367 @@ +package test_data + +import ( + "bytes" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "gitee.com/golang-module/carbon/v2" + "github.com/extrame/xls" + "github.com/xuri/excelize/v2" + "golang.org/x/text/encoding/simplifiedchinese" + "golang.org/x/text/transform" + "gorm.io/gorm" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + "strings" + "testData/global" + "testData/model" + "testData/utils" +) + +func HandleDL6850Excel(fileText *model.FileText) error { + rows := make([][]string, 0) + if strings.ToLower(path.Ext(fileText.Name)) == ".csv" { + csvBytes, err := ioutil.ReadFile(fileText.Path) + if err != nil { + log.Println("open err:", err) + return errors.New(fmt.Sprintf("open err:%s", err)) + } + //解决读取csv中文乱码的问题 + reader := csv.NewReader(transform.NewReader(bytes.NewReader(csvBytes), simplifiedchinese.GBK.NewDecoder())) + //reader := csv.NewReader(file) + reader.FieldsPerRecord = -1 + csvRows, err := reader.ReadAll() + if err != nil { + log.Println("open err:", err) + return errors.New(fmt.Sprintf("open err:%s", err)) + } + rows = csvRows + } else if strings.ToLower(path.Ext(fileText.Name)) == ".xls" { + if xlFile, err := xls.Open(fileText.Path, "utf-8"); err == nil { + //第一个sheet + sheet := xlFile.GetSheet(0) + if sheet.MaxRow != 0 { + temp := make([][]string, 0) + for i := 0; i < int(sheet.MaxRow); i++ { + row := sheet.Row(i) + if row == nil { + continue + } + data := make([]string, 0) + if row.LastCol() > 0 { + for j := 0; j < row.LastCol(); j++ { + col := row.Col(j) + data = append(data, col) + } + temp = append(temp, data) + } + } + rows = append(rows, temp...) + } else { + log.Println("open err:", err) + return errors.New(fmt.Sprintf("open err:%s", err)) + } + } + } else if strings.ToLower(path.Ext(fileText.Name)) == ".xlsx" { + xlsxFile, err := excelize.OpenFile(fileText.Path) + if err != nil { + log.Println("open err:", err) + return errors.New(fmt.Sprintf("open err:%s", err)) + } + sheetName := xlsxFile.GetSheetName(0) + rows, err = xlsxFile.GetRows(sheetName) + if err != nil { + log.Println("xlsx读取数据失败:", err) + return errors.New(fmt.Sprintf("xlsx读取数据失败:%s", err)) + } + } + + details := make(map[string]string) + newExcel := make([][]string, 0) + var title []string + titleInfoMap := make(map[string]model.DataInfo) + //sBinMap := make(map[string]model.BinInfo) + sBinMap := make(map[string]string) + paramsMap := make(map[string]string) + titleIndex, unitIndex, limitLIndex, limitUIndex, dataIndex := -1, -1, -1, -1, -1 + for i := 1; i < len(rows); i++ { + if i == len(rows)-1 && unitIndex == -1 { + log.Println("特殊文件格式,文件路径为:", fileText.Path) + return errors.New(fmt.Sprintf("特殊文件格式,文件路径为:%s", fileText.Path)) + } + if len(rows[i]) < 0 { + continue + } + rows[i][0] = strings.ReplaceAll(rows[i][0], ":", ":") + rows[i][0] = strings.ReplaceAll(rows[i][0], " ", "") + splitIndex := strings.Index(rows[i][0], ":") + if splitIndex != -1 { + details[rows[i][0][:splitIndex]] = rows[i][0][splitIndex+1:] + } + if titleIndex < 0 { + if len(rows[i]) < 5 { + continue + } + //if strings.Contains(rows[i][3], "SITE_NUM") { + // titleIndex = i + // title = rows[i] + // continue + //} + if strings.Contains(rows[i][3], "Parm_Name") { + titleIndex = i + title = []string{"PART_ID", "SITE_NUM", "PASSFG", "SOFT_BIN"} + for _, titleName := range rows[i][4:] { + title = append(title, strings.ReplaceAll(titleName, "\t", "")) + } + continue + } + } else { + if len(rows[i]) < 5 { + continue + } + if limitLIndex < 0 { + if strings.Contains(rows[i][3], "Min") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + limitLIndex = i + continue + } + } + if limitUIndex < 0 { + if strings.Contains(rows[i][3], "Max") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + limitUIndex = i + continue + } + } + if unitIndex < 0 { + if strings.Contains(rows[i][3], "Bin") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + unitIndex = i + continue + } + } else { + dataIndex = i + break + } + } + } + if titleIndex != -1 { + //rows[titleIndex] = rows[titleIndex][3:] + for i := 3; i < len(rows[titleIndex]); i++ { + titleInfoMap[strings.ReplaceAll(rows[titleIndex][i], "\t", "")] = model.DataInfo{ + Unit: strings.ReplaceAll(rows[unitIndex][i], "\t", ""), + LimitL: strings.ReplaceAll(rows[limitLIndex][i], "\t", ""), + LimitU: strings.ReplaceAll(rows[limitUIndex][i], "\t", ""), + } + } + for i := dataIndex; i < len(rows); i++ { + // 将数据中的BIN存入Map + sBinMap[rows[i][3]] = rows[i][3] + if len(rows[i]) < len(rows[titleIndex]) { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + } + newExcel = append(newExcel, rows[i]) + } + } else { + log.Println("特殊文件格式,文件路径为:", fileText.Path) + return errors.New(fmt.Sprintf("特殊文件格式,文件路径为:%s", fileText.Path)) + } + + //if details["Test_Code"] == "" { + // details["Test_Code"] = step + //} else { + // details["Test_Code"] = details["Test_Code"][:2] + //} + //strReader := transform.NewReader(bytes.NewReader([]byte(details["Device_Name"])), simplifiedchinese.GBK.NewDecoder()) + //product, _ := ioutil.ReadAll(strReader) + //if string(product) == "" { + // product = []byte(fileText.ProductName) + //} + testProgram := details["Program"][strings.LastIndex(details["Program"], "\\")+1:] + sbinHbin, _ := json.Marshal(&sBinMap) + titleInfo, _ := json.Marshal(&titleInfoMap) + paramsSbin, _ := json.Marshal(¶msMap) + var fileName string + if fileText.Procedure == "CP" { + fileName = fileText.ProductName + "_" + fileText.Lot + "_" + fileText.ChipNum + "_" + fileText.Procedure + ".csv" + } else { + fileName = fileText.ProductName + "_" + fileText.Lot + "_" + fileText.SubBatch + "_" + fileText.Procedure + ".csv" + } + //fileName := string(product) + "_" + fileText.Lot + "_" + details["Test_Code"] + ".csv" + //var waferID string + //if fileText.Factory == "saimeike" { + // if step == "CP1" || step == "CP2" { + // length := len(fileText.Name) + // waferID = fileText.Name[length-10 : length-8] + // fileName = string(product) + "_" + fileText.Lot + "_" + waferID + "_" + details["Test_Code"] + ".csv" + // } else { + // if strings.Index(fileText.SubBatch, "-") != strings.LastIndex(fileText.SubBatch, "-") { + // fileText.SubBatch = fileText.SubBatch[:strings.LastIndex(fileText.SubBatch, "-")] + // } + // fileName = string(product) + "_" + fileText.Lot + "_" + fileText.SubBatch + "_" + details["Test_Code"] + ".csv" + // } + //} else if fileText.Factory == "xinde" { + // s := strings.Split(fileText.Name, "_") + // if len(s) < 5 { + // log.Println("文件名格式有误,文件路径为:", fileText.Path) + // return + // } + // waferIDStr := s[len(s)-3] + // if len(waferIDStr) < 5 { + // log.Println("文件名格式有误,文件路径为:", fileText.Path) + // return + // } + // splitIndex := strings.Index(waferIDStr, "-") + // if splitIndex == -1 { + // log.Println("文件名格式有误,文件路径为:", fileText.Path) + // return + // } + // waferID = waferIDStr[splitIndex+1 : splitIndex+3] + // if _, ok := details["WAFER_ID"]; ok { + // details["Test_Code"] = "CP" + // if len(waferIDStr[:splitIndex]) < 8 { + // fileText.Lot = strings.ToUpper(waferIDStr[:splitIndex]) + // } + // fileText.SubBatch = "" + // fileName = string(product) + "_" + fileText.Lot + "_" + waferID + "_" + details["Test_Code"] + ".csv" + // } + //} else if fileText.Factory == "qipai" { + // //details["Test_Code"] + //} else if fileText.Factory == "changdian" { + // if details["Device_Name"] == "" { + // log.Println("文件缺少产品型号信息,文件路径为:", fileText.Path) + // return + // } + // product = []byte(details["Device_Name"]) + // fileName = details["Device_Name"] + "_" + fileText.Lot + "_" + fileText.SubBatch + "_" + details["Test_Code"] + ".csv" + //} + //strings.ReplaceAll(fileText.Lot, ".", "-") + dirPath := filepath.Join("/testData/online/" + fileText.Factory) + //dirPath := filepath.Join("/testData/test/" + fileText.Factory) + utils.MakeDir(dirPath) + filePath := filepath.Join(dirPath, fileName) + var fileHandled *model.FileHandled + if _, err := os.Stat(filePath); err != nil { + if os.IsNotExist(err) { + newExcel = append([][]string{title}, newExcel...) + _, err = os.Create(filePath) + if err != nil { + log.Println("创建文件失败:", err) + return errors.New(fmt.Sprintf("创建文件失败:%s", err)) + } + //if fileText.ChipNum != "" { + // waferID = fileText.ChipNum + //} + if errors.Is(global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled).Error, gorm.ErrRecordNotFound) { + //global.PostGreSQL.Create(&model.FileHandled{ + // Name: fileName, + // Path: filePath, + // Size: "", + // Product: string(product), + // PBI: fileText.PBI, + // Factory: fileText.Factory, + // Step: details["Test_Code"], + // Lot: fileText.Lot, + // SubBatch: fileText.SubBatch, + // TestMachineModel: "STS8200", + // TestMachine: details["Tester ID"], + // TestProgram: testProgram, + // BeginningTime: details["Beginning Time"], + // EndingTime: details["Ending Time"], + // SbinHbin: string(sbinHbin), + // ParamsSbin: string(paramsSbin), + // TitleInfo: string(titleInfo), + // WaferID: waferID, + //}) + global.PostGreSQL.Create(&model.FileHandled{ + Name: fileName, + Path: filePath, + Size: "", + Product: fileText.ProductName, + PBI: fileText.PBI, + Factory: fileText.Factory, + Step: fileText.Procedure, + Lot: fileText.Lot, + SubBatch: fileText.SubBatch, + TestMachineModel: "德律6850", + TestMachine: details["Tester ID"], + TestProgram: testProgram, + BeginningTime: details["Beginning Time"], + EndingTime: details["Ending Time"], + SbinHbin: string(sbinHbin), + ParamsSbin: string(paramsSbin), + TitleInfo: string(titleInfo), + WaferID: fileText.ChipNum, + }) + } + } + } + newCsv, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Println("打开新Excel错误:", fileText.Path) + return errors.New(fmt.Sprintf("打开新Excel错误:%s", fileText.Path)) + } + defer newCsv.Close() + writer := csv.NewWriter(newCsv) + defer writer.Flush() + err = writer.WriteAll(newExcel) + if err != nil { + log.Println("写入新Excel错误:", fileText.Path) + return errors.New(fmt.Sprintf("写入新Excel错误:%s", fileText.Path)) + } + newFile, err := os.Stat(filePath) + if err != nil { + log.Println("获取新Excel信息:", fileText.Path) + return errors.New(fmt.Sprintf("获取新Excel信息:%s", fileText.Path)) + } + global.PostGreSQL.Model(&fileHandled).Where("name = ?", fileName).Updates(map[string]interface{}{ + "product": fileText.ProductName, + "step": fileText.Procedure, + //"product": string(product), + //"step": details["Test_Code"], + "test_machine_model": "德律6850", + //"test_machine": details["Tester ID"], + "test_program": testProgram, + //"beginning_time": details["Beginning Time"], + //"ending_time": details["Ending Time"], + "sbin_hbin": string(sbinHbin), + "params_sbin": string(paramsSbin), + "title_info": string(titleInfo), + "size": utils.FormatFileSize(float64(newFile.Size())), + }) + var report *model.Report + var step string + if fileText.Procedure == "FT" || fileText.Procedure == "RT" { + step = "FT" + } else if strings.Contains(fileText.Procedure, "CP") { + step = "CP" + } + if errors.Is(global.PostGreSQL.Where("product = ? AND pbi = ? AND factory = ? AND lot = ? AND step = ? AND sub_batch = ? AND wafer_id = ?", + fileText.ProductName, fileText.PBI, fileText.Factory, fileText.Lot, step, fileText.SubBatch, fileText.ChipNum).First(&report).Error, gorm.ErrRecordNotFound) { + orderDate := carbon.Parse("20" + fileText.PBI[5:11]).Format("Y-m-d") + report = &model.Report{ + Product: fileText.ProductName, + PBI: fileText.PBI, + Factory: fileText.Factory, + Step: step, + Lot: fileText.Lot, + SubBatch: fileText.SubBatch, + //TestMachine: details["Tester ID"], + TestProgram: testProgram, + WaferID: fileText.ChipNum, + OrderDate: orderDate, + } + global.PostGreSQL.Create(&report) + } + if strings.Contains(fileText.Procedure, "CP") { + SaveCP(report) + } else { + SaveFT(report) + } + return nil +} diff --git a/repository/test.data/export.go b/repository/test.data/export.go index fd35138..925a6d5 100644 --- a/repository/test.data/export.go +++ b/repository/test.data/export.go @@ -340,7 +340,6 @@ func ExportHistogram(req *request.Histogram) string { } } } - for _, data := range datas { if req.OnlyPass && !(data[fieldMap["SOFT_BIN"]] == "1") { continue @@ -553,86 +552,6 @@ func ExportHistogram(req *request.Histogram) string { a += 20 } - //ftFile.NewSheet("ALL") - //for k, v := range selectionHistogramX { - // sheetX := []interface{}{""} - // for _, x := range v { - // sheetX = append(sheetX, x) - // } - // sheetY := []interface{}{"数量"} - // for _, y := range selectionHistogramY[k] { - // sheetY = append(sheetY, y) - // } - // for idx, rows := range [][]interface{}{ - // sheetX, - // sheetY, - // } { - // cell, err := excelize.CoordinatesToCellName(1, idx+1) - // if err != nil { - // fmt.Println(err) - // } - // if err = ftFile.SetSheetRow(k, cell, &rows); err != nil { - // fmt.Println(err) - // } - // } - // if err := ftFile.AddChart(k, "A4", &excelize.Chart{ - // Type: excelize.Col, - // Series: []excelize.ChartSeries{ - // { - // Name: k + "!$A$1", - // Categories: k + "!$B$1:$" + utils.NumToRow(strconv.Itoa(len(selectionHistogramY[k])+1)) + "$1", - // Values: k + "!$B$2:$" + utils.NumToRow(strconv.Itoa(len(selectionHistogramY[k])+1)) + "$2", - // }, - // }, - // Format: excelize.GraphicOptions{ - // ScaleX: 1, - // ScaleY: 1, - // OffsetX: 15, - // OffsetY: 10, - // }, - // Legend: excelize.ChartLegend{ - // Position: "left", - // }, - // Title: []excelize.RichTextRun{ - // { - // Text: k, - // }, - // }, - // PlotArea: excelize.ChartPlotArea{ - // ShowCatName: false, - // ShowLeaderLines: false, - // ShowVal: true, - // }, - // ShowBlanksAs: "zero", - // }, &excelize.Chart{ - // Type: excelize.Line, - // Series: []excelize.ChartSeries{ - // { - // Name: k + "!$A$1", - // Categories: k + "!$B$1:$" + utils.NumToRow(strconv.Itoa(len(selectionHistogramY[k])+1)) + "$1", - // Values: k + "!$B$2:$" + utils.NumToRow(strconv.Itoa(len(selectionHistogramY[k])+1)) + "$2", - // Marker: excelize.ChartMarker{ - // Symbol: "none", Size: 10, - // }, - // }, - // }, - // Format: excelize.GraphicOptions{ - // ScaleX: 1, - // ScaleY: 1, - // OffsetX: 15, - // OffsetY: 10, - // }, - // Legend: excelize.ChartLegend{ - // Position: "right", - // }, - // PlotArea: excelize.ChartPlotArea{ - // ShowCatName: false, - // ShowLeaderLines: false, - // }, - // }); err != nil { - // fmt.Println(err) - // } - //} col := 1 _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start), &[]interface{}{ "", "最小值", "最大值", "平均值", "δ", "数量", "Limit L", "Limit H", "UNIT"}) @@ -1155,12 +1074,15 @@ func ExportHistogram(req *request.Histogram) string { "批次差异汇总"}) _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start+1), &[]interface{}{ "", "平均值", "δ", "UNIT"}) - for _, selection := range req.Selections { - _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start+1), &[]interface{}{ - selection, subBatchDiff[selection][0] - subBatchDiff[selection][1], - subBatchDiff[selection][2] - subBatchDiff[selection][3], selectionUnit[selection]}) - col++ + if len(req.SubBatch) > 1 { + for _, selection := range req.Selections { + _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start+1), &[]interface{}{ + selection, subBatchDiff[selection][0] - subBatchDiff[selection][1], + subBatchDiff[selection][2] - subBatchDiff[selection][3], selectionUnit[selection]}) + col++ + } } + _ = histogramFile.MergeCell(sheetName, "A"+strconv.Itoa(start), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start)) _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start), NormalSheetStyle(histogramFile)) diff --git a/repository/test.data/upload.go b/repository/test.data/upload.go index 5d4791b..955cbde 100644 --- a/repository/test.data/upload.go +++ b/repository/test.data/upload.go @@ -27,9 +27,11 @@ func HandleUploadFiles(fileTexts []*model.FileText, step, machine string) error for i := 0; i < len(fileTexts)/2; i++ { MT737(fileTexts[2*i+1], fileTexts[2*i]) } - } else if machine == "DL6850" { + } else if machine == "德律6850" { for i := 0; i < len(fileTexts); i++ { - + if err := HandleDL6850Excel(fileTexts[i]); err != nil { + return err + } } } return nil diff --git a/repository/test.file.handler.go b/repository/test.file.handler.go index c874446..8163b77 100644 --- a/repository/test.file.handler.go +++ b/repository/test.file.handler.go @@ -10,7 +10,7 @@ import ( func TestFilesHandlerCron() { var fileTexts []*model.FileText //global.PostGreSQL.Where("processed = ? AND doubt = ? AND factory != ?", false, false, "江苏芯德").Order("procedure").Find(&fileTexts) - global.PostGreSQL.Where("processed = ? AND doubt = ? AND factory != ?", false, false, "亚芯微").Order("procedure").Find(&fileTexts) + global.PostGreSQL.Where("processed = ? AND doubt = ? AND factory NOT IN ?", false, false, []string{"亚芯微", "铜陵碁明"}).Order("procedure").Find(&fileTexts) for _, fileText := range fileTexts { if err := test_data.HandleSTS8200Excel(fileText); err != nil { continue @@ -33,4 +33,17 @@ func TestFilesHandlerCron() { "processed": true, }) } + fileTexts = []*model.FileText{} + global.PostGreSQL.Where("processed = ? AND doubt = ? AND factory = ?", false, false, "铜陵碁明").Order("procedure").Find(&fileTexts) + sort.Slice(fileTexts, func(i, j int) bool { + return fileTexts[i].Name < fileTexts[j].Name + }) + for _, fileText := range fileTexts { + if err := test_data.HandleDL6850Excel(fileText); err != nil { + continue + } + global.PostGreSQL.Model(&fileTexts).Updates(map[string]interface{}{ + "processed": true, + }) + } }