commit eb98dd159644b69f53fb3cf717f0e823f0ef93e1 Author: Simmons <1815481@qq.com> Date: Wed Jul 17 15:13:00 2024 +0800 V0 diff --git a/api/test.data/chart.go b/api/test.data/chart.go new file mode 100644 index 0000000..6af6611 --- /dev/null +++ b/api/test.data/chart.go @@ -0,0 +1,242 @@ +package test_data + +import ( + "github.com/gin-gonic/gin" + "testData/model/response" + test_data "testData/repository/test.data" + "testData/request" + "testData/utils" +) + +type ITestService interface { +} + +type TestService struct{} + +func InitTestService() *TestService { + return &TestService{} +} + +// @Tags 数据分析平台 +// @Summary 查询参数 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.QuerySelection true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/selection [post] +func (S *TestService) Selection(c *gin.Context) { + r := request.QuerySelection{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.QuerySelection(&r), c) +} + +// @Tags 数据分析平台 +// @Summary 直方图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Histogram true "直方图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/histogram [post] +func (S *TestService) Histogram(c *gin.Context) { + r := request.Histogram{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + data, err := test_data.Histogram(&r) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(gin.H{"data": data}, c) +} + +// @Tags 数据分析平台 +// @Summary 散点图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Scatter true "散点图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/scatter [post] +func (S *TestService) Scatter(c *gin.Context) { + r := request.Scatter{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + data, x, y, err := test_data.Scatter(&r) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(gin.H{"data": data, "x": x, "y": y}, c) +} + +// @Tags 数据分析平台 +// @Summary 饼状图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Pie true "饼状图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/pie [post] +func (S *TestService) Pie(c *gin.Context) { + r := request.Pie{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + data, err := test_data.Pie(&r) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Tags 数据分析平台 +// @Summary 折线图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Line true "折线图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/line [post] +func (S *TestService) Line(c *gin.Context) { + r := request.Line{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + data, err := test_data.Line(&r) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Tags 数据分析平台 +// @Summary CP Map图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.CPMap true "CP Map图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/cpMap [post] +func (S *TestService) CPMap(c *gin.Context) { + r := request.CPMap{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + res, err := test_data.CPMap(&r) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(res, c) +} + +// @Tags 数据分析平台 +// @Summary 导出CP Map图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.CPMap true "CP Map图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/cpMap/export [post] +func (S *TestService) CPMapExport(c *gin.Context) { + r := request.CPMap{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.ExportCPMap(&r), c) +} + +// @Tags 数据分析平台 +// @Summary 导出直方图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Histogram true "CP Map图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/ftHistogram/export [post] +func (S *TestService) ExportHistogram(c *gin.Context) { + r := request.Histogram{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.ExportHistogram(&r), c) +} + +// @Tags 数据分析平台 +// @Summary 导出散点图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.Scatter true "CP Map图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/scatter/export [post] +func (S *TestService) ExportScatter(c *gin.Context) { + r := request.Scatter{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.ExportScatter(&r), c) +} + +// @Tags 数据分析平台 +// @Summary Log各Site差异图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.LogSiteChart true "Log各Site差异图" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/logSite [post] +func (S *TestService) LogSite(c *gin.Context) { + r := request.LogSiteChart{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.LogSiteChart(&r), c) +} + +// @Tags 数据分析平台 +// @Summary 参数极限 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.SelectionLimit true "参数极限" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/selection/limit [post] +func (S *TestService) SelectionLimit(c *gin.Context) { + r := request.SelectionLimit{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + max, min := test_data.SelectionLimit(&r) + response.OkWithData(gin.H{"max": max, "min": min}, c) +} diff --git a/api/test.data/report.chart.go b/api/test.data/report.chart.go new file mode 100644 index 0000000..6fbbd0d --- /dev/null +++ b/api/test.data/report.chart.go @@ -0,0 +1,93 @@ +package test_data + +import ( + "github.com/gin-gonic/gin" + "testData/model/response" + test_data "testData/repository/test.data" + "testData/request" + "testData/utils" +) + +type IReportChartService interface { +} + +type ReportChartService struct{} + +func InitReportChartService() *ReportChartService { + return &ReportChartService{} +} + +// @Tags 数据分析平台-生产 +// @Summary 封装良率折线图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.PackagePassProbabilityLine true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/packagePassProbabilityLine [post] +func (S *ReportChartService) PackagePassProbabilityLine(c *gin.Context) { + r := request.PackagePassProbabilityLine{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + lines, max, min := test_data.PackagePassProbabilityLine(&r) + response.OkWithData(gin.H{"lines": lines, "max": max, "min": min}, c) +} + +// @Tags 数据分析平台-生产 +// @Summary 封装良率折线图 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.PackagePassProbabilityLine true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/packageOrderNumberBar [post] +func (S *ReportChartService) PackageOrderNumberBar(c *gin.Context) { + r := request.PackagePassProbabilityLine{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.OrderNumberHistogram(&r), c) +} + +// @Tags 数据分析平台-生产 +// @Summary 测试良率-按供应商 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.PassProbabilityByFactory true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/fTPassProbabilityByFactory [post] +func (S *ReportChartService) FTPassProbabilityByFactory(c *gin.Context) { + r := request.PassProbabilityByFactory{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + lines, histogram, max, min := test_data.PassProbabilityByFactory(&r) + response.OkWithData(gin.H{"lines": lines, "histogram": histogram, "max": max, "min": min}, c) +} + +// @Tags 数据分析平台-生产 +// @Summary 测试良率-按产品型号 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.PassProbabilityByProduct true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/fTPassProbabilityByProduct [post] +func (S *ReportChartService) FTPassProbabilityByProduct(c *gin.Context) { + r := request.PassProbabilityByProduct{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + lines, histogram, binLines, binHistogram := test_data.FTPassProbabilityByProduct(&r) + response.OkWithData(gin.H{"lines": lines, "histogram": histogram, "bin_lines": binLines, "bin_histogram": binHistogram}, c) +} diff --git a/api/test.data/report.list.go b/api/test.data/report.list.go new file mode 100644 index 0000000..a4d08ca --- /dev/null +++ b/api/test.data/report.list.go @@ -0,0 +1,95 @@ +package test_data + +import ( + "github.com/gin-gonic/gin" + "testData/global" + "testData/model" + "testData/model/response" + test_data "testData/repository/test.data" + "testData/request" + "testData/utils" +) + +type IReportListService interface { +} + +type ReportListService struct{} + +func InitReportService() *ReportListService { + global.PostGreSQL.AutoMigrate(&model.Report{}, &model.FinalReport{}, &model.ReportSites{}, &model.BinFail{}) + return &ReportListService{} +} + +// @Tags 数据分析平台-生产 +// @Summary 晶圆记录 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.WaferList true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/wafer [post] +func (S *ReportListService) WaferList(c *gin.Context) { + r := request.WaferList{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.WaferList(&r), c) +} + +// @Tags 数据分析平台-生产 +// @Summary CP记录 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.CPList true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/cp [post] +func (S *ReportListService) CPList(c *gin.Context) { + r := request.CPList{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + list, total := test_data.CPList(&r) + response.OkWithData(gin.H{"list": list, "total": total}, c) +} + +// @Tags 数据分析平台-生产 +// @Summary 封装记录 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.ABList true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/ab [post] +func (S *ReportListService) ABList(c *gin.Context) { + r := request.ABList{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + response.OkWithData(test_data.ABList(&r), c) +} + +// @Tags 数据分析平台-生产 +// @Summary FT记录 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.FTList true "查询参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/report/ft [post] +func (S *ReportListService) FTList(c *gin.Context) { + r := request.FTList{} + _ = c.ShouldBind(&r) + if msg, ok := utils.ValidateInfo2CN(r); !ok { + response.FailWithMessage(msg, c) + return + } + list, total := test_data.FTList(&r) + response.OkWithData(gin.H{"list": list, "total": total}, c) +} diff --git a/api/test.data/upload.go b/api/test.data/upload.go new file mode 100644 index 0000000..7d76242 --- /dev/null +++ b/api/test.data/upload.go @@ -0,0 +1,129 @@ +package test_data + +import ( + "github.com/gin-gonic/gin" + "os" + "path/filepath" + "strings" + "testData/model" + "testData/model/response" + test_data "testData/repository/test.data" + "time" +) + +type UploadService struct { +} + +func InitUpload() *UploadService { + return &UploadService{} +} + +// @Tags 数据分析平台 +// @Summary 上传没录入文件 +// @Security ApiKeyAuth +// @accept multipart/form-data +// @Param file formData file true "file" +// @Param value formData file true "product_name" +// @Param value formData file true "lot" +// @Param value formData file true "sub_batch" +// -// @Param data body request.SelectionLimit true "参数极限" +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}" +// @Router /testData/upload [post] +func (D *UploadService) UploadAnswerFile(c *gin.Context) { + form, err := c.MultipartForm() + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + files := form.File["file"] + if len(form.Value["product_name"]) < 1 { + response.FailWithMessage("缺少产品名称", c) + return + } + productName := form.Value["product_name"][0] + if len(form.Value["lot"]) < 1 { + response.FailWithMessage("缺少批次", c) + return + } + lot := form.Value["lot"][0] + if len(form.Value["sub_batch"]) < 1 { + response.FailWithMessage("缺少子批次", c) + return + } + subBatch := form.Value["sub_batch"][0] + if len(form.Value["step"]) < 1 { + response.FailWithMessage("缺少工序", c) + return + } + step := form.Value["step"][0] + if len(form.Value["machine"]) < 1 { + response.FailWithMessage("缺少机台类型", c) + return + } + machine := form.Value["machine"][0] + if (lot == "" && subBatch == "") || productName == "" || step == "" || machine == "" { + response.FailWithMessage("信息不全", c) + return + } + fileTexts := make([]*model.FileText, 0) + for _, file := range files { + suffix := file.Filename[strings.LastIndex(file.Filename, "."):] + fileName := time.Now().Format("20060102150405") + suffix + os.MkdirAll("testData/siyuanUpload", os.ModePerm) + filePath := filepath.Join("testData/siyuanUpload", fileName) + if err = c.SaveUploadedFile(file, filePath); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + fileTexts = append(fileTexts, &model.FileText{ + Name: fileName, + Path: filePath, + Factory: "", + ProductName: productName, + Lot: lot, + SubBatch: subBatch, + }) + } + //for _, file := range files { + // os.MkdirAll("testData/siyuanUpload", os.ModePerm) + // filePath := filepath.Join("testData/siyuanUpload", file.Filename) + // if err = c.SaveUploadedFile(file, filePath); err != nil { + // response.FailWithMessage(err.Error(), c) + // return + // } + // archive, err := zip.OpenReader(filePath) + // if err != nil { + // response.FailWithMessage(err.Error(), c) + // return + // } + // for _, archiveFile := range archive.File { + // archiveFilePath := filepath.Join("testData/siyuanUpload", archiveFile.Name) + // dstFile, err := os.OpenFile(archiveFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, archiveFile.Mode()) + // if err != nil { + // log.Println("创建文件" + archiveFilePath + "失败") + // } + // inArchiveFile, err := archiveFile.Open() + // if err != nil { + // log.Println("打开压缩包内文件" + archiveFile.Name + "失败") + // } + // if _, err := io.Copy(dstFile, inArchiveFile); err != nil { + // log.Println("拷贝压缩包文件至" + archiveFilePath + "失败") + // } + // dstFile.Close() + // inArchiveFile.Close() + // fileTexts = append(fileTexts, &model.FileText{ + // Name: archiveFile.Name, + // Path: archiveFilePath, + // Factory: "", + // ProductName: productName, + // Lot: lot, + // SubBatch: subBatch, + // }) + // } + // archive.Close() + //} + + test_data.HandleUploadFiles(fileTexts, step, machine) + response.Ok(c) +} diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..75cd217 --- /dev/null +++ b/config.yml @@ -0,0 +1,112 @@ +dev: true # 是否为开发环境 +dbType: mysql # postgres or mysql +Basedb: # mysql配置 + user: root + password: 123456 + host: 192.168.0.219:3306 + dbname: sys_base + charset: utf8mb4 + +Wip: + user: root + password: 123456 + host: 192.168.0.219:3306 + dbname: wip + charset: utf8mb4 + +Bug: + user: root + password: 123456 + host: 192.168.0.219:3306 + dbname: bug + charset: utf8mb4 + +Tdb: # mysql配置 + user: tpdb + password: TpMysql12#$ + host: 192.168.0.55:3306 + dbname: test_program + charset: utf8mb4 + +db: # mysql配置 + user: tpdb + password: TpMysql12#$ + host: 192.168.0.55:3306 + dbname: flybook + storeDB: store + charset: utf8mb4 + +AttendanceDB: + user: tpdb + password: TpMysql12#$ + host: 192.168.0.55:3306 + dbname: attendance + charset: utf8mb4 + +DataFlowDB: + user: root + password: 123456 + host: 192.168.0.219:3306 + dbname: data_flow + charset: utf8mb4 + +ForumDB: + user: root + password: 123456 + host: 192.168.0.219:3306 + dbname: forum + charset: utf8mb4 + +postgres: # Postgres配置 + user: tpdb + password: TpMysql12#$ + host: 192.168.0.56 + port: 5432 + dbname: test_data + +redis: + # host: redis:6379 # docker-compose 时 + host: 192.168.0.219:6379 + db: 10 + password: "" + +oracle: + host: 192.168.0.30:1521 + user: tkplusemi + password: tkplusemi + SID: topprod + +mongodb: + host: 192.168.0.219 + port: 27017 + +system: + port: :28007 + +signingKey: "tkpluse-jwt-online-token" + +captchaLength: 6 + +domain: http://192.168.0.195:28007/ # 必须以/ 结尾 + +testProgramDomain: http://192.168.0.189:28000/ + +ip2location: # 通过ip获取地理位置 + getCoordinate: https://apis.map.qq.com/ws/location/v1/ip?ip=%s&key=XFZBZ-U2VWI-BWUGT-5FDUJ-BF6MS-RYBGC + getLocation: https://apis.map.qq.com/ws/geocoder/v1/?location=%f,%f&key=XFZBZ-U2VWI-BWUGT-5FDUJ-BF6MS-RYBGC&get_poi=1 + +flybook: + public: + AppId: cli_a00ba57c05b8500d + AppSecret: C8GNm4Yyb3IBI1Zd9dEjldJA137ewix3 + VerificationToken: KMcvkJAvXfsNGE085eDkuclOAU7reueO + EncryptKey: D88KluIYjaeGL5cAVeRJxbRzjyjGOWgH + +positionIDLength: 6 + +AD: + Addr: 192.168.0.38:636 + BindUserName: "administrator@tkpluse.com" + BindPassword: "123qweASD!@#" + RootOu: "OU=TKPLUSE" + SearchDN: "DC=tkpluse,DC=com" \ No newline at end of file diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..5ed250a --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,1627 @@ +// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// This file was generated by swaggo/swag +package docs + +import ( + "bytes" + "encoding/json" + "strings" + "text/template" + + "github.com/swaggo/swag" +) + +var doc = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/testData/cpMap": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "CP Map图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPMap" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/cpMap/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出CP Map图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPMap" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/ftHistogram/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出直方图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Histogram" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/histogram": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "直方图", + "parameters": [ + { + "description": "直方图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Histogram" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/line": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "折线图", + "parameters": [ + { + "description": "折线图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Line" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/logSite": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "Log各Site差异图", + "parameters": [ + { + "description": "Log各Site差异图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.LogSiteChart" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/pie": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "饼状图", + "parameters": [ + { + "description": "饼状图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Pie" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/ab": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ABList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/cp": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "CP记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/fTPassProbabilityByFactory": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "测试良率-按供应商", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PassProbabilityByFactory" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/fTPassProbabilityByProduct": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "测试良率-按产品型号", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PassProbabilityByProduct" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/ft": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "FT记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.FTList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/packageOrderNumberBar": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装良率折线图", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PackagePassProbabilityLine" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/packagePassProbabilityLine": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装良率折线图", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PackagePassProbabilityLine" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/wafer": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "晶圆记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WaferList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/scatter": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "散点图", + "parameters": [ + { + "description": "散点图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Scatter" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/scatter/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出散点图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Scatter" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/selection": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "查询参数", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.QuerySelection" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/selection/limit": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "参数极限", + "parameters": [ + { + "description": "参数极限", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SelectionLimit" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/upload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "上传没录入文件", + "parameters": [ + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "product_name", + "name": "value", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "lot", + "name": "value", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "sub_batch", + "name": "value", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "request.ABList": { + "type": "object", + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "fail_quantity": { + "description": "封装不良品", + "type": "string" + }, + "is_finish": { + "description": "是否已完成", + "type": "string" + }, + "lot": { + "description": "批号", + "type": "string" + }, + "online_quantity": { + "description": "在线数量", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "package": { + "description": "封装", + "type": "string" + }, + "pass_probability": { + "description": "良率", + "type": "string" + }, + "pbi": { + "description": "订单号", + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "quantity": { + "description": "订单数量", + "type": "string" + }, + "seal": { + "description": "丝印", + "type": "string" + }, + "stock_in_quantity": { + "description": "入库数", + "type": "string" + }, + "stock_out_quantity": { + "description": "出库数", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + }, + "wafer_product": { + "description": "晶圆型号", + "type": "string" + } + } + }, + "request.CPList": { + "type": "object", + "properties": { + "factory": { + "description": "CP厂", + "type": "string" + }, + "lot": { + "description": "晶圆批号", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "pbi": { + "type": "string" + }, + "query_type": { + "description": "查询类型", + "type": "string" + }, + "test_machine": { + "description": "测试机台", + "type": "string" + }, + "wafer_product": { + "description": "晶圆型号", + "type": "string" + } + } + }, + "request.CPMap": { + "type": "object", + "properties": { + "hbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "hbin_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.CPMapColor" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "sbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "sbin_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.CPMapColor" + } + }, + "selection": { + "description": "参数", + "type": "array", + "items": { + "type": "string" + } + }, + "selection_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.SelectionColor" + } + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + } + } + }, + "request.CPMapColor": { + "type": "object", + "properties": { + "color": { + "description": "Bin颜色", + "type": "string" + }, + "name": { + "description": "Bin名称", + "type": "string" + } + } + }, + "request.FTList": { + "type": "object", + "properties": { + "factory": { + "description": "SubBatch string ` + "`" + `json:\"sub_batch\"` + "`" + ` // 子批次", + "type": "string" + }, + "lot": { + "description": "晶圆批号", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "pbi": { + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "query_type": { + "description": "查询类型", + "type": "string" + }, + "seal": { + "description": "丝印", + "type": "string" + }, + "test_program": { + "description": "测试程序", + "type": "string" + } + } + }, + "request.Histogram": { + "type": "object", + "properties": { + "average": { + "type": "number" + }, + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "offset": { + "description": "偏移量", + "type": "number" + }, + "only_pass": { + "type": "boolean" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selections": { + "description": "参数", + "type": "array", + "items": { + "type": "string" + } + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "splite_site": { + "type": "boolean" + }, + "splite_sub_batch": { + "type": "boolean" + }, + "standard_deviation": { + "type": "number" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "array", + "items": { + "type": "string" + } + }, + "wafer_id": { + "description": "片号", + "type": "array", + "items": { + "type": "string" + } + }, + "x_max": { + "type": "string" + }, + "x_min": { + "type": "string" + } + } + }, + "request.Line": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "offset": { + "description": "偏移量", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selection": { + "description": "参数", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + } + } + }, + "request.LogSiteChart": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "content_type": { + "description": "内容类型", + "type": "string" + }, + "lot": { + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "type": "string" + }, + "selection": { + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批", + "type": "string" + } + } + }, + "request.PackagePassProbabilityLine": { + "type": "object", + "properties": { + "date_size": { + "description": "时间大小", + "type": "string" + }, + "factory": { + "description": "封装厂", + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "晶圆批次", + "type": "array", + "items": { + "type": "string" + } + }, + "order_date_end": { + "description": "下单日期结束时间", + "type": "string" + }, + "order_date_start": { + "description": "下单日期开始时间", + "type": "string" + }, + "package": { + "description": "封装形式", + "type": "array", + "items": { + "type": "string" + } + }, + "product": { + "description": "成品型号", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "request.PassProbabilityByFactory": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.PassProbabilityByProduct": { + "type": "object", + "required": [ + "product", + "type" + ], + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.Pie": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "max": { + "description": "最大值", + "type": "string" + }, + "min": { + "description": "最小值", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "pie_interval": { + "description": "分区间", + "type": "array", + "items": { + "$ref": "#/definitions/request.PieInterval" + } + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selection": { + "description": "参数", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + } + } + }, + "request.PieInterval": { + "type": "object", + "properties": { + "max": { + "description": "最大值", + "type": "string" + }, + "min": { + "description": "最小值", + "type": "string" + }, + "name": { + "description": "区间名称", + "type": "string" + } + } + }, + "request.QuerySelection": { + "type": "object", + "properties": { + "lot": { + "description": "批号", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + } + } + }, + "request.Scatter": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "only_pass": { + "type": "boolean" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "splite_site": { + "type": "boolean" + }, + "splite_sub_batch": { + "type": "boolean" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "array", + "items": { + "type": "string" + } + }, + "wafer_id": { + "type": "array", + "items": { + "type": "string" + } + }, + "xy_selection": { + "description": "X string ` + "`" + `json:\"x\"` + "`" + `\nY string ` + "`" + `json:\"y\"` + "`" + `\nSelections []string ` + "`" + `json:\"selections\"` + "`" + ` // 参数", + "type": "array", + "items": { + "$ref": "#/definitions/request.XYSelection" + } + } + } + }, + "request.SelectionColor": { + "type": "object", + "properties": { + "color": { + "description": "参数颜色", + "type": "string" + }, + "max": { + "description": "参数范围最大值", + "type": "string" + }, + "min": { + "description": "参数范围最小值", + "type": "string" + }, + "name": { + "description": "参数名称", + "type": "string" + } + } + }, + "request.SelectionLimit": { + "type": "object", + "properties": { + "hbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "type": "string" + }, + "sbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "selection": { + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批", + "type": "string" + }, + "wafer_id": { + "type": "string" + } + } + }, + "request.WaferList": { + "type": "object", + "properties": { + "factory": { + "description": "晶圆厂", + "type": "string" + }, + "lot": { + "description": "批号", + "type": "string" + }, + "online_quantity": { + "description": "在线数量", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "pbi": { + "description": "订单号", + "type": "string" + }, + "product": { + "description": "晶圆型号", + "type": "string" + }, + "quantity": { + "description": "投片数量", + "type": "string" + }, + "return_date": { + "description": "回货日期", + "type": "string" + }, + "return_quantity": { + "description": "回货数量", + "type": "string" + }, + "wafer_size": { + "description": "晶圆尺寸", + "type": "string" + } + } + }, + "request.XYSelection": { + "type": "object", + "properties": { + "x": { + "type": "string" + }, + "y": { + "type": "string" + } + } + } + } +}` + +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{ + Version: "", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "", + Description: "", +} + +type s struct{} + +func (s *s) ReadDoc() string { + sInfo := SwaggerInfo + sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1) + + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface{}) string { + a, _ := json.Marshal(v) + return string(a) + }, + "escape": func(v interface{}) string { + // escape tabs + str := strings.Replace(v.(string), "\t", "\\t", -1) + // replace " with \", and if that results in \\", replace that with \\\" + str = strings.Replace(str, "\"", "\\\"", -1) + return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, sInfo); err != nil { + return doc + } + + return tpl.String() +} + +func init() { + swag.Register(swag.Name, &s{}) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..f9abdd7 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,1554 @@ +{ + "swagger": "2.0", + "info": { + "contact": {} + }, + "paths": { + "/testData/cpMap": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "CP Map图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPMap" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/cpMap/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出CP Map图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPMap" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/ftHistogram/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出直方图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Histogram" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/histogram": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "直方图", + "parameters": [ + { + "description": "直方图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Histogram" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/line": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "折线图", + "parameters": [ + { + "description": "折线图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Line" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/logSite": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "Log各Site差异图", + "parameters": [ + { + "description": "Log各Site差异图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.LogSiteChart" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/pie": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "饼状图", + "parameters": [ + { + "description": "饼状图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Pie" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/ab": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ABList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/cp": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "CP记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.CPList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/fTPassProbabilityByFactory": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "测试良率-按供应商", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PassProbabilityByFactory" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/fTPassProbabilityByProduct": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "测试良率-按产品型号", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PassProbabilityByProduct" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/ft": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "FT记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.FTList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/packageOrderNumberBar": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装良率折线图", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PackagePassProbabilityLine" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/packagePassProbabilityLine": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "封装良率折线图", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PackagePassProbabilityLine" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/report/wafer": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台-生产" + ], + "summary": "晶圆记录", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WaferList" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/scatter": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "散点图", + "parameters": [ + { + "description": "散点图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Scatter" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/scatter/export": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "导出散点图", + "parameters": [ + { + "description": "CP Map图", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.Scatter" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/selection": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "查询参数", + "parameters": [ + { + "description": "查询参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.QuerySelection" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/selection/limit": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "参数极限", + "parameters": [ + { + "description": "参数极限", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SelectionLimit" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/testData/upload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "数据分析平台" + ], + "summary": "上传没录入文件", + "parameters": [ + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "product_name", + "name": "value", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "lot", + "name": "value", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "sub_batch", + "name": "value", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"操作成功\"}", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "request.ABList": { + "type": "object", + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "fail_quantity": { + "description": "封装不良品", + "type": "string" + }, + "is_finish": { + "description": "是否已完成", + "type": "string" + }, + "lot": { + "description": "批号", + "type": "string" + }, + "online_quantity": { + "description": "在线数量", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "package": { + "description": "封装", + "type": "string" + }, + "pass_probability": { + "description": "良率", + "type": "string" + }, + "pbi": { + "description": "订单号", + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "quantity": { + "description": "订单数量", + "type": "string" + }, + "seal": { + "description": "丝印", + "type": "string" + }, + "stock_in_quantity": { + "description": "入库数", + "type": "string" + }, + "stock_out_quantity": { + "description": "出库数", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + }, + "wafer_product": { + "description": "晶圆型号", + "type": "string" + } + } + }, + "request.CPList": { + "type": "object", + "properties": { + "factory": { + "description": "CP厂", + "type": "string" + }, + "lot": { + "description": "晶圆批号", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "pbi": { + "type": "string" + }, + "query_type": { + "description": "查询类型", + "type": "string" + }, + "test_machine": { + "description": "测试机台", + "type": "string" + }, + "wafer_product": { + "description": "晶圆型号", + "type": "string" + } + } + }, + "request.CPMap": { + "type": "object", + "properties": { + "hbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "hbin_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.CPMapColor" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "sbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "sbin_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.CPMapColor" + } + }, + "selection": { + "description": "参数", + "type": "array", + "items": { + "type": "string" + } + }, + "selection_color": { + "type": "array", + "items": { + "$ref": "#/definitions/request.SelectionColor" + } + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + } + } + }, + "request.CPMapColor": { + "type": "object", + "properties": { + "color": { + "description": "Bin颜色", + "type": "string" + }, + "name": { + "description": "Bin名称", + "type": "string" + } + } + }, + "request.FTList": { + "type": "object", + "properties": { + "factory": { + "description": "SubBatch string `json:\"sub_batch\"` // 子批次", + "type": "string" + }, + "lot": { + "description": "晶圆批号", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "pbi": { + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "query_type": { + "description": "查询类型", + "type": "string" + }, + "seal": { + "description": "丝印", + "type": "string" + }, + "test_program": { + "description": "测试程序", + "type": "string" + } + } + }, + "request.Histogram": { + "type": "object", + "properties": { + "average": { + "type": "number" + }, + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "offset": { + "description": "偏移量", + "type": "number" + }, + "only_pass": { + "type": "boolean" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selections": { + "description": "参数", + "type": "array", + "items": { + "type": "string" + } + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "splite_site": { + "type": "boolean" + }, + "splite_sub_batch": { + "type": "boolean" + }, + "standard_deviation": { + "type": "number" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "array", + "items": { + "type": "string" + } + }, + "wafer_id": { + "description": "片号", + "type": "array", + "items": { + "type": "string" + } + }, + "x_max": { + "type": "string" + }, + "x_min": { + "type": "string" + } + } + }, + "request.Line": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "offset": { + "description": "偏移量", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selection": { + "description": "参数", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + } + } + }, + "request.LogSiteChart": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "content_type": { + "description": "内容类型", + "type": "string" + }, + "lot": { + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "type": "string" + }, + "selection": { + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批", + "type": "string" + } + } + }, + "request.PackagePassProbabilityLine": { + "type": "object", + "properties": { + "date_size": { + "description": "时间大小", + "type": "string" + }, + "factory": { + "description": "封装厂", + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "晶圆批次", + "type": "array", + "items": { + "type": "string" + } + }, + "order_date_end": { + "description": "下单日期结束时间", + "type": "string" + }, + "order_date_start": { + "description": "下单日期开始时间", + "type": "string" + }, + "package": { + "description": "封装形式", + "type": "array", + "items": { + "type": "string" + } + }, + "product": { + "description": "成品型号", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "request.PassProbabilityByFactory": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.PassProbabilityByProduct": { + "type": "object", + "required": [ + "product", + "type" + ], + "properties": { + "factory": { + "description": "封装厂", + "type": "string" + }, + "product": { + "description": "成品型号", + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.Pie": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "max": { + "description": "最大值", + "type": "string" + }, + "min": { + "description": "最小值", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "pie_interval": { + "description": "分区间", + "type": "array", + "items": { + "$ref": "#/definitions/request.PieInterval" + } + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "selection": { + "description": "参数", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + } + } + }, + "request.PieInterval": { + "type": "object", + "properties": { + "max": { + "description": "最大值", + "type": "string" + }, + "min": { + "description": "最小值", + "type": "string" + }, + "name": { + "description": "区间名称", + "type": "string" + } + } + }, + "request.QuerySelection": { + "type": "object", + "properties": { + "lot": { + "description": "批号", + "type": "string" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "string" + }, + "wafer_id": { + "description": "片号", + "type": "string" + } + } + }, + "request.Scatter": { + "type": "object", + "properties": { + "bin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "description": "批号", + "type": "string" + }, + "only_pass": { + "type": "boolean" + }, + "pbi": { + "description": "PBI", + "type": "string" + }, + "product": { + "description": "产品型号", + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "splite_site": { + "type": "boolean" + }, + "splite_sub_batch": { + "type": "boolean" + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批号", + "type": "array", + "items": { + "type": "string" + } + }, + "wafer_id": { + "type": "array", + "items": { + "type": "string" + } + }, + "xy_selection": { + "description": "X string `json:\"x\"`\nY string `json:\"y\"`\nSelections []string `json:\"selections\"` // 参数", + "type": "array", + "items": { + "$ref": "#/definitions/request.XYSelection" + } + } + } + }, + "request.SelectionColor": { + "type": "object", + "properties": { + "color": { + "description": "参数颜色", + "type": "string" + }, + "max": { + "description": "参数范围最大值", + "type": "string" + }, + "min": { + "description": "参数范围最小值", + "type": "string" + }, + "name": { + "description": "参数名称", + "type": "string" + } + } + }, + "request.SelectionLimit": { + "type": "object", + "properties": { + "hbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "lot": { + "type": "string" + }, + "pbi": { + "type": "string" + }, + "product": { + "type": "string" + }, + "sbin": { + "type": "array", + "items": { + "type": "string" + } + }, + "selection": { + "type": "string" + }, + "site": { + "type": "array", + "items": { + "type": "string" + } + }, + "step": { + "description": "工序", + "type": "string" + }, + "sub_batch": { + "description": "子批", + "type": "string" + }, + "wafer_id": { + "type": "string" + } + } + }, + "request.WaferList": { + "type": "object", + "properties": { + "factory": { + "description": "晶圆厂", + "type": "string" + }, + "lot": { + "description": "批号", + "type": "string" + }, + "online_quantity": { + "description": "在线数量", + "type": "string" + }, + "order_date": { + "description": "下单日期", + "type": "string" + }, + "pbi": { + "description": "订单号", + "type": "string" + }, + "product": { + "description": "晶圆型号", + "type": "string" + }, + "quantity": { + "description": "投片数量", + "type": "string" + }, + "return_date": { + "description": "回货日期", + "type": "string" + }, + "return_quantity": { + "description": "回货数量", + "type": "string" + }, + "wafer_size": { + "description": "晶圆尺寸", + "type": "string" + } + } + }, + "request.XYSelection": { + "type": "object", + "properties": { + "x": { + "type": "string" + }, + "y": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..259152c --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,1021 @@ +definitions: + request.ABList: + properties: + factory: + description: 封装厂 + type: string + fail_quantity: + description: 封装不良品 + type: string + is_finish: + description: 是否已完成 + type: string + lot: + description: 批号 + type: string + online_quantity: + description: 在线数量 + type: string + order_date: + description: 下单日期 + type: string + package: + description: 封装 + type: string + pass_probability: + description: 良率 + type: string + pbi: + description: 订单号 + type: string + product: + description: 成品型号 + type: string + quantity: + description: 订单数量 + type: string + seal: + description: 丝印 + type: string + stock_in_quantity: + description: 入库数 + type: string + stock_out_quantity: + description: 出库数 + type: string + wafer_id: + description: 片号 + type: string + wafer_product: + description: 晶圆型号 + type: string + type: object + request.CPList: + properties: + factory: + description: CP厂 + type: string + lot: + description: 晶圆批号 + type: string + order_date: + description: 下单日期 + type: string + page: + type: integer + page_size: + type: integer + pbi: + type: string + query_type: + description: 查询类型 + type: string + test_machine: + description: 测试机台 + type: string + wafer_product: + description: 晶圆型号 + type: string + type: object + request.CPMap: + properties: + hbin: + items: + type: string + type: array + hbin_color: + items: + $ref: '#/definitions/request.CPMapColor' + type: array + lot: + description: 批号 + type: string + pbi: + type: string + product: + description: 产品型号 + type: string + sbin: + items: + type: string + type: array + sbin_color: + items: + $ref: '#/definitions/request.CPMapColor' + type: array + selection: + description: 参数 + items: + type: string + type: array + selection_color: + items: + $ref: '#/definitions/request.SelectionColor' + type: array + site: + items: + type: string + type: array + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + type: string + wafer_id: + description: 片号 + type: string + type: object + request.CPMapColor: + properties: + color: + description: Bin颜色 + type: string + name: + description: Bin名称 + type: string + type: object + request.FTList: + properties: + factory: + description: SubBatch string `json:"sub_batch"` // 子批次 + type: string + lot: + description: 晶圆批号 + type: string + order_date: + description: 下单日期 + type: string + page: + type: integer + page_size: + type: integer + pbi: + type: string + product: + description: 成品型号 + type: string + query_type: + description: 查询类型 + type: string + seal: + description: 丝印 + type: string + test_program: + description: 测试程序 + type: string + type: object + request.Histogram: + properties: + average: + type: number + bin: + items: + type: string + type: array + lot: + description: 批号 + type: string + offset: + description: 偏移量 + type: number + only_pass: + type: boolean + pbi: + description: PBI + type: string + product: + description: 产品型号 + type: string + selections: + description: 参数 + items: + type: string + type: array + site: + items: + type: string + type: array + splite_site: + type: boolean + splite_sub_batch: + type: boolean + standard_deviation: + type: number + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + items: + type: string + type: array + wafer_id: + description: 片号 + items: + type: string + type: array + x_max: + type: string + x_min: + type: string + type: object + request.Line: + properties: + bin: + items: + type: string + type: array + lot: + description: 批号 + type: string + offset: + description: 偏移量 + type: string + pbi: + description: PBI + type: string + product: + description: 产品型号 + type: string + selection: + description: 参数 + type: string + site: + items: + type: string + type: array + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + type: string + type: object + request.LogSiteChart: + properties: + bin: + items: + type: string + type: array + content_type: + description: 内容类型 + type: string + lot: + type: string + pbi: + type: string + product: + type: string + selection: + type: string + site: + items: + type: string + type: array + step: + description: 工序 + type: string + sub_batch: + description: 子批 + type: string + type: object + request.PackagePassProbabilityLine: + properties: + date_size: + description: 时间大小 + type: string + factory: + description: 封装厂 + items: + type: string + type: array + lot: + description: 晶圆批次 + items: + type: string + type: array + order_date_end: + description: 下单日期结束时间 + type: string + order_date_start: + description: 下单日期开始时间 + type: string + package: + description: 封装形式 + items: + type: string + type: array + product: + description: 成品型号 + items: + type: string + type: array + type: object + request.PassProbabilityByFactory: + properties: + factory: + description: 封装厂 + type: string + type: + type: string + required: + - type + type: object + request.PassProbabilityByProduct: + properties: + factory: + description: 封装厂 + type: string + product: + description: 成品型号 + type: string + type: + type: string + required: + - product + - type + type: object + request.Pie: + properties: + bin: + items: + type: string + type: array + lot: + description: 批号 + type: string + max: + description: 最大值 + type: string + min: + description: 最小值 + type: string + pbi: + description: PBI + type: string + pie_interval: + description: 分区间 + items: + $ref: '#/definitions/request.PieInterval' + type: array + product: + description: 产品型号 + type: string + selection: + description: 参数 + type: string + site: + items: + type: string + type: array + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + type: string + type: object + request.PieInterval: + properties: + max: + description: 最大值 + type: string + min: + description: 最小值 + type: string + name: + description: 区间名称 + type: string + type: object + request.QuerySelection: + properties: + lot: + description: 批号 + type: string + pbi: + description: PBI + type: string + product: + description: 产品型号 + type: string + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + type: string + wafer_id: + description: 片号 + type: string + type: object + request.Scatter: + properties: + bin: + items: + type: string + type: array + lot: + description: 批号 + type: string + only_pass: + type: boolean + pbi: + description: PBI + type: string + product: + description: 产品型号 + type: string + site: + items: + type: string + type: array + splite_site: + type: boolean + splite_sub_batch: + type: boolean + step: + description: 工序 + type: string + sub_batch: + description: 子批号 + items: + type: string + type: array + wafer_id: + items: + type: string + type: array + xy_selection: + description: |- + X string `json:"x"` + Y string `json:"y"` + Selections []string `json:"selections"` // 参数 + items: + $ref: '#/definitions/request.XYSelection' + type: array + type: object + request.SelectionColor: + properties: + color: + description: 参数颜色 + type: string + max: + description: 参数范围最大值 + type: string + min: + description: 参数范围最小值 + type: string + name: + description: 参数名称 + type: string + type: object + request.SelectionLimit: + properties: + hbin: + items: + type: string + type: array + lot: + type: string + pbi: + type: string + product: + type: string + sbin: + items: + type: string + type: array + selection: + type: string + site: + items: + type: string + type: array + step: + description: 工序 + type: string + sub_batch: + description: 子批 + type: string + wafer_id: + type: string + type: object + request.WaferList: + properties: + factory: + description: 晶圆厂 + type: string + lot: + description: 批号 + type: string + online_quantity: + description: 在线数量 + type: string + order_date: + description: 下单日期 + type: string + pbi: + description: 订单号 + type: string + product: + description: 晶圆型号 + type: string + quantity: + description: 投片数量 + type: string + return_date: + description: 回货日期 + type: string + return_quantity: + description: 回货数量 + type: string + wafer_size: + description: 晶圆尺寸 + type: string + type: object + request.XYSelection: + properties: + x: + type: string + "y": + type: string + type: object +info: + contact: {} +paths: + /testData/cpMap: + post: + consumes: + - application/json + parameters: + - description: CP Map图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.CPMap' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: CP Map图 + tags: + - 数据分析平台 + /testData/cpMap/export: + post: + consumes: + - application/json + parameters: + - description: CP Map图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.CPMap' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 导出CP Map图 + tags: + - 数据分析平台 + /testData/ftHistogram/export: + post: + consumes: + - application/json + parameters: + - description: CP Map图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Histogram' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 导出直方图 + tags: + - 数据分析平台 + /testData/histogram: + post: + consumes: + - application/json + parameters: + - description: 直方图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Histogram' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 直方图 + tags: + - 数据分析平台 + /testData/line: + post: + consumes: + - application/json + parameters: + - description: 折线图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Line' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 折线图 + tags: + - 数据分析平台 + /testData/logSite: + post: + consumes: + - application/json + parameters: + - description: Log各Site差异图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.LogSiteChart' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: Log各Site差异图 + tags: + - 数据分析平台 + /testData/pie: + post: + consumes: + - application/json + parameters: + - description: 饼状图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Pie' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 饼状图 + tags: + - 数据分析平台 + /testData/report/ab: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.ABList' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 封装记录 + tags: + - 数据分析平台-生产 + /testData/report/cp: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.CPList' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: CP记录 + tags: + - 数据分析平台-生产 + /testData/report/fTPassProbabilityByFactory: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.PassProbabilityByFactory' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 测试良率-按供应商 + tags: + - 数据分析平台-生产 + /testData/report/fTPassProbabilityByProduct: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.PassProbabilityByProduct' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 测试良率-按产品型号 + tags: + - 数据分析平台-生产 + /testData/report/ft: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.FTList' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: FT记录 + tags: + - 数据分析平台-生产 + /testData/report/packageOrderNumberBar: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.PackagePassProbabilityLine' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 封装良率折线图 + tags: + - 数据分析平台-生产 + /testData/report/packagePassProbabilityLine: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.PackagePassProbabilityLine' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 封装良率折线图 + tags: + - 数据分析平台-生产 + /testData/report/wafer: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.WaferList' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 晶圆记录 + tags: + - 数据分析平台-生产 + /testData/scatter: + post: + consumes: + - application/json + parameters: + - description: 散点图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Scatter' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 散点图 + tags: + - 数据分析平台 + /testData/scatter/export: + post: + consumes: + - application/json + parameters: + - description: CP Map图 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.Scatter' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 导出散点图 + tags: + - 数据分析平台 + /testData/selection: + post: + consumes: + - application/json + parameters: + - description: 查询参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.QuerySelection' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 查询参数 + tags: + - 数据分析平台 + /testData/selection/limit: + post: + consumes: + - application/json + parameters: + - description: 参数极限 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.SelectionLimit' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 参数极限 + tags: + - 数据分析平台 + /testData/upload: + post: + consumes: + - multipart/form-data + parameters: + - description: file + in: formData + name: file + required: true + type: file + - description: product_name + in: formData + name: value + required: true + type: file + - description: lot + in: formData + name: value + required: true + type: file + - description: sub_batch + in: formData + name: value + required: true + type: file + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"操作成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 上传没录入文件 + tags: + - 数据分析平台 +swagger: "2.0" diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161410.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161410.xlsx new file mode 100644 index 0000000..4d4952b Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161410.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161601.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161601.xlsx new file mode 100644 index 0000000..bb4548a Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161601.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161740.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161740.xlsx new file mode 100644 index 0000000..2453f0c Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161740.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161908.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161908.xlsx new file mode 100644 index 0000000..9a2aa81 Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_161908.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175226.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175226.xlsx new file mode 100644 index 0000000..2d3e618 Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175226.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175332.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175332.xlsx new file mode 100644 index 0000000..c59159d Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-26_175332.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103630.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103630.xlsx new file mode 100644 index 0000000..9d2f3e5 Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103630.xlsx differ diff --git a/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103744.xlsx b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103744.xlsx new file mode 100644 index 0000000..9465628 Binary files /dev/null and b/files/2024-06/CP/TP2212B_EP8HDR.1_CpMap_2024-06-28_103744.xlsx differ diff --git a/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181222.xlsx b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181222.xlsx new file mode 100644 index 0000000..7bff9e3 Binary files /dev/null and b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181222.xlsx differ diff --git a/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181258.xlsx b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181258.xlsx new file mode 100644 index 0000000..b6922ee Binary files /dev/null and b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181258.xlsx differ diff --git a/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181449.xlsx b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181449.xlsx new file mode 100644 index 0000000..4e9211c Binary files /dev/null and b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181449.xlsx differ diff --git a/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181520.xlsx b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181520.xlsx new file mode 100644 index 0000000..f4a2110 Binary files /dev/null and b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181520.xlsx differ diff --git a/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181559.xlsx b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181559.xlsx new file mode 100644 index 0000000..de3b135 Binary files /dev/null and b/files/2024-07/FT/MP5016-5EC0_S3S592_FT_2024-07-04_181559.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163006.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163006.xlsx new file mode 100644 index 0000000..a7b6bc8 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163006.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163108.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163108.xlsx new file mode 100644 index 0000000..8bc3ad1 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163108.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163131.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163131.xlsx new file mode 100644 index 0000000..36bb889 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_163131.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164711.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164711.xlsx new file mode 100644 index 0000000..9635795 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164711.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164723.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164723.xlsx new file mode 100644 index 0000000..f21c6fc Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164723.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164819.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164819.xlsx new file mode 100644 index 0000000..1f8cb1a Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164819.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164956.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164956.xlsx new file mode 100644 index 0000000..693d638 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_164956.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_165204.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_165204.xlsx new file mode 100644 index 0000000..a2d2a2e Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_165204.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_170843.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_170843.xlsx new file mode 100644 index 0000000..4163702 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_170843.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171319.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171319.xlsx new file mode 100644 index 0000000..f4a73aa Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171319.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171600.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171600.xlsx new file mode 100644 index 0000000..32c363e Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_171600.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173331.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173331.xlsx new file mode 100644 index 0000000..641af49 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173331.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173516.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173516.xlsx new file mode 100644 index 0000000..82301bf Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173516.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173703.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173703.xlsx new file mode 100644 index 0000000..ce34535 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173703.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173906.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173906.xlsx new file mode 100644 index 0000000..5f02189 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_173906.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174408.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174408.xlsx new file mode 100644 index 0000000..fc48431 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174408.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174448.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174448.xlsx new file mode 100644 index 0000000..70930c8 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174448.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174615.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174615.xlsx new file mode 100644 index 0000000..62b8f40 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174615.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174720.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174720.xlsx new file mode 100644 index 0000000..1f91d87 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174720.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174915.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174915.xlsx new file mode 100644 index 0000000..508b168 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174915.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174937.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174937.xlsx new file mode 100644 index 0000000..20e6e39 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-11_174937.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092520.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092520.xlsx new file mode 100644 index 0000000..992478b Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092520.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092932.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092932.xlsx new file mode 100644 index 0000000..2e02bc3 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_092932.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_094408.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_094408.xlsx new file mode 100644 index 0000000..4d716fd Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_094408.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095027.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095027.xlsx new file mode 100644 index 0000000..b2b5963 Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095027.xlsx differ diff --git a/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095157.xlsx b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095157.xlsx new file mode 100644 index 0000000..599a12a Binary files /dev/null and b/files/2024-07/直方图/MP5016-5EC0_S3S592_直方图_2024-07-12_095157.xlsx differ diff --git a/global/global.go b/global/global.go new file mode 100644 index 0000000..197b076 --- /dev/null +++ b/global/global.go @@ -0,0 +1,17 @@ +package global + +import ( + "github.com/emersion/go-imap/client" + "go.mongodb.org/mongo-driver/mongo" + "go.uber.org/zap" + "gorm.io/gorm" +) + +var ( + PostGreSQL *gorm.DB + BaseDB *gorm.DB + Oracle *gorm.DB + MongoDB *mongo.Client + Log *zap.SugaredLogger + IMAP *client.Client +) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..366468a --- /dev/null +++ b/go.mod @@ -0,0 +1,125 @@ +module testData + +go 1.19 + +require github.com/natefinch/lumberjack v2.0.0+incompatible + +require ( + gitee.com/golang-module/carbon/v2 v2.3.11 // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.2.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect + github.com/bytedance/sonic v1.11.2 // indirect + github.com/casbin/casbin/v2 v2.82.0 // indirect + github.com/casbin/gorm-adapter/v3 v3.21.0 // indirect + github.com/casbin/govaluate v1.1.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dzwvip/oracle v1.3.0 // indirect + github.com/emersion/go-imap v1.2.1 // indirect + github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 // indirect + github.com/extrame/xls v0.0.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.1 // indirect + github.com/glebarez/go-sqlite v1.22.0 // indirect + github.com/glebarez/sqlite v1.10.0 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-openapi/jsonpointer v0.20.3 // indirect + github.com/go-openapi/jsonreference v0.20.5 // indirect + github.com/go-openapi/spec v0.20.15 // indirect + github.com/go-openapi/swag v0.22.10 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.19.0 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/godror/godror v0.35.0 // indirect + github.com/godror/knownpb v0.1.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgx/v5 v5.5.4 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/microsoft/go-mssqldb v1.7.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/richardlehane/mscfb v1.0.4 // indirect + github.com/richardlehane/msoleps v1.0.3 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/swaggo/files v1.0.1 // indirect + github.com/swaggo/gin-swagger v1.6.0 // indirect + github.com/swaggo/swag v1.16.3 // indirect + github.com/thoas/go-funk v0.9.3 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect + github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0 // indirect + github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/arch v0.7.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.4 // indirect + gorm.io/driver/postgres v1.5.6 // indirect + gorm.io/driver/sqlserver v1.5.3 // indirect + gorm.io/gorm v1.25.10 // indirect + gorm.io/plugin/dbresolver v1.5.1 // indirect + modernc.org/libc v1.42.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect + modernc.org/sqlite v1.29.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2cfcbf4 --- /dev/null +++ b/go.sum @@ -0,0 +1,448 @@ +gitee.com/golang-module/carbon/v2 v2.3.11 h1:lnHx65PlT/U0htW4c2fegVbDW3t5JuFT0ySQl1686EY= +gitee.com/golang-module/carbon/v2 v2.3.11/go.mod h1:10QdzWG6q/NUePI6ag183B0313WrwdtM0zMCWPdTLD8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28= +github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= +github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.11.2 h1:ywfwo0a/3j9HR8wsYGWsIWl2mvRsI950HyoxiBERw5A= +github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/casbin/casbin/v2 v2.82.0 h1:2CgvunqQQoepcbGRnMc9vEcDhuqh3B5yWKoj+kKSxf8= +github.com/casbin/casbin/v2 v2.82.0/go.mod h1:jX8uoN4veP85O/n2674r2qtfSXI6myvxW85f6TH50fw= +github.com/casbin/gorm-adapter/v3 v3.21.0 h1:1YOVpBvGc38H717WKSNCUuhsixFOjF8jmNukq792WBc= +github.com/casbin/gorm-adapter/v3 v3.21.0/go.mod h1:pvTTuyP2Es8VPHLyUssGtvOb3ETYD2tG7TfT5K8X2Sg= +github.com/casbin/govaluate v1.1.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/casbin/govaluate v1.1.1 h1:J1rFKIBhiC5xr0APd5HP6rDL+xt+BRoyq1pa4o2i/5c= +github.com/casbin/govaluate v1.1.1/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= +github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dzwvip/oracle v1.3.0 h1:b84ehEOASYkwLYutaVoq7N+ZagR9OThSVeQMLCIaeR4= +github.com/dzwvip/oracle v1.3.0/go.mod h1:WPibibY0r04N94fkltknygB+r9lqud8MUmMAgcWola4= +github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA= +github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY= +github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= +github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 h1:n+nk0bNe2+gVbRI8WRbLFVwwcBQ0rr5p+gzkKb6ol8c= +github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7/go.mod h1:GPpMrAfHdb8IdQ1/R2uIRBsNfnPnwsYE9YYI5WyY1zw= +github.com/extrame/xls v0.0.1 h1:jI7L/o3z73TyyENPopsLS/Jlekm3nF1a/kF5hKBvy/k= +github.com/extrame/xls v0.0.1/go.mod h1:iACcgahst7BboCpIMSpnFs4SKyU9ZjsvZBfNbUxZOJI= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= +github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.20.3 h1:jykzYWS/kyGtsHfRt6aV8JTB9pcQAXPIA7qlZ5aRlyk= +github.com/go-openapi/jsonpointer v0.20.3/go.mod h1:c7l0rjoouAuIxCm8v/JWKRgMjDG/+/7UBWsXMrv6PsM= +github.com/go-openapi/jsonreference v0.20.5 h1:hutI+cQI+HbSQaIGSfsBsYI0pHk+CATf8Fk5gCSj0yI= +github.com/go-openapi/jsonreference v0.20.5/go.mod h1:thAqAp31UABtI+FQGKAQfmv7DbFpKNUlva2UPCxKu2Y= +github.com/go-openapi/spec v0.20.15 h1:8bDcVxF607pTh9NpPwgsH4J5Uhh5mV5XoWnkurdiY+U= +github.com/go-openapi/spec v0.20.15/go.mod h1:o0upgqg5uYFG7O5mADrDVmSG3Wa6y6OLhwiCqQ+sTv4= +github.com/go-openapi/swag v0.22.10 h1:4y86NVn7Z2yYd6pfS4Z+Nyh3aAUL3Nul+LMbhFKy0gA= +github.com/go-openapi/swag v0.22.10/go.mod h1:Cnn8BYtRlx6BNE3DPN86f/xkapGIcLWzh3CLEb4C1jI= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godror/godror v0.33.3/go.mod h1:FbrZ7po7LyS3gUTdW/K1+kIoePvP/E044HpwptL4vqw= +github.com/godror/godror v0.35.0 h1:V9sTD76SBPREtjsDL6YtZjW2FTwF9uI+ZIVTt/phzMo= +github.com/godror/godror v0.35.0/go.mod h1:jW1+pN+z/V0h28p9XZXVNtEvfZP/2EBfaSjKJLp3E4g= +github.com/godror/godror v0.43.0 h1:qMbQwG0ejJnKma3bBvrJg1rkiyP5b4v6uxvx9zDrKJw= +github.com/godror/godror v0.43.0/go.mod h1:82Uc/HdjsFVnzR5c9Yf6IkTBalK80jzm/U6xojbTo94= +github.com/godror/knownpb v0.1.0/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE= +github.com/godror/knownpb v0.1.1 h1:A4J7jdx7jWBhJm18NntafzSC//iZDHkDi1+juwQ5pTI= +github.com/godror/knownpb v0.1.1/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= +github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= +github.com/microsoft/go-mssqldb v1.7.0 h1:sgMPW0HA6Ihd37Yx0MzHyKD726C2kY/8KJsQtXHNaAs= +github.com/microsoft/go-mssqldb v1.7.0/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= +github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= +github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= +github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= +github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= +github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= +github.com/thoas/go-funk v0.7.0/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= +github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw= +github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9 h1:JUZL5TQ/WK5veU2N171inEvwseqf4V0TxgGKl2Ypyvs= +github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9/go.mod h1:guVzD2XeU5rwULTURC4peeFyZya60U0BLKqisEjCylA= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0= +github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY= +github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/excelize/v2 v2.8.0 h1:Vd4Qy809fupgp1v7X+nCS/MioeQmYVVzi495UCTqB7U= +github.com/xuri/excelize/v2 v2.8.0/go.mod h1:6iA2edBTKxKbZAa7X5bDhcCg51xdOn1Ar5sfoXRGrQg= +github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ= +github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE= +github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0 h1:m8LOTcksvhzoCRSI4fwlCaaBJ3MShtjhfTrxv2AboHk= +github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0/go.mod h1:0hWeRQBdU+HQng3S1AXdYm8Ob0dbevUncXAWI0QswPU= +github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= +github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4= +github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= +github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A= +github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= +golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/mysql v1.5.4 h1:igQmHfKcbaTVyAIHNhhB888vvxh8EdQ2uSUT0LPcBso= +gorm.io/driver/mysql v1.5.4/go.mod h1:9rYxJph/u9SWkWc9yY4XJ1F/+xO0S/ChOmbk3+Z5Tvs= +gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= +gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0= +gorm.io/driver/postgres v1.5.6 h1:ydr9xEd5YAM0vxVDY0X139dyzNz10spDiDlC7+ibLeU= +gorm.io/driver/postgres v1.5.6/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0= +gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/plugin/dbresolver v1.5.1 h1:s9Dj9f7r+1rE3nx/Ywzc85nXptUEaeOO0pt27xdopM8= +gorm.io/plugin/dbresolver v1.5.1/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0= +modernc.org/libc v1.42.1 h1:W2T7qUhyCmEaFxqNec9x0T6ohiffM/jvifCSwKC9Gj8= +modernc.org/libc v1.42.1/go.mod h1:UbS9Tjnye2q6hLYa7gw/q73fXB9lyn/fXLBGzgser8g= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.29.3 h1:6L71d3zXVB8oubdVSuwiurNyYRetQ3It8l1FSwylwQ0= +modernc.org/sqlite v1.29.3/go.mod h1:MjUIBKZ+tU/lqjNLbVAAMjsQPdWdA/ciwdhsT9kBwk8= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/initialization/base.db.go b/initialization/base.db.go new file mode 100644 index 0000000..2092152 --- /dev/null +++ b/initialization/base.db.go @@ -0,0 +1,40 @@ +package initialization + +import ( + "github.com/spf13/viper" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "testData/global" + "time" +) + +func InitBaseDB() { + user := viper.GetString("Basedb.user") + password := viper.GetString("Basedb.password") + host := viper.GetString("Basedb.host") + dbname := viper.GetString("Basedb.dbname") + charset := viper.GetString("Basedb.charset") + dsn := user + ":" + password + "@tcp(" + host + ")/" + dbname + "?charset=" + charset + "&parseTime=True&loc=Local" + mysqlConfig := mysql.Config{ + DSN: dsn, // DSN data source name + DefaultStringSize: 255, // string 类型字段的默认长度 + DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持 + DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引 + DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 + SkipInitializeWithVersion: false, // 根据版本自动配置 + } + if db, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{ + DisableForeignKeyConstraintWhenMigrating: true, + Logger: logger.Default.LogMode(logger.Silent), + }); err != nil { + global.Log.Errorf("%s", err) + panic(err) + } else { + sqlDB, _ := db.DB() + sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量 + sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量 + sqlDB.SetConnMaxLifetime(time.Hour) // 设置了连接可复用的最大时间 + global.BaseDB = db + } +} diff --git a/initialization/config.go b/initialization/config.go new file mode 100644 index 0000000..39a04c0 --- /dev/null +++ b/initialization/config.go @@ -0,0 +1,17 @@ +package initialization + +import ( + "github.com/spf13/viper" + "os" +) + +func InitConfig() { + workDir, _ := os.Getwd() + viper.SetConfigName("config") + viper.SetConfigType("yml") + viper.AddConfigPath(workDir) + err := viper.ReadInConfig() + if err != nil { + panic(err) + } +} diff --git a/initialization/logger.go b/initialization/logger.go new file mode 100644 index 0000000..14d9404 --- /dev/null +++ b/initialization/logger.go @@ -0,0 +1,49 @@ +package initialization + +import ( + "github.com/natefinch/lumberjack" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "os" + "testData/global" + "time" +) + +func InitLogger() { + writeSyncer := getLogWriter() + encoder := getEncoder() + core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) + // 显示日志发生的代码行号 + //logger := zap.New(core, zap.AddCaller()) + // 不显示日志发生的代码行号 + logger := zap.New(core) + global.Log = logger.Sugar() +} + +func getEncoder() zapcore.Encoder { + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(t.Format("2006-01-02 15:04:05")) + } + encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder + return zapcore.NewConsoleEncoder(encoderConfig) +} + +func getLogWriter() zapcore.WriteSyncer { + lumberJackLogger := &lumberjack.Logger{ + Filename: "./log/message.log", // 日志文件路径 + MaxSize: 1, // 每个日志文件保存最大尺寸,单位 M + MaxBackups: 15, // 日志最多保存多少个备份 + MaxAge: 30, // 文件最多保存多少天 + Compress: false, // 是否压缩 + LocalTime: true, // 是否使用本地时间 + } + defer lumberJackLogger.Close() + // 日志输出至console和文件 + return zapcore.NewMultiWriteSyncer( + zapcore.AddSync(lumberJackLogger), + zapcore.AddSync(os.Stdout), + ) + // 日志只输出到文件 + //return zapcore.AddSync(lumberJackLogger) +} diff --git a/initialization/mongo.go b/initialization/mongo.go new file mode 100644 index 0000000..0a308a1 --- /dev/null +++ b/initialization/mongo.go @@ -0,0 +1,23 @@ +package initialization + +import ( + "context" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/mongo/readpref" + "testData/global" +) + +func InitMongoDB() { + //host := viper.GetString("mongodb.host") + //port := viper.GetString("mongodb.port") + //client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://"+host+":"+port)) + client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017")) + if err != nil { + panic(err) + } + if err = client.Ping(context.TODO(), readpref.Primary()); err != nil { + panic(err) + } + global.MongoDB = client +} diff --git a/initialization/oracle.go b/initialization/oracle.go new file mode 100644 index 0000000..747900a --- /dev/null +++ b/initialization/oracle.go @@ -0,0 +1,21 @@ +package initialization + +import ( + "github.com/dzwvip/oracle" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "testData/global" +) + +func InitOracle() { + con, err := gorm.Open(oracle.Open("tkplusemi/tkplusemi@192.168.0.30:1521/topprod"), // + &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + //QueryFields: true, + }) + if err != nil { + println("oracle connect error:", err) + panic(err) + } + global.Oracle = con +} diff --git a/initialization/postgre.go b/initialization/postgre.go new file mode 100644 index 0000000..cbbee95 --- /dev/null +++ b/initialization/postgre.go @@ -0,0 +1,36 @@ +package initialization + +import ( + "fmt" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "log" + "testData/global" + "testData/model" + "time" +) + +func InitPostgres() { + dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", + "192.168.0.56", + "tpdb", + "TpMysql12#$", + "test_data", + "5432", + ) + if db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ + DisableForeignKeyConstraintWhenMigrating: true, + //Logger: logger.Default.LogMode(logger.Silent), + }); err != nil { + log.Printf("PostgreSQL Connection error: %s", err) + panic(err) + } else { + postgresDB, _ := db.DB() + postgresDB.SetMaxIdleConns(10) + postgresDB.SetMaxOpenConns(100) + postgresDB.SetConnMaxLifetime(time.Hour) + _ = db.AutoMigrate(&model.FileHandled{}) + global.PostGreSQL = db + _ = global.PostGreSQL.AutoMigrate(&model.FileHandled{}) + } +} diff --git a/initialization/router.go b/initialization/router.go new file mode 100644 index 0000000..057f98f --- /dev/null +++ b/initialization/router.go @@ -0,0 +1,40 @@ +package initialization + +import ( + "github.com/gin-gonic/gin" + "github.com/spf13/viper" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" + "net/http" + testdata "testData/api/test.data" + _ "testData/docs" + "testData/middleware" + "testData/model/response" + "testData/router" +) + +func InitRouter() *gin.Engine { + r := gin.New() + r.Use(gin.Recovery(), middleware.Cors(), middleware.Log()) + // 判断是否线上环境 + if viper.GetBool("dev") { + r.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + } + r.StaticFS("files", http.Dir("./files")) + + testData := r.Group("testData") + { + router.InitChartRouter(testData) + router.InitReportListRouter(testData) + router.InitReportChartRouter(testData) + } + testDataUpload := r.Group("testData") + testDataUploadService := testdata.InitUpload() + { + testDataUpload.POST("upload", testDataUploadService.UploadAnswerFile) + } + r.NoRoute(func(c *gin.Context) { + response.FailWithMessage("Not Found", c) + }) + return r +} diff --git a/initialization/run.server.go b/initialization/run.server.go new file mode 100644 index 0000000..8c53db1 --- /dev/null +++ b/initialization/run.server.go @@ -0,0 +1,23 @@ +package initialization + +import ( + "github.com/spf13/viper" + "net/http" + "time" +) + +func RunServer() { + port := viper.GetString("system.port") + r := InitRouter() + s := &http.Server{ + Addr: port, + Handler: r, + ReadTimeout: 120 * time.Second, + WriteTimeout: 120 * time.Second, + MaxHeaderBytes: 1 << 20, + } + println("run on port", port) + if err := s.ListenAndServe(); err != nil { + panic(err) + } +} diff --git a/log/message.log b/log/message.log new file mode 100644 index 0000000..ae3211d --- /dev/null +++ b/log/message.log @@ -0,0 +1,1021 @@ +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 564µs | GET | 未登录 | /docs/index.html +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 2.2931ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 998.1µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 1.6943ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 252.8µs | GET | 未登录 | /docs/doc.json +2024-03-08 17:19:30 INFO | 192.168.0.219 | 200 | 974µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 561.2µs | GET | 未登录 | /docs/index.html +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 737.1µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 1.0175ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 586.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 403.7µs | GET | 未登录 | /docs/doc.json +2024-03-11 11:34:39 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-11 11:35:11 INFO | 192.168.0.219 | 200 | 2.9159017s | POST | 未登录 | /testData +2024-03-12 14:53:09 INFO | 192.168.0.219 | 200 | 3.8130469s | POST | 未登录 | /testData +2024-03-12 14:54:10 INFO | 192.168.0.219 | 200 | 3.9892954s | POST | 未登录 | /testData +2024-03-12 14:54:57 INFO | 192.168.0.219 | 200 | 24.2653ms | POST | 未登录 | /testData +2024-03-12 14:56:40 INFO | 192.168.0.219 | 200 | 3.8150598s | POST | 未登录 | /testData +2024-03-12 16:02:31 INFO | 192.168.0.248 | 200 | 9.8602ms | POST | 未登录 | /testData +2024-03-12 16:03:34 INFO | 192.168.0.248 | 200 | 3.856756s | POST | 未登录 | /testData +2024-03-12 16:06:32 INFO | 192.168.0.248 | 200 | 3.3536155s | POST | 未登录 | /testData +2024-03-12 16:09:40 INFO | 192.168.0.248 | 200 | 3.3287517s | POST | 未登录 | /testData +2024-03-12 16:12:57 INFO | 192.168.0.248 | 200 | 4.2395859s | POST | 未登录 | /testData +2024-03-12 16:14:26 INFO | 192.168.0.248 | 200 | 3.8898797s | POST | 未登录 | /testData +2024-03-12 16:16:47 INFO | 192.168.0.248 | 200 | 3.4292196s | POST | 未登录 | /testData +2024-03-12 16:18:42 INFO | 192.168.0.248 | 200 | 3.2216407s | POST | 未登录 | /testData +2024-03-12 16:22:17 INFO | 192.168.0.248 | 200 | 3.3157985s | POST | 未登录 | /testData +2024-03-12 16:23:48 INFO | 192.168.0.219 | 200 | 3.5568361s | POST | 未登录 | /testData +2024-03-12 16:25:46 INFO | 192.168.0.248 | 200 | 3.2673971s | POST | 未登录 | /testData +2024-03-12 16:26:17 INFO | 192.168.0.248 | 200 | 3.2649589s | POST | 未登录 | /testData +2024-03-12 16:27:39 INFO | 192.168.0.248 | 200 | 3.021361s | POST | 未登录 | /testData +2024-03-12 16:28:10 INFO | 192.168.0.219 | 200 | 3.1366709s | POST | 未登录 | /testData +2024-03-12 16:28:21 INFO | 192.168.0.248 | 200 | 3.524726s | POST | 未登录 | /testData +2024-03-12 16:29:53 INFO | 192.168.0.248 | 200 | 3.2259884s | POST | 未登录 | /testData +2024-03-12 16:40:21 INFO | 192.168.0.219 | 200 | 3.7881058s | POST | 未登录 | /testData +2024-03-12 16:41:30 INFO | 192.168.0.219 | 200 | 4.0441926s | POST | 未登录 | /testData +2024-03-12 16:41:38 INFO | 192.168.0.248 | 200 | 3.8217484s | POST | 未登录 | /testData +2024-03-12 16:43:02 INFO | 192.168.0.248 | 200 | 3.8758157s | POST | 未登录 | /testData +2024-03-12 16:44:06 INFO | 192.168.0.219 | 200 | 4.7184328s | POST | 未登录 | /testData +2024-03-12 16:50:08 INFO | 192.168.0.219 | 200 | 4.7295867s | POST | 未登录 | /testData +2024-03-12 16:54:42 INFO | 192.168.0.219 | 200 | 15.6509864s | POST | 未登录 | /testData +2024-03-12 16:58:01 INFO | 192.168.0.219 | 200 | 4.7434135s | POST | 未登录 | /testData +2024-03-12 16:58:39 INFO | 192.168.0.248 | 200 | 4.4283445s | POST | 未登录 | /testData +2024-03-12 16:59:53 INFO | 192.168.0.248 | 200 | 3.8235738s | POST | 未登录 | /testData +2024-03-12 17:02:00 INFO | 192.168.0.248 | 200 | 3.6613964s | POST | 未登录 | /testData +2024-03-12 17:21:14 INFO | 192.168.0.248 | 200 | 4.7118966s | POST | 未登录 | /testData +2024-03-12 17:23:34 INFO | 192.168.0.248 | 200 | 3.9315334s | POST | 未登录 | /testData +2024-03-12 17:25:47 INFO | 192.168.0.248 | 200 | 4.1100187s | POST | 未登录 | /testData +2024-03-12 17:28:40 INFO | 192.168.0.248 | 200 | 3.7838935s | POST | 未登录 | /testData +2024-03-12 17:29:11 INFO | 192.168.0.248 | 200 | 4.4364323s | POST | 未登录 | /testData +2024-03-12 17:32:36 INFO | 192.168.0.248 | 200 | 3.6898284s | POST | 未登录 | /testData +2024-03-12 17:35:22 INFO | 192.168.0.248 | 200 | 3.6484112s | POST | 未登录 | /testData +2024-03-12 17:36:53 INFO | 192.168.0.248 | 200 | 3.746444s | POST | 未登录 | /testData +2024-03-12 17:38:04 INFO | 192.168.0.248 | 200 | 3.5624085s | POST | 未登录 | /testData +2024-03-12 17:39:15 INFO | 192.168.0.248 | 200 | 4.0199875s | POST | 未登录 | /testData +2024-03-12 17:44:01 INFO | 192.168.0.248 | 200 | 4.2541884s | POST | 未登录 | /testData +2024-03-12 17:53:11 INFO | 192.168.0.248 | 200 | 4.5357969s | POST | 未登录 | /testData +2024-03-12 17:55:38 INFO | 192.168.0.248 | 200 | 3.7073317s | POST | 未登录 | /testData +2024-03-12 17:57:07 INFO | 192.168.0.189 | 200 | 3.8389933s | POST | 未登录 | /testData +2024-03-12 17:57:15 INFO | 192.168.0.189 | 200 | 3.6847993s | POST | 未登录 | /testData +2024-03-13 09:47:29 INFO | 192.168.0.248 | 200 | 5.4158491s | POST | 未登录 | /testData +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 1.0163ms | GET | 未登录 | /docs/index.html +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 828.9µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 1.2933ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 729.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 519.9µs | GET | 未登录 | /docs/doc.json +2024-03-13 10:20:46 INFO | 192.168.0.219 | 200 | 725.3µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 10:22:40 INFO | 192.168.0.219 | 200 | 3.8565262s | POST | 未登录 | /testData/scatter +2024-03-13 10:23:12 INFO | 192.168.0.219 | 200 | 1.061ms | GET | 未登录 | /docs/index.html +2024-03-13 10:23:35 INFO | 192.168.0.219 | 200 | 212.7µs | GET | 未登录 | /docs/index.html +2024-03-13 10:23:36 INFO | 192.168.0.219 | 200 | 1.439ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-13 10:23:36 INFO | 192.168.0.219 | 200 | 621.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-13 10:23:36 INFO | 192.168.0.219 | 200 | 621.8µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-13 10:23:36 INFO | 192.168.0.219 | 200 | 514.8µs | GET | 未登录 | /docs/doc.json +2024-03-13 10:23:36 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 10:24:39 INFO | 192.168.0.219 | 200 | 24.3719509s | POST | 未登录 | /testData/scatter +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 566.3µs | GET | 未登录 | /docs/index.html +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 921.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 328.6µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 981.6µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 882.5µs | GET | 未登录 | /docs/doc.json +2024-03-13 10:49:10 INFO | 192.168.0.219 | 200 | 465.3µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 4.2194ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 1.4847ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 16.7785ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 846µs | GET | 未登录 | /docs/doc.json +2024-03-13 10:51:00 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 11:00:47 INFO | 192.168.0.248 | 200 | 4.8928985s | POST | 未登录 | /testData/scatter +2024-03-13 11:00:48 INFO | 192.168.0.248 | 200 | 5.5665586s | POST | 未登录 | /testData +2024-03-13 11:06:06 INFO | 192.168.0.248 | 200 | 4.6984055s | POST | 未登录 | /testData/scatter +2024-03-13 11:06:07 INFO | 192.168.0.248 | 200 | 5.2747205s | POST | 未登录 | /testData +2024-03-13 11:06:26 INFO | 192.168.0.219 | 200 | 4.1723385s | POST | 未登录 | /testData/scatter +2024-03-13 11:06:27 INFO | 192.168.0.219 | 200 | 5.4325215s | POST | 未登录 | /testData +2024-03-13 11:07:45 INFO | 192.168.0.219 | 200 | 3.0154675s | POST | 未登录 | /testData/scatter +2024-03-13 11:08:05 INFO | 192.168.0.248 | 200 | 3.5385464s | POST | 未登录 | /testData/scatter +2024-03-13 11:11:50 INFO | 192.168.0.219 | 200 | 18.9533479s | POST | 未登录 | /testData/scatter +2024-03-13 11:13:52 INFO | 192.168.0.219 | 200 | 9.167239s | POST | 未登录 | /testData/scatter +2024-03-13 11:14:42 INFO | 192.168.0.248 | 200 | 3.399481s | POST | 未登录 | /testData/scatter +2024-03-13 11:16:01 INFO | 192.168.0.219 | 200 | 11.0427538s | POST | 未登录 | /testData/scatter +2024-03-13 11:20:47 INFO | 192.168.0.189 | 200 | 4.3802393s | POST | 未登录 | /testData/scatter +2024-03-13 11:24:04 INFO | 192.168.0.219 | 200 | 3.9379463s | POST | 未登录 | /testData/scatter +2024-03-13 11:24:29 INFO | 192.168.0.248 | 200 | 3.1648193s | POST | 未登录 | /testData/scatter +2024-03-13 11:27:12 INFO | 192.168.0.248 | 200 | 3.2051924s | POST | 未登录 | /testData/scatter +2024-03-13 11:28:29 INFO | 192.168.0.248 | 200 | 3.3004227s | POST | 未登录 | /testData/scatter +2024-03-13 11:40:19 INFO | 192.168.0.219 | 200 | 4.2024551s | POST | 未登录 | /testData/scatter +2024-03-13 14:13:02 INFO | 192.168.0.248 | 200 | 4.7008967s | POST | 未登录 | /testData/scatter +2024-03-13 14:13:02 INFO | 192.168.0.248 | 200 | 5.2623947s | POST | 未登录 | /testData +2024-03-13 14:13:26 INFO | 192.168.0.248 | 200 | 3.8234405s | POST | 未登录 | /testData/scatter +2024-03-13 14:13:27 INFO | 192.168.0.248 | 200 | 4.3413103s | POST | 未登录 | /testData +2024-03-13 14:16:22 INFO | 192.168.0.248 | 200 | 4.0270694s | POST | 未登录 | /testData/scatter +2024-03-13 14:16:23 INFO | 192.168.0.248 | 200 | 4.6673598s | POST | 未登录 | /testData +2024-03-13 14:22:26 INFO | 192.168.0.248 | 200 | 4.759514s | POST | 未登录 | /testData/scatter +2024-03-13 14:22:26 INFO | 192.168.0.248 | 200 | 5.2805165s | POST | 未登录 | /testData +2024-03-13 14:23:40 INFO | 192.168.0.248 | 200 | 3.7778303s | POST | 未登录 | /testData/scatter +2024-03-13 14:23:40 INFO | 192.168.0.248 | 200 | 4.299949s | POST | 未登录 | /testData +2024-03-13 15:57:35 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 15:57:55 INFO | 192.168.0.219 | 200 | 2.9346863s | POST | 未登录 | /testData +2024-03-13 16:01:34 INFO | 192.168.0.248 | 200 | 3.3443441s | POST | 未登录 | /testData/scatter +2024-03-13 16:01:35 INFO | 192.168.0.248 | 200 | 4.0211768s | POST | 未登录 | /testData +2024-03-13 16:02:38 INFO | 192.168.0.248 | 200 | 3.4525623s | POST | 未登录 | /testData/scatter +2024-03-13 16:02:38 INFO | 192.168.0.248 | 200 | 3.9209446s | POST | 未登录 | /testData +2024-03-13 16:10:05 INFO | 192.168.0.248 | 200 | 3.4689356s | POST | 未登录 | /testData/scatter +2024-03-13 16:10:06 INFO | 192.168.0.248 | 200 | 4.0026563s | POST | 未登录 | /testData +2024-03-13 16:11:34 INFO | 192.168.0.248 | 200 | 3.0276029s | POST | 未登录 | /testData/scatter +2024-03-13 16:11:35 INFO | 192.168.0.248 | 200 | 3.5116919s | POST | 未登录 | /testData +2024-03-13 16:17:31 INFO | 192.168.0.248 | 200 | 3.3046167s | POST | 未登录 | /testData/scatter +2024-03-13 16:17:32 INFO | 192.168.0.248 | 200 | 3.8162802s | POST | 未登录 | /testData +2024-03-13 16:18:11 INFO | 192.168.0.248 | 200 | 3.4513224s | POST | 未登录 | /testData/scatter +2024-03-13 16:18:11 INFO | 192.168.0.248 | 200 | 3.9478056s | POST | 未登录 | /testData +2024-03-13 16:42:11 INFO | 192.168.0.248 | 200 | 4.7803099s | POST | 未登录 | /testData/scatter +2024-03-13 16:42:11 INFO | 192.168.0.248 | 200 | 4.9140188s | POST | 未登录 | /testData +2024-03-13 16:42:40 INFO | 192.168.0.248 | 200 | 3.4397826s | POST | 未登录 | /testData/scatter +2024-03-13 16:42:41 INFO | 192.168.0.248 | 200 | 4.0321734s | POST | 未登录 | /testData +2024-03-13 16:43:28 INFO | 192.168.0.248 | 200 | 3.3506488s | POST | 未登录 | /testData/scatter +2024-03-13 16:43:29 INFO | 192.168.0.248 | 200 | 3.6123838s | POST | 未登录 | /testData +2024-03-13 16:46:05 INFO | 192.168.0.248 | 200 | 2.3681777s | POST | 未登录 | /testData/scatter +2024-03-13 16:46:05 INFO | 192.168.0.248 | 200 | 2.8928031s | POST | 未登录 | /testData +2024-03-13 16:48:24 INFO | 192.168.0.248 | 200 | 3.2019519s | POST | 未登录 | /testData/scatter +2024-03-13 16:48:24 INFO | 192.168.0.248 | 200 | 3.4812382s | POST | 未登录 | /testData +2024-03-13 16:51:23 INFO | 192.168.0.248 | 200 | 2.3488082s | POST | 未登录 | /testData/scatter +2024-03-13 16:51:24 INFO | 192.168.0.248 | 200 | 3.0898251s | POST | 未登录 | /testData +2024-03-13 16:52:44 INFO | 192.168.0.248 | 200 | 2.3886916s | POST | 未登录 | /testData/scatter +2024-03-13 16:52:45 INFO | 192.168.0.248 | 200 | 2.9504815s | POST | 未登录 | /testData +2024-03-13 16:54:46 INFO | 192.168.0.248 | 200 | 2.5562131s | POST | 未登录 | /testData/scatter +2024-03-13 16:54:47 INFO | 192.168.0.248 | 200 | 3.0249335s | POST | 未登录 | /testData +2024-03-13 16:59:02 INFO | 192.168.0.219 | 200 | 3.504326s | POST | 未登录 | /testData/scatter +2024-03-13 16:59:03 INFO | 192.168.0.219 | 200 | 4.0618369s | POST | 未登录 | /testData +2024-03-13 16:59:35 INFO | 192.168.0.219 | 200 | 3.2369104s | POST | 未登录 | /testData/scatter +2024-03-13 16:59:36 INFO | 192.168.0.219 | 200 | 3.838965s | POST | 未登录 | /testData +2024-03-13 17:00:09 INFO | 192.168.0.189 | 200 | 2.3937344s | POST | 未登录 | /testData/scatter +2024-03-13 17:00:10 INFO | 192.168.0.189 | 200 | 2.9568351s | POST | 未登录 | /testData +2024-03-13 17:03:44 INFO | 192.168.0.248 | 200 | 2.4430777s | POST | 未登录 | /testData/scatter +2024-03-13 17:03:44 INFO | 192.168.0.248 | 200 | 2.9137726s | POST | 未登录 | /testData +2024-03-13 17:04:01 INFO | 192.168.0.219 | 200 | 2.833817s | POST | 未登录 | /testData/scatter +2024-03-13 17:04:01 INFO | 192.168.0.219 | 200 | 3.3277228s | POST | 未登录 | /testData +2024-03-13 17:04:59 INFO | 192.168.0.248 | 200 | 2.7328293s | POST | 未登录 | /testData/scatter +2024-03-13 17:05:00 INFO | 192.168.0.248 | 200 | 3.2909257s | POST | 未登录 | /testData +2024-03-13 17:06:06 INFO | 192.168.0.248 | 200 | 2.2908212s | POST | 未登录 | /testData/scatter +2024-03-13 17:06:07 INFO | 192.168.0.248 | 200 | 2.7740693s | POST | 未登录 | /testData +2024-03-13 17:08:27 INFO | 192.168.0.248 | 200 | 2.3673439s | POST | 未登录 | /testData/scatter +2024-03-13 17:08:28 INFO | 192.168.0.248 | 200 | 2.8922735s | POST | 未登录 | /testData +2024-03-13 17:09:30 INFO | 192.168.0.248 | 200 | 2.953341s | POST | 未登录 | /testData/scatter +2024-03-13 17:09:30 INFO | 192.168.0.248 | 200 | 3.4413371s | POST | 未登录 | /testData +2024-03-13 17:15:16 INFO | 192.168.0.248 | 200 | 2.8715915s | POST | 未登录 | /testData/scatter +2024-03-13 17:15:16 INFO | 192.168.0.248 | 200 | 3.3772392s | POST | 未登录 | /testData +2024-03-13 17:23:38 INFO | 192.168.0.248 | 200 | 3.4845001s | POST | 未登录 | /testData/scatter +2024-03-13 17:23:39 INFO | 192.168.0.248 | 200 | 4.0657125s | POST | 未登录 | /testData +2024-03-13 17:25:15 INFO | 192.168.0.248 | 200 | 2.8107546s | POST | 未登录 | /testData/scatter +2024-03-13 17:25:15 INFO | 192.168.0.248 | 200 | 3.2826583s | POST | 未登录 | /testData +2024-03-13 17:25:39 INFO | 192.168.0.248 | 200 | 2.3168309s | POST | 未登录 | /testData/scatter +2024-03-13 17:25:40 INFO | 192.168.0.248 | 200 | 2.7911862s | POST | 未登录 | /testData +2024-03-13 17:34:16 INFO | 192.168.0.248 | 200 | 3.4581519s | POST | 未登录 | /testData/scatter +2024-03-13 17:34:16 INFO | 192.168.0.248 | 200 | 4.031153s | POST | 未登录 | /testData +2024-03-13 17:34:43 INFO | 192.168.0.248 | 200 | 2.7635621s | POST | 未登录 | /testData/scatter +2024-03-13 17:34:44 INFO | 192.168.0.248 | 200 | 3.2928347s | POST | 未登录 | /testData +2024-03-13 17:36:19 INFO | 192.168.0.248 | 200 | 2.3435688s | POST | 未登录 | /testData/scatter +2024-03-13 17:36:19 INFO | 192.168.0.248 | 200 | 2.8202348s | POST | 未登录 | /testData +2024-03-13 17:39:30 INFO | 192.168.0.248 | 200 | 2.404386s | POST | 未登录 | /testData/scatter +2024-03-13 17:39:30 INFO | 192.168.0.248 | 200 | 2.978297s | POST | 未登录 | /testData +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 1.0905ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 2.7153ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 8.6847ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 1.7111ms | GET | 未登录 | /docs/doc.json +2024-03-13 17:42:17 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-13 17:45:52 INFO | 192.168.0.248 | 200 | 3.5037489s | POST | 未登录 | /testData/scatter +2024-03-13 17:45:52 INFO | 192.168.0.248 | 200 | 4.1459619s | POST | 未登录 | /testData +2024-03-13 17:45:59 INFO | 192.168.0.248 | 200 | 3.4408762s | POST | 未登录 | /testData +2024-03-13 17:53:32 INFO | 192.168.0.219 | 200 | 3.8264535s | POST | 未登录 | /testData/scatter +2024-03-13 17:53:32 INFO | 192.168.0.219 | 200 | 4.4402771s | POST | 未登录 | /testData +2024-03-13 17:54:13 INFO | 192.168.0.219 | 200 | 3.3692193s | POST | 未登录 | /testData +2024-03-13 17:55:22 INFO | 192.168.0.248 | 200 | 2.9002218s | POST | 未登录 | /testData +2024-03-13 17:56:16 INFO | 192.168.0.248 | 200 | 2.3185811s | POST | 未登录 | /testData/scatter +2024-03-13 17:56:17 INFO | 192.168.0.248 | 200 | 2.8961797s | POST | 未登录 | /testData +2024-03-13 17:56:34 INFO | 192.168.0.248 | 200 | 3.1559172s | POST | 未登录 | /testData/scatter +2024-03-13 17:56:34 INFO | 192.168.0.248 | 200 | 3.6740004s | POST | 未登录 | /testData +2024-03-13 17:57:18 INFO | 192.168.0.219 | 200 | 3.4605368s | POST | 未登录 | /testData +2024-03-13 17:58:31 INFO | 192.168.0.219 | 200 | 3.0801339s | POST | 未登录 | /testData/scatter +2024-03-13 17:58:31 INFO | 192.168.0.219 | 200 | 3.682977s | POST | 未登录 | /testData +2024-03-13 17:58:38 INFO | 192.168.0.219 | 200 | 3.313773s | POST | 未登录 | /testData +2024-03-13 17:59:17 INFO | 192.168.0.248 | 200 | 2.4838757s | POST | 未登录 | /testData/scatter +2024-03-13 17:59:18 INFO | 192.168.0.248 | 200 | 3.0051858s | POST | 未登录 | /testData +2024-03-13 17:59:33 INFO | 192.168.0.248 | 200 | 2.466797s | POST | 未登录 | /testData +2024-03-13 18:00:47 INFO | 192.168.0.248 | 200 | 2.4160315s | POST | 未登录 | /testData/scatter +2024-03-13 18:00:47 INFO | 192.168.0.248 | 200 | 2.931156s | POST | 未登录 | /testData +2024-03-13 18:04:12 INFO | 192.168.0.219 | 200 | 3.6420554s | POST | 未登录 | /testData/scatter +2024-03-13 18:04:13 INFO | 192.168.0.219 | 200 | 4.1049015s | POST | 未登录 | /testData +2024-03-13 18:04:29 INFO | 192.168.0.219 | 200 | 2.6366629s | POST | 未登录 | /testData +2024-03-13 18:04:52 INFO | 192.168.0.248 | 200 | 2.8521904s | POST | 未登录 | /testData/scatter +2024-03-13 18:04:52 INFO | 192.168.0.248 | 200 | 3.2516269s | POST | 未登录 | /testData +2024-03-13 18:05:09 INFO | 192.168.0.219 | 200 | 3.2887118s | POST | 未登录 | /testData +2024-03-13 18:05:19 INFO | 192.168.0.219 | 200 | 2.5500771s | POST | 未登录 | /testData +2024-03-13 18:05:20 INFO | 192.168.0.248 | 200 | 2.6216731s | POST | 未登录 | /testData +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 22µs | GET | 未登录 | /docs/index.html +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 125.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 504.9µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 2.4314ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 899.1µs | GET | 未登录 | /docs/doc.json +2024-03-14 09:49:47 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 10:01:12 INFO | 192.168.0.219 | 200 | 733.2µs | GET | 未登录 | /docs/index.html +2024-03-14 10:01:12 INFO | 192.168.0.219 | 200 | 893.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 10:01:12 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 10:01:12 INFO | 192.168.0.219 | 200 | 525.6µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 10:01:13 INFO | 192.168.0.219 | 200 | 236.7µs | GET | 未登录 | /docs/doc.json +2024-03-14 10:01:13 INFO | 192.168.0.219 | 200 | 952.7µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 584.1µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 889µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 627µs | GET | 未登录 | /docs/doc.json +2024-03-14 10:01:35 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 10:02:11 INFO | 192.168.0.219 | 200 | 3.3225801s | POST | 未登录 | /testData/pie +2024-03-14 10:02:40 INFO | 192.168.0.219 | 200 | 3.1556433s | POST | 未登录 | /testData/pie +2024-03-14 10:03:02 INFO | 192.168.0.219 | 200 | 2.5309682s | POST | 未登录 | /testData/pie +2024-03-14 10:04:43 INFO | 192.168.0.219 | 200 | 3.8409844s | POST | 未登录 | /testData/pie +2024-03-14 10:05:14 INFO | 192.168.0.219 | 200 | 2.7909283s | POST | 未登录 | /testData/pie +2024-03-14 10:05:53 INFO | 192.168.0.219 | 200 | 3.3524357s | POST | 未登录 | /testData/pie +2024-03-14 10:06:36 INFO | 192.168.0.219 | 200 | 2.9974238s | POST | 未登录 | /testData/pie +2024-03-14 10:11:47 INFO | 192.168.0.219 | 200 | 3.6591787s | POST | 未登录 | /testData/pie +2024-03-14 10:12:24 INFO | 192.168.0.219 | 200 | 2.9245834s | POST | 未登录 | /testData/pie +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 2.2686ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 7.1715ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 10.4269ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 794.8µs | GET | 未登录 | /docs/doc.json +2024-03-14 11:13:08 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 11:29:19 INFO | 192.168.0.248 | 200 | 0s | POST | 未登录 | /testData +2024-03-14 11:29:19 INFO | 192.168.0.248 | 200 | 0s | POST | 未登录 | /testData +2024-03-14 11:29:23 INFO | 192.168.0.248 | 200 | 3.3490853s | POST | 未登录 | /testData/scatter +2024-03-14 11:29:59 INFO | 192.168.0.248 | 200 | 0s | POST | 未登录 | /testData +2024-03-14 11:30:02 INFO | 192.168.0.248 | 200 | 3.4390237s | POST | 未登录 | /testData/scatter +2024-03-14 11:30:03 INFO | 192.168.0.248 | 200 | 3.8088264s | POST | 未登录 | /testData/pie +2024-03-14 11:30:30 INFO | 192.168.0.248 | 200 | 0s | POST | 未登录 | /testData +2024-03-14 11:31:03 INFO | 192.168.0.248 | 200 | 0s | POST | 未登录 | /testData +2024-03-14 11:31:06 INFO | 192.168.0.248 | 200 | 2.9398204s | POST | 未登录 | /testData/scatter +2024-03-14 11:31:06 INFO | 192.168.0.248 | 200 | 3.2162799s | POST | 未登录 | /testData/pie +2024-03-14 11:32:00 INFO | 192.168.0.248 | 200 | 2.6726028s | POST | 未登录 | /testData/pie +2024-03-14 11:33:59 INFO | 192.168.0.248 | 200 | 2.4401946s | POST | 未登录 | /testData/pie +2024-03-14 11:34:35 INFO | 192.168.0.248 | 200 | 2.4339393s | POST | 未登录 | /testData/pie +2024-03-14 11:35:09 INFO | 192.168.0.248 | 200 | 2.4474716s | POST | 未登录 | /testData/pie +2024-03-14 11:35:37 INFO | 192.168.0.248 | 200 | 2.5174344s | POST | 未登录 | /testData/pie +2024-03-14 11:35:47 INFO | 192.168.0.219 | 200 | 2.7076014s | POST | 未登录 | /testData/pie +2024-03-14 11:35:56 INFO | 192.168.0.248 | 200 | 2.2559032s | POST | 未登录 | /testData/pie +2024-03-14 11:36:02 INFO | 192.168.0.219 | 200 | 2.3998547s | POST | 未登录 | /testData/pie +2024-03-14 11:38:29 INFO | 192.168.0.248 | 200 | 2.5959808s | POST | 未登录 | /testData/pie +2024-03-14 11:39:52 INFO | 192.168.0.248 | 200 | 2.6436176s | POST | 未登录 | /testData/pie +2024-03-14 15:03:35 INFO | 192.168.0.248 | 200 | 4.046914s | POST | 未登录 | /testData/pie +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 521.6µs | GET | 未登录 | /docs/index.html +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 954.2µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 633.1µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 856.8µs | GET | 未登录 | /docs/doc.json +2024-03-14 15:07:04 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 15:07:56 INFO | 192.168.0.219 | 200 | 2.8481085s | POST | 未登录 | /testData/line +2024-03-14 15:09:01 INFO | 192.168.0.219 | 200 | 703.9µs | GET | 未登录 | /docs/index.html +2024-03-14 15:09:02 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 15:09:02 INFO | 192.168.0.219 | 200 | 997.6µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 15:09:02 INFO | 192.168.0.219 | 200 | 997.6µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 15:09:02 INFO | 192.168.0.219 | 200 | 997.9µs | GET | 未登录 | /docs/doc.json +2024-03-14 15:09:02 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 15:09:46 INFO | 192.168.0.219 | 200 | 23.0941941s | POST | 未登录 | /testData/line +2024-03-14 15:09:49 INFO | 192.168.0.219 | 200 | 103.7µs | GET | 未登录 | /docs/index.html +2024-03-14 15:31:45 INFO | 192.168.0.219 | 304 | 58.7µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 15:31:45 INFO | 192.168.0.219 | 304 | 0s | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 15:31:45 INFO | 192.168.0.219 | 304 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 15:31:45 INFO | 192.168.0.219 | 200 | 134.7µs | GET | 未登录 | /docs/doc.json +2024-03-14 15:31:45 INFO | 192.168.0.219 | 304 | 174.7µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 16:13:34 INFO | 192.168.0.219 | 200 | 7.0767724s | POST | 未登录 | /testData/pie +2024-03-14 16:13:36 INFO | 192.168.0.248 | 200 | 7.0763705s | POST | 未登录 | /testData/pie +2024-03-14 16:16:44 INFO | 192.168.0.248 | 200 | 4.5425662s | POST | 未登录 | /testData/pie +2024-03-14 16:23:59 INFO | 192.168.0.248 | 200 | 5.8844633s | POST | 未登录 | /testData/pie +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 536.9µs | GET | 未登录 | /docs/index.html +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 10.3236ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 14.0797ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 8.5697ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 226µs | GET | 未登录 | /docs/doc.json +2024-03-14 16:35:39 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-14 16:35:41 INFO | 192.168.0.248 | 200 | 542.7µs | GET | 未登录 | /docs/index.html +2024-03-14 16:55:05 INFO | 192.168.0.248 | 200 | 4.8761855s | POST | 未登录 | /testData/line +2024-03-14 16:55:06 INFO | 192.168.0.248 | 200 | 6.2281026s | POST | 未登录 | /testData/pie +2024-03-14 16:56:12 INFO | 192.168.0.248 | 200 | 4.5004671s | POST | 未登录 | /testData/line +2024-03-14 16:56:13 INFO | 192.168.0.248 | 200 | 5.6028142s | POST | 未登录 | /testData/pie +2024-03-14 16:57:02 INFO | 192.168.0.248 | 200 | 4.3565391s | POST | 未登录 | /testData/line +2024-03-14 16:57:04 INFO | 192.168.0.248 | 200 | 5.6554892s | POST | 未登录 | /testData/pie +2024-03-14 16:58:51 INFO | 192.168.0.248 | 200 | 3.7749513s | POST | 未登录 | /testData/line +2024-03-14 16:58:52 INFO | 192.168.0.248 | 200 | 4.9786919s | POST | 未登录 | /testData/pie +2024-03-14 17:01:44 INFO | 192.168.0.248 | 200 | 4.4927548s | POST | 未登录 | /testData/pie +2024-03-14 17:15:57 INFO | 192.168.0.219 | 200 | 6.3055154s | POST | 未登录 | /testData/pie +2024-03-14 17:15:58 INFO | 192.168.0.248 | 200 | 6.0673873s | POST | 未登录 | /testData/pie +2024-03-15 14:59:14 INFO | 192.168.0.248 | 200 | 3.9693987s | POST | 未登录 | /testData/pie +2024-03-15 15:01:23 INFO | 192.168.0.248 | 200 | 2.4681099s | POST | 未登录 | /testData/pie +2024-03-15 15:01:59 INFO | 192.168.0.248 | 200 | 2.8539559s | POST | 未登录 | /testData/pie +2024-03-15 15:02:20 INFO | 192.168.0.248 | 200 | 2.4592723s | POST | 未登录 | /testData/pie +2024-03-15 15:02:30 INFO | 192.168.0.248 | 200 | 2.5271675s | POST | 未登录 | /testData/pie +2024-03-15 15:03:01 INFO | 192.168.0.248 | 200 | 2.6514035s | POST | 未登录 | /testData/pie +2024-03-15 15:03:20 INFO | 192.168.0.248 | 200 | 2.6384739s | POST | 未登录 | /testData/pie +2024-03-18 14:53:55 INFO | 192.168.0.248 | 200 | 3.3955694s | POST | 未登录 | /testData/scatter +2024-03-18 14:53:55 INFO | 192.168.0.248 | 200 | 3.9864728s | POST | 未登录 | /testData/pie +2024-03-19 15:21:56 INFO | 192.168.0.219 | 200 | 517.7µs | GET | 未登录 | /docs/index.html +2024-03-19 15:21:56 INFO | 192.168.0.219 | 200 | 512.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-19 15:21:56 INFO | 192.168.0.219 | 200 | 503.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-19 15:21:56 INFO | 192.168.0.219 | 200 | 1.5704ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-19 15:21:57 INFO | 192.168.0.219 | 200 | 368.1µs | GET | 未登录 | /docs/doc.json +2024-03-19 15:21:57 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-19 15:22:06 INFO | 192.168.0.219 | 200 | 3.7564861s | POST | 未登录 | /testData/cpMap +2024-03-19 15:22:26 INFO | 192.168.0.219 | 200 | 422.8µs | GET | 未登录 | /docs/index.html +2024-03-19 15:22:30 INFO | 192.168.0.219 | 200 | 527µs | GET | 未登录 | /docs/index.html +2024-03-19 15:22:30 INFO | 192.168.0.219 | 200 | 422.2µs | GET | 未登录 | /docs/doc.json +2024-03-19 15:27:51 INFO | 192.168.0.248 | 200 | 3.7516813s | POST | 未登录 | /testData/cpMap +2024-03-19 15:29:01 INFO | 192.168.0.248 | 200 | 3.5910146s | POST | 未登录 | /testData/cpMap +2024-03-19 15:29:30 INFO | 192.168.0.248 | 200 | 3.5929516s | POST | 未登录 | /testData/cpMap +2024-03-19 15:40:45 INFO | 192.168.0.248 | 200 | 3.6264008s | POST | 未登录 | /testData/cpMap +2024-03-19 15:41:17 INFO | 192.168.0.248 | 200 | 3.604867s | POST | 未登录 | /testData/cpMap +2024-03-19 15:42:26 INFO | 192.168.0.248 | 200 | 3.6310362s | POST | 未登录 | /testData/cpMap +2024-03-19 15:43:47 INFO | 192.168.0.248 | 200 | 3.597126s | POST | 未登录 | /testData/cpMap +2024-03-19 15:44:49 INFO | 192.168.0.248 | 200 | 3.6055836s | POST | 未登录 | /testData/cpMap +2024-03-19 15:46:13 INFO | 192.168.0.248 | 200 | 3.5977676s | POST | 未登录 | /testData/cpMap +2024-03-19 15:47:13 INFO | 192.168.0.248 | 200 | 3.6154147s | POST | 未登录 | /testData/cpMap +2024-03-19 15:47:48 INFO | 192.168.0.248 | 200 | 3.6249519s | POST | 未登录 | /testData/cpMap +2024-03-19 15:48:54 INFO | 192.168.0.248 | 200 | 3.5858214s | POST | 未登录 | /testData/cpMap +2024-03-19 15:54:23 INFO | 192.168.0.248 | 200 | 3.668721s | POST | 未登录 | /testData/cpMap +2024-03-19 16:02:43 INFO | 192.168.0.248 | 200 | 3.6336069s | POST | 未登录 | /testData/cpMap +2024-03-19 16:07:34 INFO | 192.168.0.248 | 200 | 3.6339201s | POST | 未登录 | /testData/cpMap +2024-03-19 16:08:20 INFO | 192.168.0.248 | 200 | 3.5863751s | POST | 未登录 | /testData/cpMap +2024-03-19 16:09:56 INFO | 192.168.0.248 | 200 | 3.6223108s | POST | 未登录 | /testData/cpMap +2024-03-19 16:12:42 INFO | 192.168.0.219 | 200 | 3.7926966s | POST | 未登录 | /testData/cpMap +2024-03-19 16:21:46 INFO | 192.168.0.248 | 200 | 3.6397548s | POST | 未登录 | /testData/cpMap +2024-03-19 16:27:14 INFO | 192.168.0.248 | 200 | 3.7019671s | POST | 未登录 | /testData/cpMap +2024-03-19 16:29:15 INFO | 192.168.0.248 | 200 | 3.6149459s | POST | 未登录 | /testData/cpMap +2024-03-19 16:40:24 INFO | 192.168.0.219 | 200 | 3.6109373s | POST | 未登录 | /testData/cpMap +2024-03-19 16:41:13 INFO | 192.168.0.248 | 200 | 4.0373071s | POST | 未登录 | /testData/cpMap +2024-03-19 16:45:56 INFO | 192.168.0.248 | 200 | 3.539524s | POST | 未登录 | /testData/cpMap +2024-03-19 16:46:27 INFO | 192.168.0.248 | 200 | 3.5215826s | POST | 未登录 | /testData/cpMap +2024-03-19 16:46:46 INFO | 192.168.0.248 | 200 | 3.5212142s | POST | 未登录 | /testData/cpMap +2024-03-19 16:50:19 INFO | 192.168.0.248 | 200 | 3.5708539s | POST | 未登录 | /testData/cpMap +2024-03-19 16:56:57 INFO | 192.168.0.248 | 200 | 4.3348073s | POST | 未登录 | /testData/cpMap +2024-03-19 16:58:32 INFO | 192.168.0.248 | 200 | 3.5560684s | POST | 未登录 | /testData/cpMap +2024-03-19 16:59:03 INFO | 192.168.0.248 | 200 | 3.7940719s | POST | 未登录 | /testData/cpMap +2024-03-19 17:00:09 INFO | 192.168.0.248 | 200 | 3.5956857s | POST | 未登录 | /testData/cpMap +2024-03-19 17:02:11 INFO | 192.168.0.248 | 200 | 3.5414204s | POST | 未登录 | /testData/cpMap +2024-03-19 17:04:33 INFO | 192.168.0.248 | 200 | 3.542279s | POST | 未登录 | /testData/cpMap +2024-03-19 17:09:05 INFO | 192.168.0.248 | 200 | 3.6491933s | POST | 未登录 | /testData/cpMap +2024-03-19 17:16:05 INFO | 192.168.0.248 | 200 | 3.5891599s | POST | 未登录 | /testData/cpMap +2024-03-19 17:17:14 INFO | 192.168.0.248 | 200 | 3.536329s | POST | 未登录 | /testData/cpMap +2024-03-19 17:18:34 INFO | 192.168.0.248 | 200 | 3.5401804s | POST | 未登录 | /testData/cpMap +2024-03-19 17:19:01 INFO | 192.168.0.248 | 200 | 3.5359234s | POST | 未登录 | /testData/cpMap +2024-03-19 17:21:24 INFO | 192.168.0.248 | 200 | 3.5230988s | POST | 未登录 | /testData/cpMap +2024-03-19 17:23:22 INFO | 192.168.0.248 | 200 | 3.60441s | POST | 未登录 | /testData/cpMap +2024-03-19 17:32:00 INFO | 192.168.0.219 | 200 | 3.6762531s | POST | 未登录 | /testData/cpMap +2024-03-19 17:33:27 INFO | 192.168.0.248 | 200 | 3.6092173s | POST | 未登录 | /testData/cpMap +2024-03-19 17:49:50 INFO | 192.168.0.219 | 200 | 3.5592569s | POST | 未登录 | /testData/scatter +2024-03-19 17:49:50 INFO | 192.168.0.219 | 200 | 4.1400151s | POST | 未登录 | /testData/pie +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 535.4µs | GET | 未登录 | /docs/index.html +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 1.0345ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 925µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 530µs | GET | 未登录 | /docs/doc.json +2024-03-21 15:46:18 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-21 15:46:34 INFO | 192.168.0.219 | 200 | 64.7727ms | POST | 未登录 | /testData/logSite +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 527.5µs | GET | 未登录 | /docs/index.html +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 94.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 177.3µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 1.2649ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 260.2µs | GET | 未登录 | /docs/doc.json +2024-03-22 13:54:43 INFO | 192.168.0.219 | 200 | 43.3µs | GET | 未登录 | /docs/favicon-32x32.png +2024-03-22 13:55:02 INFO | 192.168.0.219 | 200 | 63.0369ms | POST | 未登录 | /testData/logSite +2024-03-22 14:10:42 INFO | 192.168.0.219 | 200 | 64.1468ms | POST | 未登录 | /testData/logSite +2024-03-22 14:12:41 INFO | 192.168.0.219 | 200 | 1m11.798636s | POST | 未登录 | /testData/logSite +2024-03-22 14:12:49 INFO | 192.168.0.219 | 200 | 78.4455ms | POST | 未登录 | /testData/logSite +2024-03-22 14:13:21 INFO | 192.168.0.219 | 200 | 82.6509ms | POST | 未登录 | /testData/logSite +2024-03-22 14:14:17 INFO | 192.168.0.219 | 200 | 88.2404ms | POST | 未登录 | /testData/logSite +2024-03-22 14:14:35 INFO | 192.168.0.219 | 200 | 9.1918928s | POST | 未登录 | /testData/logSite +2024-03-22 14:14:42 INFO | 192.168.0.219 | 200 | 84.0813ms | POST | 未登录 | /testData/logSite +2024-03-22 14:15:07 INFO | 192.168.0.219 | 200 | 78.39ms | POST | 未登录 | /testData/logSite +2024-03-22 14:15:47 INFO | 192.168.0.219 | 200 | 78.785ms | POST | 未登录 | /testData/logSite +2024-03-22 14:16:27 INFO | 192.168.0.219 | 200 | 103.4216ms | POST | 未登录 | /testData/logSite +2024-03-22 14:23:01 INFO | 192.168.0.219 | 200 | 93.1688ms | POST | 未登录 | /testData/logSite +2024-03-22 14:23:08 INFO | 192.168.0.219 | 200 | 80.5553ms | POST | 未登录 | /testData/logSite +2024-03-22 15:11:30 INFO | 192.168.0.219 | 200 | 98.8716ms | POST | 未登录 | /testData/logSite +2024-03-22 15:18:02 INFO | 192.168.0.219 | 200 | 101.4051ms | POST | 未登录 | /testData/logSite +2024-03-22 15:18:07 INFO | 192.168.0.219 | 200 | 0s | OPTIONS | 未登录 | /testData/cpMap +2024-03-22 15:20:22 INFO | 192.168.0.219 | 200 | 92.8252ms | POST | 未登录 | /testData/logSite +2024-03-22 15:20:34 INFO | 192.168.0.219 | 200 | 7.8526059s | POST | 未登录 | /testData/cpMap +2024-03-27 14:26:58 INFO | 192.168.0.219 | 200 | 106.363ms | POST | 未登录 | /testData/logSite +2024-03-28 11:23:56 INFO | 192.168.0.248 | 200 | 5.2299323s | POST | 未登录 | /testData/scatter +2024-03-28 11:23:58 INFO | 192.168.0.248 | 200 | 6.5475414s | POST | 未登录 | /testData/pie +2024-03-28 11:45:54 INFO | 192.168.0.219 | 200 | 694.7542ms | POST | 未登录 | /testData/cpMap +2024-03-28 15:22:37 INFO | 192.168.0.219 | 200 | 2.912593s | POST | 未登录 | /testData/cpMap +2024-03-28 15:30:05 INFO | 192.168.0.248 | 200 | 2.7850964s | POST | 未登录 | /testData/cpMap +2024-03-28 16:02:52 INFO | 192.168.0.219 | 200 | 2.9878538s | POST | 未登录 | /testData/cpMap +2024-03-28 16:25:07 INFO | 192.168.0.219 | 200 | 3.1412086s | POST | 未登录 | /testData/cpMap +2024-03-28 16:28:09 INFO | 192.168.0.219 | 200 | 3.4952807s | POST | 未登录 | /testData/scatter +2024-03-28 16:28:10 INFO | 192.168.0.219 | 200 | 4.1251988s | POST | 未登录 | /testData/pie +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 872.9µs | GET | 未登录 | /docs/index.html +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 2.8539ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 4.5509ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 20.7947ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 253.2µs | GET | 未登录 | /docs/doc.json +2024-03-28 19:33:21 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-03-29 08:55:04 INFO | 192.168.0.219 | 200 | 3.5387193s | POST | 未登录 | /testData/cpMap +2024-03-29 08:56:14 INFO | 192.168.0.248 | 200 | 3.0181216s | POST | 未登录 | /testData/cpMap +2024-03-29 12:21:04 INFO | 192.168.0.219 | 200 | 3.0317529s | POST | 未登录 | /testData/cpMap +2024-03-29 12:21:09 INFO | 192.168.0.248 | 200 | 3.0719588s | POST | 未登录 | /testData/cpMap +2024-03-29 12:52:05 INFO | 192.168.0.219 | 200 | 4.5124158s | POST | 未登录 | /testData/cpMap +2024-03-29 12:52:05 INFO | 192.168.0.248 | 200 | 4.3104684s | POST | 未登录 | /testData/cpMap +2024-03-29 13:23:04 INFO | 192.168.0.219 | 200 | 3.3806072s | POST | 未登录 | /testData/cpMap +2024-03-29 13:23:06 INFO | 192.168.0.248 | 200 | 4.2117216s | POST | 未登录 | /testData/cpMap +2024-03-29 15:24:14 INFO | 192.168.0.248 | 200 | 3.0572592s | POST | 未登录 | /testData/cpMap +2024-03-29 18:43:37 INFO | 192.168.0.219 | 200 | 3.5018644s | POST | 未登录 | /testData/cpMap +2024-03-29 19:15:04 INFO | 192.168.0.219 | 200 | 3.0961337s | POST | 未登录 | /testData/cpMap +2024-03-29 19:46:09 INFO | 192.168.0.219 | 200 | 3.4321392s | POST | 未登录 | /testData/cpMap +2024-03-29 20:17:11 INFO | 192.168.0.219 | 200 | 3.2960887s | POST | 未登录 | /testData/cpMap +2024-03-29 20:48:12 INFO | 192.168.0.219 | 200 | 3.2520334s | POST | 未登录 | /testData/cpMap +2024-03-29 21:22:04 INFO | 192.168.0.219 | 200 | 3.5318562s | POST | 未登录 | /testData/cpMap +2024-03-29 21:53:06 INFO | 192.168.0.219 | 200 | 3.4768959s | POST | 未登录 | /testData/cpMap +2024-03-29 22:24:05 INFO | 192.168.0.219 | 200 | 3.4109954s | POST | 未登录 | /testData/cpMap +2024-03-29 22:55:09 INFO | 192.168.0.219 | 200 | 3.2327911s | POST | 未登录 | /testData/cpMap +2024-03-29 23:26:08 INFO | 192.168.0.219 | 200 | 3.2046272s | POST | 未登录 | /testData/cpMap +2024-03-29 23:57:10 INFO | 192.168.0.219 | 200 | 3.1954343s | POST | 未登录 | /testData/cpMap +2024-03-30 00:28:06 INFO | 192.168.0.219 | 200 | 3.4235128s | POST | 未登录 | /testData/cpMap +2024-03-30 00:59:05 INFO | 192.168.0.219 | 200 | 3.142151s | POST | 未登录 | /testData/cpMap +2024-03-30 01:30:04 INFO | 192.168.0.219 | 200 | 3.2434122s | POST | 未登录 | /testData/cpMap +2024-03-30 02:01:04 INFO | 192.168.0.219 | 200 | 3.4512821s | POST | 未登录 | /testData/cpMap +2024-03-30 02:32:04 INFO | 192.168.0.219 | 200 | 3.2505378s | POST | 未登录 | /testData/cpMap +2024-03-30 03:03:05 INFO | 192.168.0.219 | 200 | 3.2591547s | POST | 未登录 | /testData/cpMap +2024-03-30 03:36:04 INFO | 192.168.0.219 | 200 | 3.5242914s | POST | 未登录 | /testData/cpMap +2024-03-30 04:07:04 INFO | 192.168.0.219 | 200 | 3.2137615s | POST | 未登录 | /testData/cpMap +2024-03-30 04:38:07 INFO | 192.168.0.219 | 200 | 3.2452192s | POST | 未登录 | /testData/cpMap +2024-03-30 05:09:07 INFO | 192.168.0.219 | 200 | 3.4126969s | POST | 未登录 | /testData/cpMap +2024-03-30 05:40:06 INFO | 192.168.0.219 | 200 | 3.2960266s | POST | 未登录 | /testData/cpMap +2024-03-30 06:11:05 INFO | 192.168.0.219 | 200 | 3.773729s | POST | 未登录 | /testData/cpMap +2024-03-30 06:42:07 INFO | 192.168.0.219 | 200 | 3.3414067s | POST | 未登录 | /testData/cpMap +2024-03-30 07:14:04 INFO | 192.168.0.219 | 200 | 3.2081291s | POST | 未登录 | /testData/cpMap +2024-03-30 09:10:16 INFO | 192.168.0.219 | 200 | 3.4147392s | POST | 未登录 | /testData/cpMap +2024-03-30 09:42:04 INFO | 192.168.0.219 | 200 | 3.3039523s | POST | 未登录 | /testData/cpMap +2024-03-30 10:14:05 INFO | 192.168.0.219 | 200 | 3.5150352s | POST | 未登录 | /testData/cpMap +2024-03-30 10:45:04 INFO | 192.168.0.219 | 200 | 3.3202219s | POST | 未登录 | /testData/cpMap +2024-03-30 11:16:04 INFO | 192.168.0.219 | 200 | 3.2065639s | POST | 未登录 | /testData/cpMap +2024-03-30 11:47:05 INFO | 192.168.0.219 | 200 | 3.4426619s | POST | 未登录 | /testData/cpMap +2024-03-30 12:18:04 INFO | 192.168.0.219 | 200 | 3.299533s | POST | 未登录 | /testData/cpMap +2024-03-30 13:22:23 INFO | 192.168.0.219 | 200 | 3.1950691s | POST | 未登录 | /testData/cpMap +2024-03-30 13:54:05 INFO | 192.168.0.219 | 200 | 3.4905127s | POST | 未登录 | /testData/cpMap +2024-03-30 14:25:05 INFO | 192.168.0.219 | 200 | 3.3060795s | POST | 未登录 | /testData/cpMap +2024-03-30 14:56:11 INFO | 192.168.0.219 | 200 | 3.6832828s | POST | 未登录 | /testData/cpMap +2024-03-30 15:27:10 INFO | 192.168.0.219 | 200 | 3.2592884s | POST | 未登录 | /testData/cpMap +2024-03-30 15:58:08 INFO | 192.168.0.219 | 200 | 3.4063887s | POST | 未登录 | /testData/cpMap +2024-03-30 16:29:06 INFO | 192.168.0.219 | 200 | 3.3245735s | POST | 未登录 | /testData/cpMap +2024-03-30 17:00:04 INFO | 192.168.0.219 | 200 | 3.2935885s | POST | 未登录 | /testData/cpMap +2024-03-30 17:31:05 INFO | 192.168.0.219 | 200 | 3.5693797s | POST | 未登录 | /testData/cpMap +2024-03-30 18:02:04 INFO | 192.168.0.219 | 200 | 3.3025251s | POST | 未登录 | /testData/cpMap +2024-03-30 18:33:05 INFO | 192.168.0.219 | 200 | 4.240472s | POST | 未登录 | /testData/cpMap +2024-03-30 19:06:04 INFO | 192.168.0.219 | 200 | 3.2406123s | POST | 未登录 | /testData/cpMap +2024-03-30 19:37:06 INFO | 192.168.0.219 | 200 | 3.5152501s | POST | 未登录 | /testData/cpMap +2024-03-30 20:08:06 INFO | 192.168.0.219 | 200 | 3.2879869s | POST | 未登录 | /testData/cpMap +2024-03-30 20:39:05 INFO | 192.168.0.219 | 200 | 3.5705788s | POST | 未登录 | /testData/cpMap +2024-03-30 21:10:05 INFO | 192.168.0.219 | 200 | 3.2843193s | POST | 未登录 | /testData/cpMap +2024-03-30 21:41:09 INFO | 192.168.0.219 | 200 | 3.6437838s | POST | 未登录 | /testData/cpMap +2024-03-30 22:13:04 INFO | 192.168.0.219 | 200 | 3.3386002s | POST | 未登录 | /testData/cpMap +2024-03-30 22:44:05 INFO | 192.168.0.219 | 200 | 3.537315s | POST | 未登录 | /testData/cpMap +2024-03-30 23:15:07 INFO | 192.168.0.219 | 200 | 3.2970273s | POST | 未登录 | /testData/cpMap +2024-03-30 23:46:20 INFO | 192.168.0.219 | 200 | 3.2334865s | POST | 未登录 | /testData/cpMap +2024-03-31 00:18:04 INFO | 192.168.0.219 | 200 | 3.3041679s | POST | 未登录 | /testData/cpMap +2024-03-31 00:51:05 INFO | 192.168.0.219 | 200 | 3.545755s | POST | 未登录 | /testData/cpMap +2024-03-31 01:22:07 INFO | 192.168.0.219 | 200 | 3.3596904s | POST | 未登录 | /testData/cpMap +2024-03-31 01:53:09 INFO | 192.168.0.219 | 200 | 3.3227066s | POST | 未登录 | /testData/cpMap +2024-03-31 02:24:07 INFO | 192.168.0.219 | 200 | 3.5591305s | POST | 未登录 | /testData/cpMap +2024-03-31 02:55:05 INFO | 192.168.0.219 | 200 | 3.2391481s | POST | 未登录 | /testData/cpMap +2024-03-31 03:26:09 INFO | 192.168.0.219 | 200 | 3.3123973s | POST | 未登录 | /testData/cpMap +2024-03-31 03:57:08 INFO | 192.168.0.219 | 200 | 3.2497906s | POST | 未登录 | /testData/cpMap +2024-03-31 04:28:07 INFO | 192.168.0.219 | 200 | 3.5294313s | POST | 未登录 | /testData/cpMap +2024-03-31 04:59:08 INFO | 192.168.0.219 | 200 | 3.3729226s | POST | 未登录 | /testData/cpMap +2024-03-31 05:30:10 INFO | 192.168.0.219 | 200 | 3.585894s | POST | 未登录 | /testData/cpMap +2024-03-31 06:01:08 INFO | 192.168.0.219 | 200 | 3.4236316s | POST | 未登录 | /testData/cpMap +2024-03-31 06:32:12 INFO | 192.168.0.219 | 200 | 3.6569871s | POST | 未登录 | /testData/cpMap +2024-03-31 07:03:25 INFO | 192.168.0.219 | 200 | 3.316263s | POST | 未登录 | /testData/cpMap +2024-03-31 07:36:05 INFO | 192.168.0.219 | 200 | 3.2367552s | POST | 未登录 | /testData/cpMap +2024-03-31 08:07:12 INFO | 192.168.0.219 | 200 | 3.3917081s | POST | 未登录 | /testData/cpMap +2024-03-31 08:38:09 INFO | 192.168.0.219 | 200 | 3.2911331s | POST | 未登录 | /testData/cpMap +2024-03-31 09:09:12 INFO | 192.168.0.219 | 200 | 3.2783881s | POST | 未登录 | /testData/cpMap +2024-03-31 09:40:11 INFO | 192.168.0.219 | 200 | 3.6161182s | POST | 未登录 | /testData/cpMap +2024-03-31 10:11:15 INFO | 192.168.0.219 | 200 | 3.3590277s | POST | 未登录 | /testData/cpMap +2024-03-31 10:42:15 INFO | 192.168.0.219 | 200 | 3.217091s | POST | 未登录 | /testData/cpMap +2024-03-31 11:13:15 INFO | 192.168.0.219 | 200 | 3.6273629s | POST | 未登录 | /testData/cpMap +2024-03-31 11:44:11 INFO | 192.168.0.219 | 200 | 3.3692773s | POST | 未登录 | /testData/cpMap +2024-03-31 12:15:15 INFO | 192.168.0.219 | 200 | 3.3610748s | POST | 未登录 | /testData/cpMap +2024-03-31 12:46:15 INFO | 192.168.0.219 | 200 | 3.3492158s | POST | 未登录 | /testData/cpMap +2024-03-31 13:17:15 INFO | 192.168.0.219 | 200 | 3.3428632s | POST | 未登录 | /testData/cpMap +2024-03-31 13:48:15 INFO | 192.168.0.219 | 200 | 3.352989s | POST | 未登录 | /testData/cpMap +2024-03-31 15:23:00 INFO | 192.168.0.219 | 200 | 3.3937425s | POST | 未登录 | /testData/cpMap +2024-03-31 15:54:05 INFO | 192.168.0.219 | 200 | 3.3393515s | POST | 未登录 | /testData/cpMap +2024-03-31 16:25:08 INFO | 192.168.0.219 | 200 | 3.3729285s | POST | 未登录 | /testData/cpMap +2024-03-31 16:56:07 INFO | 192.168.0.219 | 200 | 3.2859764s | POST | 未登录 | /testData/cpMap +2024-03-31 17:27:07 INFO | 192.168.0.219 | 200 | 3.3350315s | POST | 未登录 | /testData/cpMap +2024-03-31 17:58:07 INFO | 192.168.0.219 | 200 | 3.3112179s | POST | 未登录 | /testData/cpMap +2024-03-31 18:29:57 INFO | 192.168.0.248 | 200 | 633.9µs | GET | 未登录 | /docs/index.html +2024-03-31 18:29:57 INFO | 192.168.0.248 | 200 | 1.1615ms | GET | 未登录 | /docs/swagger-ui.css +2024-03-31 18:29:57 INFO | 192.168.0.248 | 200 | 10.3804ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-03-31 18:29:57 INFO | 192.168.0.248 | 200 | 12.0811ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-03-31 18:29:57 INFO | 192.168.0.248 | 200 | 259.8µs | GET | 未登录 | /docs/doc.json +2024-04-01 09:05:41 INFO | 192.168.0.219 | 200 | 3.5479472s | POST | 未登录 | /testData/cpMap +2024-04-01 10:48:30 INFO | 192.168.0.248 | 200 | 2.9416765s | POST | 未登录 | /testData/cpMap +2024-04-01 12:22:11 INFO | 192.168.0.219 | 200 | 5.8955689s | POST | 未登录 | /testData/cpMap +2024-04-01 12:22:11 INFO | 192.168.0.248 | 200 | 5.9574528s | POST | 未登录 | /testData/cpMap +2024-04-01 12:53:09 INFO | 192.168.0.219 | 200 | 4.0367284s | POST | 未登录 | /testData/cpMap +2024-04-01 13:24:16 INFO | 192.168.0.219 | 200 | 4.1462099s | POST | 未登录 | /testData/cpMap +2024-04-01 14:08:20 INFO | 192.168.0.248 | 200 | 3.6556944s | POST | 未登录 | /testData/scatter +2024-04-01 14:08:21 INFO | 192.168.0.248 | 200 | 4.2875241s | POST | 未登录 | /testData/pie +2024-04-01 16:49:37 INFO | 192.168.0.248 | 200 | 3.4307322s | POST | 未登录 | /testData/scatter +2024-04-01 16:49:38 INFO | 192.168.0.248 | 200 | 4.0156044s | POST | 未登录 | /testData/pie +2024-04-01 16:49:57 INFO | 192.168.0.248 | 200 | 3.1198461s | POST | 未登录 | /testData/scatter +2024-04-01 16:49:57 INFO | 192.168.0.248 | 200 | 3.5940491s | POST | 未登录 | /testData/pie +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 547.4µs | GET | 未登录 | /docs/index.html +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 1.2056ms | GET | 未登录 | /docs/swagger-ui.css +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 7.1808ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 9.7702ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 309.2µs | GET | 未登录 | /docs/doc.json +2024-04-02 15:30:15 INFO | 192.168.0.248 | 200 | 213.2µs | GET | 未登录 | /docs/favicon-32x32.png +2024-04-02 15:32:28 INFO | 192.168.0.248 | 200 | 688.6µs | GET | 未登录 | /docs/index.html +2024-04-02 15:32:29 INFO | 192.168.0.248 | 200 | 562.1µs | GET | 未登录 | /docs/doc.json +2024-04-02 17:15:34 INFO | 192.168.0.219 | 200 | 1.5666932s | POST | 未登录 | /testData/histogram +2024-04-03 16:03:45 INFO | 192.168.0.219 | 200 | 17.6530654s | POST | 未登录 | /testData/histogram +2024-04-03 16:04:08 INFO | 192.168.0.219 | 200 | 6.0076542s | POST | 未登录 | /testData/histogram +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 533µs | GET | 未登录 | /docs/index.html +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 473.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 1.3476ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 1.3476ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 93.4µs | GET | 未登录 | /docs/doc.json +2024-04-03 17:57:59 INFO | 192.168.0.219 | 200 | 1.0285ms | GET | 未登录 | /docs/favicon-32x32.png +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 1.0478ms | GET | 未登录 | /docs/index.html +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 956µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 3.2993ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 8.202ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 373.5µs | GET | 未登录 | /docs/doc.json +2024-04-08 15:24:02 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 527.1µs | GET | 未登录 | /docs/index.html +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 911.1µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 630.3µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 521.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 534.1µs | GET | 未登录 | /docs/doc.json +2024-04-09 15:18:04 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-04-10 16:51:04 INFO | 192.168.0.248 | 200 | 6.817ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-10 16:51:04 INFO | 192.168.0.248 | 200 | 6.8574ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-10 16:51:04 INFO | 192.168.0.248 | 200 | 811.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-10 16:51:04 INFO | 192.168.0.248 | 200 | 444.2µs | GET | 未登录 | /docs/doc.json +2024-04-10 16:51:06 INFO | 192.168.0.248 | 200 | 804.5µs | GET | 未登录 | /docs/index.html +2024-04-10 16:51:06 INFO | 192.168.0.248 | 200 | 633.1µs | GET | 未登录 | /docs/doc.json +2024-04-10 16:51:06 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-04-10 17:20:14 INFO | 192.168.0.248 | 200 | 670.6µs | GET | 未登录 | /docs/index.html +2024-04-10 17:20:15 INFO | 192.168.0.248 | 200 | 864.9µs | GET | 未登录 | /docs/doc.json +2024-04-11 09:26:24 INFO | 192.168.0.248 | 200 | 1.3171ms | GET | 未登录 | /docs/index.html +2024-04-11 09:26:24 INFO | 192.168.0.248 | 200 | 726.6µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-11 09:26:24 INFO | 192.168.0.248 | 200 | 7.6729ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-11 09:26:24 INFO | 192.168.0.248 | 200 | 7.4344ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-11 09:26:25 INFO | 192.168.0.248 | 200 | 415.4µs | GET | 未登录 | /docs/doc.json +2024-04-11 09:26:25 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-04-12 11:04:33 INFO | 192.168.0.219 | 200 | 528.1µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-12 11:04:33 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui.css +2024-04-12 11:04:33 INFO | 192.168.0.219 | 200 | 528.1µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-12 11:04:33 INFO | 192.168.0.219 | 200 | 655.9µs | GET | 未登录 | /docs/doc.json +2024-04-12 11:04:37 INFO | 192.168.0.219 | 200 | 490µs | GET | 未登录 | /docs/index.html +2024-04-12 11:04:37 INFO | 192.168.0.219 | 200 | 354.3µs | GET | 未登录 | /docs/doc.json +2024-04-12 11:04:37 INFO | 192.168.0.219 | 200 | 87.7µs | GET | 未登录 | /docs/favicon-32x32.png +2024-04-12 11:04:51 INFO | 192.168.0.219 | 200 | 12.305ms | POST | 未登录 | /testData/cpMap +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 279.8µs | GET | 未登录 | /docs/index.html +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 529.7µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 856.9µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 617µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 975.4µs | GET | 未登录 | /docs/doc.json +2024-04-15 14:49:52 INFO | 192.168.0.219 | 200 | 612.6µs | GET | 未登录 | /docs/favicon-32x32.png +2024-04-15 14:50:14 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-04-15 14:50:14 INFO | 192.168.0.248 | 200 | 946.4µs | GET | 未登录 | /docs/swagger-ui.css +2024-04-15 14:50:14 INFO | 192.168.0.248 | 200 | 5.0234ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-15 14:50:14 INFO | 192.168.0.248 | 200 | 8.0573ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-15 14:50:15 INFO | 192.168.0.248 | 200 | 257.7µs | GET | 未登录 | /docs/doc.json +2024-04-15 14:50:15 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-04-18 16:01:34 INFO | 192.168.0.219 | 200 | 12.2778008s | POST | 未登录 | /testData/upload +2024-04-18 16:09:01 INFO | 192.168.0.219 | 200 | 548.3µs | POST | 未登录 | /testData/upload +2024-04-18 16:09:09 INFO | 192.168.0.219 | 200 | 759.1µs | POST | 未登录 | /testData/upload +2024-04-18 16:09:15 INFO | 192.168.0.219 | 200 | 0s | POST | 未登录 | /testData/upload +2024-04-18 16:27:21 INFO | 192.168.0.219 | 200 | 0s | POST | 未登录 | /testData/upload +2024-04-18 16:27:34 INFO | 192.168.0.219 | 200 | 4.816496s | POST | 未登录 | /testData/upload +2024-04-18 16:31:11 INFO | 192.168.0.219 | 200 | 8.7738561s | POST | 未登录 | /testData/upload +2024-04-18 16:32:06 INFO | 192.168.0.219 | 200 | 40.0108073s | POST | 未登录 | /testData/upload +2024-04-18 17:47:03 INFO | 192.168.0.248 | 200 | 1.0007ms | GET | 未登录 | /docs/index.html +2024-04-18 17:47:03 INFO | 192.168.0.248 | 200 | 1.0548ms | GET | 未登录 | /docs/swagger-ui.css +2024-04-18 17:47:03 INFO | 192.168.0.248 | 200 | 2.7505ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-04-18 17:47:03 INFO | 192.168.0.248 | 200 | 8.3937ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-04-18 17:47:03 INFO | 192.168.0.248 | 200 | 2.2969ms | GET | 未登录 | /docs/doc.json +2024-04-23 11:10:17 INFO | 192.168.0.248 | 200 | 11.1µs | GET | 未登录 | /docs/favicon-32x32.png +2024-05-13 11:02:04 INFO | 192.168.0.219 | 200 | 511.3µs | GET | 未登录 | /docs/favicon-32x32.png +2024-05-20 14:25:03 INFO | 192.168.0.219 | 200 | 11.1662ms | POST | 未登录 | /testData/cpMap +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 924.7µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 1.4083ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 807.2µs | GET | 未登录 | /docs/doc.json +2024-05-20 14:26:55 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 579µs | GET | 未登录 | /docs/index.html +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 129.6µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 532.2µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 538.9µs | GET | 未登录 | /docs/doc.json +2024-05-20 14:54:22 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 67.1µs | GET | 未登录 | /docs/index.html +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 947.4µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 1.7014ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 1ms | GET | 未登录 | /docs/doc.json +2024-05-20 14:55:23 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-20 15:01:26 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | / +2024-05-20 15:01:26 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /favicon.ico +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 185.5µs | GET | 未登录 | /docs/index.html +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 5.2051ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 7.8466ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 13.2885ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 1.3715ms | GET | 未登录 | /docs/doc.json +2024-05-20 15:01:31 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-21 10:01:39 INFO | 192.168.0.248 | 200 | 208.7µs | GET | 未登录 | /docs/index.html +2024-05-21 10:01:39 INFO | 192.168.0.248 | 200 | 1.3013ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-21 10:01:39 INFO | 192.168.0.248 | 200 | 8.4629ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-21 10:01:39 INFO | 192.168.0.248 | 200 | 8.3005ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-21 10:01:39 INFO | 192.168.0.248 | 200 | 273.6µs | GET | 未登录 | /docs/doc.json +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 532.5µs | GET | 未登录 | /docs/index.html +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 190.4µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 536.9µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 912.4µs | GET | 未登录 | /docs/doc.json +2024-05-21 15:30:58 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 541.7µs | GET | 未登录 | /docs/index.html +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 687.2µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 1.0899ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 558.4µs | GET | 未登录 | /docs/doc.json +2024-05-21 15:31:43 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-21 15:32:03 INFO | 192.168.0.219 | 200 | 655.5774ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:33:09 INFO | 192.168.0.219 | 200 | 496.5978ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:34:00 INFO | 192.168.0.219 | 200 | 170.7761ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:34:08 INFO | 192.168.0.219 | 200 | 6.9669ms | POST | 未登录 | /testData/report/wafer +2024-05-21 15:34:28 INFO | 192.168.0.219 | 200 | 548.3947ms | POST | 未登录 | /testData/report/wafer +2024-05-21 15:36:24 INFO | 192.168.0.219 | 200 | 215.516ms | POST | 未登录 | /testData/report/wafer +2024-05-21 15:37:07 INFO | 192.168.0.219 | 200 | 186.6733ms | POST | 未登录 | /testData/report/wafer +2024-05-21 15:37:35 INFO | 192.168.0.219 | 200 | 109.0113ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:38:58 INFO | 192.168.0.219 | 200 | 106.6775ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:39:54 INFO | 192.168.0.219 | 200 | 354.3758ms | POST | 未登录 | /testData/report/ab +2024-05-21 15:42:07 INFO | 192.168.0.219 | 200 | 2m5.0770022s | POST | 未登录 | /testData/report/ab +2024-05-21 15:43:10 INFO | 192.168.0.219 | 200 | 42.3046845s | POST | 未登录 | /testData/report/ab +2024-05-21 15:45:16 INFO | 192.168.0.219 | 200 | 8.7836285s | POST | 未登录 | /testData/report/ab +2024-05-21 15:46:43 INFO | 192.168.0.219 | 200 | 15.4292582s | POST | 未登录 | /testData/report/ab +2024-05-21 15:56:42 INFO | 192.168.0.219 | 200 | 9m10.1819419s | POST | 未登录 | /testData/report/ab +2024-05-21 15:57:42 INFO | 192.168.0.219 | 200 | 40.6346638s | POST | 未登录 | /testData/report/ab +2024-05-21 16:02:31 INFO | 192.168.0.219 | 200 | 2m16.909703s | POST | 未登录 | /testData/report/ab +2024-05-21 16:04:21 INFO | 192.168.0.219 | 200 | 8.0804927s | POST | 未登录 | /testData/report/ab +2024-05-21 16:06:32 INFO | 192.168.0.219 | 200 | 218.4367ms | POST | 未登录 | /testData/report/ab +2024-05-21 17:24:51 INFO | 192.168.0.248 | 200 | 1.2018ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-21 17:24:51 INFO | 192.168.0.248 | 200 | 9.2964ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-21 17:24:51 INFO | 192.168.0.248 | 200 | 11.2401ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-21 17:24:51 INFO | 192.168.0.248 | 200 | 592.7µs | GET | 未登录 | /docs/doc.json +2024-05-21 17:24:53 INFO | 192.168.0.248 | 200 | 1.1739ms | GET | 未登录 | /docs/index.html +2024-05-21 17:24:53 INFO | 192.168.0.248 | 200 | 133.5µs | GET | 未登录 | /docs/doc.json +2024-05-21 17:24:53 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-21 18:19:21 INFO | 192.168.0.219 | 200 | 299.9376ms | POST | 未登录 | /testData/report/ab +2024-05-21 18:19:27 INFO | 192.168.0.219 | 200 | 318.9411ms | POST | 未登录 | /testData/report/ab +2024-05-21 18:20:21 INFO | 192.168.0.219 | 200 | 341.9036ms | POST | 未登录 | /testData/report/ab +2024-05-22 14:25:34 INFO | 192.168.0.248 | 304 | 819.8µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-22 14:25:34 INFO | 192.168.0.248 | 304 | 0s | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-22 14:25:34 INFO | 192.168.0.248 | 304 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-22 14:25:34 INFO | 192.168.0.248 | 200 | 827.1µs | GET | 未登录 | /docs/doc.json +2024-05-27 16:47:06 INFO | 192.168.0.219 | 200 | 514.7µs | GET | 未登录 | /docs/index.html +2024-05-27 16:47:06 INFO | 192.168.0.219 | 200 | 1.1549ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-27 16:47:06 INFO | 192.168.0.219 | 200 | 1.6423ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-27 16:47:06 INFO | 192.168.0.219 | 200 | 5.9077ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-27 16:47:07 INFO | 192.168.0.219 | 200 | 485.8µs | GET | 未登录 | /docs/doc.json +2024-05-27 16:47:24 INFO | 192.168.0.219 | 200 | 1.1880775s | POST | 未登录 | /testData/report/ab +2024-05-27 16:48:04 INFO | 192.168.0.219 | 200 | 34.453482s | POST | 未登录 | /testData/report/ab +2024-05-27 16:48:15 INFO | 192.168.0.219 | 200 | 5.5711112s | POST | 未登录 | /testData/report/ab +2024-05-27 16:50:41 INFO | 192.168.0.219 | 200 | 26.0615431s | POST | 未登录 | /testData/report/ab +2024-05-27 16:51:40 INFO | 192.168.0.219 | 200 | 22.7818992s | POST | 未登录 | /testData/report/ab +2024-05-27 16:52:00 INFO | 192.168.0.219 | 200 | 728.8242ms | POST | 未登录 | /testData/report/ab +2024-05-27 16:56:27 INFO | 192.168.0.219 | 200 | 4m7.0016527s | POST | 未登录 | /testData/report/ab +2024-05-27 16:56:31 INFO | 192.168.0.219 | 200 | 4.3596192s | POST | 未登录 | /testData/report/ab +2024-05-27 16:56:57 INFO | 192.168.0.219 | 200 | 758.2037ms | POST | 未登录 | /testData/report/ab +2024-05-27 16:57:22 INFO | 192.168.0.219 | 200 | 1.2754824s | POST | 未登录 | /testData/report/ab +2024-05-27 16:58:54 INFO | 192.168.0.219 | 200 | 1.3479184s | POST | 未登录 | /testData/report/ab +2024-05-27 17:41:37 INFO | 192.168.0.219 | 200 | 14.1750023s | POST | 未登录 | /testData/report/ab +2024-05-27 17:43:22 INFO | 192.168.0.219 | 200 | 6.6715642s | POST | 未登录 | /testData/report/ab +2024-05-27 17:44:18 INFO | 192.168.0.219 | 200 | 1.9436109s | POST | 未登录 | /testData/report/ab +2024-05-27 17:45:22 INFO | 192.168.0.219 | 200 | 3.9649259s | POST | 未登录 | /testData/report/ab +2024-05-27 17:45:55 INFO | 192.168.0.219 | 200 | 4.7515083s | POST | 未登录 | /testData/report/ab +2024-05-27 17:47:00 INFO | 192.168.0.219 | 200 | 8.0469332s | POST | 未登录 | /testData/report/ab +2024-05-27 17:48:06 INFO | 192.168.0.219 | 200 | 2.8312546s | POST | 未登录 | /testData/report/ab +2024-05-27 17:50:30 INFO | 192.168.0.219 | 200 | 7.8667857s | POST | 未登录 | /testData/report/ab +2024-05-27 17:51:18 INFO | 192.168.0.219 | 200 | 38.8221683s | POST | 未登录 | /testData/report/ab +2024-05-27 17:51:43 INFO | 192.168.0.219 | 200 | 11.0652906s | POST | 未登录 | /testData/report/ab +2024-05-27 18:06:16 INFO | 192.168.0.219 | 200 | 8.1444479s | POST | 未登录 | /testData/report/ab +2024-05-27 18:07:15 INFO | 192.168.0.219 | 200 | 14.2053281s | POST | 未登录 | /testData/report/ab +2024-05-27 18:07:51 INFO | 192.168.0.219 | 200 | 5.5263322s | POST | 未登录 | /testData/report/ab +2024-05-27 18:09:28 INFO | 192.168.0.219 | 200 | 946.0901ms | POST | 未登录 | /testData/report/ab +2024-05-27 18:11:22 INFO | 192.168.0.219 | 200 | 147.8298ms | POST | 未登录 | /testData/report/ab +2024-05-27 18:12:23 INFO | 192.168.0.219 | 200 | 41.9022114s | POST | 未登录 | /testData/report/ab +2024-05-27 18:12:45 INFO | 192.168.0.219 | 200 | 6.7460906s | POST | 未登录 | /testData/report/ab +2024-05-27 18:18:34 INFO | 192.168.0.219 | 200 | 1m2.490938s | POST | 未登录 | /testData/report/ab +2024-05-27 18:26:06 INFO | 192.168.0.219 | 200 | 36.7831856s | POST | 未登录 | /testData/report/ab +2024-05-27 18:26:51 INFO | 192.168.0.219 | 200 | 15.3637216s | POST | 未登录 | /testData/report/ab +2024-05-27 18:31:48 INFO | 192.168.0.219 | 200 | 4m39.6156363s | POST | 未登录 | /testData/report/ab +2024-05-27 18:32:06 INFO | 192.168.0.219 | 200 | 17.9866383s | POST | 未登录 | /testData/report/ab +2024-05-27 18:33:25 INFO | 192.168.0.219 | 200 | 12.0897014s | POST | 未登录 | /testData/report/ab +2024-05-28 09:20:29 INFO | 192.168.0.219 | 200 | 13.6742345s | POST | 未登录 | /testData/report/ab +2024-05-28 09:38:53 INFO | 192.168.0.219 | 200 | 11.4027581s | POST | 未登录 | /testData/report/ab +2024-05-28 09:40:50 INFO | 192.168.0.219 | 200 | 8.2352434s | POST | 未登录 | /testData/report/ab +2024-05-28 09:44:42 INFO | 192.168.0.219 | 200 | 12.2996994s | POST | 未登录 | /testData/report/ab +2024-05-28 09:46:56 INFO | 192.168.0.219 | 200 | 3.5978276s | POST | 未登录 | /testData/report/ab +2024-05-28 09:50:58 INFO | 192.168.0.219 | 200 | 3m34.7971859s | POST | 未登录 | /testData/report/ab +2024-05-28 10:03:02 INFO | 192.168.0.219 | 200 | 15.4927867s | POST | 未登录 | /testData/report/ab +2024-05-28 10:05:07 INFO | 192.168.0.219 | 200 | 23.812974s | POST | 未登录 | /testData/report/ab +2024-05-28 10:08:13 INFO | 192.168.0.219 | 200 | 13.3829342s | POST | 未登录 | /testData/report/ab +2024-05-28 14:31:48 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-28 14:57:56 INFO | 192.168.0.219 | 200 | 560.5µs | GET | 未登录 | /docs/index.html +2024-05-28 14:57:56 INFO | 192.168.0.219 | 200 | 740.9µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-28 14:57:56 INFO | 192.168.0.219 | 200 | 1.2891ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-28 14:57:56 INFO | 192.168.0.219 | 200 | 1.8281ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-28 14:57:56 INFO | 192.168.0.219 | 200 | 881.2µs | GET | 未登录 | /docs/doc.json +2024-05-28 14:58:15 INFO | 192.168.0.219 | 200 | 2.2045ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 14:58:55 INFO | 192.168.0.219 | 200 | 1.8164ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 14:59:41 INFO | 192.168.0.219 | 200 | 3.9191ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:00:03 INFO | 192.168.0.219 | 200 | 1.8227ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:00:24 INFO | 192.168.0.219 | 200 | 6.8555465s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:00:38 INFO | 192.168.0.219 | 200 | 4.4786445s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:01:03 INFO | 192.168.0.219 | 200 | 20.2364128s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:01:47 INFO | 192.168.0.219 | 200 | 20.9107667s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:08:35 INFO | 192.168.0.219 | 200 | 2m5.2065996s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:09:20 INFO | 192.168.0.219 | 200 | 26.4422674s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:11:17 INFO | 192.168.0.219 | 200 | 33.6379612s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:12:04 INFO | 192.168.0.219 | 200 | 28.1297698s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 15:13:30 INFO | 192.168.0.219 | 200 | 5.381025s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:01:28 INFO | 192.168.0.219 | 200 | 40m35.0492484s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:01:50 INFO | 192.168.0.219 | 200 | 2.3206037s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:02:24 INFO | 192.168.0.219 | 200 | 411.9895ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:44:27 INFO | 192.168.0.219 | 200 | 5.2229231s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 854.1µs | GET | 未登录 | /docs/index.html +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 931.7µs | GET | 未登录 | /docs/swagger-ui.css +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 1.0289ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 1.0289ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 1.3934ms | GET | 未登录 | /docs/doc.json +2024-05-28 16:46:49 INFO | 192.168.0.219 | 200 | 1.0537ms | GET | 未登录 | /docs/favicon-32x32.png +2024-05-28 16:47:13 INFO | 192.168.0.219 | 200 | 1.1985ms | GET | 未登录 | /docs/index.html +2024-05-28 16:47:13 INFO | 192.168.0.219 | 200 | 633µs | GET | 未登录 | /docs/doc.json +2024-05-28 16:47:43 INFO | 192.168.0.219 | 200 | 6.5316ms | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:48:50 INFO | 192.168.0.219 | 200 | 10.4448136s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:49:07 INFO | 192.168.0.219 | 200 | 8.2046077s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:50:10 INFO | 192.168.0.219 | 200 | 5.0894329s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:51:51 INFO | 192.168.0.219 | 200 | 52.441852s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 16:57:45 INFO | 192.168.0.219 | 200 | 5.0428987s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 17:02:57 INFO | 192.168.0.219 | 200 | 4.0022076s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-28 17:03:39 INFO | 192.168.0.219 | 200 | 4.042027s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 927.7µs | GET | 未登录 | /docs/index.html +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 2.169ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 3.4942ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 11.0262ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 162.3µs | GET | 未登录 | /docs/doc.json +2024-05-29 09:52:30 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-05-29 09:52:32 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-05-29 09:52:32 INFO | 192.168.0.248 | 200 | 369.2µs | GET | 未登录 | /docs/doc.json +2024-05-29 14:53:00 INFO | 192.168.0.219 | 200 | 5.9686331s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 14:53:40 INFO | 192.168.0.219 | 200 | 8.7557078s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 15:00:15 INFO | 192.168.0.219 | 200 | 10.154675s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 15:27:20 INFO | 192.168.0.219 | 200 | 9.5338639s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 15:27:44 INFO | 192.168.0.219 | 200 | 9.3917621s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 15:29:14 INFO | 192.168.0.219 | 200 | 9.4020711s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-29 15:29:46 INFO | 192.168.0.219 | 200 | 10.7156582s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-05-31 13:52:34 INFO | 192.168.0.248 | 200 | 1.6107ms | GET | 未登录 | /docs/swagger-ui.css +2024-05-31 13:52:34 INFO | 192.168.0.248 | 200 | 8.0255ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-05-31 13:52:34 INFO | 192.168.0.248 | 200 | 11.8353ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-05-31 13:52:34 INFO | 192.168.0.248 | 200 | 957.7µs | GET | 未登录 | /docs/doc.json +2024-05-31 16:23:01 INFO | 192.168.0.248 | 200 | 2.6736ms | GET | 未登录 | /docs/index.html +2024-05-31 16:23:01 INFO | 192.168.0.248 | 200 | 345.8µs | GET | 未登录 | /docs/doc.json +2024-05-31 16:23:01 INFO | 192.168.0.248 | 200 | 812.1µs | GET | 未登录 | /docs/favicon-32x32.png +2024-05-31 16:58:45 INFO | 192.168.0.248 | 200 | 597.8µs | GET | 未登录 | / +2024-05-31 16:58:45 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /favicon.ico +2024-06-03 14:11:51 INFO | 192.168.0.248 | 200 | 556.5µs | GET | 未登录 | /docs/index.html +2024-06-03 14:11:51 INFO | 192.168.0.248 | 200 | 22.2576ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-03 14:11:51 INFO | 192.168.0.248 | 200 | 22.2012ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-03 14:11:51 INFO | 192.168.0.248 | 200 | 157.0705ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-03 14:11:53 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-03 14:11:53 INFO | 192.168.0.248 | 200 | 136µs | GET | 未登录 | /docs/doc.json +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 515.6µs | GET | 未登录 | /docs/index.html +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui.css +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 504µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 1.2711ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 1.4227ms | GET | 未登录 | /docs/doc.json +2024-06-05 09:33:30 INFO | 192.168.0.219 | 200 | 81µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-05 09:48:04 INFO | 192.168.0.219 | 200 | 14m27.4772771s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-06-05 09:48:09 INFO | 192.168.0.219 | 200 | 4.8580264s | POST | 未登录 | /testData/report/packagePassProbabilityLine +2024-06-05 15:55:36 INFO | 192.168.0.219 | 200 | 14.3393331s | POST | 未登录 | /testData/report/ab +2024-06-05 15:56:25 INFO | 192.168.0.219 | 200 | 389.9µs | GET | 未登录 | /docs/index.html +2024-06-05 15:56:36 INFO | 192.168.0.219 | 200 | 578µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-05 15:56:36 INFO | 192.168.0.219 | 200 | 1.4847ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-05 15:56:36 INFO | 192.168.0.219 | 200 | 1.2405ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-05 15:56:36 INFO | 192.168.0.219 | 200 | 188.4µs | GET | 未登录 | /docs/doc.json +2024-06-05 15:56:36 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-05 16:01:11 INFO | 192.168.0.219 | 200 | 1.076ms | GET | 未登录 | /docs/index.html +2024-06-05 16:01:11 INFO | 192.168.0.219 | 200 | 1.1244ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-05 16:01:11 INFO | 192.168.0.219 | 200 | 1.0599ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-05 16:01:11 INFO | 192.168.0.219 | 200 | 583.6µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-05 16:01:12 INFO | 192.168.0.219 | 200 | 940.8µs | GET | 未登录 | /docs/doc.json +2024-06-05 16:01:12 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-05 16:01:26 INFO | 192.168.0.219 | 200 | 2.1866ms | POST | 未登录 | /testData/report/ft +2024-06-05 16:02:38 INFO | 192.168.0.219 | 200 | 9.6837ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:41:26 INFO | 192.168.0.219 | 200 | 12.5441ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:42:16 INFO | 192.168.0.219 | 200 | 9.3405ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:42:45 INFO | 192.168.0.219 | 200 | 7.2226ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:43:04 INFO | 192.168.0.219 | 200 | 11.2375ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:46:58 INFO | 192.168.0.219 | 200 | 1.0704ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:49:42 INFO | 192.168.0.219 | 200 | 1m46.1489702s | POST | 未登录 | /testData/report/ft +2024-06-06 09:50:00 INFO | 192.168.0.219 | 200 | 2.0716848s | POST | 未登录 | /testData/report/ft +2024-06-06 09:50:25 INFO | 192.168.0.219 | 200 | 2.0183ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:50:27 INFO | 192.168.0.219 | 200 | 1.9692ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:51:54 INFO | 192.168.0.219 | 200 | 33.2895107s | POST | 未登录 | /testData/report/ft +2024-06-06 09:52:09 INFO | 192.168.0.219 | 200 | 2.9524ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:52:37 INFO | 192.168.0.219 | 200 | 2.8999ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:55:10 INFO | 192.168.0.219 | 200 | 1.1816ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:55:24 INFO | 192.168.0.219 | 200 | 2.3206ms | POST | 未登录 | /testData/report/ft +2024-06-06 09:55:45 INFO | 192.168.0.219 | 200 | 3.3621105s | POST | 未登录 | /testData/report/ft +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 2.6526ms | GET | 未登录 | /docs/index.html +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 900.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 2.7618ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 8.6434ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 154.3µs | GET | 未登录 | /docs/doc.json +2024-06-06 14:54:44 INFO | 192.168.0.248 | 200 | 576µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-06 15:03:07 INFO | 192.168.0.219 | 200 | 6.4952ms | POST | 未登录 | /testData/report/ft +2024-06-06 15:52:09 INFO | 192.168.0.219 | 200 | 49.0710788s | POST | 未登录 | /testData/report/ft +2024-06-06 15:52:30 INFO | 192.168.0.219 | 200 | 4.01537s | POST | 未登录 | /testData/report/ft +2024-06-06 15:57:28 INFO | 192.168.0.219 | 200 | 14.0163275s | POST | 未登录 | /testData/report/ft +2024-06-06 15:59:08 INFO | 192.168.0.219 | 200 | 16.6273762s | POST | 未登录 | /testData/report/ft +2024-06-06 16:02:34 INFO | 192.168.0.219 | 200 | 3m11.0344597s | POST | 未登录 | /testData/report/ft +2024-06-06 16:02:34 INFO | 192.168.0.219 | 200 | 7.4696ms | POST | 未登录 | /testData/report/ft +2024-06-07 11:05:15 INFO | 192.168.0.219 | 200 | 14.3724ms | POST | 未登录 | /testData/report/ft +2024-06-07 14:35:37 INFO | 192.168.0.219 | 200 | 23.1295ms | POST | 未登录 | /testData/report/ft +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 549µs | GET | 未登录 | /docs/index.html +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 526.6µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 612.2µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 88.6µs | GET | 未登录 | /docs/doc.json +2024-06-07 17:40:13 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-07 17:40:33 INFO | 192.168.0.219 | 200 | 996.7µs | POST | 未登录 | /testData/report/cp +2024-06-07 17:47:16 INFO | 192.168.0.219 | 200 | 4.1256ms | POST | 未登录 | /testData/report/cp +2024-06-11 09:56:47 INFO | 192.168.0.219 | 200 | 12.0907ms | POST | 未登录 | /testData/report/cp +2024-06-11 14:32:01 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-06-11 14:32:01 INFO | 192.168.0.248 | 200 | 1.2999ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-11 14:32:01 INFO | 192.168.0.248 | 200 | 8.0675ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-11 14:32:01 INFO | 192.168.0.248 | 200 | 10.8107ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-11 14:32:01 INFO | 192.168.0.248 | 200 | 2.4721ms | GET | 未登录 | /docs/doc.json +2024-06-11 17:13:58 INFO | 192.168.0.248 | 200 | 632.1µs | GET | 未登录 | /docs/index.html +2024-06-11 17:13:58 INFO | 192.168.0.248 | 200 | 1.3114ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-11 17:13:58 INFO | 192.168.0.248 | 200 | 5.2234ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-11 17:13:58 INFO | 192.168.0.248 | 200 | 6.5334ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-11 17:13:58 INFO | 192.168.0.248 | 200 | 361.3µs | GET | 未登录 | /docs/doc.json +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 515.6µs | GET | 未登录 | /docs/index.html +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 676.3µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 1.2471ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 514.8µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 1.2591ms | GET | 未登录 | /docs/doc.json +2024-06-13 10:14:50 INFO | 192.168.0.219 | 200 | 833µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-13 10:15:00 INFO | 192.168.0.219 | 200 | 3.2037021s | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-13 11:40:07 INFO | 192.168.0.219 | 200 | 8.7996ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-13 14:08:02 INFO | 192.168.0.219 | 200 | 8.1068ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-13 14:10:15 INFO | 192.168.0.219 | 200 | 9.0959ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-13 14:13:12 INFO | 192.168.0.219 | 200 | 3.7549ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-13 14:14:07 INFO | 192.168.0.219 | 200 | 5.4016ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-14 10:48:54 INFO | 192.168.0.219 | 200 | 9.3266ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 539.5µs | GET | 未登录 | /docs/index.html +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 91.8µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 1.4738ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 1.4738ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 650.5µs | GET | 未登录 | /docs/doc.json +2024-06-17 17:52:39 INFO | 192.168.0.219 | 200 | 506.5µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-17 17:52:48 INFO | 192.168.0.219 | 200 | 3.0803ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 17:53:35 INFO | 192.168.0.219 | 200 | 2.2429ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 17:54:44 INFO | 192.168.0.219 | 200 | 378.9µs | GET | 未登录 | /docs/index.html +2024-06-17 17:54:44 INFO | 192.168.0.219 | 200 | 611.4µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-17 17:54:44 INFO | 192.168.0.219 | 200 | 524.3µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-17 17:54:44 INFO | 192.168.0.219 | 200 | 524.3µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-17 17:54:45 INFO | 192.168.0.219 | 200 | 1.4128ms | GET | 未登录 | /docs/doc.json +2024-06-17 17:54:45 INFO | 192.168.0.219 | 200 | 182µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-17 17:54:49 INFO | 192.168.0.219 | 200 | 1.4977ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 17:55:05 INFO | 192.168.0.219 | 200 | 2.7067ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 17:55:11 INFO | 192.168.0.219 | 200 | 1.4475ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:04:23 INFO | 192.168.0.219 | 200 | 59.5575282s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:04:54 INFO | 192.168.0.219 | 200 | 24.3529962s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:05:49 INFO | 192.168.0.219 | 200 | 18.8363739s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:11:24 INFO | 192.168.0.219 | 200 | 1m24.0207239s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:12:10 INFO | 192.168.0.219 | 200 | 31.088887s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:16:52 INFO | 192.168.0.219 | 200 | 4m38.170295s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:16:52 INFO | 192.168.0.219 | 200 | 31.9956ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:20:21 INFO | 192.168.0.219 | 200 | 3m7.7066777s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:20:46 INFO | 192.168.0.219 | 200 | 23.6968018s | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:21:07 INFO | 192.168.0.219 | 200 | 7.5738ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:22:39 INFO | 192.168.0.219 | 200 | 2.2481ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-17 18:22:48 INFO | 192.168.0.219 | 200 | 2.9352ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-18 15:54:52 INFO | 192.168.0.219 | 200 | 8.5871ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 16:06:30 INFO | 192.168.0.219 | 200 | 655.5µs | GET | 未登录 | /docs/index.html +2024-06-18 16:06:30 INFO | 192.168.0.219 | 200 | 550.6µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-18 16:06:30 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-18 16:06:30 INFO | 192.168.0.219 | 200 | 1.0814ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-18 16:06:31 INFO | 192.168.0.219 | 200 | 1.0487ms | GET | 未登录 | /docs/doc.json +2024-06-18 16:06:31 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-18 16:07:12 INFO | 192.168.0.219 | 200 | 1.1017ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 16:07:22 INFO | 192.168.0.219 | 200 | 1.689ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 16:07:46 INFO | 192.168.0.219 | 200 | 2.6836ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 16:37:54 INFO | 192.168.0.248 | 200 | 197.3µs | GET | 未登录 | /docs/index.html +2024-06-18 16:37:54 INFO | 192.168.0.248 | 200 | 2.7902ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-18 16:37:54 INFO | 192.168.0.248 | 200 | 5.4608ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-18 16:37:54 INFO | 192.168.0.248 | 200 | 6.9375ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-18 16:37:55 INFO | 192.168.0.248 | 200 | 549.3µs | GET | 未登录 | /docs/doc.json +2024-06-18 16:37:55 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-06-18 17:15:16 INFO | 192.168.0.219 | 200 | 7.727ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 17:31:25 INFO | 192.168.0.219 | 200 | 2.2636ms | POST | 未登录 | /testData/report/fTPassProbabilityByFactory +2024-06-18 17:32:23 INFO | 192.168.0.219 | 200 | 10.7322ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-18 17:33:34 INFO | 192.168.0.219 | 200 | 1.8965ms | POST | 未登录 | /testData/report/fTPassProbabilityByProduct +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 928.5µs | GET | 未登录 | /docs/index.html +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 797.5µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 520.9µs | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 994.6µs | GET | 未登录 | /docs/doc.json +2024-06-20 09:26:51 INFO | 192.168.0.219 | 200 | 201.1µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-24 10:42:18 INFO | 192.168.0.248 | 200 | 1.0958ms | GET | 未登录 | /docs/index.html +2024-06-24 10:42:18 INFO | 192.168.0.248 | 200 | 1.0343ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-24 10:42:18 INFO | 192.168.0.248 | 200 | 3.2306ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-24 10:42:18 INFO | 192.168.0.248 | 200 | 9.0777ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-24 10:42:18 INFO | 192.168.0.248 | 200 | 654µs | GET | 未登录 | /docs/doc.json +2024-06-24 19:28:23 INFO | 192.168.0.248 | 200 | 208.2µs | GET | 未登录 | /docs/index.html +2024-06-24 19:28:23 INFO | 192.168.0.248 | 200 | 1.0558ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-24 19:28:23 INFO | 192.168.0.248 | 200 | 7.6473ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-24 19:28:23 INFO | 192.168.0.248 | 200 | 4.5486ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-24 19:28:23 INFO | 192.168.0.248 | 200 | 462.2µs | GET | 未登录 | /docs/doc.json +2024-06-26 15:33:12 INFO | 192.168.0.219 | 200 | 545.3µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-26 15:49:11 INFO | 192.168.0.248 | 200 | 1.4468ms | GET | 未登录 | /docs/swagger-ui.css +2024-06-26 15:49:11 INFO | 192.168.0.248 | 200 | 3.019ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-26 15:49:11 INFO | 192.168.0.248 | 200 | 7.2656ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-26 15:49:11 INFO | 192.168.0.248 | 200 | 137.9µs | GET | 未登录 | /docs/doc.json +2024-06-26 15:49:11 INFO | 192.168.0.248 | 200 | 928.2µs | GET | 未登录 | /docs/favicon-32x32.png +2024-06-26 15:49:18 INFO | 192.168.0.248 | 200 | 3.3508ms | GET | 未登录 | /docs/index.html +2024-06-26 15:49:18 INFO | 192.168.0.248 | 200 | 181.9µs | GET | 未登录 | /docs/doc.json +2024-06-26 15:50:03 INFO | 192.168.0.219 | 200 | 893.6µs | GET | 未登录 | /docs/index.html +2024-06-26 15:50:03 INFO | 192.168.0.219 | 200 | 272.1µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-26 15:50:03 INFO | 192.168.0.219 | 200 | 556.1µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-26 15:50:03 INFO | 192.168.0.219 | 200 | 1.0775ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-26 15:50:04 INFO | 192.168.0.219 | 200 | 1.1772ms | GET | 未登录 | /docs/doc.json +2024-06-26 15:50:10 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-06-26 15:50:10 INFO | 192.168.0.248 | 200 | 285.9µs | GET | 未登录 | /docs/doc.json +2024-06-28 14:21:24 INFO | 192.168.0.248 | 200 | 731.5µs | GET | 未登录 | /docs/swagger-ui.css +2024-06-28 14:21:24 INFO | 192.168.0.248 | 200 | 1.6511ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-06-28 14:21:24 INFO | 192.168.0.248 | 200 | 9.2355ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-06-28 14:21:24 INFO | 192.168.0.248 | 200 | 897.3µs | GET | 未登录 | /docs/doc.json +2024-07-01 17:07:19 INFO | 192.168.0.219 | 200 | 24.5492646s | POST | 未登录 | /testData/report/ft +2024-07-08 11:50:09 INFO | 192.168.0.248 | 200 | 1.0931ms | GET | 未登录 | /docs/index.html +2024-07-08 11:50:10 INFO | 192.168.0.248 | 200 | 758µs | GET | 未登录 | /docs/swagger-ui.css +2024-07-08 11:50:10 INFO | 192.168.0.248 | 200 | 5.1757ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-08 11:50:10 INFO | 192.168.0.248 | 200 | 20.9562ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-08 11:50:10 INFO | 192.168.0.248 | 200 | 219.5µs | GET | 未登录 | /docs/doc.json +2024-07-08 11:50:10 INFO | 192.168.0.248 | 200 | 650.6µs | GET | 未登录 | /docs/favicon-32x32.png +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/index.html +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 735.2µs | GET | 未登录 | /docs/swagger-ui.css +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 1.0478ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 319.1µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 424.5µs | GET | 未登录 | /docs/doc.json +2024-07-08 14:52:44 INFO | 192.168.0.219 | 200 | 682µs | GET | 未登录 | /docs/favicon-32x32.png +2024-07-10 11:47:53 INFO | 192.168.0.248 | 200 | 1.051ms | GET | 未登录 | /docs/index.html +2024-07-10 11:47:53 INFO | 192.168.0.248 | 200 | 1.3397ms | GET | 未登录 | /docs/swagger-ui.css +2024-07-10 11:47:53 INFO | 192.168.0.248 | 200 | 7.8881ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-10 11:47:53 INFO | 192.168.0.248 | 200 | 10.8067ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-10 11:47:53 INFO | 192.168.0.248 | 200 | 2.1158ms | GET | 未登录 | /docs/doc.json +2024-07-11 09:28:19 INFO | 192.168.0.219 | 200 | 1.101ms | GET | 未登录 | /docs/index.html +2024-07-11 09:28:19 INFO | 192.168.0.219 | 200 | 559.1µs | GET | 未登录 | /docs/swagger-ui.css +2024-07-11 09:28:19 INFO | 192.168.0.219 | 200 | 559.1µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-11 09:28:19 INFO | 192.168.0.219 | 200 | 1.0838ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-11 09:28:19 INFO | 192.168.0.219 | 200 | 195.7µs | GET | 未登录 | /docs/doc.json +2024-07-11 09:58:53 INFO | 192.168.0.248 | 200 | 111.5µs | GET | 未登录 | /docs/index.html +2024-07-11 09:58:53 INFO | 192.168.0.248 | 200 | 2.3885ms | GET | 未登录 | /docs/swagger-ui.css +2024-07-11 09:58:53 INFO | 192.168.0.248 | 200 | 7.5117ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-11 09:58:53 INFO | 192.168.0.248 | 200 | 14.0745ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-11 09:58:53 INFO | 192.168.0.248 | 200 | 426µs | GET | 未登录 | /docs/doc.json +2024-07-11 10:08:34 INFO | 192.168.0.219 | 200 | 516.8µs | GET | 未登录 | /docs/index.html +2024-07-11 10:08:34 INFO | 192.168.0.219 | 304 | 0s | GET | 未登录 | /docs/swagger-ui.css +2024-07-11 10:08:34 INFO | 192.168.0.219 | 304 | 0s | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-11 10:08:34 INFO | 192.168.0.219 | 304 | 154.1µs | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-11 10:08:34 INFO | 192.168.0.219 | 200 | 810.4µs | GET | 未登录 | /docs/doc.json +2024-07-11 10:08:34 INFO | 192.168.0.219 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-07-11 10:09:25 INFO | 192.168.0.219 | 200 | 466.7µs | GET | 未登录 | /docs/index.html +2024-07-11 10:09:25 INFO | 192.168.0.219 | 200 | 1.4091ms | GET | 未登录 | /docs/doc.json +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 503.1µs | GET | 未登录 | /docs/index.html +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 700.6µs | GET | 未登录 | /docs/swagger-ui.css +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 3.8037ms | GET | 未登录 | /docs/swagger-ui-standalone-preset.js +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 9.1332ms | GET | 未登录 | /docs/swagger-ui-bundle.js +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 1.0782ms | GET | 未登录 | /docs/doc.json +2024-07-11 10:15:16 INFO | 192.168.0.248 | 200 | 0s | GET | 未登录 | /docs/favicon-32x32.png +2024-07-12 09:49:15 INFO | 192.168.0.219 | 200 | 386.437419ms | POST | 未登录 | /testData/histogram +2024-07-12 09:50:00 INFO | 192.168.0.219 | 200 | 402.622902ms | POST | 未登录 | /testData/histogram +2024-07-12 09:50:27 INFO | 192.168.0.219 | 200 | 4.61953397s | POST | 未登录 | /testData/ftHistogram/export +2024-07-12 09:50:28 INFO | 192.168.0.219 | 200 | 3.776567ms | GET | 未登录 | /files/2024-07/%E7%9B%B4%E6%96%B9%E5%9B%BE/MP5016-5EC0_S3S592_%E7%9B%B4%E6%96%B9%E5%9B%BE_2024-07-12_095027.xlsx +2024-07-12 09:51:57 INFO | 192.168.0.219 | 200 | 4.624707668s | POST | 未登录 | /testData/ftHistogram/export +2024-07-12 09:51:58 INFO | 192.168.0.219 | 200 | 3.251175ms | GET | 未登录 | /files/2024-07/%E7%9B%B4%E6%96%B9%E5%9B%BE/MP5016-5EC0_S3S592_%E7%9B%B4%E6%96%B9%E5%9B%BE_2024-07-12_095157.xlsx diff --git a/main.go b/main.go new file mode 100644 index 0000000..191701a --- /dev/null +++ b/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "testData/initialization" +) + +func main() { + initialization.InitConfig() + initialization.InitPostgres() + initialization.InitBaseDB() + initialization.InitOracle() + //initialization.InitMongoDB() + initialization.InitLogger() + //var reports []*model.Report + //global.PostGreSQL.Where("step = ?", "FT").Find(&reports) + //fmt.Println(len(reports)) + //for _, report := range reports { + // test_data.SaveFT(report) + //} + //var fileHandles []*model.FileHandled + //global.PostGreSQL.Where("product = ? AND lot = ? AND wafer_id IN ?", "TP2202B", "EP5NYR.1", []string{"01", "02", "04", "06"}). + // Find(&fileHandles) + //for _, fileHandle := range fileHandles { + // var report *model.Report + // global.PostGreSQL.Where("product = ? AND lot = ? AND wafer_id = ?", "TP2202B", "EP5NYR.1", fileHandle.WaferID).Find(&report) + // test_data.SaveCP(fileHandle.Product, fileHandle.Lot, fileHandle.WaferID, report) + //} + initialization.RunServer() +} diff --git a/middleware/casbin.go b/middleware/casbin.go new file mode 100644 index 0000000..088c976 --- /dev/null +++ b/middleware/casbin.go @@ -0,0 +1,48 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "testData/global" + "testData/model" + "testData/model/response" + "testData/service" + "testData/utils" +) + +func CasbinHandler() gin.HandlerFunc { + return func(c *gin.Context) { + user, _ := utils.JWTGetUser(c) + // 获取请求的PATH + obj := c.Request.URL.Path + // 获取请求方法 + act := c.Request.Method + // 获取用户的角色 + //sub := user.RoleId + var isExist bool + var u *model.User + global.BaseDB.Where("user_id = ?", user.UserId).Preload("Role").Find(&u) + for _, v := range u.Role { + sub := v.RoleId + e := service.CasbinServiceApp.Casbin() + // 判断策略中是否存在 + success, _ := e.Enforce(sub, obj, act) + if success { + isExist = true + } + } + if isExist { + c.Next() + } else { + response.FailWithDetailed(gin.H{}, "权限不足", c) + c.Abort() + return + } + //if success { + // c.Next() + //} else { + // response.FailWithDetailed(gin.H{}, "权限不足", c) + // c.Abort() + // return + //} + } +} diff --git a/middleware/cors.go b/middleware/cors.go new file mode 100644 index 0000000..c9bc9a9 --- /dev/null +++ b/middleware/cors.go @@ -0,0 +1,25 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +// Cors 处理跨域请求,支持options访问 +func Cors() gin.HandlerFunc { + return func(c *gin.Context) { + c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin")) + c.Header("Access-Control-Allow-Headers", "Content-Type, AccessToken, X-CSRF-Token, Authorization, Token, X-Token, X-User-Id, Origin, X-Requested-With") + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT") + //c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") + c.Header("Access-Control-Expose-Headers", c.GetHeader("Access-Control-Request-Headers")) + c.Header("Access-Control-Allow-Credentials", "true") + c.Writer.Header().Set("Access-Control-Max-Age", "3600") + // 放行所有OPTIONS方法 + if c.Request.Method == "OPTIONS" { + c.AbortWithStatus(http.StatusNoContent) + } + // 处理请求 + c.Next() + } +} diff --git a/middleware/jwt.go b/middleware/jwt.go new file mode 100644 index 0000000..bb0e845 --- /dev/null +++ b/middleware/jwt.go @@ -0,0 +1,39 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "testData/model/response" + "testData/repository" + "testData/utils" +) + +func JWTAuth() gin.HandlerFunc { + return func(c *gin.Context) { + token := c.Request.Header.Get("x-token") + if token == "" { + response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c) + c.Abort() + return + } + j := utils.NewJWT() + // parseToken 解析token包含的信息 + claims, err := j.ParseToken(token) + if err != nil { + if err == utils.TokenExpired { + response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c) + c.Abort() + return + } + response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + c.Abort() + return + } + if err, u := repository.GetUserByID(claims.ID); err != nil { + response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + c.Abort() + } else { + c.Set("claims", u) + c.Next() + } + } +} diff --git a/middleware/log.go b/middleware/log.go new file mode 100644 index 0000000..8a74c30 --- /dev/null +++ b/middleware/log.go @@ -0,0 +1,30 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "testData/global" + "testData/model" + "time" +) + +func Log() gin.HandlerFunc { + return func(c *gin.Context) { + startTime := time.Now() + c.Next() + statusCode := c.Writer.Status() + endTime := time.Now() + u, _ := c.Get("claims") + user := &model.User{} + if u != nil { + user = u.(*model.User) + } else { + user.Username = "未登录" + } + latencyTime := endTime.Sub(startTime) + reqMethod := c.Request.Method + reqUri := c.Request.RequestURI + clientIp := c.ClientIP() + global.Log.Infof("| %15s | %3d | %15s | %6s | %s | %s", + clientIp, statusCode, latencyTime, reqMethod, user.Username, reqUri) + } +} diff --git a/middleware/recovery.go b/middleware/recovery.go new file mode 100644 index 0000000..b3b6408 --- /dev/null +++ b/middleware/recovery.go @@ -0,0 +1,12 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "testData/global" +) + +func Recovery() func(c *gin.Context) { + return gin.CustomRecovery(func(c *gin.Context, err interface{}) { + global.Log.Errorf("%s", err) + }) +} diff --git a/model/api.go b/model/api.go new file mode 100644 index 0000000..7e4a888 --- /dev/null +++ b/model/api.go @@ -0,0 +1,21 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Api struct { + ID uint `gorm:"primaryKey" json:"id"` + Path string `json:"path" gorm:"comment:api路径"` // api路径 + Description string `json:"description" gorm:"comment:api描述"` // api描述 + ApiGroup string `json:"group" gorm:"comment:api分组"` // api分组 + Method string `json:"method" gorm:"default:POST;comment:方法"` // 方法:POST|GET|PUT|DELETE + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (Api) TableName() string { + return "api" +} diff --git a/model/casbin.go b/model/casbin.go new file mode 100644 index 0000000..698b0d3 --- /dev/null +++ b/model/casbin.go @@ -0,0 +1,9 @@ +package model + +type Casbin struct { + Ptype string `json:"ptype" gorm:"column:ptype"` + AuthorityId string `json:"role" gorm:"column:v0"` + Path string `json:"path" gorm:"column:v1"` + Method string `json:"method" gorm:"column:v2"` + ApiId string `json:"api_id" gorm:"column:v3"` +} diff --git a/model/chart.go b/model/chart.go new file mode 100644 index 0000000..463e19c --- /dev/null +++ b/model/chart.go @@ -0,0 +1,44 @@ +package model + +type Histogram struct { + Field string + Average float64 + StandardDeviation float64 + N float64 + Max string + Min string + X []string + Y []string +} + +type Scatter struct { + Field string + Datas [][]string +} + +type ScatterLimit struct { + Max string + Min string +} + +type Pie struct { + Name string `json:"name"` + Value int `json:"value"` +} + +type Line struct { + Name string + X []string + Y []string +} + +type CPMap struct { + X string + Y string + Field []Field +} + +type Field struct { + Name string + Value string +} diff --git a/model/company.go b/model/company.go new file mode 100644 index 0000000..bd4a5b8 --- /dev/null +++ b/model/company.go @@ -0,0 +1,5 @@ +package model + +type Company struct { + ID int64 `json:"id" gorm:"primaryKey"` +} diff --git a/model/department.go b/model/department.go new file mode 100644 index 0000000..5e81cdf --- /dev/null +++ b/model/department.go @@ -0,0 +1,25 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Departments struct { + ID uint `gorm:"primaryKey" json:"id"` + DepartmentId string `json:"department_id" gorm:"index"` + Name string `json:"name"` + Description string `json:"description" gorm:"type:text"` + ParentId uint `json:"parent_id"` + UUID string `json:"uuid"` + DN string `json:"dn"` + TencentID int64 `json:"tencent_id"` + Children []*Departments `json:"children" gorm:"foreignkey:ParentId"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (Departments) TableName() string { + return "departments" +} diff --git a/model/erp.go b/model/erp.go new file mode 100644 index 0000000..76523b9 --- /dev/null +++ b/model/erp.go @@ -0,0 +1,129 @@ +package model + +import "time" + +type TcSfcFile struct { + TcSfc01 string `json:"tc_sfc01"` // PBI + TcSfc02 time.Time `json:"tc_sfc02"` // 下单日期 + TcSfc04 string `json:"tc_sfc04"` // 厂商编号 + PmcFile PmcFile `gorm:"foreignKey:Pmc01;references:TcSfc04"` + TcSfc08 string `json:"tc_sfc08"` // 加工类型 + TcSfdFile []TcSfdFile `gorm:"foreignKey:TcSfd01;references:TcSfc01"` + TcSfeFile []TcSfeFile `gorm:"foreignKey:TcSfe01;references:TcSfc01"` +} + +func (TcSfcFile) TableName() string { return "tc_sfc_file" } + +type TcSfdFile struct { + TcSfd01 string `json:"tc_sfd01"` // PBI + TcSfd02 int `json:"tc_sfd02"` // 回货项次 + TcSfd03 string `json:"tc_sfd03"` // 料号 + ImaFile ImaFile `gorm:"foreignKey:Ima01;references:TcSfd03"` + TcSfd05 float64 `json:"tc_sfd05"` // 数量 + TcSfd06 string `json:"tc_sfd06"` // 批号 + TcSfd13 string `json:"tc_sfd13"` // 委外工单号 + SfbFile SfbFile `gorm:"foreignKey:Sfb01;references:TcSfd13"` + //RvbFile []RvbFile `gorm:"foreignKey:Rvb34;references:TcSfd13"` + TcSfd14 string `json:"tc_sfd14"` // 委外采购单号 + RvaFile []RvaFile `gorm:"foreignKey:Rva02;references:TcSfd14"` + TcSfdUd02 string `json:"tc_sfdud02" gorm:"column:TC_SFDUD02"` // 丝印 +} + +func (TcSfdFile) TableName() string { return "tc_sfd_file" } + +type TcSfeFile struct { + TcSfe01 string `json:"tc_sfe01"` // PBI + TcSfe02 int `json:"tc_sfe02"` // 回货项次 + TcSfe04 string `json:"tc_sfe04"` // 料号 + ImaFile ImaFile `gorm:"foreignKey:Ima01;references:TcSfe04"` + TcSfe10 string `json:"tc_sfe10"` // 晶圆批号 + TcSfe15 string `json:"tc_sfe15"` // 片号 + TcSfe17 string `json:"tc_sfe17"` // 是否主芯 +} + +func (TcSfeFile) TableName() string { return "tc_sfe_file" } + +type ImaFile struct { + Ima01 string `json:"ima01"` // 料号 + Ima02 string `json:"ima02"` // 型号 + Ima021 string `json:"ima021"` // 规格 +} + +func (ImaFile) TableName() string { return "ima_file" } + +type PmmFile struct { + Pmm01 string `json:"pmm01"` // 采购单号 + Pmm04 time.Time `json:"pmm04"` // 采购日期 + Pmm09 string `json:"pmm09"` // 供应厂商编号 + PmnFile PmnFile `gorm:"foreignKey:Pmn01;references:Pmm01"` + PmcFile PmcFile `gorm:"foreignKey:Pmc01;references:Pmm09"` + RvbFile []RvbFile `gorm:"foreignKey:Rvb04;references:Pmm01"` +} + +func (PmmFile) TableName() string { return "pmm_file" } + +type PmnFile struct { + Pmn01 string `json:"pmn01"` + Pmn04 string `json:"pmn04"` // 料件编号 + ImaFile ImaFile `gorm:"foreignKey:Ima01;references:Pmn04"` + Pmn20 float64 `json:"pmn20"` // 采购量 + Pmn53 float64 `json:"pmn53"` // 已交量 + Pmn82 string `json:"pmn82"` // 采购数量 + Pmn041 string `json:"pmn041"` // 品名规格 +} + +func (PmnFile) TableName() string { return "pmn_file" } + +type RvaFile struct { + Rva01 string `json:"rva01"` // 收货单号 + IddFile []IddFile `gorm:"foreignKey:Idd10;references:Rva01"` + Rva02 string `json:"rva02"` // 采购单号 + Rva06 string `json:"rva06"` +} + +func (RvaFile) TableName() string { return "rva_file" } + +type RvvFile struct { + Rvv36 string `json:"rvv36"` // 采购单号 + Rvv84 string `json:"rvv84"` // 数量 + RvaFile []RvaFile `gorm:"foreignKey:Rva02;references:Rvv36"` +} + +func (RvvFile) TableName() string { return "rvv_file" } + +type PmcFile struct { + Pmc01 string `json:"pmc01"` // 厂商编号 + Pmc03 string `json:"pmc03"` // 厂商名称 +} + +func (PmcFile) TableName() string { return "pmc_file" } + +type RvbFile struct { + Rvb01 string `json:"rvb01"` // 收货单号 + //IddFile IddFile `gorm:"foreignKey:Idd10;references:Rvb01"` + Rvb04 string `json:"rvb04"` // 采购单号 + Rvb12 time.Time `json:"rvb12"` // 收货日期 + Rvb29 float64 `json:"rvb29"` // 退货量 + Rvb30 float64 `json:"rvb30"` // 入库数 + Rvb34 string `json:"rvb34"` // PBI + Rvb38 string `json:"rvb38"` // 批号 +} + +func (RvbFile) TableName() string { return "rvb_file" } + +type IddFile struct { + Idd01 string `json:"idd01"` // 料号 + Idd04 string `json:"idd04"` // 批号 + Idd06 string `json:"idd06"` // 良品/不良品 + Idd10 string `json:"idd10"` // 收货单号 + Idd13 float64 `json:"idd13"` // 数量 +} + +func (IddFile) TableName() string { return "idd_file" } + +type SfbFile struct { + Sfb01 string `json:"sfb01"` + Sfb04 string `json:"sfb04"` +} + +func (SfbFile) TableName() string { return "sfb_file" } diff --git a/model/excel.go b/model/excel.go new file mode 100644 index 0000000..91fbf19 --- /dev/null +++ b/model/excel.go @@ -0,0 +1,95 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type FileText struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `json:"name" gorm:"comment:文件名;index"` + Path string `json:"path" gorm:"comment:文件路径;index"` + Size string `json:"size" gorm:"comment:文件大小"` + ModTime int64 `json:"modtime" gorm:"comment:文件修改时间"` + IsCsv bool `json:"isCsv" gorm:"comment:是否为csv文件"` + Sha1 string `json:"sha1" gorm:"comment:文件sha1值"` + Factory string `json:"factory" gorm:"comment:厂商"` + Processed bool `json:"processed" gorm:"comment:是否已处理"` + ProductName string `json:"product_name"` + Lot string `json:"lot" gorm:"comment:批次号"` + SubBatch string `json:"sub_batch" gorm:"子批次"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (FileText) TableName() string { + return "file_text" +} + +type FileCompress struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `json:"name" gorm:"comment:文件名;index"` + Path string `json:"path" gorm:"comment:文件路径;index"` + Size string `json:"size" gorm:"comment:文件大小"` + ModTime int64 `json:"modtime" gorm:"comment:文件修改时间"` + NewName string `json:"newName" gorm:"comment:重命名后的文件名"` + NewPath string `json:"newPath" gorm:"comment:重命名后的文件路径"` + Decompressed bool `json:"decompressed" gorm:"comment:是否已解压"` + Unzip string `json:"unzip" gorm:"comment:解压后的文件路径"` + Sha1 string `json:"sha1" gorm:"comment:文件sha1值"` + Factory string `json:"factory" gorm:"comment:厂商"` + ProductName string `json:"product_name"` + Lot string `json:"lot" gorm:"comment:批次号"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (FileCompress) TableName() string { + return "file_compress" +} + +type FileHandled struct { + ID int `json:"id" gorm:"primary_key"` + Name string `json:"name"` + Path string `json:"path"` + Size string `json:"size"` + Factory string `json:"factory"` // 厂商 + PBI string `json:"pbi" comment:"PBI"` + Product string `json:"product"` // 产品型号 + Step string `json:"step"` // 测试工序 + Lot string `json:"lot"` // 批号 + SubBatch string `json:"sub_batch"` // 子批 + TestMachineModel string `json:"test_machine_model"` // 测试机台型号 + TestMachine string `json:"test_machine"` // 测试机台 + TestProgram string `json:"test_program"` // 测试程序 + WaferID string `json:"wafer_id"` + BeginningTime string `json:"beginning_time"` // 开始时间 + EndingTime string `json:"ending_time"` // 结束时间 + SbinHbin string `json:"sbin_hbin"` // Sbin/Hbin + TitleInfo string `json:"title_info"` // 参数信息 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} + +type DataInfo struct { + Unit string + LimitL string + LimitU string +} + +type BinInfo struct { + //Number string + Name string + HBin string +} + +type CQ774P struct { + ID int `json:"id" gorm:"primary_key"` + Data string `json:"data" gorm:"type:text"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} diff --git a/model/factory.go b/model/factory.go new file mode 100644 index 0000000..913ab7c --- /dev/null +++ b/model/factory.go @@ -0,0 +1,26 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Factory struct { + ID int64 `json:"id" gorm:"primaryKey"` + Name string `json:"name"` + Email string `json:"email"` + Keyword string `json:"keyword"` + FactoryExcel []FactoryExcel `json:"factory_excel" gorm:"foreignKey:FactoryID;references:ID"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"` +} + +type FactoryExcel struct { + ID int64 `json:"id" gorm:"primaryKey"` + ExcelTitle string `json:"excel_title"` + Title string `json:"title"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"` +} diff --git a/model/menu.go b/model/menu.go new file mode 100644 index 0000000..5ac11a0 --- /dev/null +++ b/model/menu.go @@ -0,0 +1,38 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Menu struct { + ID uint `json:"id" gorm:"primary_key"` + Name string `json:"name"` // 路由名称 英文名 + Title string `json:"title"` // 菜单名称 + GroupName string `json:"group_name"` // 项目名称 + Role []*Role `json:"role" gorm:"many2many:role_menus"` + //ParentID uint `json:"parent_id"` // 父菜单ID + //Sort uint `json:"sort"` + //Children []*Menu `json:"children" gorm:"foreignkey:ParentID"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} + +type MenuForLeader struct { + GroupName string `json:"group_name"` // 项目名称 + Menus []*Menus `json:"menus"` // 菜单 +} + +type Menus struct { + ID uint `json:"id"` + Name string `json:"name"` // 路由名称 + Title string `json:"title"` // 菜单名称 +} + +/* +resp: + { + roles:["name", "name"] // Menu.Name +} +*/ diff --git a/model/position.go b/model/position.go new file mode 100644 index 0000000..325bbe6 --- /dev/null +++ b/model/position.go @@ -0,0 +1,22 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Position struct { + ID uint `gorm:"primaryKey" json:"id"` + PositionId string `json:"position_id" gorm:"index"` + Name string `json:"name"` + Description string `json:"description" gorm:"type:text"` + ParentId uint `json:"parent_id"` + Children []*Position `json:"children" gorm:"foreignkey:ParentId"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (Position) TableName() string { + return "positions" +} diff --git a/model/report.go b/model/report.go new file mode 100644 index 0000000..0732ddd --- /dev/null +++ b/model/report.go @@ -0,0 +1,128 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Report struct { + ID int64 `json:"id" gorm:"primaryKey"` + Product string `json:"product"` // 成品型号 + Lot string `json:"lot"` //晶圆批次 + Factory string `json:"factory"` // 测试厂 + TestMachine string `json:"test_machine"` // 测试机台 + TestProgram string `json:"test_program"` // 测试程序 + PBI string `json:"pbi"` // PBI + SubBatch string `json:"sub_batch"` // 子批次 + OrderDate string `json:"order_date"` // 下单日期 + Seal string `json:"seal"` // 丝印 + TestQuantity string `json:"test_quantity"` // 测试数量 + FirstPassQuantity string `json:"first_pass_quantity"` // 初测良品数量 + FirstPassProbability string `json:"first_pass_probability"` // 初测良率 + PassQuantity string `json:"pass_quantity"` // 良品数量(包括回收数据) + PassProbability string `json:"pass_probability"` // 良率(包括回收数据) + WaferID string `json:"wafer_id"` // 片号 + TestTime string `json:"test_time"` // 测试时间 + Step string `json:"step"` // 工序 + StackingMaterials bool `json:"stacking_materials"` // 是否叠料 + BinFail []BinFail `json:"bin_fail" gorm:"foreignKey:ReportID"` // 硬件和软件Bin的不良数量 + Site []ReportSites `json:"site" gorm:"foreignKey:ReportID"` // Site测试情况 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +type FinalReport struct { + ID int64 `json:"id" gorm:"primaryKey"` + Product string `json:"product"` + Lot string `json:"lot"` + PBI string `json:"pbi"` + Step string `json:"step"` + ReportTestQuantity string `json:"report_test_quantity"` // 报表测试数量 + ReportPassQuantity string `json:"report_pass_quantity"` // 报表良品数量 + ReportPassProbability string `json:"report_pass_probability"` // 报表良率 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +type ReportSites struct { + ID int64 `json:"id" gorm:"primaryKey"` + ReportID int64 `json:"report_id"` + Site string `json:"site"` // Site + TestQuantity string `json:"test_quantity"` // 测试总数 + PassQuantity string `json:"pass_quantity"` // 测试良品数 + PassProbability string `json:"pass_probability"` // 良率 + BinFail []BinFail `json:"bin_fail" gorm:"foreignKey:ReportSiteID"` // 硬件和软件Bin的不良数量 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +type BinFail struct { + ID int64 `json:"id" gorm:"primaryKey"` + ReportID int64 `json:"report_id"` + ReportSiteID int64 `json:"report_site_id"` + HardBin string `json:"hard_bin"` // 硬件Bin名称 + SoftBin string `json:"soft_bin"` // 软件Bin名称 + Quantity string `json:"quantity"` // 数量 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +type ReportList struct { + ID int64 `json:"id" gorm:"primaryKey"` + Product string `json:"product"` // 成品型号 + Lot string `json:"lot"` //晶圆批次 + Factory string `json:"factory"` // 测试厂 + TestMachine string `json:"test_machine"` // 测试机台 + TestProgram string `json:"test_program"` // 测试程序 + PBI string `json:"pbi"` // PBI + SubBatch string `json:"sub_batch"` // 子批次 + OrderDate string `json:"order_date"` // 下单日期 + Seal string `json:"seal"` // 丝印 + TestQuantity string `json:"test_quantity"` // 测试数量 + FirstPassQuantity string `json:"first_pass_quantity"` // 初测良品数量 + FirstPassProbability string `json:"first_pass_probability"` // 初测良率 + PassQuantity string `json:"pass_quantity"` // 良品数量(包括回收数据) + PassProbability string `json:"pass_probability"` // 良率(包括回收数据) + ReportTestQuantity string `json:"report_test_quantity"` // 报表测试数量 + ReportPassQuantity string `json:"report_pass_quantity"` // 报表良品数量 + ReportPassProbability string `json:"report_pass_probability"` // 报表良率 + WaferID string `json:"wafer_id"` // 片号 + TestTime string `json:"test_time"` // 测试时间 + Step string `json:"step"` // 工序 + TestQuantityDiff string `json:"test_quantity_diff"` // 测试数量差异 + TestQuantityDiffLabel bool `json:"test_quantity_diff_label"` + PassQuantityDiff string `json:"pass_quantity_diff"` // 良品数量差异 + PassQuantityDiffLabel bool `json:"pass_quantity_diff_label"` + ReturnProbability string `json:"return_probability"` // 回收率 + ReturnProbabilityLabel bool `json:"return_probability_label"` + StackingMaterials bool `json:"stacking_materials"` // 是否叠料 + SoftBinFailMap map[string]float64 `json:"soft_bin_fail_map"` // 软件Bin的不良数量 + HardBinFailMap map[string]float64 `json:"hard_bin_fail_map"` // 硬件Bin的不良数量 + SoftBinFail []*ReportBinFail `json:"soft_bin_fail"` // 软件Bin的不良数量 + HardBinFail []*ReportBinFail `json:"hard_bin_fail"` // 硬件Bin的不良数量 + Site []*ReportListSites `json:"site"` // Site测试情况 +} + +type ReportListSites struct { + ID int64 `json:"id" gorm:"primaryKey"` + ReportID int64 `json:"report_id"` + Site string `json:"site"` // Site + TestQuantity string `json:"test_quantity"` // 测试总数 + PassQuantity string `json:"pass_quantity"` // 测试良品数 + PassProbability string `json:"pass_probability"` // 良率 + SoftBinFailMap map[string]float64 `json:"soft_bin_fail_map"` // 软件Bin的不良数量 + HardBinFailMap map[string]float64 `json:"hard_bin_fail_map"` // 硬件Bin的不良数量 + SoftBinFail []*ReportBinFail `json:"soft_bin_fail"` // 软件Bin的不良数量 + HardBinFail []*ReportBinFail `json:"hard_bin_fail"` // 硬件Bin的不良数量 +} + +type ReportBinFail struct { + Bin string `json:"bin"` + Quantity float64 `json:"quantity"` + Proportion string `json:"proportion"` + ReportProportion string `json:"report_proportion"` +} diff --git a/model/report.list.go b/model/report.list.go new file mode 100644 index 0000000..73fd675 --- /dev/null +++ b/model/report.list.go @@ -0,0 +1,43 @@ +package model + +type WaferList struct { + OrderDate string `json:"order_date"` // 下单日期 + PBI string `json:"pbi"` // 订单号 + Product string `json:"product"` // 晶圆型号 + Factory string `json:"factory"` // 晶圆厂 + WaferSize string `json:"wafer_size"` // 晶圆尺寸 + Quantity float64 `json:"quantity"` // 投片数量 + OnlineQuantity float64 `json:"online_quantity"` // 在线数量 + ReturnDate string `json:"return_date"` // 回货日期 + Lot string `json:"lot"` // 批号 + ReturnQuantity float64 `json:"return_quantity"` // 回货数量 +} + +type ABList struct { + OrderDate string `json:"order_date"` // 下单日期 + PBI string `json:"pbi"` // 订单号 + OutsourcingPBI string `json:"outsourcing_pbi"` // 委外工单号 + Product string `json:"product"` // 成品型号 + WaferProduct string `json:"wafer_product"` // 晶圆型号 + Package string `json:"package"` // 封装 + Factory string `json:"factory"` // 封装厂 + Lot string `json:"lot"` // 批号 + Seal string `json:"seal"` // 丝印 + WaferID string `json:"wafer_id"` // 片号 + Quantity float64 `json:"quantity"` // 订单数量 + OnlineQuantity float64 `json:"online_quantity"` // 在线数量 + IsFinish string `json:"is_finish"` // 是否已完成 + PassProbability string `json:"pass_probability"` // 良率 + StockOutQuantity float64 `json:"stock_out_quantity"` // 出库数 + StockInQuantity float64 `json:"stock_in_quantity"` // 入库数 + FailQuantity float64 `json:"fail_quantity"` // 封装不良品 + ABWaferList []*ABWaferList `json:"ab_wafer_list"` +} + +type ABWaferList struct { + Material string `json:"material"` // 料号 + Product string `json:"product"` // 品名 + Specification string `json:"specification"` // 规格 + Lot string `json:"lot"` // 批号 + WaferID string `json:"wafer_id"` // 片号 +} diff --git a/model/response/response.go b/model/response/response.go new file mode 100644 index 0000000..81c71d7 --- /dev/null +++ b/model/response/response.go @@ -0,0 +1,54 @@ +package response + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +type Response struct { + Code int `json:"code"` + Data interface{} `json:"data"` + Msg string `json:"msg"` +} + +const ( + ERROR = 7 + SUCCESS = 0 +) + +func Result(code int, data interface{}, msg string, c *gin.Context) { + // 开始时间 + c.JSON(http.StatusOK, Response{ + code, + data, + msg, + }) +} + +func Ok(c *gin.Context) { + Result(SUCCESS, map[string]interface{}{}, "操作成功", c) +} + +func OkWithMessage(message string, c *gin.Context) { + Result(SUCCESS, map[string]interface{}{}, message, c) +} + +func OkWithData(data interface{}, c *gin.Context) { + Result(SUCCESS, data, "操作成功", c) +} + +func OkWithDetailed(data interface{}, message string, c *gin.Context) { + Result(SUCCESS, data, message, c) +} + +func Fail(c *gin.Context) { + Result(ERROR, map[string]interface{}{}, "操作失败", c) +} + +func FailWithMessage(message string, c *gin.Context) { + Result(ERROR, map[string]interface{}{}, message, c) +} + +func FailWithDetailed(data interface{}, message string, c *gin.Context) { + Result(ERROR, data, message, c) +} diff --git a/model/role.go b/model/role.go new file mode 100644 index 0000000..f2fa866 --- /dev/null +++ b/model/role.go @@ -0,0 +1,23 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type Role struct { + ID uint `json:"id" gorm:"primary_key"` + RoleId string `json:"role_id" gorm:"index"` + Name string `json:"name"` + ParentId uint `json:"parent_id"` + Children []*Role `json:"children" gorm:"foreignkey:ParentId"` + Menu []*Menu `json:"menu" gorm:"many2many:role_menus;foreignKey:ID"` + User []*User `json:"user" gorm:"many2many:user_role;foreignkey:RoleId;references:UserId"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (Role) TableName() string { + return "roles" +} diff --git a/model/user.go b/model/user.go new file mode 100644 index 0000000..d9b9163 --- /dev/null +++ b/model/user.go @@ -0,0 +1,84 @@ +package model + +import ( + "gorm.io/gorm" + "time" +) + +type User struct { + ID uint `gorm:"primaryKey" json:"id"` + Uuid string `json:"uuid" gorm:"index"` + UserId string `json:"user_id"` + Email string `json:"email" gorm:"index"` + Username string `json:"username" gorm:"index"` + LinuxName string `json:"linux_name" gorm:"index"` + Phone string `json:"phone" gorm:"index"` + //RoleId string `json:"role_id"` + //Role Role `json:"role" gorm:"foreignkey:RoleId;references:RoleId"` + Role []*Role `json:"role" gorm:"many2many:user_role;foreignkey:UserId;references:RoleId"` + DepartmentId string `json:"department_id"` + Department Departments `json:"department" gorm:"foreignkey:DepartmentId;references:DepartmentId"` + Departments []Departments `json:"departments" gorm:"many2many:user_department_relations;foreignkey:UserId;references:DepartmentId"` + PositionId string `json:"position_id"` + Position Position `json:"position" gorm:"foreignkey:PositionId;references:PositionId"` + LastLoginAt string `json:"last_login_at"` + LastLoginIp string `json:"last_login_ip"` + LastLoginAddress string `json:"last_login_address"` + Password string `json:"-"` + Gender string `json:"gender"` + Active bool `json:"active"` + IsManager bool `json:"is_manager" gorm:"default:false"` + IsRestrict bool `json:"is_restrict" gorm:"default:false"` + IpRange string `json:"ip_range"` + // 补充字段 + Company string `json:"company" gorm:"comment:归属分公司"` + DefaultShell string `json:"default_shell" gorm:"用户默认shell"` + Home string `json:"home" gorm:"comment:用户home目录路径"` + Uid string `json:"uid" gorm:"comment:用户在Nis中的uid"` + Salt string `json:"-" gorm:"comment:密码盐"` + Iv string `json:"-"` + SosManager bool `json:"sos_manager" gorm:"comment:为true,默认加载到sos配置文件的admin中"` + ProjectManager bool `json:"project_manager" gorm:"comment:为true,能查看所有项目"` + CompanyManager bool `json:"company_manager" gorm:"comment:为true,可管理用户,用户组"` + Groups []*Group `json:"groups" gorm:"many2many:user_group;"` + DN string `json:"dn"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (User) TableName() string { + return "users" +} + +type LoginRecord struct { + ID uint `gorm:"primaryKey" json:"id"` + Uuid string `json:"uuid" gorm:"index"` + Username string `json:"username"` + IP string `json:"ip"` + Address string `json:"address"` + Msg string `json:"msg"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (LoginRecord) TableName() string { + return "login_Record" +} + +// +// Group +/* @Description: 根据项目,将项目内成员分组,如TP0001S */ +type Group struct { + ID uint `gorm:"primaryKey" json:"id"` + Name string `json:"name" gorm:"comment:组名"` + Users []*User `json:"users" gorm:"many2many:user_group;"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +func (Group) TableName() string { + return "group" +} diff --git a/repository/STS8200.go b/repository/STS8200.go new file mode 100644 index 0000000..63b201e --- /dev/null +++ b/repository/STS8200.go @@ -0,0 +1,324 @@ +package repository + +import ( + "bytes" + "encoding/csv" + "encoding/json" + "errors" + "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 HandleSTS8200Excel(fileText *model.FileText, step string) { + 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 + } + //解决读取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 + } + 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 + } + } + } else if strings.ToLower(path.Ext(fileText.Name)) == ".xlsx" { + xlsxFile, err := excelize.OpenFile(fileText.Path) + if err != nil { + log.Println("open err:", err) + return + } + sheetName := xlsxFile.GetSheetName(0) + rows, err = xlsxFile.GetRows(sheetName) + if err != nil { + log.Println("xlsx读取数据失败:", err) + return + } + } + + details := make(map[string]string) + newExcel := make([][]string, 0) + var title []string + titleInfoMap := make(map[string]model.DataInfo) + sBinMap := make(map[string]model.BinInfo) + sbinStartIndex, sbinEndIndex := -1, -1 + titleIndex, unitIndex, limitLIndex, limitUIndex, dataIndex := -1, -1, -1, -1, -1 + for i := 1; i < len(rows); i++ { + if rows[i][0] == "" { + continue + } + if i == len(rows)-1 && unitIndex == -1 { + log.Println("特殊文件格式,文件路径为:", fileText.Path) + return + } + if sbinEndIndex < 0 { + if strings.Contains(rows[i][0], "SBin") { + if sbinStartIndex < 0 { + sbinStartIndex = i + } + s := rows[i][0] + if strings.Index(s, "]") != -1 { + sbinNumStartIndex := strings.Index(s, "[") + sbinNumEndIndex := strings.Index(s, "]") + var startIndex, endIndex int + for index := sbinNumEndIndex + 1; index < len(s); index++ { + if startIndex == 0 { + if s[index] != ' ' { + startIndex = index + } + } else { + if s[index] == ' ' || s[index] == '_' { + endIndex = index + break + } + } + } + sBinMap[s[sbinNumStartIndex+1:sbinNumEndIndex]] = model.BinInfo{ + Name: s[startIndex:endIndex], + HBin: s[strings.LastIndex(s, " ")+1:], + } + //sBinMap[s[startIndex:endIndex]] = model.BinInfo{ + // Number: s[sbinNumStartIndex+1 : sbinNumEndIndex], + // HBin: s[strings.LastIndex(s, " ")+1:], + //} + + } + } else { + if sbinStartIndex > 0 { + sbinEndIndex = i + continue + } + } + } + //if len(sBinMap) == 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 strings.Contains(rows[i][0], "SITE_NUM") { + titleIndex = i + title = rows[i] + continue + } + } else { + if unitIndex < 0 { + if strings.Contains(rows[i][0], "Unit") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + unitIndex = i + continue + } + } + if limitLIndex < 0 { + if strings.Contains(rows[i][0], "LimitL") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + limitLIndex = i + continue + } + } + if limitUIndex < 0 { + if strings.Contains(rows[i][0], "LimitU") { + rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...) + limitUIndex = i + continue + } + } + if dataIndex < 0 && limitUIndex > 0 { + if rows[i][0] != rows[i][2] { + dataIndex = i + break + } + } + } + } + if titleIndex != -1 { + for k, v := range rows[titleIndex] { + titleInfoMap[v] = model.DataInfo{ + Unit: rows[unitIndex][k], + LimitL: rows[limitLIndex][k], + LimitU: rows[limitUIndex][k], + } + } + for i := dataIndex; i < len(rows); i++ { + 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 + } + + 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) + 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/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 + } + 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), + 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), + TitleInfo: string(titleInfo), + WaferID: waferID, + }) + } + } + } + newCsv, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Println("打开新Excel错误:", fileText.Path) + return + } + defer newCsv.Close() + writer := csv.NewWriter(newCsv) + defer writer.Flush() + err = writer.WriteAll(newExcel) + if err != nil { + log.Println("写入新Excel错误:", fileText.Path) + return + } + newFile, err := os.Stat(filePath) + if err != nil { + log.Println("获取新Excel信息:", fileText.Path) + return + } + global.PostGreSQL.Model(&fileHandled).Where("name = ?", fileName).Updates(map[string]interface{}{ + "product": string(product), + "step": details["Test_Code"], + "test_machine_model": "STS8200", + "test_machine": details["Tester ID"], + "test_program": testProgram, + "beginning_time": details["Beginning Time"], + "ending_time": details["Ending Time"], + "sbin_hbin": string(sbinHbin), + "title_info": string(titleInfo), + "size": utils.FormatFileSize(float64(newFile.Size())), + }) +} diff --git a/repository/TQT601.go b/repository/TQT601.go new file mode 100644 index 0000000..dd6afde --- /dev/null +++ b/repository/TQT601.go @@ -0,0 +1,286 @@ +package repository + +import ( + "encoding/csv" + "encoding/json" + "errors" + "github.com/extrame/xls" + "gorm.io/gorm" + "log" + "os" + "path/filepath" + "strings" + "testData/global" + "testData/model" + "testData/utils" +) + +func HandlerTQT601Excel(fileText *model.FileText, step string) { + var isXls bool + file, err := os.Open(fileText.Path) + if err != nil { + log.Println("open err:", err) + return + } + reader := csv.NewReader(file) + reader.FieldsPerRecord = -1 + reader.LazyQuotes = true + rows, err := reader.ReadAll() + if err != nil { + if xlFile, err := xls.Open(fileText.Path, "utf-8"); err == nil { + //第一个sheet + sheet := xlFile.GetSheet(0) + if sheet.MaxRow != 0 { + temp := make([][]string, sheet.MaxRow) + for i := 0; i < int(sheet.MaxRow); i++ { + row := sheet.Row(i) + data := make([]string, 0) + if row.LastCol() > 0 { + for j := 0; j < row.LastCol(); j++ { + col := row.Col(j) + data = append(data, col) + } + temp[i] = data + } + } + rows = append(rows, temp...) + } + isXls = true + } else { + log.Println("open err:", err) + return + } + } + + newExcel := make([][]string, 0) + var title []string + details := make(map[string]string) + titleInfoMap := make(map[string]model.DataInfo) + index, titleIndex, unitIndex, limitLIndex, limitUIndex := 0, -1, -1, -1, -1 + if len(rows) == 0 { + log.Println(fileText.Path, "文件为空") + return + } + for { + if index == len(rows)-1 { + break + } + if !isXls { + rows[index][0], err = utils.DecodeToUnicode(rows[index][0]) + if err != nil { + return + } + rows[index] = strings.Split(rows[index][0], "\t") + } + if len(titleInfoMap) == 0 { + if strings.Contains(rows[index][0], "=") { + splitIndex := strings.Index(rows[index][0], "=") + details[rows[index][0][:splitIndex]] = rows[index][0][splitIndex+1:] + } + if titleIndex < 0 && len(rows[index]) > 1 { + if strings.Contains(rows[index][1], "Test") { + titleIndex = index + index++ + continue + } + } else { + if limitUIndex < 0 && len(rows[index]) > 1 { + if strings.Contains(rows[index][1], "High_limits") { + limitUIndex = index + index++ + continue + } + } + if limitLIndex < 0 && len(rows[index]) > 1 { + if strings.Contains(rows[index][1], "Low_limits") { + limitLIndex = index + index++ + continue + } + } + if unitIndex < 0 && len(rows[index]) > 1 { + if strings.Contains(rows[index][1], "Units") { + unitIndex = index + rows[limitUIndex] = append(rows[limitUIndex], utils.FillData(len(rows[titleIndex])-len(rows[limitUIndex]))...) + rows[limitLIndex] = append(rows[limitLIndex], utils.FillData(len(rows[titleIndex])-len(rows[limitLIndex]))...) + rows[unitIndex] = append(rows[unitIndex], utils.FillData(len(rows[titleIndex])-len(rows[unitIndex]))...) + title = append(title, []string{"DieID", "SBIN"}...) + for rowIndex := 2; rowIndex < len(rows[index]); rowIndex++ { + title = append(title, rows[titleIndex][rowIndex]) + titleInfoMap[rows[titleIndex][rowIndex]] = model.DataInfo{ + Unit: rows[unitIndex][rowIndex], + LimitL: rows[limitLIndex][rowIndex], + LimitU: rows[limitUIndex][rowIndex], + } + } + //newExcel = append(newExcel, title) + index++ + continue + } + } + } + } else { + if len(rows[index]) > 1 { + if strings.Contains(rows[index][1], "Test") || strings.Contains(rows[index][1], "High_limits") || + strings.Contains(rows[index][1], "Low_limits") || strings.Contains(rows[index][1], "Units") { + index++ + continue + } + if !strings.Contains(rows[index][1], "SBIN") { + rows[index] = append(rows[index], utils.FillData(len(rows[titleIndex])-len(rows[index]))...) + newExcel = append(newExcel, rows[index]) + } + } + } + index++ + } + fileText.Name = strings.ReplaceAll(fileText.Name, "__", "_") + if details["Test_Code"] == "" { + details["Test_Code"] = step + } else { + details["Test_Code"] = details["Test_Code"][:2] + } + pointLastIndex := strings.LastIndex(fileText.Name, ".") + pointIndex := pointLastIndex - 1 + for { + if pointIndex == 0 { + log.Println("文件名格式错误:", fileText.Path) + return + } + if fileText.Name[pointIndex] == '.' { + break + } + pointIndex-- + } + if pointIndex != pointLastIndex { + start, end := pointIndex, pointIndex+2 + //for { + // if fileText.Name[end] == '_' { + // break + // } + // end++ + // if end > pointLastIndex { + // fmt.Println("文件名格式错误:", fileText.Path) + // return + // } + //} + for { + if fileText.Name[start] == '_' { + break + } + start-- + if start < 0 { + log.Println("文件名格式错误:", fileText.Path) + return + } + } + for i := 2; i < start; i++ { + if details["Test_Code"] == "FT" { + if fileText.Name[i-2:i] == "FT" { + for { + if fileText.Name[i] == '_' { + break + } + i++ + } + if i > start-1 { + log.Println("文件名格式错误:", fileText.Path) + return + } + details["product"] = fileText.Name[i+1 : start] + break + } + } else if details["Test_Code"] == "RT" { + if fileText.Name[i-2:i] == "RT" { + for { + if fileText.Name[i] == '_' { + break + } + i++ + } + details["product"] = fileText.Name[i+1 : start] + break + } + } + } + details["lot"] = fileText.Name[start+1 : end] + } + testProgram := details["TestProgram"] + fileName := details["product"] + "_" + details["lot"] + "_" + details["Test_Code"] + ".csv" + utils.MakeDir("/testData/test") + filePath := filepath.Join("/testData/test", fileName) + titleInfo, _ := json.Marshal(&titleInfoMap) + 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 + } + if errors.Is(global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled).Error, gorm.ErrRecordNotFound) { + global.PostGreSQL.Create(&model.FileHandled{ + Name: fileName, + Path: filePath, + Size: "", + Factory: fileText.Factory, + Product: details["product"], + Step: details["Test_Code"], + Lot: details["lot"], + TestMachineModel: "TQT601", + TestMachine: details["TesterNO."], + TestProgram: testProgram, + BeginningTime: details["Beginning Time"], + EndingTime: details["Ending Time"], + TitleInfo: string(titleInfo), + }) + } + } + } + newCsv, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Println("打开新Excel错误:", err) + return + } + defer newCsv.Close() + global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled) + writer := csv.NewWriter(newCsv) + defer writer.Flush() + err = writer.WriteAll(newExcel) + if err != nil { + log.Println("写入新Excel错误:", err) + return + } + newFile, err := os.Stat(filePath) + if err != nil { + log.Println("获取新Excel信息:", err) + return + } + if fileHandled.TestMachine != "" { + details["TesterNO."] = fileHandled.TestMachine + } + if fileHandled.TestProgram != "" { + testProgram = fileHandled.TestProgram + } + if fileHandled.BeginningTime != "" { + details["Beginning Time"] = fileHandled.BeginningTime + } + if fileHandled.EndingTime != "" { + details["Ending Time"] = fileHandled.EndingTime + } + if fileHandled.TitleInfo != "" { + titleInfo = []byte(fileHandled.TitleInfo) + } + global.PostGreSQL.Where("name = ?", fileName).Model(&fileHandled).Updates(map[string]interface{}{ + "product": details["product"], + "step": details["Test_Code"], + "test_machine_model": "TQT601", + "test_machine": details["TesterNO."], + "test_program": testProgram, + "beginning_time": details["Beginning Time"], + "ending_time": details["Ending Time"], + "title_info": string(titleInfo), + "size": utils.FormatFileSize(float64(newFile.Size())), + }) +} diff --git a/repository/changdian.go b/repository/changdian.go new file mode 100644 index 0000000..4e6217a --- /dev/null +++ b/repository/changdian.go @@ -0,0 +1,40 @@ +package repository + +import ( + "log" + "os" + "path" + "strings" + "testData/global" + "testData/model" +) + +// ChangDian 长电 +func ChangDian() { + var fileTexts []*model.FileText + global.PostGreSQL. + Where("factory = ?", "changdian"). + Where("name LIKE ? OR name LIKE ?", "%FT%", "%RT%").Find(&fileTexts) + for _, fileText := range fileTexts { + if path.Ext(fileText.Name) == ".xls" { + continue + } + if strings.Contains(fileText.Name, "FT_MT") || strings.Contains(fileText.Name, "FT_EQC") || + strings.Contains(fileText.Name, "FT_GU") || strings.Contains(fileText.Name, "FT_VT") || + strings.Contains(fileText.Name, "FT_ET") { + continue + } + file, err := os.Open(fileText.Path) + if err != nil { + log.Println(err) + } + var step string + if strings.Contains(fileText.Name, "RT") { + step = "RT" + } else { + step = "FT" + } + HandleSTS8200Excel(fileText, step) + file.Close() + } +} diff --git a/repository/chengte.go b/repository/chengte.go new file mode 100644 index 0000000..85bd251 --- /dev/null +++ b/repository/chengte.go @@ -0,0 +1,25 @@ +package repository + +import ( + "strings" + "testData/global" + "testData/model" +) + +// ChengTe 诚特 +func ChengTe() { + var fileTexts []*model.FileText + global.PostGreSQL.Debug(). + Where("factory = ?", "chengte"). + Where("name LIKE ? AND name NOT LIKE ? AND name NOT LIKE ? AND name NOT LIKE ? AND name NOT LIKE ?", + "%FT%", "%FT_LV%", "%FT_EQC%", "%FT_QC%", "%FT_NT%").Find(&fileTexts) + for _, fileText := range fileTexts { + var step string + if strings.Contains(fileText.Name, "RT") { + step = "RT" + } else { + step = "FT" + } + HandlerTQT601Excel(fileText, step) + } +} diff --git a/repository/csv.go b/repository/csv.go new file mode 100644 index 0000000..e37ec1d --- /dev/null +++ b/repository/csv.go @@ -0,0 +1,38 @@ +package repository + +import ( + "bufio" + "log" + "os" + "strings" +) + +func GetCsvDatas(selections []string) { + //selections := []string{"SITE_NUM", "VREF_BF", "IB_VOR_BF", "SOFT_BIN"} + f, err := os.Open("./SY8821-QLGKRN_CQ774P.1_FT.csv") + if err != nil { + log.Println(err) + } + defer f.Close() + scanner := bufio.NewScanner(f) + m := make(map[string]int) + datas := make([]map[string]string, 0) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + if len(m) == 0 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + m[cell] = index + } + continue + } + data := make(map[string]string) + for _, selection := range selections { + data[selection] = s[m[selection]] + } + datas = append(datas, data) + } +} diff --git a/repository/qipai.go b/repository/qipai.go new file mode 100644 index 0000000..0cfbaa6 --- /dev/null +++ b/repository/qipai.go @@ -0,0 +1,39 @@ +package repository + +import ( + "fmt" + "path" + "strings" + "testData/global" + "testData/model" +) + +// QiPai 气派 +func QiPai() { + var fileTexts []*model.FileText + global.PostGreSQL. + Where("factory = ?", "qipai").Find(&fileTexts) + for _, fileText := range fileTexts { + if strings.ToLower(path.Ext(fileText.Name)) != ".csv" && + strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" { + continue + } + s := strings.Split(fileText.Name, "_") + if len(s) == 9 && strings.Contains(fileText.Name, "P(A)_STS8200_4Site_(1P0)") { + ss := strings.Split(fileText.Name, "P(A)_STS8200_4Site_(1P0)") + sss := strings.Split(ss[0], "_") + fmt.Println(sss) + product := sss[len(sss)-2] + if strings.Index(product, "(") != -1 { + product = product[:strings.Index(product, "(")] + } + lotArray := strings.Split(sss[1], "-") + if len(lotArray) > 4 { + fmt.Println(sss[1]) + } + //fmt.Println("批号:", sss[2]) + fmt.Println("产品型号:", product) + } + //HandleSTS8200Excel(fileText, "") + } +} diff --git a/repository/saimeike.go b/repository/saimeike.go new file mode 100644 index 0000000..9cf04b4 --- /dev/null +++ b/repository/saimeike.go @@ -0,0 +1,45 @@ +package repository + +import ( + "path" + "strings" + "testData/global" + "testData/model" +) + +func SaiMeiKe() { + // 赛美科 + var fileTexts []*model.FileText + global.PostGreSQL. + Where("factory = ?", "saimeike").Find(&fileTexts) + for _, fileText := range fileTexts { + //fileText.Name = strings.ToLower(fileText.Name) + //if path.Ext(fileText.Name) != ".csv" && path.Ext(fileText.Name) != ".xls" && path.Ext(fileText.Name) != ".xlsx" { + // continue + //} + if strings.ToLower(path.Ext(fileText.Name)) != ".csv" && + strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" { + continue + } + var step string + if len(fileText.Name) > 8 { + if fileText.Name[len(fileText.Name)-7:] == "cp1.csv" { + step = "CP1" + } else if fileText.Name[len(fileText.Name)-7:] == "cp2.csv" { + step = "CP2" + } + } + messages := strings.Split(fileText.Name, "_") + if len(messages) >= 3 { + if strings.Contains(messages[2], "r") { + step = "RT" + } else if strings.Contains(messages[2], "t") { + step = "FT" + } + } + if step == "" { + continue + } + HandleSTS8200Excel(fileText, step) + } +} diff --git a/repository/test.data/chart.go b/repository/test.data/chart.go new file mode 100644 index 0000000..3d7e763 --- /dev/null +++ b/repository/test.data/chart.go @@ -0,0 +1,1203 @@ +package test_data + +import ( + "bufio" + "encoding/json" + "errors" + "github.com/shopspring/decimal" + "log" + "math" + "os" + "sort" + "strconv" + "strings" + "testData/global" + "testData/model" + "testData/request" +) + +// QuerySelection 查询可选择的参数 +func QuerySelection(req *request.QuerySelection) map[string][]string { + return LotInMultipleFilesSelection(req.Product, req.Lot, req.PBI) +} + +// Histogram 直方图 +func Histogram(req *request.Histogram) ([]*model.Histogram, error) { + var fTHistogram []*model.Histogram + var x, groups []string + var xMax, xMin string + + //var datas [][]string + //fieldMap := make(map[string]int) + if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + //datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI, req.Step) + groups = append(groups, "") + } else if len(req.SubBatch) != 0 { + groups = req.SubBatch + } else if len(req.WaferID) != 0 { + groups = req.WaferID + } + + for _, group := range groups { + var datas [][]string + fieldMap := make(map[string]int) + if group == "" { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else if len(req.SubBatch) != 0 { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, group, "") + } else if len(req.WaferID) != 0 { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, "", group) + } + + left := req.Average - req.Offset*req.StandardDeviation + right := req.Average + req.Offset*req.StandardDeviation + for _, selection := range req.Selections { + if _, ok := fieldMap[selection]; !ok { + + continue + } + if len(req.Site) == 0 { + var n float64 + var sumSelection float64 = 0 + // 计算最大值、最小值、标准差、均值、数量 + //var standardDeviation float64 + var max, min string + for _, data := range datas { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[selection]]) + if req.XMax != "" && req.XMin != "" { + xMaxDecimal, _ := decimal.NewFromString(req.XMax) + xMinDecimal, _ := decimal.NewFromString(req.XMin) + if !(selectionDecimal.LessThanOrEqual(xMaxDecimal) && xMinDecimal.LessThanOrEqual(selectionDecimal)) { + continue + } + } + + if req.Offset != 0 { + leftDecimal := decimal.NewFromFloat(left) + rightDecimal := decimal.NewFromFloat(right) + if selectionDecimal.LessThan(leftDecimal) || rightDecimal.LessThan(selectionDecimal) { + continue + } + } + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if binInclude { + if data[fieldMap[selection]] != "" { + selectionData, _ := strconv.ParseFloat(data[fieldMap[selection]], 64) + sumSelection += selectionData + n++ + //difference := sumSelection/n - selectionData + //standardDeviation += math.Pow(difference, 2) + if max == "" { + max = data[fieldMap[selection]] + } else { + maxDecimal, _ := strconv.ParseFloat(max, 64) + if maxDecimal < selectionData { + max = data[fieldMap[selection]] + } + } + if min == "" { + min = data[fieldMap[selection]] + } else { + minDecimal, _ := strconv.ParseFloat(min, 64) + if selectionData < minDecimal { + min = data[fieldMap[selection]] + } + } + if xMax == "" { + xMax = data[fieldMap[selection]] + } else { + maxDecimal, _ := strconv.ParseFloat(xMax, 64) + if maxDecimal < selectionData { + xMax = data[fieldMap[selection]] + } + } + if xMin == "" { + xMin = data[fieldMap[selection]] + } else { + minDecimal, _ := strconv.ParseFloat(xMin, 64) + if selectionData < minDecimal { + xMin = data[fieldMap[selection]] + } + } + } + } + } + averageFloat64 := sumSelection / n + //standardDeviation = math.Sqrt(standardDeviation / n) + var filed string + if group == "" { + filed = selection + } else { + filed = selection + "-" + group + } + fTHistogram = append(fTHistogram, &model.Histogram{ + Field: filed, + Average: averageFloat64, + //StandardDeviation: standardDeviation, + Max: max, + Min: min, + N: n, + }) + } else { + for _, site := range req.Site { + var n float64 + var sumSelection float64 = 0 + // 计算最大值、最小值、标准差、均值、数量 + //var standardDeviation float64 + var max, min string + for _, data := range datas { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[selection]]) + if req.XMax != "" && req.XMin != "" { + xMaxDecimal, _ := decimal.NewFromString(req.XMax) + xMinDecimal, _ := decimal.NewFromString(req.XMin) + if !(selectionDecimal.LessThanOrEqual(xMaxDecimal) && xMinDecimal.LessThanOrEqual(selectionDecimal)) { + continue + } + } + + if req.Offset != 0 { + leftDecimal := decimal.NewFromFloat(left) + rightDecimal := decimal.NewFromFloat(right) + if selectionDecimal.LessThan(leftDecimal) || rightDecimal.LessThan(rightDecimal) { + continue + } + } + // 筛选Site + var siteInclude bool + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + } + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if siteInclude && binInclude { + if data[fieldMap[selection]] != "" { + selectionData, _ := strconv.ParseFloat(data[fieldMap[selection]], 64) + sumSelection += selectionData + n++ + //difference := sumSelection/n - selectionData + //standardDeviation += math.Pow(difference, 2) + if max == "" { + max = data[fieldMap[selection]] + } else { + maxDecimal, _ := strconv.ParseFloat(max, 64) + if maxDecimal < selectionData { + max = data[fieldMap[selection]] + } + } + if min == "" { + min = data[fieldMap[selection]] + } else { + minDecimal, _ := strconv.ParseFloat(min, 64) + if selectionData < minDecimal { + min = data[fieldMap[selection]] + } + } + if xMax == "" { + xMax = data[fieldMap[selection]] + } else { + maxDecimal, _ := strconv.ParseFloat(xMax, 64) + if maxDecimal < selectionData { + xMax = data[fieldMap[selection]] + } + } + if xMin == "" { + xMin = data[fieldMap[selection]] + } else { + minDecimal, _ := strconv.ParseFloat(xMin, 64) + if selectionData < minDecimal { + xMin = data[fieldMap[selection]] + } + } + } + } + } + + averageFloat64 := sumSelection / n + //standardDeviation = math.Sqrt(standardDeviation / n) + var filed string + if group == "" { + filed = selection + "-Site" + site + } else { + filed = selection + "-" + group + "-Site" + site + } + fTHistogram = append(fTHistogram, &model.Histogram{ + Field: filed, + Average: averageFloat64, + //StandardDeviation: standardDeviation, + Max: max, + Min: min, + N: n, + }) + } + } + } + } + + // 生成X坐标 + if req.XMax != "" { + xMax = req.XMax + } + if req.XMin != "" { + xMin = req.XMin + } + //minDecimal, _ := strconv.ParseFloat(xMin, 64) + //maxDecimal, _ := strconv.ParseFloat(xMax, 64) + //interval := (maxDecimal - minDecimal) / 50 + //for i := 0; i < 51; i++ { + // xPoint := strconv.FormatFloat(minDecimal+interval*float64(i), 'f', 6, 64) + // x = append(x, xPoint) + //} + + minDecimal, _ := decimal.NewFromString(xMin) + if minDecimal.LessThan(decimal.NewFromInt(0)) { + minDecimal = minDecimal.RoundUp(0) + } else { + minDecimal = minDecimal.RoundDown(0) + } + maxDecimal, _ := decimal.NewFromString(xMax) + if maxDecimal.LessThan(decimal.NewFromInt(0)) { + maxDecimal = maxDecimal.RoundDown(0) + } else { + maxDecimal = maxDecimal.RoundUp(0) + } + interval := maxDecimal.Sub(minDecimal).Div(decimal.NewFromInt(50)) + for i := 0; i < 51; i++ { + xPoint := minDecimal.Add(interval.Mul(decimal.NewFromInt(int64(i)))).String() + x = append(x, xPoint) + } + + for _, group := range groups { + var datas [][]string + fieldMap := make(map[string]int) + if group == "" { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else if len(req.SubBatch) != 0 { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, group, "") + } else if len(req.WaferID) != 0 { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, "", group) + } + + for _, selection := range req.Selections { + if _, ok := fieldMap[selection]; !ok { + continue + } + if len(req.Site) == 0 { + var filed string + if group == "" { + filed = selection + } else { + filed = selection + "-" + group + } + var standardDeviation, average float64 + var index int + for k, v := range fTHistogram { + if v.Field == filed { + average = v.Average + index = k + break + } + } + var y []string + counter := make(map[float64]int) + // 计算最大值、最小值、标准差、均值、数量 + for _, data := range datas { + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if binInclude { + if data[fieldMap[selection]] != "" { + selectionData, _ := strconv.ParseFloat(data[fieldMap[selection]], 64) + standardDeviation += math.Pow(average-selectionData, 2) + counter[selectionData]++ + } + } + } + fTHistogram[index].StandardDeviation = math.Sqrt(standardDeviation / fTHistogram[index].N) + + for i := 0; i < len(x); i++ { + if i == len(x)-1 { + xFloat, _ := strconv.ParseFloat(x[i], 64) + if yValue, ok := counter[xFloat]; ok { + y = append(y, strconv.Itoa(yValue)) + } else { + y = append(y, "0") + } + break + } + xPointMin, _ := decimal.NewFromString(x[i]) + xPointMax, _ := decimal.NewFromString(x[i+1]) + + var yCounter float64 = 0 + for k, v := range counter { + if xPointMin.LessThanOrEqual(decimal.NewFromFloat(k)) && decimal.NewFromFloat(k).LessThan(xPointMax) { + yCounter += float64(v) + } + } + yPoint := strconv.FormatFloat(yCounter, 'f', 0, 64) + y = append(y, yPoint) + } + + fTHistogram[index].X = x + fTHistogram[index].Y = y + } else { + for _, site := range req.Site { + var filed string + if group == "" { + filed = selection + "-Site" + site + } else { + filed = selection + "-" + group + "-Site" + site + } + var standardDeviation, average float64 + var index int + for k, v := range fTHistogram { + if v.Field == filed { + average = v.Average + index = k + break + } + } + var y []string + counter := make(map[float64]int) + for _, data := range datas { + // 筛选Site + var siteInclude bool + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + } + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if siteInclude && binInclude { + if data[fieldMap[selection]] != "" { + selectionData, _ := strconv.ParseFloat(data[fieldMap[selection]], 64) + standardDeviation += math.Pow(average-selectionData, 2) + counter[selectionData]++ + } + } + } + fTHistogram[index].StandardDeviation = math.Sqrt(standardDeviation / fTHistogram[index].N) + for i := 0; i < len(x); i++ { + if i == len(x)-1 { + xFloat, _ := strconv.ParseFloat(x[i], 64) + if yValue, ok := counter[xFloat]; ok { + y = append(y, strconv.Itoa(yValue)) + } else { + y = append(y, "0") + } + break + } + xPointMin, _ := strconv.ParseFloat(x[i], 64) + xPointMax, _ := strconv.ParseFloat(x[i+1], 64) + var yCounter float64 = 0 + for k, v := range counter { + if xPointMin <= k && k < xPointMax { + yCounter += float64(v) + } + } + yPoint := strconv.FormatFloat(yCounter, 'f', 0, 64) + y = append(y, yPoint) + } + + fTHistogram[index].X = x + fTHistogram[index].Y = y + } + } + } + } + return fTHistogram, nil +} + +// Scatter 散点图 +func Scatter(req *request.Scatter) ([]*model.Scatter, model.ScatterLimit, model.ScatterLimit, error) { + var groups []string + + if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + groups = append(groups, "") + } else if len(req.SubBatch) != 0 { + groups = req.SubBatch + } else if len(req.WaferID) != 0 { + groups = req.WaferID + } + // 判断子批次还是大批次查询数据 + var datas [][]string + fieldMap := make(map[string]int) + if len(req.SubBatch) == 0 { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + for _, group := range groups { + if len(req.SubBatch) != 0 { + groupDatas, groupFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, group, "") + datas = append(datas, groupDatas...) + fieldMap = groupFieldMap + } else { + groupDatas, groupFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, "", group) + datas = append(datas, groupDatas...) + fieldMap = groupFieldMap + } + } + } + + var scatters []*model.Scatter + var xScatterLimit, yScatterLimit model.ScatterLimit + if len(req.Site) == 0 { + scatterFieldMap := make(map[string]int) + counter := make(map[string]map[string]int) + for _, data := range datas { + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if binInclude { + for _, xySelection := range req.XYSelection { + if data[fieldMap[xySelection.X]] == "" || data[fieldMap[xySelection.Y]] == "" { + continue + } + if _, ok := counter[xySelection.X+","+xySelection.Y]; !ok { + counter[xySelection.X+","+xySelection.Y] = map[string]int{} + } + // 过滤重复点 + needAppend := true + coordinate := data[fieldMap[xySelection.X]] + "," + data[fieldMap[xySelection.Y]] + if _, ok := counter[xySelection.X+","+xySelection.Y][coordinate]; ok { + needAppend = false + } + if needAppend { + counter[xySelection.X+","+xySelection.Y][coordinate]++ + if _, ok := scatterFieldMap[xySelection.X+","+xySelection.Y]; !ok { + scatter := &model.Scatter{ + Field: xySelection.X + "," + xySelection.Y + " All Site", Datas: [][]string{}} + scatterFieldMap[xySelection.X+","+xySelection.Y] = len(scatters) + scatters = append(scatters, scatter) + } + scatters[scatterFieldMap[xySelection.X+","+xySelection.Y]].Datas = append( + scatters[scatterFieldMap[xySelection.X+","+xySelection.Y]].Datas, + []string{data[fieldMap[xySelection.X]], data[fieldMap[xySelection.Y]]}) + if xScatterLimit.Min == "" { + xScatterLimit.Min = data[fieldMap[xySelection.X]] + } else { + xScatterLimitFloat, _ := strconv.ParseFloat(xScatterLimit.Min, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.X]], 8) + if xScatterLimitFloat > dataFloat { + xScatterLimit.Min = data[fieldMap[xySelection.X]] + } + } + if xScatterLimit.Max == "" { + xScatterLimit.Max = data[fieldMap[xySelection.X]] + } else { + xScatterLimitFloat, _ := strconv.ParseFloat(xScatterLimit.Max, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.X]], 8) + if xScatterLimitFloat < dataFloat { + xScatterLimit.Max = data[fieldMap[xySelection.X]] + } + } + if yScatterLimit.Min == "" { + yScatterLimit.Min = data[fieldMap[xySelection.Y]] + } else { + yScatterLimitFloat, _ := strconv.ParseFloat(yScatterLimit.Min, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.Y]], 8) + if yScatterLimitFloat > dataFloat { + yScatterLimit.Min = data[fieldMap[xySelection.Y]] + } + } + if yScatterLimit.Max == "" { + yScatterLimit.Max = data[fieldMap[xySelection.Y]] + } else { + yScatterLimitFloat, _ := strconv.ParseFloat(yScatterLimit.Max, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.Y]], 8) + if yScatterLimitFloat < dataFloat { + yScatterLimit.Max = data[fieldMap[xySelection.Y]] + } + } + } + } + } + } + } else { + scatterFieldMap := make(map[string]int) + for _, site := range req.Site { + counter := make(map[string]map[string]int) + for _, data := range datas { + // 筛选Site + if data[fieldMap["SITE_NUM"]] != site { + continue + } + // 筛选SBin + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if binInclude { + for _, xySelection := range req.XYSelection { + if data[fieldMap[xySelection.X]] == "" || data[fieldMap[xySelection.Y]] == "" { + continue + } + if _, ok := counter[xySelection.X+","+xySelection.Y]; !ok { + counter[xySelection.X+","+xySelection.Y] = map[string]int{} + } + // 过滤重复点 + needAppend := true + coordinate := data[fieldMap[xySelection.X]] + "," + data[fieldMap[xySelection.Y]] + if _, ok := counter[xySelection.X+","+xySelection.Y][coordinate]; ok { + needAppend = false + } + if needAppend { + counter[xySelection.X+","+xySelection.Y][coordinate]++ + if _, ok := scatterFieldMap[xySelection.X+","+xySelection.Y]; !ok { + scatter := &model.Scatter{ + Field: xySelection.X + "," + xySelection.Y + "-Site" + site, Datas: [][]string{}} + scatterFieldMap[xySelection.X+","+xySelection.Y] = len(scatters) + scatters = append(scatters, scatter) + } + scatters[scatterFieldMap[xySelection.X+","+xySelection.Y]].Datas = append( + scatters[scatterFieldMap[xySelection.X+","+xySelection.Y]].Datas, + []string{data[fieldMap[xySelection.X]], data[fieldMap[xySelection.Y]]}) + if xScatterLimit.Min == "" { + xScatterLimit.Min = data[fieldMap[xySelection.X]] + } else { + xScatterLimitFloat, _ := strconv.ParseFloat(xScatterLimit.Min, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.X]], 8) + if xScatterLimitFloat > dataFloat { + xScatterLimit.Min = data[fieldMap[xySelection.X]] + } + } + if xScatterLimit.Max == "" { + xScatterLimit.Max = data[fieldMap[xySelection.X]] + } else { + xScatterLimitFloat, _ := strconv.ParseFloat(xScatterLimit.Max, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.X]], 8) + if xScatterLimitFloat < dataFloat { + xScatterLimit.Max = data[fieldMap[xySelection.X]] + } + } + if yScatterLimit.Min == "" { + yScatterLimit.Min = data[fieldMap[xySelection.Y]] + } else { + yScatterLimitFloat, _ := strconv.ParseFloat(yScatterLimit.Min, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.Y]], 8) + if yScatterLimitFloat > dataFloat { + yScatterLimit.Min = data[fieldMap[xySelection.Y]] + } + } + if yScatterLimit.Max == "" { + yScatterLimit.Max = data[fieldMap[xySelection.Y]] + } else { + yScatterLimitFloat, _ := strconv.ParseFloat(yScatterLimit.Max, 8) + dataFloat, _ := strconv.ParseFloat(data[fieldMap[xySelection.Y]], 8) + if yScatterLimitFloat < dataFloat { + yScatterLimit.Max = data[fieldMap[xySelection.Y]] + } + } + } + } + } + } + } + } + return scatters, xScatterLimit, yScatterLimit, nil +} + +func Pie(req *request.Pie) ([]*model.Pie, error) { + var pie []*model.Pie + var datas [][]string + fieldMap := make(map[string]int) + if req.SubBatch == "" { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, req.SubBatch, req.Step) + } + if _, ok := fieldMap[req.Selection]; !ok { + return nil, errors.New("不存在该参数") + } + m := make(map[string]int) + if req.Min == "" { + req.Min = "0" + } + if req.Max == "" { + req.Max = "0" + } + minDecimal, _ := decimal.NewFromString(req.Min) + maxDecimal, _ := decimal.NewFromString(req.Max) + for _, data := range datas { + var siteInclude bool + if len(req.Site) == 0 { + siteInclude = true + } else { + for _, site := range req.Site { + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + break + } + } + } + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if siteInclude && binInclude { + if data[fieldMap[req.Selection]] == "" { + data[fieldMap[req.Selection]] = "0" + } + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[req.Selection]]) + if minDecimal.LessThanOrEqual(selectionDecimal) && selectionDecimal.LessThanOrEqual(maxDecimal) { + var isValid bool + for _, interval := range req.PieInterval { + if interval.Min == "" { + interval.Min = "0" + } + if interval.Max == "" { + interval.Max = "0" + } + minIntervalDecimal, _ := decimal.NewFromString(interval.Min) + maxIntervalDecimal, _ := decimal.NewFromString(interval.Max) + if minIntervalDecimal.LessThanOrEqual(selectionDecimal) && selectionDecimal.LessThan(maxIntervalDecimal) { + m[interval.Name]++ + isValid = true + break + } + } + if !isValid { + m["else"]++ + } + } + } + } + for k, v := range m { + pie = append(pie, &model.Pie{ + Name: k, + Value: v, + }) + } + return pie, nil +} + +func Line(req *request.Line) (*model.Line, error) { + var datas [][]string + fieldMap := make(map[string]int) + if req.SubBatch == "" { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, req.SubBatch, req.Step) + } + var x, y []string + for index, data := range datas { + var siteInclude bool + if len(req.Site) == 0 { + siteInclude = true + } else { + for _, site := range req.Site { + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + break + } + } + } + var binInclude bool + if len(req.Bin) == 0 { + binInclude = true + } else { + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + binInclude = true + break + } + } + } + if siteInclude && binInclude { + x = append(x, strconv.Itoa(index)) + y = append(y, data[fieldMap[req.Selection]]) + } + } + lineChart := &model.Line{ + X: x, + Y: y, + } + return lineChart, nil +} + +// CPMap CP晶圆图 +func CPMap(req *request.CPMap) (map[string]interface{}, error) { + // 需要显示的参数 + selections := []string{"SITE_NUM", "SOFT_BIN", "HARD_BIN"} + if len(req.Selection) > 0 { + selections = append(selections, req.Selection[0]) + } + + // CP测试没有子批次 + var fileHandle *model.FileHandled + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", + req.PBI, req.Product, req.Lot, req.WaferID). + Find(&fileHandle) + + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + return nil, err + } + defer f.Close() + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + + sbinHbinMap := make(map[string]map[string]string) + res := make(map[string]interface{}) + resDatas := make([]map[string]interface{}, 0) + selectDatas := make(map[string]interface{}) + // 颜色、标题、数据数组初始化 + color := []string{"#4FFF00", "#FF0000", "#1B81FF", "#FF0000", "#E12AE8"} + datasTitle := []string{"第一次测试Pass", "第一次测试Fail", "复测Pass", "复测Fail", "复测Fail变动"} + selectDatas["第一次测试Pass"] = [][]string{} + selectDatas["第一次测试Fail"] = [][]string{} + selectDatas["复测Pass"] = [][]string{} + selectDatas["复测Fail"] = [][]string{} + selectDatas["复测Fail变动"] = [][]string{} + for _, sBinColor := range req.SBinColor { + color = append(color, sBinColor.Color) + datasTitle = append(datasTitle, sBinColor.Name) + selectDatas[sBinColor.Name] = [][]string{} + } + for _, hBinColor := range req.HBinColor { + color = append(color, hBinColor.Color) + datasTitle = append(datasTitle, hBinColor.Name) + selectDatas[hBinColor.Name] = [][]string{} + } + for _, selectionColor := range req.SelectionColor { + color = append(color, selectionColor.Color) + datasTitle = append(datasTitle, selectionColor.Name+":"+selectionColor.Min+"~"+selectionColor.Max) + selectDatas[selectionColor.Name+":"+selectionColor.Min+"~"+selectionColor.Max] = [][]string{} + } + + sbinHbinByte := []byte(fileHandle.SbinHbin) + _ = json.Unmarshal(sbinHbinByte, &sbinHbinMap) + + passArray := selectDatas["复测Pass"].([][]string) + failArray := selectDatas["复测Fail"].([][]string) + failChangeArray := selectDatas["复测Fail变动"].([][]string) + lastPassArray := selectDatas["第一次测试Pass"].([][]string) + lastFailArray := selectDatas["第一次测试Fail"].([][]string) + var total, pass float64 + binMap := make(map[string]int) + sbinColorMap := make(map[string]int) + hbinColorMap := make(map[string]int) + selectionColorMap := make(map[string]int) + for _, data := range datas { + binInfoMap := sbinHbinMap[data[fieldMap["SOFT_BIN"]]] + // 筛选Site + var siteInclude bool + if len(req.Site) == 0 { + siteInclude = true + } else { + for _, site := range req.Site { + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + break + } + } + } + if !siteInclude { + continue + } + // 筛选Soft Bin + var sBinInclude bool + if len(req.SBin) == 0 { + sBinInclude = true + } else { + for _, bin := range req.SBin { + if data[fieldMap["SOFT_BIN"]] == bin { + sBinInclude = true + break + } + } + + } + if !sBinInclude { + continue + } + // 筛选Hard Bin + var hBinInclude bool + if len(req.HBin) == 0 { + hBinInclude = true + } else { + for _, bin := range req.HBin { + if binInfoMap["HBin"] == bin { + hBinInclude = true + break + } + } + + } + if !hBinInclude { + continue + } + + // 将HBin写入单行信息内 + //data = append(data, binInfoMap["HBin"]) + x := data[fieldMap["X_COORD"]] + y := data[fieldMap["Y_COORD"]] + data[fieldMap["PASSFG"]] = strings.ToLower(data[fieldMap["PASSFG"]]) + // 判断测试点是否通过测试 + var isPass bool + if data[fieldMap["PASSFG"]] == "true" { + isPass = true + } + + // 需要显示的参数 + var field []string + for _, selection := range selections { + var dataValue string + if selection == "HARD_BIN" { + dataValue = binInfoMap["HBin"] + field = append(field, []string{selection, dataValue}...) + continue + } + if _, ok := fieldMap[selection]; !ok { + dataValue = "0" + } else { + dataValue = data[fieldMap[selection]] + } + field = append(field, []string{selection, dataValue}...) + } + + // 区分通过、不通过、第一次测试数据 + var isSamePoint bool + var isFinal bool + for _, lastPoint := range lastFailArray { + if lastPoint[0] == x && lastPoint[1] == y { + if isPass { + passArray = append(passArray, append([]string{x, y}, field...)) + } else { + var isChangeFail bool + for lastPointFieldIndex := 2; lastPointFieldIndex < len(lastPoint); lastPointFieldIndex++ { + if lastPoint[lastPointFieldIndex] == "SOFT_BIN" { + for pointFieldIndex := 2; pointFieldIndex < len(field); pointFieldIndex++ { + if field[pointFieldIndex] == "SOFT_BIN" && lastPoint[lastPointFieldIndex+1] != field[pointFieldIndex+1] { + isChangeFail = true + } + } + } + } + if isChangeFail { + failArray = append(failArray, append([]string{x, y}, field...)) + failChangeArray = append(failChangeArray, append([]string{x, y}, field...)) + } else { + failArray = append(failArray, append([]string{x, y}, field...)) + } + } + isFinal = true + isSamePoint = true + break + } + } + if !isSamePoint { + if isPass { + lastPassArray = append(lastPassArray, append([]string{x, y}, field...)) + isFinal = true + } else { + lastFailArray = append(lastFailArray, append([]string{x, y}, field...)) + } + } + + if isFinal { + total++ + if isPass { + pass++ + } + binMap[data[fieldMap["SOFT_BIN"]]]++ + sbinColorMap[data[fieldMap["SOFT_BIN"]]]++ + hbinColorMap[binInfoMap["HBin"]]++ + // 根据SOFT_BIN区分颜色 + for _, sBinColor := range req.SBinColor { + array := selectDatas[sBinColor.Name].([][]string) + var isReplace bool + for _, point := range array { + if point[0] == x && point[1] == y { + point = append([]string{x, y}, field...) + isReplace = true + break + } + } + if !isReplace && data[fieldMap["SOFT_BIN"]] == sBinColor.Name { + array = append(array, append([]string{x, y}, field...)) + selectDatas[sBinColor.Name] = array + break + } + } + + // 根据HARD_BIN区分颜色 + for _, hBinColor := range req.HBinColor { + array := selectDatas[hBinColor.Name].([][]string) + var isReplace bool + for _, point := range array { + if point[0] == x && point[1] == y { + point = append([]string{x, y}, field...) + isReplace = true + break + } + } + if !isReplace && binInfoMap["HBin"] == hBinColor.Name { + array = append(array, append([]string{x, y}, field...)) + selectDatas[hBinColor.Name] = array + break + } + } + + // 根据参数范围区分颜色 + for _, selectionColor := range req.SelectionColor { + if data[fieldMap[selectionColor.Name]] == "" { + break + } + selection, _ := decimal.NewFromString(data[fieldMap[selectionColor.Name]]) + max, _ := decimal.NewFromString(selectionColor.Max) + min, _ := decimal.NewFromString(selectionColor.Min) + if selection.LessThanOrEqual(max) && min.LessThanOrEqual(selection) { + s := selectionColor.Name + ":" + selectionColor.Min + "~" + selectionColor.Max + selectionColorMap[s]++ + array := selectDatas[s].([][]string) + var isReplace bool + for _, point := range array { + if point[0] == x && point[1] == y { + point = append([]string{x, y}, field...) + isReplace = true + selectDatas[s] = array + break + } + } + if !isReplace { + array = append(array, append([]string{x, y}, field...)) + selectDatas[s] = array + break + } + } + //selection, _ := strconv.ParseFloat(data[fieldMap[selectionColor.Name]], 8) + //max, _ := strconv.ParseFloat(selectionColor.Max, 8) + //min, _ := strconv.ParseFloat(selectionColor.Min, 8) + //if selection <= max && min <= selection { + // selectionColorMap[selectionColor.Name]++ + // s := selectionColor.Name + ":" + selectionColor.Min + "~" + selectionColor.Max + // array := selectDatas[s].([][]string) + // var isReplace bool + // for _, point := range array { + // if point[0] == x && point[1] == y { + // point = append([]string{x, y}, field...) + // isReplace = true + // selectDatas[s] = array + // break + // } + // } + // if !isReplace { + // array = append(array, append([]string{x, y}, field...)) + // selectDatas[s] = array + // break + // } + //} + } + } + } + + selectDatas["复测Pass"] = passArray + selectDatas["复测Fail"] = failArray + selectDatas["复测Fail变动"] = failChangeArray + + selectDatas["第一次测试Pass"] = lastPassArray + selectDatas["第一次测试Fail"] = lastFailArray + + // 将根据标题顺序存入数组 + for _, v := range datasTitle { + resDatas = append(resDatas, map[string]interface{}{ + "name": v, + "data": selectDatas[v], + }) + } + res["color"] = color + res["datas_title"] = datasTitle + res["datas"] = resDatas + + totalDecimal := decimal.NewFromFloat(total) + passDecimal := decimal.NewFromFloat(pass) + res["Total"] = totalDecimal.String() + if !totalDecimal.IsZero() { + res["PassProbability"] = passDecimal.Div(totalDecimal).Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + } + var binArray []string + for bin := range binMap { + binArray = append(binArray, bin) + } + sort.Slice(binArray, func(i, j int) bool { + return binMap[binArray[i]] > binMap[binArray[j]] + }) + var binProbability [][]string + for _, bin := range binArray { + binDecimal := decimal.NewFromInt(int64(binMap[bin])) + probability := "0%" + if !totalDecimal.IsZero() { + probability = binDecimal.Div(totalDecimal).Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + } + binProbability = append(binProbability, []string{"BIN " + bin, probability, strconv.Itoa(binMap[bin])}) + } + res["Bin情况"] = binProbability + res["Sbin数量"] = sbinColorMap + res["Hbin数量"] = hbinColorMap + res["参数数量"] = selectionColorMap + + return res, nil +} + +func LogSiteChart(req *request.LogSiteChart) *model.Histogram { + //var fileHandle *model.FileHandled + //global.PostGreSQL.Where("product = ? AND sub_batch = ?", req.Product, req.SubBatch).Find(&fileHandle) + var datas [][]string + fieldMap := make(map[string]int) + if req.SubBatch == "" { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, req.SubBatch, req.Step) + } + var x []string + for _, v := range req.Site { + x = append(x, "Site"+v) + } + var y []string + if req.ContentType == "数量" { + counter := make(map[string]int) + for _, data := range datas { + counter[data[fieldMap["SITE_NUM"]]]++ + } + for _, v := range req.Site { + y = append(y, strconv.Itoa(counter[v])) + } + //y = append(y, strconv.Itoa(counter["Site1"]), strconv.Itoa(counter["Site2"]), strconv.Itoa(counter["Site3"]), strconv.Itoa(counter["Site4"])) + } else if req.ContentType == "良率" { + counter := make(map[string]int) + passCounter := make(map[string]int) + for _, data := range datas { + counter[data[fieldMap["SITE_NUM"]]]++ + if data[fieldMap["PASSFG"]] == "True" { + passCounter[data[fieldMap["SITE_NUM"]]]++ + } + } + for _, v := range x { + counterDecimal := decimal.NewFromInt(int64(counter[v])) + passCounterDecimal := decimal.NewFromInt(int64(passCounter[v])) + s := passCounterDecimal.Div(counterDecimal).Round(4).Mul(decimal.NewFromInt(10000)).String() + if s == "0" { + y = append(y, "0%") + continue + } + s = s[:2] + "." + s[2:] + "%" + y = append(y, s) + } + } else if req.ContentType == "参数均值" { + counter := make(map[string]int) + sum := make(map[string]string) + for _, data := range datas { + if len(req.Bin) != 0 { + var isContain bool + for _, bin := range req.Bin { + if data[fieldMap["SOFT_BIN"]] == bin { + isContain = true + break + } + } + if !isContain { + continue + } + } + counter[data[fieldMap["SITE_NUM"]]]++ + if data[fieldMap[req.Selection]] == "" { + data[fieldMap[req.Selection]] = "0" + } + if sum[data[fieldMap["SITE_NUM"]]] == "" { + sum[data[fieldMap["SITE_NUM"]]] = "0" + } + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[req.Selection]]) + sumDecimal, _ := decimal.NewFromString(sum[data[fieldMap["SITE_NUM"]]]) + sum[data[fieldMap["SITE_NUM"]]] = sumDecimal.Add(selectionDecimal).String() + } + for _, v := range req.Site { + counterDecimal := decimal.NewFromInt(int64(counter[v])) + passCounterDecimal, _ := decimal.NewFromString(sum[v]) + s := passCounterDecimal.Div(counterDecimal).Round(4).String() + y = append(y, s) + } + } + return &model.Histogram{ + X: x, + Y: y, + } +} diff --git a/repository/test.data/excel.go b/repository/test.data/excel.go new file mode 100644 index 0000000..56a2611 --- /dev/null +++ b/repository/test.data/excel.go @@ -0,0 +1,368 @@ +package test_data + +import ( + "bufio" + "encoding/json" + "log" + "math" + "os" + "strconv" + "strings" + "testData/global" + "testData/model" + "testData/request" +) + +func LotInAFileSelection(product, lot, pbi, subBatch, step string) ([]string, []string, []string, []string) { + var fileHandle *model.FileHandled + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step = ?", + product, lot, pbi, subBatch, step).Find(&fileHandle) + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + defer f.Close() + scanner := bufio.NewScanner(f) + var selection []string + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + if step == "CP" { + selection = s[8 : len(s)-1] + } else { + selection = s[6 : len(s)-1] + } + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + binMap := make(map[string]interface{}) + hBinMap := make(map[string]int) + siteMap := make(map[string]int) + for _, data := range datas { + siteMap[data[fieldMap["SITE_NUM"]]] = 1 + } + var sBin, hBin, site []string + _ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap) + for k, v := range binMap { + sBin = append(sBin, k) + sBinInfoMap := v.(map[string]interface{}) + hBinMap[sBinInfoMap["HBin"].(string)] = 1 + } + for k := range siteMap { + site = append(site, k) + } + for k := range hBinMap { + hBin = append(hBin, k) + } + return selection, sBin, hBin, site +} + +func LotInAFile(product, lot, pbi, subBatch, waferID string) ([][]string, map[string]int) { + var fileHandle *model.FileHandled + if subBatch != "" { + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step != ?", + product, lot, pbi, subBatch, "RT").Find(&fileHandle) + } else if waferID != "" { + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND wafer_id = ?", + product, lot, pbi, waferID).Find(&fileHandle) + } else { + return nil, nil + } + + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + defer f.Close() + xyMap := make(map[string]int) + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + if strings.Contains(fileHandle.Step, "CP") { + x := s[fieldMap["X_COORD"]] + y := s[fieldMap["Y_COORD"]] + if _, ok := xyMap[x+","+y]; !ok { + xyMap[x+","+y] = len(datas) + datas = append(datas, s[:len(s)-1]) + } else { + datas[xyMap[x+","+y]] = s[:len(s)-1] + } + } else { + datas = append(datas, s[:len(s)-1]) + } + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + return datas, fieldMap +} + +func LotInMultipleFilesSelection(product, lot, pbi string) map[string][]string { + var fileHandles []*model.FileHandled + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ?", product, lot, pbi).Find(&fileHandles) + + datas := make([][]string, 0) + fieldMap := make(map[string]int) + binMap := make(map[string]interface{}) + subBatchMap := make(map[string]int) + waferIDMap := make(map[string]int) + var selection []string + var subBatch, waferID []string + for _, fileHandle := range fileHandles { + if strings.Contains(fileHandle.Step, "CP") { + waferIDMap[fileHandle.WaferID] = 1 + } else { + subBatchMap[fileHandle.SubBatch] = 1 + } + + singleDatas := make([][]string, 0) + _ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap) + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + scanner := bufio.NewScanner(f) + xyMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + if strings.Contains(fileHandle.Step, "CP") { + x := s[fieldMap["X_COORD"]] + y := s[fieldMap["Y_COORD"]] + if _, ok := xyMap[x+","+y]; !ok { + xyMap[x+","+y] = len(singleDatas) + singleDatas = append(singleDatas, s[:len(s)-1]) + } + } else { + singleDatas = append(singleDatas, s[:len(s)-1]) + } + if len(singleDatas) == 1 { + if strings.Contains(fileHandle.Step, "CP") { + selection = s[8 : len(s)-1] + } else { + selection = s[6 : len(s)-1] + } + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(singleDatas) >= 1 { + singleDatas = singleDatas[1:] + } + datas = append(datas, singleDatas...) + f.Close() + } + + sBinMap := make(map[string]int) + siteMap := make(map[string]int) + for _, data := range datas { + sBinMap[data[fieldMap["SOFT_BIN"]]] = 1 + siteMap[data[fieldMap["SITE_NUM"]]] = 1 + } + hBinMap := make(map[string]int) + var sBin, hBin, site []string + for k := range sBinMap { + if _, ok := binMap[k]; ok { + sBin = append(sBin, k) + sBinInfoMap := binMap[k].(map[string]interface{}) + hBinMap[sBinInfoMap["HBin"].(string)] = 1 + } + } + for k := range siteMap { + site = append(site, k) + } + for k := range hBinMap { + hBin = append(hBin, k) + } + for k := range subBatchMap { + subBatch = append(subBatch, k) + } + for k := range waferIDMap { + waferID = append(waferID, k) + } + res := make(map[string][]string) + res["selection"] = selection + res["sbin"] = sBin + res["hbin"] = hBin + res["site"] = site + res["subBatch"] = subBatch + res["waferID"] = waferID + return res +} + +func LotInMultipleFiles(product, lot, pbi string) ([][]string, map[string]int) { + var fileHandles []*model.FileHandled + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND step != ?", product, lot, pbi, "RT").Find(&fileHandles) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for _, fileHandle := range fileHandles { + fileDatas := make([][]string, 0) + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + xyMap := make(map[string]int) + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + if strings.Contains(fileHandle.Step, "CP") { + x := s[fieldMap["X_COORD"]] + y := s[fieldMap["Y_COORD"]] + if _, ok := xyMap[x+","+y]; !ok { + xyMap[x+","+y] = len(fileDatas) + fileDatas = append(fileDatas, s[:len(s)-1]) + } else { + fileDatas[xyMap[x+","+y]] = s[:len(s)-1] + } + } else { + fileDatas = append(fileDatas, s[:len(s)-1]) + } + if len(datas) == 0 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + f.Close() + if len(fileDatas) >= 1 { + fileDatas = fileDatas[1:] + } + datas = append(datas, fileDatas...) + } + return datas, fieldMap +} + +func SelectionLimit(req *request.SelectionLimit) (string, string) { + // CP测试没有子批次 + var fileHandle *model.FileHandled + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", req.PBI, req.Product, req.Lot, req.WaferID). + Find(&fileHandle) + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + return "", "" + } + defer f.Close() + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + maxStr := strconv.Itoa(math.MinInt) + minStr := strconv.Itoa(math.MaxInt) + sbinHbinMap := make(map[string]map[string]string) + selectionData := make(map[string]int) + sbinHbinByte := []byte(fileHandle.SbinHbin) + _ = json.Unmarshal(sbinHbinByte, &sbinHbinMap) + for _, data := range datas { + binInfoMap := sbinHbinMap[data[fieldMap["SOFT_BIN"]]] + // 筛选Site + var siteInclude bool + if len(req.Site) == 0 { + siteInclude = true + } else { + for _, site := range req.Site { + if data[fieldMap["SITE_NUM"]] == site { + siteInclude = true + break + } + } + } + if !siteInclude { + continue + } + // 筛选Soft Bin + var sBinInclude bool + if len(req.SBin) == 0 { + sBinInclude = true + } else { + for _, bin := range req.SBin { + if data[fieldMap["SOFT_BIN"]] == bin { + sBinInclude = true + break + } + } + } + if !sBinInclude { + continue + } + // 筛选Hard Bin + var hBinInclude bool + if len(req.HBin) == 0 { + hBinInclude = true + } else { + for _, bin := range req.HBin { + if binInfoMap["HBin"] == bin { + hBinInclude = true + break + } + } + } + if !hBinInclude { + continue + } + if len(data) > fieldMap[req.Selection] && data[fieldMap[req.Selection]] != "" { + selectionData[data[fieldMap[req.Selection]]] = 1 + } + } + for k := range selectionData { + maxDecimal, _ := strconv.ParseFloat(maxStr, 64) + minDecimal, _ := strconv.ParseFloat(minStr, 64) + dataDecimal, _ := strconv.ParseFloat(k, 64) + if dataDecimal <= minDecimal { + minStr = k + } + if maxDecimal <= dataDecimal { + maxStr = k + } + } + if maxStr == strconv.Itoa(math.MinInt) { + maxStr = "NA" + } + if minStr == strconv.Itoa(math.MaxInt) { + minStr = "NA" + } + return maxStr, minStr +} diff --git a/repository/test.data/export.go b/repository/test.data/export.go new file mode 100644 index 0000000..ad882a5 --- /dev/null +++ b/repository/test.data/export.go @@ -0,0 +1,1443 @@ +package test_data + +import ( + "bufio" + "encoding/json" + "fmt" + "github.com/shopspring/decimal" + "github.com/spf13/viper" + "github.com/xuri/excelize/v2" + "log" + "math" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "testData/global" + "testData/model" + "testData/request" + "testData/utils" + "time" +) + +func ExportCPMap(req *request.CPMap) string { + // CP测试没有子批次 + var fileHandles []*model.FileHandled + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ?", req.PBI, req.Product, req.Lot). + Order("wafer_id").Find(&fileHandles) + cpFile := excelize.NewFile() + passStyle := CPMapPassStyle(cpFile) + failStyle := CPMapFailStyle(cpFile) + + _ = cpFile.SetSheetName("Sheet1", "Summary") + allBinMap := make(map[string]int) + + for _, fileHandle := range fileHandles { + _, err := strconv.Atoi(fileHandle.WaferID) + if err != nil { + continue + } + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + for _, data := range datas { + allBinMap[data[fieldMap["SOFT_BIN"]]] = 1 + } + f.Close() + } + var binStrs []string + for k := range allBinMap { + binStrs = append(binStrs, "BIN "+k) + } + sort.Slice(binStrs, func(i, j int) bool { + iInt, _ := strconv.Atoi(binStrs[i][4:]) + jInt, _ := strconv.Atoi(binStrs[j][4:]) + return iInt < jInt + }) + + var title []string + title = append(title, []string{"产品", "工序", "PBI", "批号", "片号", "Total", "Pass", "Fail", "Yield"}...) + rowIndex := 1 + title = append(title, binStrs...) + indexMap := make(map[string]int) + for index, field := range title { + indexMap[field] = index + 1 + } + _ = cpFile.SetSheetRow("Summary", "A1", &title) + + maxProbability, minProbability, maxRowIndex, minRowIndex := "-1", "-1", -1, -1 + for _, fileHandle := range fileHandles { + _, err := strconv.Atoi(fileHandle.WaferID) + if err != nil { + continue + } + rowIndex++ + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + } + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + + sbinHbinMap := make(map[string]map[string]string) + sbinHbinByte := []byte(fileHandle.SbinHbin) + _ = json.Unmarshal(sbinHbinByte, &sbinHbinMap) + + var rowData []interface{} + var latestDatas [][]string + endRow, endCol := 0, 0 + binMap := make(map[string]int) + + sheetIndex, _ := cpFile.NewSheet(fileHandle.WaferID) + sheetName := cpFile.GetSheetName(sheetIndex) + + for _, data := range datas { + binInfoMap := sbinHbinMap[data[fieldMap["SOFT_BIN"]]] + x := data[fieldMap["X_COORD"]] + y := data[fieldMap["Y_COORD"]] + + xInt, _ := strconv.Atoi(x) + yInt, _ := strconv.Atoi(y) + if endRow < xInt { + endRow = xInt + } + if endCol < yInt { + endCol = yInt + } + //xDecimal, _ := decimal.NewFromString(x) + //yDecimal, _ := decimal.NewFromString(y) + //endRowDecimal, _ := decimal.NewFromString(endRow) + //endColDecimal, _ := decimal.NewFromString(endCol) + //if endRowDecimal.LessThan(xDecimal) { + // endRow = x + //} + //if endColDecimal.LessThan(yDecimal) { + // endCol = y + //} + + isAppendData := true + for _, mainData := range latestDatas { + if mainData[0] == x && mainData[1] == y { + mainData = []string{x, y, data[fieldMap["SOFT_BIN"]], binInfoMap["HBin"]} + isAppendData = false + break + } + } + if isAppendData { + latestDatas = append(latestDatas, []string{x, y, + data[fieldMap["SOFT_BIN"]], binInfoMap["HBin"]}) //field[5] + } + + } + for _, mainData := range latestDatas { + binMap[mainData[2]]++ + x := utils.NumToRow(mainData[0]) + y := mainData[1] + if mainData[2] == "1" { + _ = cpFile.SetCellValue(sheetName, x+y, 1) + _ = cpFile.SetCellStyle(sheetName, x+y, x+y, passStyle) + } else { + _ = cpFile.SetCellValue(sheetName, x+y, mainData[2]+":"+mainData[3]) + _ = cpFile.SetCellStyle(sheetName, x+y, x+y, failStyle) + } + } + + _ = cpFile.SetColWidth(sheetName, utils.NumToRow("1"), utils.NumToRow(strconv.Itoa(endRow)), 2) + //endColIndex, _ := strconv.Atoi(endCol) + //for i := 0; i < endColIndex; i++ { + // _ = cpFile.SetRowHeight(sheetName, i, 10) + //} + for i := 0; i < endCol; i++ { + _ = cpFile.SetRowHeight(sheetName, i, 10) + } + + totalDecimal := decimal.NewFromFloat(float64(len(latestDatas))) + passDecimal := decimal.NewFromFloat(float64(binMap["1"])) + maxProbabilityDecimal, _ := decimal.NewFromString(maxProbability) + minProbabilityDecimal, _ := decimal.NewFromString(minProbability) + var passProbability string + if totalDecimal.IsZero() { + passProbability = "0" + minProbability = passProbability + minRowIndex = rowIndex + if maxProbability == "-1" { + maxProbability = passProbability + maxRowIndex = rowIndex + } + } else { + passProbability = passDecimal.Div(totalDecimal).Round(4).Mul(decimal.NewFromInt(100)).String() + if maxProbability == "-1" { + maxProbability = passProbability + maxRowIndex = rowIndex + } else { + if maxProbabilityDecimal.LessThan(passDecimal.Div(totalDecimal).Round(4).Mul(decimal.NewFromInt(100))) { + maxProbability = passProbability + maxRowIndex = rowIndex + } + } + if minProbability == "-1" { + minProbability = passProbability + minRowIndex = rowIndex + } else { + if passDecimal.Div(totalDecimal).Round(4).Mul(decimal.NewFromInt(100)).LessThan(minProbabilityDecimal) { + minProbability = passProbability + minRowIndex = rowIndex + } + } + } + + total, _ := strconv.Atoi(totalDecimal.String()) + pass, _ := strconv.Atoi(passDecimal.String()) + fail, _ := strconv.Atoi(totalDecimal.Sub(passDecimal).String()) + rowData = []interface{}{fileHandle.Product, fileHandle.Step, fileHandle.PBI, fileHandle.Lot, fileHandle.WaferID, + total, pass, fail, + passProbability + "%"} + for _, bin := range binStrs { + if quantity, ok := binMap[bin[4:]]; !ok { + rowData = append(rowData, "") + } else { + rowData = append(rowData, quantity) + } + } + _ = cpFile.SetSheetRow("Summary", "A"+strconv.Itoa(rowIndex), &rowData) + f.Close() + } + + // Total + _ = cpFile.SetSheetCol("Summary", "D"+strconv.Itoa(rowIndex+1), &[]interface{}{"Total", "Max Yield", "Min Yield", "Average Yield"}) + _ = cpFile.SetCellValue("Summary", "E"+strconv.Itoa(rowIndex+1), rowIndex-1) + _ = cpFile.SetCellFormula("Summary", "F"+strconv.Itoa(rowIndex+1), "=SUM(F2:F"+strconv.Itoa(rowIndex)+")") + _ = cpFile.SetCellFormula("Summary", "G"+strconv.Itoa(rowIndex+1), "=SUM(G2:G"+strconv.Itoa(rowIndex)+")") + _ = cpFile.SetCellFormula("Summary", "H"+strconv.Itoa(rowIndex+1), "=SUM(H2:H"+strconv.Itoa(rowIndex)+")") + + // Max Yield + _ = cpFile.SetCellFormula("Summary", "E"+strconv.Itoa(rowIndex+2), "=E"+strconv.Itoa(maxRowIndex)) + _ = cpFile.SetCellFormula("Summary", "F"+strconv.Itoa(rowIndex+2), "=F"+strconv.Itoa(maxRowIndex)) + _ = cpFile.SetCellFormula("Summary", "G"+strconv.Itoa(rowIndex+2), "=G"+strconv.Itoa(maxRowIndex)) + _ = cpFile.SetCellFormula("Summary", "H"+strconv.Itoa(rowIndex+2), "=H"+strconv.Itoa(maxRowIndex)) + _ = cpFile.SetCellFormula("Summary", "I"+strconv.Itoa(rowIndex+2), "=I"+strconv.Itoa(maxRowIndex)) + + // Min Yield + _ = cpFile.SetCellFormula("Summary", "E"+strconv.Itoa(rowIndex+3), "=E"+strconv.Itoa(minRowIndex)) + _ = cpFile.SetCellFormula("Summary", "F"+strconv.Itoa(rowIndex+3), "=F"+strconv.Itoa(minRowIndex)) + _ = cpFile.SetCellFormula("Summary", "G"+strconv.Itoa(rowIndex+3), "=G"+strconv.Itoa(minRowIndex)) + _ = cpFile.SetCellFormula("Summary", "H"+strconv.Itoa(rowIndex+3), "=H"+strconv.Itoa(minRowIndex)) + _ = cpFile.SetCellFormula("Summary", "I"+strconv.Itoa(rowIndex+3), "=I"+strconv.Itoa(minRowIndex)) + + // Average Yield + percentStyle, _ := cpFile.NewStyle(&excelize.Style{ + NumFmt: 10, + }) + _ = cpFile.SetCellFormula("Summary", "I"+strconv.Itoa(rowIndex+4), "=G"+strconv.Itoa(rowIndex+1)+"/F"+strconv.Itoa(rowIndex+1)) + _ = cpFile.SetCellStyle("Summary", "F"+strconv.Itoa(rowIndex+4), "F"+strconv.Itoa(rowIndex+4), percentStyle) + for binIndex, bin := range binStrs { + colName := utils.NumToRow(strconv.Itoa(indexMap[bin])) + // Total + _ = cpFile.SetCellFormula("Summary", colName+strconv.Itoa(rowIndex+1), "=SUM("+colName+"2:"+colName+strconv.Itoa(rowIndex)+")") + // Max Yield + _ = cpFile.SetCellFormula("Summary", colName+strconv.Itoa(rowIndex+2), "="+colName+strconv.Itoa(maxRowIndex)) + // Min Yield + _ = cpFile.SetCellFormula("Summary", colName+strconv.Itoa(rowIndex+3), "="+colName+strconv.Itoa(minRowIndex)) + // Average Yield + _ = cpFile.SetCellFormula("Summary", colName+strconv.Itoa(rowIndex+4), "="+colName+strconv.Itoa(rowIndex+1)+"/F"+strconv.Itoa(rowIndex+1)) + + if binIndex == len(binStrs)-1 { + _ = cpFile.SetCellStyle("Summary", "I"+strconv.Itoa(rowIndex+4), colName+strconv.Itoa(rowIndex+4), percentStyle) + } + } + _ = cpFile.SetColWidth("Summary", "A", "A", 15) + _ = cpFile.SetColWidth("Summary", "C", "C", 30) + _ = cpFile.SetColWidth("Summary", "D", "D", 20) + filePath := time.Now().Format("_CpMap_2006-01-02_150405.xlsx") + filePath = req.Product + "_" + req.Lot + filePath + filePath = filepath.Join(utils.MakeSavePath("CP"), filePath) + _ = cpFile.SaveAs(filePath) + defer cpFile.Close() + return strings.ReplaceAll(viper.GetString("domain"), "\\", "/") + filePath +} + +type SelectionInfo struct { + Field string + Min float64 + Max float64 + Average float64 + StandardDeviation float64 + Num float64 +} + +func ExportHistogram(req *request.Histogram) string { + var fileHandle *model.FileHandled + global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ?", + req.Product, req.Lot, req.PBI).Find(&fileHandle) + histogramFile := excelize.NewFile() + row := 1 + m := make(map[string]map[string]string) + _ = json.Unmarshal([]byte(fileHandle.TitleInfo), &m) + sheetName := histogramFile.GetSheetName(0) + _ = histogramFile.SetSheetName(sheetName, "汇总表") + sheetName = "汇总表" + if ((len(req.SubBatch) == 0 && len(req.WaferID) == 0) || len(req.SubBatch) != 0 || len(req.WaferID) != 0) && + !req.SpliteSubBatch { + start := row + selectionInfo := make(map[string][]float64) + var datas [][]string + fieldMap := make(map[string]int) + if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + if len(req.SubBatch) != 0 { + for _, subBatch := range req.SubBatch { + subBatchDatas, subBatchFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, subBatch, "") + datas = append(datas, subBatchDatas...) + fieldMap = subBatchFieldMap + } + } else if len(req.WaferID) != 0 { + for _, waferID := range req.WaferID { + waferIDDatas, waferIDFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, "", waferID) + datas = append(datas, waferIDDatas...) + fieldMap = waferIDFieldMap + } + } + } + + for _, data := range datas { + if req.OnlyPass && !(data[fieldMap["SOFT_BIN"]] == "1") { + continue + } + for _, selection := range req.Selections { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[selection]]) + selectionFloat, _ := selectionDecimal.Float64() + var filed string + if req.SpliteSite { + filed = selection + "_Site" + data[fieldMap["SITE_NUM"]] + } else { + filed = selection + } + if _, ok := selectionInfo[filed]; !ok { + selectionInfo[filed] = []float64{math.MaxInt, math.MinInt, 0, 0} + } + if selectionInfo[filed][0] > selectionFloat { + selectionInfo[filed][0] = selectionFloat + } + if selectionInfo[filed][1] < selectionFloat { + selectionInfo[filed][1] = selectionFloat + } + selectionInfo[filed][2] += selectionFloat + selectionInfo[filed][3]++ + } + } + + selectionHistogramX := make(map[string][]string) + selectionHistogramY := make(map[string][]int) + for k, v := range selectionInfo { + selectionInfo[k] = []float64{v[0], v[1], v[2], v[3], v[2] / v[3], 0, 0} + selectionHistogramX[k] = []string{} + minDecimal := decimal.NewFromFloat(v[0]) + if minDecimal.Abs().LessThan(decimal.NewFromInt(1)) { + if minDecimal.LessThan(decimal.NewFromInt(0)) { + minDecimal = minDecimal.RoundUp(0) + } else { + minDecimal = minDecimal.RoundDown(0) + } + } else { + if minDecimal.LessThan(decimal.NewFromInt(0)) { + minDecimal = minDecimal.RoundDown(1) + } else { + minDecimal = minDecimal.RoundUp(1) + } + } + maxDecimal := decimal.NewFromFloat(v[1]) + if maxDecimal.Abs().LessThan(decimal.NewFromInt(1)) { + if maxDecimal.LessThan(decimal.NewFromInt(0)) { + maxDecimal = maxDecimal.RoundDown(0) + } else { + maxDecimal = maxDecimal.RoundUp(0) + } + } else { + if maxDecimal.LessThan(decimal.NewFromInt(0)) { + maxDecimal = maxDecimal.RoundDown(1) + } else { + maxDecimal = maxDecimal.RoundUp(1) + } + } + interval := maxDecimal.Sub(minDecimal).Div(decimal.NewFromInt(20)) + for i := 0; i < 21; i++ { + xPoint := minDecimal.Add(interval.Mul(decimal.NewFromInt(int64(i)))).String() + selectionHistogramX[k] = append(selectionHistogramX[k], xPoint) + } + } + for _, data := range datas { + if req.OnlyPass && !(data[fieldMap["SOFT_BIN"]] == "1") { + continue + } + for k, v := range selectionInfo { + var field, site string + if req.SpliteSite { + field = strings.Split(k, "_Site")[0] + site = strings.Split(k, "_Site")[1] + if !(site == data[fieldMap["SITE_NUM"]]) { + continue + } + } else { + field = k + } + if data[fieldMap[field]] != "" { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[field]]) + averageDecimal := decimal.NewFromFloat(v[4]) + d, _ := averageDecimal.Sub(selectionDecimal).Pow(decimal.NewFromInt(2)). + Float64() + + for i := 0; i < len(selectionHistogramX[k]); i++ { + if i == len(selectionHistogramX[k])-1 { + xPointDecimal, _ := decimal.NewFromString(selectionHistogramX[k][i]) + if xPointDecimal.Equals(selectionDecimal) { + selectionHistogramY[k][i]++ + } + break + } + xPointMin, _ := decimal.NewFromString(selectionHistogramX[k][i]) + xPointMax, _ := decimal.NewFromString(selectionHistogramX[k][i+1]) + if _, ok := selectionHistogramY[k]; !ok { + selectionHistogramY[k] = make([]int, len(selectionHistogramX[k])) + } + if xPointMin.LessThanOrEqual(selectionDecimal) && selectionDecimal.LessThan(xPointMax) { + selectionHistogramY[k][i]++ + } + } + v[5] += d + v[6]++ + } + } + } + + rowIndex := 2 + histogramFile.NewSheet("All") + selectionValueMap := make(map[string][]int) + for k, v := range selectionHistogramX { + sheetX := []interface{}{k} + 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, rowIndex+idx) + if err != nil { + fmt.Println(err) + } + if err = histogramFile.SetSheetRow("All", cell, &rows); err != nil { + fmt.Println(err) + } + } + selectionValueMap[k] = []int{rowIndex, len(selectionHistogramY[k]) + 1} + rowIndex += 2 + } + a := 1 + for _, selection := range req.Selections { + b := 1 + for k, v := range selectionValueMap { + if strings.Contains(k, selection) { + if err := histogramFile.AddChart("All", utils.NumToRow(strconv.Itoa(b))+strconv.Itoa(a), &excelize.Chart{ + Type: excelize.Col, + Series: []excelize.ChartSeries{ + { + Name: "All" + "!$A$1", + Categories: "All" + "!$B$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: "All" + "!$B$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + Marker: excelize.ChartMarker{ + Symbol: "none", Size: 10, + }, + }, + }, + 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: "All" + "!$A$1", + Categories: "All" + "!$B$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: "All" + "!$B$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + 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) + } + b += 9 + } + } + 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"}) + col++ + siteDiff := make(map[string][]float64) + selectionUnit := make(map[string]string) + + var selectionInfoArray []SelectionInfo + for _, selection := range req.Selections { + var oneSelectionInfo []SelectionInfo + for k, v := range selectionInfo { + if !strings.Contains(k, selection) { + continue + } + oneSelectionInfo = append(oneSelectionInfo, SelectionInfo{ + Field: k, + Min: v[0], + Max: v[1], + Average: v[4], + StandardDeviation: math.Sqrt(v[5] / v[6]), + Num: v[3], + }) + } + sort.Slice(oneSelectionInfo, func(i, j int) bool { + return oneSelectionInfo[i].Field < oneSelectionInfo[j].Field + }) + selectionInfoArray = append(selectionInfoArray, oneSelectionInfo...) + } + + for _, v := range selectionInfoArray { + field := strings.Split(v.Field, "_Site")[0] + limitLDecimal, _ := decimal.NewFromString(m[field]["LimitL"]) + limitLFloat, _ := limitLDecimal.Float64() + limitUDecimal, _ := decimal.NewFromString(m[field]["LimitU"]) + limitUFloat, _ := limitUDecimal.Float64() + if req.SpliteSite { + if _, ok := siteDiff[field]; !ok { + siteDiff[field] = []float64{v.Average, v.Average, v.StandardDeviation, v.StandardDeviation} + selectionUnit[field] = m[field]["Unit"] + } else { + if v.Average > siteDiff[field][0] { + siteDiff[field][0] = v.Average + } + if v.Average < siteDiff[field][1] { + siteDiff[field][1] = v.Average + } + if v.StandardDeviation > siteDiff[field][2] { + siteDiff[field][2] = v.StandardDeviation + } + if v.StandardDeviation < siteDiff[field][3] { + siteDiff[field][3] = v.StandardDeviation + } + } + } + _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start), &[]interface{}{ + v.Field, v.Min, v.Max, v.Average, v.StandardDeviation, v.Num, limitLFloat, limitUFloat, m[field]["Unit"]}) + col++ + } + + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start), + TitleStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+1), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+5), + ActualLimitStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+6), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+8), + LimitStyle(histogramFile)) + _ = histogramFile.SetColWidth(sheetName, "A", utils.NumToRow(strconv.Itoa(col-1)), + 20) + + if req.SpliteSite { + start += 10 + col = 2 + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start), &[]interface{}{ + "SITE差异"}) + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start+1), &[]interface{}{ + "", "平均值", "δ", "UNIT"}) + for k, v := range siteDiff { + _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start+1), &[]interface{}{ + k, v[0] - v[1], v[2] - v[3], selectionUnit[k]}) + 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)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+1), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+1), + TitleStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+2), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+3), + ActualLimitStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+4), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+4), + LimitStyle(histogramFile)) + } + } else { + start := row + selectionUnit := make(map[string]string) + subBatchDiff := make(map[string][]float64) + + var groups []string + var isFT bool + if len(req.SubBatch) != 0 { + groups = req.SubBatch + isFT = true + } else if len(req.WaferID) != 0 { + groups = req.WaferID + } else if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + global.PostGreSQL.Model(&model.FileHandled{}).Where("product = ? AND lot = ? AND pbi = ?", + req.Product, req.Lot, req.PBI).Group("wafer_id").Select("wafer_id").Find(&groups) + if len(groups) == 0 || groups[0] == "" { + global.PostGreSQL.Model(&model.FileHandled{}).Where("product = ? AND lot = ? AND pbi = ?", + req.Product, req.Lot, req.PBI).Group("sub_batch").Select("sub_batch").Find(&groups) + isFT = true + } + } + for _, group := range groups { + siteSelectionInfo := make(map[string][]float64) + selectionInfo := make(map[string][]float64) + var datas [][]string + fieldMap := make(map[string]int) + if isFT { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, group, "") + } else { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, "", group) + } + group = strings.ReplaceAll(group, "-", "_") + + for _, data := range datas { + if req.OnlyPass && !(data[fieldMap["SOFT_BIN"]] == "1") { + continue + } + for _, selection := range req.Selections { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[selection]]) + selectionFloat, _ := selectionDecimal.Float64() + var filed string + if req.SpliteSite { + filed = selection + "_Site" + data[fieldMap["SITE_NUM"]] + } else { + filed = selection + } + if _, ok := siteSelectionInfo[filed]; !ok { + siteSelectionInfo[filed] = []float64{math.MaxInt, math.MinInt, 0, 0} + } + if siteSelectionInfo[filed][0] > selectionFloat { + siteSelectionInfo[filed][0] = selectionFloat + } + if siteSelectionInfo[filed][1] < selectionFloat { + siteSelectionInfo[filed][1] = selectionFloat + } + siteSelectionInfo[filed][2] += selectionFloat + siteSelectionInfo[filed][3]++ + + if _, ok := selectionInfo[selection]; !ok { + selectionInfo[selection] = []float64{math.MaxInt, math.MinInt, 0, 0} + } + if selectionInfo[selection][0] > selectionFloat { + selectionInfo[selection][0] = selectionFloat + } + if selectionInfo[selection][1] < selectionFloat { + selectionInfo[selection][1] = selectionFloat + } + selectionInfo[selection][2] += selectionFloat + selectionInfo[selection][3]++ + } + } + + selectionHistogramX := make(map[string][]string) + selectionHistogramY := make(map[string][]int) + for k, v := range siteSelectionInfo { + siteSelectionInfo[k] = []float64{v[0], v[1], v[2], v[3], v[2] / v[3], 0, 0} + if req.SpliteSite { + selectionHistogramX[group+"_"+k] = []string{} + minDecimal := decimal.NewFromFloat(v[0]) + if minDecimal.LessThan(decimal.NewFromInt(0)) { + minDecimal = minDecimal.RoundUp(0) + } else { + minDecimal = minDecimal.RoundDown(0) + } + maxDecimal := decimal.NewFromFloat(v[1]) + if maxDecimal.LessThan(decimal.NewFromInt(0)) { + maxDecimal = maxDecimal.RoundDown(0) + } else { + maxDecimal = maxDecimal.RoundUp(0) + } + interval := maxDecimal.Sub(minDecimal).Div(decimal.NewFromInt(20)) + for i := 0; i < 21; i++ { + xPoint := minDecimal.Add(interval.Mul(decimal.NewFromInt(int64(i)))).String() + selectionHistogramX[group+"_"+k] = append(selectionHistogramX[group+"_"+k], xPoint) + } + } + } + for k, v := range selectionInfo { + selectionInfo[k] = []float64{v[0], v[1], v[2], v[3], v[2] / v[3], 0, 0} + if !req.SpliteSite { + selectionHistogramX[group+"_"+k] = []string{} + minDecimal := decimal.NewFromFloat(v[0]) + if minDecimal.LessThan(decimal.NewFromInt(0)) { + minDecimal = minDecimal.RoundUp(0) + } else { + minDecimal = minDecimal.RoundDown(0) + } + maxDecimal := decimal.NewFromFloat(v[1]) + if maxDecimal.LessThan(decimal.NewFromInt(0)) { + maxDecimal = maxDecimal.RoundDown(0) + } else { + maxDecimal = maxDecimal.RoundUp(0) + } + + interval := maxDecimal.Sub(minDecimal).Div(decimal.NewFromInt(20)) + for i := 0; i < 21; i++ { + xPoint := minDecimal.Add(interval.Mul(decimal.NewFromInt(int64(i)))).String() + selectionHistogramX[group+"_"+k] = append(selectionHistogramX[group+"_"+k], xPoint) + } + } + } + + for _, data := range datas { + if req.OnlyPass && !(data[fieldMap["SOFT_BIN"]] == "1") { + continue + } + for k, v := range siteSelectionInfo { + var field, site string + if req.SpliteSite { + field = strings.Split(k, "_Site")[0] + site = strings.Split(k, "_Site")[1] + if !(site == data[fieldMap["SITE_NUM"]]) { + continue + } + } else { + field = k + } + if data[fieldMap[field]] != "" { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[field]]) + averageDecimal := decimal.NewFromFloat(v[4]) + d, _ := averageDecimal.Sub(selectionDecimal).Pow(decimal.NewFromInt(2)). + Float64() + + if req.SpliteSite { + a := group + "_" + k + for i := 0; i < len(selectionHistogramX[a]); i++ { + if i == len(selectionHistogramX[a])-1 { + xPointDecimal, _ := decimal.NewFromString(selectionHistogramX[a][i]) + if xPointDecimal.Equals(selectionDecimal) { + selectionHistogramY[a][i]++ + } + break + } + xPointMin, _ := decimal.NewFromString(selectionHistogramX[a][i]) + xPointMax, _ := decimal.NewFromString(selectionHistogramX[a][i+1]) + if _, ok := selectionHistogramY[a]; !ok { + selectionHistogramY[a] = make([]int, len(selectionHistogramX[a])) + } + if xPointMin.LessThanOrEqual(selectionDecimal) && selectionDecimal.LessThan(xPointMax) { + selectionHistogramY[a][i]++ + } + } + } + + v[5] += d + v[6]++ + } + } + + for k, v := range selectionInfo { + if data[fieldMap[k]] != "" { + selectionDecimal, _ := decimal.NewFromString(data[fieldMap[k]]) + averageDecimal := decimal.NewFromFloat(v[4]) + d, _ := averageDecimal.Sub(selectionDecimal).Pow(decimal.NewFromInt(2)). + Float64() + + if !req.SpliteSite { + field := group + "_" + k + for i := 0; i < len(selectionHistogramX[field]); i++ { + if i == len(selectionHistogramX[field])-1 { + xPointDecimal, _ := decimal.NewFromString(selectionHistogramX[field][i]) + if xPointDecimal.Equals(selectionDecimal) { + selectionHistogramY[field][i]++ + } + break + } + xPointMin, _ := decimal.NewFromString(selectionHistogramX[field][i]) + xPointMax, _ := decimal.NewFromString(selectionHistogramX[field][i+1]) + if _, ok := selectionHistogramY[field]; !ok { + selectionHistogramY[field] = make([]int, len(selectionHistogramX[field])) + } + if xPointMin.LessThanOrEqual(selectionDecimal) && selectionDecimal.LessThan(xPointMax) { + selectionHistogramY[field][i]++ + } + } + } + + v[5] += d + v[6]++ + } + } + + } + + rowIndex, colIndex := 2, 1 + histogramFile.NewSheet(group) + selectionValueMap := make(map[string][]int) + for k, v := range selectionHistogramX { + sheetX := []interface{}{k} + 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(colIndex, rowIndex+idx) + if err != nil { + fmt.Println(err) + } + if err = histogramFile.SetSheetRow(group, cell, &rows); err != nil { + fmt.Println(err) + } + } + selectionValueMap[k] = []int{rowIndex, len(selectionHistogramY[k]) + 1} + rowIndex += 2 + } + a := 1 + for _, selection := range req.Selections { + b := 1 + for k, v := range selectionValueMap { + if strings.Contains(k, selection) { + if err := histogramFile.AddChart(group, utils.NumToRow(strconv.Itoa(b))+strconv.Itoa(a), &excelize.Chart{ + Type: excelize.Col, + Series: []excelize.ChartSeries{ + { + Name: group + "!$A$1", + Categories: group + "!$B$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: group + "!$B$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + Marker: excelize.ChartMarker{ + Symbol: "none", Size: 10, + }, + }, + }, + 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: group + "!$A$1", + Categories: group + "!$B$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: group + "!$B$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + 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) + } + b += 9 + } + } + a += 20 + } + + col := 1 + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start), &[]interface{}{ + "子批:" + group}) + + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start+1), &[]interface{}{ + "", "最小值", "最大值", "平均值", "δ", "数量", "Limit L", "Limit H", "UNIT"}) + col++ + siteDiff := make(map[string][]float64) + + var selectionInfoArray []SelectionInfo + for _, selection := range req.Selections { + var oneSelectionInfo []SelectionInfo + for k, v := range siteSelectionInfo { + if !strings.Contains(k, selection) { + continue + } + oneSelectionInfo = append(oneSelectionInfo, SelectionInfo{ + Field: k, + Min: v[0], + Max: v[1], + Average: v[4], + StandardDeviation: math.Sqrt(v[5] / v[6]), + Num: v[3], + }) + } + sort.Slice(oneSelectionInfo, func(i, j int) bool { + return oneSelectionInfo[i].Field < oneSelectionInfo[j].Field + }) + selectionInfoArray = append(selectionInfoArray, oneSelectionInfo...) + } + + for _, v := range selectionInfoArray { + field := strings.Split(v.Field, "_Site")[0] + limitLDecimal, _ := decimal.NewFromString(m[field]["LimitL"]) + limitLFloat, _ := limitLDecimal.Float64() + limitUDecimal, _ := decimal.NewFromString(m[field]["LimitU"]) + limitUFloat, _ := limitUDecimal.Float64() + selectionUnit[field] = m[field]["Unit"] + if req.SpliteSite { + if _, ok := siteDiff[field]; !ok { + siteDiff[field] = []float64{v.Average, v.Average, v.StandardDeviation, v.StandardDeviation} + } else { + if v.Average > siteDiff[field][0] { + siteDiff[field][0] = v.Average + } + if v.Average < siteDiff[field][1] { + siteDiff[field][1] = v.Average + } + if v.StandardDeviation > siteDiff[field][2] { + siteDiff[field][2] = v.StandardDeviation + } + if v.StandardDeviation < siteDiff[field][3] { + siteDiff[field][3] = v.StandardDeviation + } + } + } + _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start+1), &[]interface{}{ + v.Field, v.Min, v.Max, v.Average, v.StandardDeviation, v.Num, limitLFloat, limitUFloat, m[field]["Unit"]}) + col++ + } + + for k, v := range selectionInfo { + if _, ok := subBatchDiff[k]; !ok { + subBatchDiff[k] = []float64{v[4], v[4], v[5] / v[6], v[5] / v[6]} + selectionUnit[k] = m[k]["Unit"] + } else { + if v[4] > subBatchDiff[k][0] { + subBatchDiff[k][0] = v[4] + } + if v[4] < subBatchDiff[k][1] { + subBatchDiff[k][1] = v[4] + } + if v[5]/v[6] > subBatchDiff[k][2] { + subBatchDiff[k][2] = v[5] / v[6] + } + if v[5]/v[6] < subBatchDiff[k][3] { + subBatchDiff[k][3] = v[5] / v[6] + } + } + } + + _ = 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)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+1), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+1), + TitleStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+2), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+6), + ActualLimitStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+7), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+9), + LimitStyle(histogramFile)) + _ = histogramFile.SetColWidth(sheetName, "A", utils.NumToRow(strconv.Itoa(col-1)), + 20) + start += 10 + + if req.SpliteSite { + start += 1 + col = 2 + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start), &[]interface{}{ + "SITE差异-" + group}) + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start+1), &[]interface{}{ + "", "平均值", "δ", "UNIT"}) + for k, v := range siteDiff { + _ = histogramFile.SetSheetCol(sheetName, utils.NumToRow(strconv.Itoa(col))+strconv.Itoa(start+1), &[]interface{}{ + k, v[0] - v[1], v[2] - v[3], selectionUnit[k]}) + 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)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+1), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+1), + TitleStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+2), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+3), + ActualLimitStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+4), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+4), + LimitStyle(histogramFile)) + start += 5 + } + start += 1 + } + + start += 1 + col := 2 + _ = histogramFile.SetSheetCol(sheetName, "A"+strconv.Itoa(start), &[]interface{}{ + "批次差异汇总"}) + _ = 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++ + } + _ = 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)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+1), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+1), + TitleStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+2), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+3), + ActualLimitStyle(histogramFile)) + _ = histogramFile.SetCellStyle(sheetName, "A"+strconv.Itoa(start+4), utils.NumToRow(strconv.Itoa(col-1))+strconv.Itoa(start+4), + LimitStyle(histogramFile)) + } + filePath := time.Now().Format("_直方图_2006-01-02_150405.xlsx") + filePath = req.Product + "_" + req.Lot + filePath + filePath = filepath.Join(utils.MakeSavePath("直方图"), filePath) + _ = histogramFile.SaveAs(filePath) + defer histogramFile.Close() + return strings.ReplaceAll(viper.GetString("domain"), "\\", "/") + filePath +} + +func ExportScatter(req *request.Scatter) string { + scatterFile := excelize.NewFile() + //((len(req.SubBatch) == 0 && len(req.WaferID) == 0) || len(req.SubBatch) != 0 || len(req.WaferID) != 0) && + if !req.SpliteSubBatch { + var datas [][]string + fieldMap := make(map[string]int) + if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + datas, fieldMap = LotInMultipleFiles(req.Product, req.Lot, req.PBI) + } else { + if len(req.SubBatch) != 0 { + for _, subBatch := range req.SubBatch { + subBatchDatas, subBatchFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, subBatch, "") + datas = append(datas, subBatchDatas...) + fieldMap = subBatchFieldMap + } + } else if len(req.WaferID) != 0 { + for _, waferID := range req.WaferID { + waferIDDatas, waferIDFieldMap := LotInAFile(req.Product, req.Lot, req.PBI, "", waferID) + datas = append(datas, waferIDDatas...) + fieldMap = waferIDFieldMap + } + } + } + + selectionPointsMap := make(map[string]map[string]int) + for _, data := range datas { + if req.OnlyPass { + if data[fieldMap["SOFT_BIN"]] != "1" { + continue + } + } + for _, selection := range req.XYSelection { + var field string + if req.SpliteSite { + field = selection.X + "," + selection.Y + "_SITE" + data[fieldMap["SITE_NUM"]] + } else { + field = selection.X + "," + selection.Y + } + if _, ok := selectionPointsMap[field]; !ok { + selectionPointsMap[field] = map[string]int{} + } + selectionPointsMap[field][data[fieldMap[selection.X]]+","+data[fieldMap[selection.Y]]]++ + } + } + + scatterFile.SetSheetName("Sheet1", "All") + sheetName := scatterFile.GetSheetName(0) + selectionValueMap := make(map[string][]int) + + rowIndex := 1 + for _, selection := range req.XYSelection { + for k := range selectionPointsMap { + if strings.Contains(k, selection.X+","+selection.Y) { + sheetX := []interface{}{k, selection.X} + sheetY := []interface{}{"", selection.Y} + for point := range selectionPointsMap[k] { + pointXY := strings.Split(point, ",") + xDecimal, _ := decimal.NewFromString(pointXY[0]) + x, _ := xDecimal.Float64() + yDecimal, _ := decimal.NewFromString(pointXY[1]) + y, _ := yDecimal.Float64() + sheetX = append(sheetX, x) + sheetY = append(sheetY, y) + } + for idx, row := range [][]interface{}{ + sheetX, + sheetY, + } { + cell, err := excelize.CoordinatesToCellName(1, rowIndex+idx) + if err != nil { + fmt.Println(err) + } + if err = scatterFile.SetSheetRow(sheetName, cell, &row); err != nil { + fmt.Println(err) + } + } + selectionValueMap[k] = []int{rowIndex, len(sheetY) + 1} + rowIndex += 2 + } + } + } + a := 1 + for _, selection := range req.XYSelection { + b := 1 + for k, v := range selectionValueMap { + if strings.Contains(k, selection.X+","+selection.Y) { + if err := scatterFile.AddChart("All", utils.NumToRow(strconv.Itoa(b))+strconv.Itoa(a), &excelize.Chart{ + Type: excelize.Scatter, + Series: []excelize.ChartSeries{ + { + Name: "All" + "!$A$1", + Categories: "All" + "!$C$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: "All" + "!$C$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + Marker: excelize.ChartMarker{ + Symbol: "circle", Size: 1, + }, + }, + }, + Format: excelize.GraphicOptions{ + ScaleX: 1, + ScaleY: 1, + OffsetX: 15, + OffsetY: 10, + }, + Legend: excelize.ChartLegend{ + Position: "bottom", + }, + Title: []excelize.RichTextRun{ + { + Text: k, + }, + }, + //PlotArea: excelize.ChartPlotArea{ + // ShowCatName: false, + // ShowLeaderLines: false, + //}, + ShowBlanksAs: "zero", + }); err != nil { + fmt.Println(err) + } + b += 9 + } + } + a += 20 + } + } else { + var groups []string + var isFT bool + if len(req.SubBatch) != 0 { + groups = req.SubBatch + isFT = true + } else if len(req.WaferID) != 0 { + groups = req.WaferID + } else if len(req.SubBatch) == 0 && len(req.WaferID) == 0 { + global.PostGreSQL.Model(&model.FileHandled{}).Where("product = ? AND lot = ? AND pbi = ?", + req.Product, req.Lot, req.PBI).Group("wafer_id").Select("wafer_id").Find(&groups) + if len(groups) == 0 || groups[0] == "" { + global.PostGreSQL.Model(&model.FileHandled{}).Where("product = ? AND lot = ? AND pbi = ?", + req.Product, req.Lot, req.PBI).Group("sub_batch").Select("sub_batch").Find(&groups) + isFT = true + } + } + for _, group := range groups { + var datas [][]string + fieldMap := make(map[string]int) + if isFT { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, group, "") + } else { + datas, fieldMap = LotInAFile(req.Product, req.Lot, req.PBI, "", group) + } + group = strings.ReplaceAll(group, "-", "_") + selectionPointsMap := make(map[string]map[string]int) + for _, data := range datas { + if req.OnlyPass { + if data[fieldMap["SOFT_BIN"]] != "1" { + continue + } + } + for _, selection := range req.XYSelection { + var field string + if req.SpliteSite { + field = selection.X + "," + selection.Y + "_SITE" + data[fieldMap["SITE_NUM"]] + } else { + field = selection.X + "," + selection.Y + } + if _, ok := selectionPointsMap[field]; !ok { + selectionPointsMap[field] = map[string]int{} + } + selectionPointsMap[field][data[fieldMap[selection.X]]+","+data[fieldMap[selection.Y]]]++ + } + } + + scatterFile.NewSheet(group) + selectionValueMap := make(map[string][]int) + + rowIndex := 1 + for _, selection := range req.XYSelection { + for k := range selectionPointsMap { + if strings.Contains(k, selection.X+","+selection.Y) { + sheetX := []interface{}{k, selection.X} + sheetY := []interface{}{"", selection.Y} + for point := range selectionPointsMap[k] { + pointXY := strings.Split(point, ",") + xDecimal, _ := decimal.NewFromString(pointXY[0]) + x, _ := xDecimal.Float64() + yDecimal, _ := decimal.NewFromString(pointXY[1]) + y, _ := yDecimal.Float64() + sheetX = append(sheetX, x) + sheetY = append(sheetY, y) + } + for idx, row := range [][]interface{}{ + sheetX, + sheetY, + } { + cell, err := excelize.CoordinatesToCellName(1, rowIndex+idx) + if err != nil { + fmt.Println(err) + } + if err = scatterFile.SetSheetRow(group, cell, &row); err != nil { + fmt.Println(err) + } + } + selectionValueMap[k] = []int{rowIndex, len(sheetY) + 1} + rowIndex += 2 + } + } + } + a := 1 + for _, selection := range req.XYSelection { + b := 1 + for k, v := range selectionValueMap { + if strings.Contains(k, selection.X+","+selection.Y) { + if err := scatterFile.AddChart(group, utils.NumToRow(strconv.Itoa(b))+strconv.Itoa(a), &excelize.Chart{ + Type: excelize.Scatter, + Series: []excelize.ChartSeries{ + { + Name: group + "!$A$1", + Categories: group + "!$C$" + strconv.Itoa(v[0]) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]), + Values: group + "!$C$" + strconv.Itoa(v[0]+1) + ":$" + + utils.NumToRow(strconv.Itoa(v[1])) + "$" + strconv.Itoa(v[0]+1), + Marker: excelize.ChartMarker{ + Symbol: "circle", Size: 1, + }, + }, + }, + Format: excelize.GraphicOptions{ + ScaleX: 1, + ScaleY: 1, + OffsetX: 15, + OffsetY: 10, + }, + Legend: excelize.ChartLegend{ + Position: "bottom", + }, + Title: []excelize.RichTextRun{ + { + Text: k, + }, + }, + //PlotArea: excelize.ChartPlotArea{ + // ShowCatName: false, + // ShowLeaderLines: false, + //}, + ShowBlanksAs: "zero", + }); err != nil { + fmt.Println(err) + } + b += 9 + } + } + a += 20 + } + } + } + scatterFile.DeleteSheet("Sheet1") + filePath := time.Now().Format("_散点图_2006-01-02_150405.xlsx") + filePath = req.Product + "_" + req.Lot + filePath + filePath = filepath.Join(utils.MakeSavePath("散点图"), filePath) + _ = scatterFile.SaveAs(filePath) + defer scatterFile.Close() + return strings.ReplaceAll(viper.GetString("domain"), "\\", "/") + filePath +} diff --git a/repository/test.data/export.style.go b/repository/test.data/export.style.go new file mode 100644 index 0000000..ebdd969 --- /dev/null +++ b/repository/test.data/export.style.go @@ -0,0 +1,117 @@ +package test_data + +import "github.com/xuri/excelize/v2" + +func NormalSheetStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + Alignment: &excelize.Alignment{ + Horizontal: "center", + }, + }) + return style +} + +func TitleStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#4F81BD"}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + Alignment: &excelize.Alignment{ + Horizontal: "center", + }, + }) + return style +} + +func ActualLimitStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#D0D8E8"}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + Alignment: &excelize.Alignment{ + Horizontal: "center", + }, + }) + return style +} + +func LimitStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#FFF2CC"}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + Alignment: &excelize.Alignment{ + Horizontal: "center", + }, + }) + return style +} + +func CPMapPassStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#4FFF00"}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + }) + return style +} + +func CPMapFailStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#FF0000"}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + }) + return style +} + +func NormalNumberSheetStyle(f *excelize.File) int { + style, _ := f.NewStyle(&excelize.Style{ + Border: []excelize.Border{ + {Type: "left", Color: "000000", Style: 1}, + {Type: "top", Color: "000000", Style: 1}, + {Type: "bottom", Color: "000000", Style: 1}, + {Type: "right", Color: "000000", Style: 1}, + }, + NumFmt: 2, + Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{}}, + Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false}, + Alignment: &excelize.Alignment{ + Horizontal: "center", + }, + }) + return style +} diff --git a/repository/test.data/report.chart.go b/repository/test.data/report.chart.go new file mode 100644 index 0000000..579c8c9 --- /dev/null +++ b/repository/test.data/report.chart.go @@ -0,0 +1,455 @@ +package test_data + +import ( + "gitee.com/golang-module/carbon/v2" + "github.com/shopspring/decimal" + "gorm.io/gorm" + "math" + "sort" + "strconv" + "testData/global" + "testData/model" + "testData/request" +) + +func PackagePassProbabilityLine(r *request.PackagePassProbabilityLine) ([]*model.Line, int, int) { + var sql string + if r.OrderDateStart != "" && r.OrderDateEnd != "" { + sql += "tc_sfc02 BETWEEN DATE '" + r.OrderDateStart + "' AND DATE '" + r.OrderDateEnd + "'" + } + //else if r.OrderDateStart != "" && r.OrderDateEnd == "" { + // sql += "tc_sfc02 >= DATE '" + r.OrderDateStart + "'" + //} else if r.OrderDateStart == "" && r.OrderDateEnd != "" { + // sql += "tc_sfc02 <= DATE '" + r.OrderDateEnd + "'" + //} + var factories, x []string + if len(r.Factory) == 0 { + global.Oracle.Model(&model.TcSfcFile{}).Where("tc_sfc08 LIKE ?", "%AB%").Where(sql). + Group("tc_sfc04").Select("tc_sfc04").Find(&factories) + } else { + factories = r.Factory + } + productMap := make(map[string]int) + for _, product := range r.Product { + productMap[product] = 1 + } + lotMap := make(map[string]int) + for _, lot := range r.Lot { + lotMap[lot] = 1 + } + specificationMap := make(map[string]int) + for _, specification := range r.Package { + specificationMap[specification] = 1 + } + if r.DateSize == "天" { + days := int(carbon.Parse(r.OrderDateStart).DiffAbsInDays(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < days; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddDays(i).Format("Y-m-d")) + } + } else if r.DateSize == "周" { + weeks := int(carbon.Parse(r.OrderDateStart).DiffAbsInWeeks(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < weeks; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddWeeks(i).Format("Y-m-d")) + } + } else if r.DateSize == "月" { + months := int(carbon.Parse(r.OrderDateStart).DiffAbsInMonths(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < months; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddMonths(i).Format("Y-m")) + } + } else if r.DateSize == "年" { + years := int(carbon.Parse(r.OrderDateStart).DiffAbsInYears(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < years; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddYears(i).Format("Y")) + } + } + max := math.MinInt + min := math.MaxInt + var line []*model.Line + for _, factory := range factories { + var tcSfcFile []*model.TcSfcFile + global.Oracle.Where("tc_sfc08 LIKE ? AND tc_sfc04 = ?", "%AB%", factory).Where(sql). + Preload("PmcFile"). + Preload("TcSfdFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile").Preload("RvaFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("IddFile") + }) + }).Preload("TcSfeFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile") + }).Order("tc_sfc02").Find(&tcSfcFile) + quantityMap := make(map[string][]float64) + var y []string + for _, tcSfc := range tcSfcFile { + for _, tcSfd := range tcSfc.TcSfdFile { + if _, ok := productMap[tcSfd.ImaFile.Ima02]; !ok && len(productMap) > 0 { + continue + } + if _, ok := specificationMap[tcSfd.ImaFile.Ima021]; !ok && len(specificationMap) > 0 { + continue + } + var stockInQuantity, failQuantity float64 + for _, rva := range tcSfd.RvaFile { + for _, idd := range rva.IddFile { + if _, ok := lotMap[idd.Idd04]; !ok && len(lotMap) > 0 { + continue + } + stockInQuantity += idd.Idd13 + if idd.Idd06 == "BIN99" { + failQuantity += idd.Idd13 + } + } + } + var s string + if r.DateSize == "天" { + s = carbon.Parse(r.OrderDateStart).AddDays(int(carbon.Parse(r.OrderDateStart). + DiffAbsInDays(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d") + } else if r.DateSize == "周" { + s = carbon.Parse(r.OrderDateStart).AddWeeks(int(carbon.Parse(r.OrderDateStart). + DiffAbsInWeeks(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d") + } else if r.DateSize == "月" { + s = carbon.Parse(r.OrderDateStart).AddMonths(int(carbon.Parse(r.OrderDateStart). + DiffAbsInMonths(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m") + } else if r.DateSize == "年" { + s = carbon.Parse(r.OrderDateStart).AddYears(int(carbon.Parse(r.OrderDateStart). + DiffAbsInYears(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y") + } + if _, ok := quantityMap[s]; !ok { + quantityMap[s] = []float64{stockInQuantity - failQuantity, stockInQuantity} + } else { + quantityMap[s][0] += stockInQuantity - failQuantity + quantityMap[s][1] += stockInQuantity + } + } + } + + for _, xDate := range x { + if _, ok := quantityMap[xDate]; ok { + if quantityMap[xDate][1] == 0 { + y = append(y, "") + } else { + passProbability := decimal.NewFromFloat(quantityMap[xDate][0]).Div(decimal.NewFromFloat(quantityMap[xDate][1])). + Round(4).Mul(decimal.NewFromFloat(100)) + + passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String()) + if passProbabilityInt > max { + max = passProbabilityInt + 1 + } + if passProbabilityInt < min { + min = passProbabilityInt - 1 + } + y = append(y, passProbability.String()) + } + } else { + y = append(y, "") + } + } + line = append(line, &model.Line{ + Name: factory, + X: x, + Y: y, + }) + } + return line, max, min +} + +func OrderNumberHistogram(r *request.PackagePassProbabilityLine) []*model.Histogram { + var fTHistogram []*model.Histogram + var sql string + if r.OrderDateStart != "" && r.OrderDateEnd != "" { + sql += "tc_sfc02 BETWEEN DATE '" + r.OrderDateStart + "' AND DATE '" + r.OrderDateEnd + "'" + } + //else if r.OrderDateStart != "" && r.OrderDateEnd == "" { + // sql += "tc_sfc02 >= DATE '" + r.OrderDateStart + "'" + //} else if r.OrderDateStart == "" && r.OrderDateEnd != "" { + // sql += "tc_sfc02 <= DATE '" + r.OrderDateEnd + "'" + //} + var factories, x []string + if len(r.Factory) == 0 { + global.Oracle.Model(&model.TcSfcFile{}).Where("tc_sfc08 LIKE ?", "%AB%").Where(sql). + Group("tc_sfc04").Select("tc_sfc04").Find(&factories) + } else { + factories = r.Factory + } + productMap := make(map[string]int) + for _, product := range r.Product { + productMap[product] = 1 + } + lotMap := make(map[string]int) + for _, lot := range r.Lot { + lotMap[lot] = 1 + } + specificationMap := make(map[string]int) + for _, specification := range r.Package { + specificationMap[specification] = 1 + } + if r.DateSize == "天" { + days := int(carbon.Parse(r.OrderDateStart).DiffAbsInDays(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < days; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddDays(i).Format("Y-m-d")) + } + } else if r.DateSize == "周" { + weeks := int(carbon.Parse(r.OrderDateStart).DiffAbsInWeeks(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < weeks; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddWeeks(i).Format("Y-m-d")) + } + } else if r.DateSize == "月" { + months := int(carbon.Parse(r.OrderDateStart).DiffAbsInMonths(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < months; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddMonths(i).Format("m")) + } + } else if r.DateSize == "年" { + years := int(carbon.Parse(r.OrderDateStart).DiffAbsInYears(carbon.Parse(r.OrderDateEnd))) + 1 + for i := 0; i < years; i++ { + x = append(x, carbon.Parse(r.OrderDateStart).AddYears(i).Format("Y")) + } + } + for _, factory := range factories { + var tcSfcFile []*model.TcSfcFile + global.Oracle.Where("tc_sfc08 LIKE ? AND tc_sfc04 = ?", "%AB%", factory).Where(sql). + Preload("PmcFile"). + Preload("TcSfdFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile").Preload("RvaFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("IddFile") + }) + }).Preload("TcSfeFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile") + }).Order("tc_sfc02").Find(&tcSfcFile) + quantityMap := make(map[string]float64) + var y []string + for _, tcSfc := range tcSfcFile { + for _, tcSfd := range tcSfc.TcSfdFile { + if _, ok := productMap[tcSfd.ImaFile.Ima02]; !ok && len(productMap) > 0 { + continue + } + if _, ok := specificationMap[tcSfd.ImaFile.Ima021]; !ok && len(specificationMap) > 0 { + continue + } + var stockInQuantity float64 + for _, rva := range tcSfd.RvaFile { + for _, idd := range rva.IddFile { + if _, ok := lotMap[idd.Idd04]; !ok && len(lotMap) > 0 { + continue + } + stockInQuantity += idd.Idd13 + } + } + var s string + if r.DateSize == "天" { + s = carbon.Parse(r.OrderDateStart).AddDays(int(carbon.Parse(r.OrderDateStart). + DiffAbsInDays(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d") + } else if r.DateSize == "周" { + s = carbon.Parse(r.OrderDateStart).AddWeeks(int(carbon.Parse(r.OrderDateStart). + DiffAbsInWeeks(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d") + } else if r.DateSize == "月" { + s = carbon.Parse(r.OrderDateStart).AddMonths(int(carbon.Parse(r.OrderDateStart). + DiffAbsInMonths(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("m") + } else if r.DateSize == "年" { + s = carbon.Parse(r.OrderDateStart).AddYears(int(carbon.Parse(r.OrderDateStart). + DiffAbsInYears(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y") + } + if _, ok := quantityMap[s]; !ok { + quantityMap[s] = stockInQuantity + } else { + quantityMap[s] += stockInQuantity + } + } + } + + for _, xDate := range x { + if _, ok := quantityMap[xDate]; ok { + y = append(y, decimal.NewFromFloat(quantityMap[xDate]).String()) + } else { + y = append(y, "0") + } + } + fTHistogram = append(fTHistogram, &model.Histogram{ + Field: factory, + X: x, + Y: y, + }) + } + return fTHistogram +} + +func PassProbabilityByFactory(r *request.PassProbabilityByFactory) ([]*model.Line, []*model.Histogram, int, int) { + var lines []*model.Line + var histogram []*model.Histogram + max := math.MinInt + min := math.MaxInt + startDate := carbon.Now().SubYear().StartOfMonth().Format("Y-m-d") + endDate := carbon.Now().EndOfMonth().Format("Y-m-d") + var factorys []string + var sql string + if r.Factory != "" { + sql += "factory = '" + r.Factory + "'" + } + global.PostGreSQL.Model(&model.Report{}).Where("step = ? AND order_date BETWEEN ? AND ?", r.Type, startDate, endDate). + Where(sql).Group("factory").Select("Factory").Find(&factorys) + for _, factory := range factorys { + var x, lineY, histogramY []string + var reports []*model.Report + global.PostGreSQL.Where("step = ? AND factory = ? AND order_date BETWEEN ? AND ?", r.Type, factory, startDate, endDate). + Find(&reports) + factoryMap := make(map[string][]string) + for _, report := range reports { + if _, ok := factoryMap[report.OrderDate[:7]]; !ok { + factoryMap[report.OrderDate[:7]] = []string{report.TestQuantity, report.PassQuantity} + } else { + factoryMapTestQuantity, _ := decimal.NewFromString(factoryMap[report.OrderDate[:7]][0]) + factoryMapPassQuantity, _ := decimal.NewFromString(factoryMap[report.OrderDate[:7]][1]) + testQuantity, _ := decimal.NewFromString(report.TestQuantity) + passQuantity, _ := decimal.NewFromString(report.PassQuantity) + factoryMap[report.OrderDate[:7]] = []string{factoryMapTestQuantity.Add(testQuantity).String(), + factoryMapPassQuantity.Add(passQuantity).String()} + } + } + month := carbon.Now().SubYear().StartOfMonth().Format("Y-m") + for { + if month == carbon.Now().EndOfMonth().Format("Y-m") { + break + } + x = append(x, month) + if _, ok := factoryMap[month]; !ok { + lineY = append(lineY, "") + histogramY = append(histogramY, "") + } else { + testQuantity, _ := decimal.NewFromString(factoryMap[month][0]) + passQuantity, _ := decimal.NewFromString(factoryMap[month][1]) + passProbability := passQuantity.Div(testQuantity). + Round(4).Mul(decimal.NewFromFloat(100)) + passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String()) + if passProbabilityInt > max { + max = passProbabilityInt + 1 + } + if passProbabilityInt < min { + min = passProbabilityInt - 1 + } + lineY = append(lineY, passProbability.String()) + histogramY = append(histogramY, factoryMap[month][0]) + } + month = carbon.Parse(month).AddMonth().Format("Y-m") + } + lines = append(lines, &model.Line{ + Name: factory, + X: x, + Y: lineY, + }) + histogram = append(histogram, &model.Histogram{ + Field: factory, + X: x, + Y: histogramY, + }) + } + return lines, histogram, max, min +} + +func FTPassProbabilityByProduct(r *request.PassProbabilityByProduct) (*model.Line, *model.Histogram, *model.Line, *model.Histogram) { + var line, binLine *model.Line + var histogram, binHistogram *model.Histogram + max := math.MinInt + min := math.MaxInt + startDate := carbon.Now().SubYear().StartOfMonth().Format("Y-m-d") + endDate := carbon.Now().EndOfMonth().Format("Y-m-d") + var sql string + if r.Factory != "" { + sql += "factory = '" + r.Factory + "'" + } + var reports []*model.Report + global.PostGreSQL.Where("step = ? AND product = ? AND order_date BETWEEN ? AND ?", + r.Type, r.Product, startDate, endDate).Preload("BinFail", func(db *gorm.DB) *gorm.DB { + return db.Where("report_site_id = ?", 0) + }).Where(sql).Find(&reports) + productMap := make(map[string][]string) + binMap := make(map[string]float64) + var x, lineY, histogramY []string + for _, report := range reports { + if _, ok := productMap[report.OrderDate[:7]]; !ok { + productMap[report.OrderDate[:7]] = []string{report.TestQuantity, report.PassQuantity} + } else { + factoryMapTestQuantity, _ := decimal.NewFromString(productMap[report.OrderDate[:7]][0]) + factoryMapPassQuantity, _ := decimal.NewFromString(productMap[report.OrderDate[:7]][1]) + testQuantity, _ := decimal.NewFromString(report.TestQuantity) + passQuantity, _ := decimal.NewFromString(report.PassQuantity) + productMap[report.OrderDate[:7]] = []string{factoryMapTestQuantity.Add(testQuantity).String(), + factoryMapPassQuantity.Add(passQuantity).String()} + } + for _, binFail := range report.BinFail { + if _, ok := binMap[binFail.HardBin]; !ok { + binMap[binFail.HardBin] = 0 + } + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + binMap[binFail.HardBin] += quantity + } + } + month := carbon.Now().SubYear().StartOfMonth().Format("Y-m") + var testStr, passStr string + for { + if month == carbon.Now().EndOfMonth().Format("Y-m") { + break + } + x = append(x, month) + if _, ok := productMap[month]; !ok { + lineY = append(lineY, "") + histogramY = append(histogramY, "") + } else { + testQuantity, _ := decimal.NewFromString(productMap[month][0]) + passQuantity, _ := decimal.NewFromString(productMap[month][1]) + testDecimal, _ := decimal.NewFromString(testStr) + passDecimal, _ := decimal.NewFromString(passStr) + testStr = testDecimal.Add(testQuantity).String() + passStr = passDecimal.Add(passQuantity).String() + passProbability := passQuantity.Div(testQuantity). + Round(4).Mul(decimal.NewFromFloat(100)) + passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String()) + if passProbabilityInt > max { + max = passProbabilityInt + 1 + } + if passProbabilityInt < min { + min = passProbabilityInt - 1 + } + lineY = append(lineY, passProbability.String()) + histogramY = append(histogramY, productMap[month][0]) + } + month = carbon.Parse(month).AddMonth().Format("Y-m") + } + var binX, binHistogramY, binLineY []string + for bin := range binMap { + if bin != "1" { + binX = append(binX, bin) + } + } + sort.Slice(binX, func(i, j int) bool { + return binMap[binX[i]] > binMap[binX[j]] + }) + var accumulation float64 + testDecimal, _ := decimal.NewFromString(testStr) + passDecimal, _ := decimal.NewFromString(passStr) + failQuantity, _ := testDecimal.Sub(passDecimal).Float64() + for _, bin := range binX { + binHistogramY = append(binHistogramY, decimal.NewFromFloat(binMap[bin]).String()) + accumulation += binMap[bin] + binLineY = append(binLineY, decimal.NewFromFloat(accumulation).Div(decimal.NewFromFloat(failQuantity)). + Round(4).Mul(decimal.NewFromFloat(100)).String()) + } + line = &model.Line{ + Name: r.Product, + X: x, + Y: lineY, + } + histogram = &model.Histogram{ + Field: r.Product, + X: x, + Y: histogramY, + } + binLine = &model.Line{ + Name: r.Product, + X: binX, + Y: binLineY, + } + binHistogram = &model.Histogram{ + Field: r.Product, + X: binX, + Y: binHistogramY, + } + return line, histogram, binLine, binHistogram +} diff --git a/repository/test.data/report.go b/repository/test.data/report.go new file mode 100644 index 0000000..88bb772 --- /dev/null +++ b/repository/test.data/report.go @@ -0,0 +1,743 @@ +package test_data + +import ( + "bufio" + "encoding/json" + "errors" + "gitee.com/golang-module/carbon/v2" + "github.com/shopspring/decimal" + "github.com/xuri/excelize/v2" + "gorm.io/gorm" + "log" + "os" + "strconv" + "strings" + "testData/global" + "testData/model" + "time" +) + +//func Emails() { +// fmt.Println("Connecting to server...") +// +// // Connect to server +// c, err := client.DialTLS("imap.exmail.qq.com:993", nil) +// if err != nil { +// fmt.Println("连接IMAP服务器出错:", err) +// return +// } +// fmt.Println("Connected QQ Imap Receive Server(imap.exmail.qq.com)...") +// +// // Login +// if err = c.Login("wip@tkplusemi.com", "Tkpluse123ip"); err != nil { +// fmt.Println("登陆IMAP服务器出错:", err) +// return +// } +// //if err := c.Login("jh_peng@tkplusemi.com", "Jimmy123"); err != nil { +// // log.Fatal(err) +// //} +// fmt.Println("Logged in...") +// +// global.IMAP = c +// +// // List mailboxes +// mailboxes := make(chan *imap.MailboxInfo, 10) +// done := make(chan error, 10) +// go func() { +// done <- global.IMAP.List("", "*", mailboxes) +// }() +// log.Println("Mailboxes:") +// for m := range mailboxes { +// fmt.Println("* " + m.Name) +// } +// +// if err := <-done; err != nil { +// fmt.Println(err) +// } +// +// // Select INBOX +// mbox, err := global.IMAP.Select("INBOX", false) +// if err != nil { +// fmt.Println(err) +// } +// fmt.Println("mbox:", mbox) +// //fmt.Println("Flags for INBOX:", mbox.Flags) +// +// // 创建搜索条件 +// criteria := imap.NewSearchCriteria() +// // 搜索未读标志的邮件 +// criteria.WithoutFlags = []string{"\\Seen"} +// // 获取未读标志邮件的UID +// ids, _ := global.IMAP.UidSearch(criteria) +// // 按UID获取邮件 +// seqset := new(imap.SeqSet) +// seqset.AddNum(ids...) +// +// // 获取邮件 +// messages := make(chan *imap.Message) +// section := imap.BodySectionName{} +// // 获取邮件标志, 内容 +// items := []imap.FetchItem{imap.FetchFlags, section.FetchItem()} +// done = make(chan error, len(ids)) +// go func() { +// // 按UID获取邮件 +// done <- global.IMAP.UidFetch(seqset, items, messages) +// }() +// +// var index int +// var factorys []*model.Factory +// global.PostGreSQL.Find(&factorys) +// +// imap.CharsetReader = charset.Reader +// for msg := range messages { +// start := time.Now() +// r := msg.GetBody(§ion) +// if r == nil { +// log.Println("服务器未返回邮件正文") +// } +// fmt.Printf("获取邮件内容耗时:%s\n", time.Now().Sub(start).String()) +// mr, err := mail.CreateReader(r) +// if err != nil { +// log.Fatal(err) +// } +// header := mr.Header +// var subject string +// // 获取邮件发件人 +// if from, err := header.AddressList("From"); err == nil { +// fmt.Println(from[0].Address) +// startFrom := time.Now() +// address := from[0].Address +// if orgsender, err := header.AddressList("X-Qq-Csender"); err == nil { // X-Qq-Orgsender +// if len(orgsender) > 0 && orgsender[0].Address != "" { +// address = orgsender[0].Address +// } +// } +// if len(from) != 1 { +// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String()) +// fmt.Printf("当前邮件处理From耗时:%s\n", time.Now().Sub(startFrom).String()) +// continue +// } +// var needHandle bool +// for j := 0; j < len(factorys); j++ { +// if address != factorys[j].Email { +// continue +// } +// // 获取邮件主题 +// if subject, err = header.Subject(); err == nil { +// if !strings.Contains(subject, factorys[j].Keyword) || factorys[j].Keyword == "" { +// continue +// } +// needHandle = true +// index = j +// log.Println("Subject:", subject) +// } +// +// } +// if !needHandle { +// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String()) +// fmt.Printf("当前邮件处理From耗时:%s\n", time.Now().Sub(startFrom).String()) +// continue +// } +// log.Println("From:", from) +// } +// var companyName string +// companyName = factorys[index].Name +// // 处理邮件正文 +// for { +// p, err := mr.NextPart() +// if err == io.EOF { +// break +// } else if err != nil { +// log.Fatal("NextPart:err ", err) +// } +// switch h := p.Header.(type) { +// case *mail.AttachmentHeader: +// // 正文内附件 +// b, _ := ioutil.ReadAll(p.Body) +// filename, _ := h.Filename() +// var a []byte +// p.Body.Read(a) +// suffixIndex := strings.LastIndex(filename, ".") +// suffix := strings.ToLower(filename[suffixIndex:]) +// filename = filename[:suffixIndex] + suffix +// if suffix != ".xlsx" && suffix != ".xls" && suffix != ".csv" { +// continue +// } +// +// // 根据公司名生成文件路径 +// folderPath := utils.MakeSavePath(companyName) +// var newFileName string +// if strings.Contains(filename, ".xlsx") { +// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xlsx")) +// f, _ := os.OpenFile(newFileName, os.O_RDWR|os.O_CREATE, 0766) +// _, err = f.Write(b) +// if err != nil { +// log.Println("download file", filename, "err") +// _ = os.Remove(filename) +// } +// f.Close() +// } else if strings.Contains(filename, ".xls") { +// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xls")) +// f, _ := os.OpenFile(newFileName, os.O_RDWR|os.O_CREATE, 0766) +// _, err = f.Write(b) +// if err != nil { +// log.Println("download file", filename, "err") +// _ = os.Remove(filename) +// } +// _ = f.Close() +// utils.ToXlsx("xls", newFileName) +// newFileName += ".xlsx" +// } else if strings.Contains(filename, ".csv") { +// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xlsx")) +// rows := strings.Split(string(b), "\r\n") +// f := excelize.NewFile() +// // 获取Sheet工作表名称 +// sheetName := f.GetSheetName(0) +// for i := 0; i < len(rows); i++ { +// columns := strings.Split(rows[i], ",") +// _ = f.SetSheetRow(sheetName, string(byte(65))+strconv.Itoa(i+1), &columns) +// } +// _ = f.SaveAs(newFileName) +// _ = f.Close() +// } +// // 处理Excel +// switch companyName { +// +// } +// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String()) +// default: +// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String()) +// continue +// } +// } +// } +// // 添加标志 +// item := imap.FormatFlagsOp(imap.AddFlags, true) +// // 已读标志\Seen +// flags := []interface{}{imap.SeenFlag} +// // 将处理的未读邮件设置为已读 +// err = global.IMAP.UidStore(seqset, item, flags, nil) +// if err != nil { +// log.Println(err) +// } +// global.IMAP.Logout() +//} + +func SMCFT(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := "FT0801 test Yield(" + carbon.Now().SubMonth().Format("Y.m") + ")" + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 3 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[1] { + title[cell] = index + } + var fTReports []*model.Report + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + for i := 2; i < len(rows); i++ { + var tcSFDFile *model.TcSfdFile + tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["客户订单号"]], rows[i][title["客户批号"]]).Find(&tcSFDFile) + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号"]], "-")[1][:6]).Format("Y-m-d") + fTReports = append(fTReports, &model.Report{ + Product: rows[i][title["完成型号"]], + Lot: rows[i][title["客户批号"]], + Factory: "saimeike", + TestProgram: rows[i][title["测试程序"]], + PBI: rows[i][title["客户订单号"]], + SubBatch: rows[i][title["厂内批号"]], + OrderDate: orderDate, + Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""), + TestQuantity: rows[i][title["主数量"]], + PassQuantity: rows[i][title["PASS数"]], + PassProbability: rows[i][title["良率"]], + Step: "FT", + }) + } + return nil + }) + global.PostGreSQL.Create(&fTReports) +} + +func QiPaiFT(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := file.GetSheetName(1) + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 2 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[0] { + title[cell] = index + } + var fTReports []*model.Report + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + for i := 1; i < len(rows); i++ { + var tcSFDFile *model.TcSfdFile + tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["客户订单编号"]], rows[i][title["芯片批号"]]).Find(&tcSFDFile) + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单编号"]], "-")[1][:6]).Format("Y-m-d") + fTReports = append(fTReports, &model.Report{ + Product: rows[i][title["出货品名"]], + Lot: rows[i][title["芯片批号"]], + Factory: "qipai", + TestProgram: "", + PBI: rows[i][title["客户订单编号"]], + SubBatch: rows[i][title["组装批次"]], + OrderDate: orderDate, + Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""), + TestQuantity: rows[i][title["订单数量"]], + PassQuantity: rows[i][title["入库良品数量"]], + PassProbability: rows[i][title["总良率"]], + Step: "FT", + }) + } + return nil + }) + global.PostGreSQL.Create(&fTReports) +} + +func QingYiFT(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := "Test " + time.Now().Format("01") + "月" + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 4 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[2] { + title[cell] = index + } + var fTReports []*model.Report + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + for i := 3; i < len(rows); i++ { + var tcSFDFile *model.TcSfdFile + tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["订单号"]], rows[i][title["下单批号"]]).Find(&tcSFDFile) + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["订单号"]], "-")[1][:6]).Format("Y-m-d") + fTReports = append(fTReports, &model.Report{ + Product: rows[i][title["产品型号"]], + Lot: rows[i][title["下单批号"]], + Factory: "qingyi", + TestProgram: rows[i][title["测试程序"]], + PBI: rows[i][title["订单号"]], + SubBatch: rows[i][title["厂内批号"]], + OrderDate: orderDate, + Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""), + TestQuantity: rows[i][title["测试投入数"]], + PassQuantity: rows[i][title["测试良品数"]], + PassProbability: rows[i][title["良率"]], + Step: "FT", + }) + } + return nil + }) + global.PostGreSQL.Create(&fTReports) +} + +func RuiSiFT(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := file.GetSheetName(1) + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 2 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[0] { + title[strings.ReplaceAll(cell, " ", "")] = index + } + var fTReports []*model.Report + for i := 1; i < len(rows); i++ { + if rows[i][0] == "" { + break + } + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["订单号码"]], "-")[1][:6]).Format("Y-m-d") + quantityDecimal, _ := decimal.NewFromString(rows[i][title["数量"]]) + failDecimal, _ := decimal.NewFromString(rows[i][title["不良品数量"]]) + missingDecimal, _ := decimal.NewFromString(rows[i][title["缺失数量"]]) + fTReports = append(fTReports, &model.Report{ + Product: rows[i][title["产品型号"]], + Lot: rows[i][title["LOTNO"]], + Factory: "ruisi", + TestProgram: rows[i][title["测试程序"]], + PBI: rows[i][title["订单号码"]], + SubBatch: rows[i][title["厂内批号"]], + OrderDate: orderDate, + Seal: rows[i][title["印字内容"]], + TestQuantity: rows[i][title["数量"]], + PassQuantity: quantityDecimal.Sub(failDecimal).Sub(missingDecimal).String(), + PassProbability: rows[i][title["良率"]], + Step: "FT", + }) + } + global.PostGreSQL.Create(&fTReports) +} + +func SuQianChangDianFT(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := file.GetSheetName(0) + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 2 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[0] { + title[strings.ReplaceAll(cell, "\n", "")] = index + } + var fTReports []*model.Report + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + for i := 1; i < len(rows); i++ { + var tcSFDFile *model.TcSfdFile + tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["订单号"]], rows[i][title["下单批号"]]).Find(&tcSFDFile) + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号order number"]], "-")[1][:6]).Format("Y-m-d") + fTReports = append(fTReports, &model.Report{ + Product: rows[i][title["产品型号Device"]], + Lot: rows[i][title["客户批号Customer lot"]], + Factory: "changdian", + TestProgram: rows[i][title["测试程序test program"]], + PBI: rows[i][title["客户订单号order number"]], + SubBatch: rows[i][title["扩散批号wafer lot"]], + OrderDate: orderDate, + Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""), + TestQuantity: rows[i][title["投料量order quantity"]], + PassQuantity: rows[i][title["测试流出数Test out"]], + PassProbability: rows[i][title["测试良率yield of test"]], + Step: "FT", + }) + } + return nil + }) + global.PostGreSQL.Create(&fTReports) +} + +func SMCCP(filePath string) { + file, _ := excelize.OpenFile(filePath) + sheetName := file.GetSheetName(0) + rows, err := file.GetRows(sheetName) + if err != nil { + log.Println(err) + } + if len(rows) < 7 { + log.Println("Sheet ", sheetName, "格式不规范") + return + } + title := make(map[string]int) + for index, cell := range rows[0] { + title[cell] = index + } + rows[2][0] = strings.ReplaceAll(rows[2][0], ":", ":") + rows[2][0] = strings.ReplaceAll(rows[2][0], ": ", ":") + infosArray := strings.Split(rows[2][0], " ") + m := make(map[string]string) + for _, infos := range infosArray { + if infos != "" { + info := strings.Split(infos, ":") + m[info[0]] = info[1] + } + } + var cpReports []*model.Report + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + for i := 1; i < len(rows); i++ { + if rows[i][0] == "Total" { + break + } + var tcSFDFile *model.TcSfdFile + tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", m["型号"], m["批号"]).Find(&tcSFDFile) + orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号order number"]], "-")[1][:6]).Format("Y-m-d") + cpReports = append(cpReports, &model.Report{ + Product: m["出货型号"], + Lot: rows[i][title["客户批号Customer lot"]], + Factory: "saimeike", + TestProgram: m["测试程序名"], + PBI: "", + OrderDate: orderDate, + TestQuantity: rows[i][title["Total"]], + PassQuantity: rows[i][title["Pass"]], + PassProbability: rows[i][title["良率(%)"]], + WaferID: rows[i][title["片号"]], + TestTime: rows[i][title["测试时间"]], + Step: m["测试工步"], + }) + } + return nil + }) + global.PostGreSQL.Create(&cpReports) +} + +func SaveCP(pbi, product, lot, waferID string, report *model.Report) { + var fileHandle *model.FileHandled + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", pbi, product, lot, waferID). + Find(&fileHandle) + + f, err := os.Open(fileHandle.Path) + if err != nil { + log.Println(err) + return + } + defer f.Close() + scanner := bufio.NewScanner(f) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + + sbinHbinMap := make(map[string]map[string]string) + sbinHbinByte := []byte(fileHandle.SbinHbin) + _ = json.Unmarshal(sbinHbinByte, &sbinHbinMap) + binCounter := make(map[string]int) + firstBinCounter := make(map[string]int) + firstBinCounters := make(map[string]map[string]int) + var latestDatas [][]string + var firstDatas [][]string + for _, data := range datas { + isAppendData := true + for _, mainData := range latestDatas { + if mainData[0] == data[fieldMap["X_COORD"]] && mainData[1] == data[fieldMap["Y_COORD"]] { + mainData = []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]], + data[fieldMap["SITE_NUM"]], data[fieldMap["SOFT_BIN"]]} + isAppendData = false + break + } + } + if isAppendData { + latestDatas = append(latestDatas, []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]], data[fieldMap["SITE_NUM"]], + data[fieldMap["SOFT_BIN"]]}) + firstDatas = append(firstDatas, []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]], data[fieldMap["SITE_NUM"]], + data[fieldMap["SOFT_BIN"]]}) + } + } + for _, mainData := range latestDatas { + binCounter[mainData[3]]++ + //if _, ok := siteCounters[mainData[2]]; !ok { + // siteCounters[mainData[2]] = make(map[string]int) + //} + //siteCounters[mainData[2]][mainData[3]]++ + } + for _, siteData := range firstDatas { + firstBinCounter[siteData[3]]++ + if _, ok := firstBinCounters[siteData[2]]; !ok { + firstBinCounters[siteData[2]] = make(map[string]int) + } + firstBinCounters[siteData[2]][siteData[3]]++ + } + + firstPassProbabilityDecimal := decimal.NewFromFloat(float64(firstBinCounter["1"]) / float64(len(firstDatas)) * 100).Round(2).String() + passProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]) / float64(len(latestDatas)) * 100).Round(2).String() + global.PostGreSQL.Model(&report).Updates(map[string]interface{}{ + "test_quantity": strconv.Itoa(len(latestDatas)), + "first_pass_quantity": strconv.Itoa(firstBinCounter["1"]), + "first_pass_probability": firstPassProbabilityDecimal, + "pass_quantity": strconv.Itoa(binCounter["1"]), + "pass_probability": passProbabilityDecimal + "%", + }) + var binFail []*model.BinFail + for bin, num := range binCounter { + binFail = append(binFail, &model.BinFail{ + ReportID: report.ID, + HardBin: sbinHbinMap[bin]["HBin"], + SoftBin: bin, + Quantity: strconv.Itoa(num), + }) + } + var siteReports []*model.ReportSites + for site := range firstBinCounters { + siteReports = append(siteReports, &model.ReportSites{ + ReportID: report.ID, + Site: site, + }) + } + global.PostGreSQL.Create(&siteReports) + siteReports = []*model.ReportSites{} + global.PostGreSQL.Where("report_id = ?", report.ID).Find(&siteReports) + for _, siteReport := range siteReports { + var sum, pass int + for bin, num := range firstBinCounters[siteReport.Site] { + sum += num + if bin == "1" { + pass += num + } + binFail = append(binFail, &model.BinFail{ + ReportID: report.ID, + ReportSiteID: siteReport.ID, + HardBin: sbinHbinMap[bin]["HBin"], + SoftBin: bin, + Quantity: strconv.Itoa(num), + }) + } + sumDecimal := decimal.NewFromInt(int64(sum)) + passDecimal := decimal.NewFromInt(int64(pass)) + global.PostGreSQL.Model(&siteReport).Updates(map[string]interface{}{ + "test_quantity": sumDecimal.String(), + "pass_quantity": passDecimal.String(), + "pass_probability": passDecimal.Div(sumDecimal).Mul(decimal.NewFromInt(100)).Round(2).String() + "%", + }) + } + global.PostGreSQL.Create(&binFail) +} + +func SaveFT(report *model.Report) { //pbi, product, lot, subBatch string, + var ftFile *model.FileHandled + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND sub_batch = ? AND step = ?", + report.PBI, report.Product, report.Lot, report.SubBatch, "FT").Find(&ftFile) + + ft, err := os.Open(ftFile.Path) + if err != nil { + log.Println(err) + return + } + defer ft.Close() + scanner := bufio.NewScanner(ft) + datas := make([][]string, 0) + fieldMap := make(map[string]int) + for scanner.Scan() { + line := scanner.Text() + s := strings.Split(line, ",") + datas = append(datas, s[:len(s)-1]) + if len(datas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + fieldMap[cell] = index + } + } + } + if len(datas) >= 1 { + datas = datas[1:] + } + + sbinHbinMap := make(map[string]map[string]string) + sbinHbinByte := []byte(ftFile.SbinHbin) + _ = json.Unmarshal(sbinHbinByte, &sbinHbinMap) + binCounter := make(map[string]int) + siteCounters := make(map[string]map[string]int) + for _, data := range datas { + binCounter[data[fieldMap["SOFT_BIN"]]]++ + if _, ok := siteCounters[data[fieldMap["SITE_NUM"]]]; !ok { + siteCounters[data[fieldMap["SITE_NUM"]]] = make(map[string]int) + } + siteCounters[data[fieldMap["SITE_NUM"]]][data[fieldMap["SOFT_BIN"]]]++ + } + + var rtFile *model.FileHandled + var passCounter int + if !errors.Is(global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND sub_batch = ? AND step = ?", + report.PBI, report.Product, report.Lot, report.SubBatch, "RT"). + Find(&rtFile).Error, gorm.ErrRecordNotFound) { + rt, err := os.Open(rtFile.Path) + if err != nil { + log.Println(err) + } + defer rt.Close() + rtScanner := bufio.NewScanner(rt) + rtDatas := make([][]string, 0) + rtFieldMap := make(map[string]int) + for rtScanner.Scan() { + line := rtScanner.Text() + s := strings.Split(line, ",") + rtDatas = append(rtDatas, s[:len(s)-1]) + if len(rtDatas) == 1 { + for index, cell := range s { + if index == len(s)-1 { + continue + } + rtFieldMap[cell] = index + } + } + } + if len(rtDatas) >= 1 { + rtDatas = rtDatas[1:] + } + for _, rtData := range rtDatas { + if rtData[rtFieldMap["SOFT_BIN"]] == "1" { + passCounter++ + } + } + } + + firstPassProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]) / float64(len(datas)) * 100).Round(2).String() + passProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]+passCounter) / float64(len(datas)) * 100).Round(2).String() + global.PostGreSQL.Model(&report).Updates(map[string]interface{}{ + "test_quantity": strconv.Itoa(len(datas)), + "first_pass_quantity": strconv.Itoa(binCounter["1"]), + "first_pass_probability": firstPassProbabilityDecimal + "%", + "pass_quantity": strconv.Itoa(binCounter["1"] + passCounter), + "pass_probability": passProbabilityDecimal + "%", + }) + var binFail []*model.BinFail + for bin, num := range binCounter { + binFail = append(binFail, &model.BinFail{ + ReportID: report.ID, + HardBin: sbinHbinMap[bin]["HBin"], + SoftBin: bin, + Quantity: strconv.Itoa(num), + }) + } + var siteReports []*model.ReportSites + for site := range siteCounters { + siteReports = append(siteReports, &model.ReportSites{ + ReportID: report.ID, + Site: site, + }) + } + global.PostGreSQL.Create(&siteReports) + siteReports = []*model.ReportSites{} + global.PostGreSQL.Where("report_id = ?", report.ID).Find(&siteReports) + for _, siteReport := range siteReports { + var sum, pass int + for bin, num := range siteCounters[siteReport.Site] { + sum += num + if bin == "1" { + pass += num + } + binFail = append(binFail, &model.BinFail{ + ReportID: report.ID, + ReportSiteID: siteReport.ID, + HardBin: sbinHbinMap[bin]["HBin"], + SoftBin: bin, + Quantity: strconv.Itoa(num), + }) + } + sumDecimal := decimal.NewFromInt(int64(sum)) + passDecimal := decimal.NewFromInt(int64(pass)) + global.PostGreSQL.Model(&siteReport).Updates(map[string]interface{}{ + "test_quantity": sumDecimal.String(), + "pass_quantity": passDecimal.String(), + "pass_probability": passDecimal.Div(sumDecimal).Mul(decimal.NewFromInt(100)).Round(2).String() + "%", + }) + } + global.PostGreSQL.Create(&binFail) +} diff --git a/repository/test.data/report.list.go b/repository/test.data/report.list.go new file mode 100644 index 0000000..5ac2a21 --- /dev/null +++ b/repository/test.data/report.list.go @@ -0,0 +1,1141 @@ +package test_data + +import ( + "gitee.com/golang-module/carbon/v2" + "github.com/shopspring/decimal" + "gorm.io/gorm" + "sort" + "strconv" + "strings" + "testData/global" + "testData/model" + "testData/request" +) + +func WaferList(r *request.WaferList) []*model.WaferList { + var sql string + if r.OrderDate != "" { + sql += "pmm04 = DATE '" + r.OrderDate + "'" + } + if r.PBI != "" { + if sql != "" { + sql += " AND pmm01 = '" + r.PBI + "'" + } else { + sql += "pmm01 = '" + r.PBI + "'" + } + } + if r.Factory != "" { + var pmc *model.PmcFile + global.Oracle.Where("pmc03 LIKE ?", "%"+r.Factory+"%").Find(&pmc) + if sql != "" { + sql += " AND pmm09 = '" + pmc.Pmc01 + "'" + } else { + sql += "pmm09 = '" + pmc.Pmc01 + "'" + } + } + + var pmms []*model.PmmFile + global.Oracle.Where("pmm02 = ? ", "WB0").Where(sql). + Preload("PmnFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile") + }).Preload("PmcFile").Preload("RvbFile", func(db *gorm.DB) *gorm.DB { + return db.Order("rvb12 desc") + }).Order("pmm01 desc").Find(&pmms) + + var waferList []*model.WaferList + for _, pmm := range pmms { + if r.WaferSize != "" && r.WaferSize != pmm.PmnFile.ImaFile.Ima021 { + continue + } + if r.Quantity != "" { + quantity, _ := strconv.ParseFloat(r.Quantity, 64) + if quantity != pmm.PmnFile.Pmn20 { + continue + } + } + if r.OnlineQuantity != "" { + quantity, _ := strconv.ParseFloat(r.OnlineQuantity, 64) + if quantity != pmm.PmnFile.Pmn20-pmm.PmnFile.Pmn53 { + continue + } + } + if r.ReturnQuantity != "" { + quantity, _ := strconv.ParseFloat(r.ReturnQuantity, 64) + if quantity != pmm.PmnFile.Pmn53 { + continue + } + } + var returnDate, lot string + if len(pmm.RvbFile) > 0 { + returnDate = pmm.RvbFile[0].Rvb12.Format("2006-01-02") + lot = pmm.RvbFile[0].Rvb38 + } + if r.ReturnDate != "" && r.ReturnDate != returnDate { + continue + } + if r.Lot != "" && r.Lot != lot { + continue + } + waferList = append(waferList, &model.WaferList{ + OrderDate: pmm.Pmm04.Format("2006-01-02"), + PBI: pmm.Pmm01, + Product: pmm.PmnFile.Pmn041, + Factory: pmm.PmcFile.Pmc03, + WaferSize: pmm.PmnFile.ImaFile.Ima021, + Quantity: pmm.PmnFile.Pmn20, + OnlineQuantity: pmm.PmnFile.Pmn20 - pmm.PmnFile.Pmn53, + ReturnDate: returnDate, + Lot: lot, + ReturnQuantity: pmm.PmnFile.Pmn53, + }) + } + return waferList +} + +func ABList(r *request.ABList) []*model.ABList { + var sql string + if r.OrderDate != "" { + sql += "tc_sfc02 = DATE '" + r.OrderDate + "'" + } else { + start := carbon.Now().SubYears(2).Format("Y-m-d") + end := carbon.Now().Format("Y-m-d") + sql += "tc_sfc02 BETWEEN DATE '" + start + "' AND DATE '" + end + "'" + } + if r.PBI != "" { + if sql != "" { + sql += " AND tc_sfc01 = '" + r.PBI + "'" + } else { + sql += "tc_sfc01 = '" + r.PBI + "'" + } + } + if r.Factory != "" { + var pmc *model.PmcFile + global.Oracle.Where("pmc03 LIKE ?", "%"+r.Factory+"%").Find(&pmc) + if sql != "" { + sql += " AND tc_sfc04 = '" + pmc.Pmc01 + "'" + } else { + sql += "tc_sfc04 = '" + pmc.Pmc01 + "'" + } + } + var tcSfcFile []*model.TcSfcFile + var tcSfcFilePBIs []string + _ = global.Oracle.Transaction(func(tx *gorm.DB) error { + tx.Model(&model.TcSfcFile{}).Where("tc_sfc08 LIKE ? AND tc_sfc10 = ?", "%AB%", "N").Where(sql). + Order("tc_sfc01").Select("tc_sfc01").Find(&tcSfcFilePBIs) + page := len(tcSfcFilePBIs)/200 + 1 + for i := 0; i < page; i++ { + var pageTcSfcFile []*model.TcSfcFile + var s []string + if i == page-1 { + s = tcSfcFilePBIs[i*200:] + } else { + s = tcSfcFilePBIs[i*200 : (i+1)*200] + } + tx.Where("tc_sfc01 IN ? AND tc_sfc08 LIKE ?", s, "%AB%"). + Preload("TcSfdFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("SfbFile").Preload("ImaFile").Preload("RvaFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("IddFile") + }) + }).Preload("TcSfeFile", func(db *gorm.DB) *gorm.DB { + return db.Preload("ImaFile") + }). + Preload("PmcFile").Find(&pageTcSfcFile) + tcSfcFile = append(tcSfcFile, pageTcSfcFile...) + } + return nil + }) + + var abList []*model.ABList + for _, tcSfc := range tcSfcFile { + for _, tcSfd := range tcSfc.TcSfdFile { + if r.Product != "" && r.Product != tcSfd.ImaFile.Ima02 { + continue + } + if r.Package != "" && r.Package != tcSfd.ImaFile.Ima021 { + continue + } + if r.Lot != "" && r.Lot != tcSfd.TcSfd06 { + continue + } + if r.Seal != "" && r.Seal != tcSfd.TcSfdUd02 { + continue + } + if r.Quantity != "" { + quantity, _ := strconv.ParseFloat(r.Quantity, 64) + if quantity != tcSfd.TcSfd05 { + continue + } + } + if r.StockOutQuantity != "" { + quantity, _ := strconv.ParseFloat(r.StockOutQuantity, 64) + if quantity != tcSfd.TcSfd05 { + continue + } + } + var waferProduct, waferID string + var abWafer []*model.ABWaferList + for _, tcSfe := range tcSfc.TcSfeFile { + if tcSfe.TcSfe01 == tcSfc.TcSfc01 && tcSfe.TcSfe02 == tcSfd.TcSfd02 { + if tcSfe.TcSfe17 == "Y" { + waferProduct = tcSfe.ImaFile.Ima02 + waferID = tcSfe.TcSfe15 + } + abWafer = append(abWafer, &model.ABWaferList{ + Material: tcSfe.TcSfe04, + Product: tcSfe.ImaFile.Ima02, + Specification: tcSfe.ImaFile.Ima021, + Lot: tcSfe.TcSfe10, + WaferID: tcSfe.TcSfe15, + }) + } + } + if r.WaferProduct != "" && r.WaferProduct != waferProduct { + continue + } + if r.WaferID != "" && r.WaferID != waferID { + continue + } + var stockInQuantity, failQuantity, passQuantity, onlineQuantity float64 + for _, rva := range tcSfd.RvaFile { + for _, idd := range rva.IddFile { + stockInQuantity += idd.Idd13 + if idd.Idd06 == "BIN99" { + failQuantity += idd.Idd13 + } else { + passQuantity += idd.Idd13 + } + } + } + if r.StockInQuantity != "" { + quantity, _ := strconv.ParseFloat(r.StockInQuantity, 64) + if quantity != stockInQuantity { + continue + } + } + isFinish := "进行中" + if tcSfd.SfbFile.Sfb04 == "8" { + isFinish = "已完成" + } + if r.IsFinish != "" && r.IsFinish != isFinish { + continue + } + var passProbability string + if strings.Contains(tcSfc.TcSfc01, "M596") { + var reports []*model.Report + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ?", tcSfc.TcSfc01, tcSfd.ImaFile.Ima02, + tcSfd.TcSfd06).Find(&reports) + for _, report := range reports { + testQuantityDecimal, _ := decimal.NewFromString(report.TestQuantity) + testQuantityFloat, _ := testQuantityDecimal.Float64() + passQuantity += testQuantityFloat + } + if tcSfd.SfbFile.Sfb04 == "8" { + onlineQuantity = 0 + failQuantity = tcSfd.TcSfd05 - passQuantity + passProbability = decimal.NewFromFloat(passQuantity).Div(decimal.NewFromFloat(tcSfd.TcSfd05)). + Round(4).Mul(decimal.NewFromFloat(100)).String() + } + } else { + if tcSfd.SfbFile.Sfb04 == "8" { + onlineQuantity = 0 + failQuantity = tcSfd.TcSfd05 - passQuantity + passProbability = decimal.NewFromFloat(passQuantity).Div(decimal.NewFromFloat(tcSfd.TcSfd05)). + Round(4).Mul(decimal.NewFromFloat(100)).String() + } else { + onlineQuantity = tcSfd.TcSfd05 - stockInQuantity + passProbability = decimal.NewFromFloat(passQuantity).Div(decimal.NewFromFloat(tcSfd.TcSfd05)). + Round(4).Mul(decimal.NewFromFloat(100)).String() + } + } + if r.FailQuantity != "" { + quantity, _ := strconv.ParseFloat(r.FailQuantity, 64) + if quantity != failQuantity { + continue + } + } + if r.OnlineQuantity != "" { + quantity, _ := strconv.ParseFloat(r.OnlineQuantity, 64) + if quantity != onlineQuantity { + continue + } + } + if r.PassProbability != "" && r.PassProbability != passProbability+"%" { + continue + } + abList = append(abList, &model.ABList{ + OrderDate: tcSfc.TcSfc02.Format("2006-01-02"), + PBI: tcSfc.TcSfc01, + OutsourcingPBI: tcSfd.TcSfd13, + Product: tcSfd.ImaFile.Ima02, + WaferProduct: waferProduct, + Package: tcSfd.ImaFile.Ima021, + Factory: tcSfc.PmcFile.Pmc03, + Lot: tcSfd.TcSfd06, + Seal: tcSfd.TcSfdUd02, + WaferID: waferID, + Quantity: tcSfd.TcSfd05, + OnlineQuantity: onlineQuantity, + IsFinish: isFinish, + PassProbability: passProbability + "%", + StockOutQuantity: tcSfd.TcSfd05, + StockInQuantity: stockInQuantity, + FailQuantity: failQuantity, + ABWaferList: abWafer, + }) + } + } + return abList +} + +func CPList(r *request.CPList) ([]*model.ReportList, int64) { + var sql string + if r.WaferProduct != "" { + sql += "product = '" + r.WaferProduct + "'" + } + if r.Lot != "" { + if sql == "" { + sql += "lot ='" + r.Lot + "'" + } else { + sql += " AND lot = '" + r.Lot + "'" + } + } + if r.Factory != "" { + if sql == "" { + sql += "factory ='" + r.Factory + "'" + } else { + sql += " AND factory = '" + r.Factory + "'" + } + } + if r.TestMachine != "" { + if sql == "" { + sql += "test_machine ='" + r.TestMachine + "'" + } else { + sql += " AND test_machine = '" + r.TestMachine + "'" + } + } + if r.PBI != "" { + if sql == "" { + sql += "pbi ='" + r.PBI + "'" + } else { + sql += " AND pbi = '" + r.PBI + "'" + } + } + if r.OrderDate != "" { + if sql == "" { + sql += "order_date ='" + r.OrderDate + "'" + } else { + sql += " AND order_date = '" + r.OrderDate + "'" + } + } + if r.Page > 0 { + r.Page-- + } + var reportList []*model.ReportList + var total int64 + if r.QueryType == "List" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "CP").Order("pbi").Find(&reports).Count(&total). + Offset(r.Page * r.PageSize).Limit(r.PageSize).Find(&reports) + for _, report := range reports { + var finalReport *model.FinalReport + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND step = ?", + report.PBI, report.Product, report.Lot, "CP").Find(&finalReport) + isAppend := true + for _, list := range reportList { + if list.PBI == report.PBI { + firstPassQuantity, _ := decimal.NewFromString(report.FirstPassQuantity) + listFirstPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + testQuantity, _ := decimal.NewFromString(report.TestQuantity) + passQuantity, _ := decimal.NewFromString(report.PassQuantity) + listTestQuantity, _ := decimal.NewFromString(list.TestQuantity) + listPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + list.TestQuantity = testQuantity.Add(listTestQuantity).String() + list.PassQuantity = passQuantity.Add(listPassQuantity).String() + list.PassProbability = passQuantity.Add(listPassQuantity).Div(testQuantity.Add(listTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + + list.FirstPassQuantity = firstPassQuantity.Add(listFirstPassQuantity).String() + list.FirstPassProbability = firstPassQuantity.Add(listFirstPassQuantity).Div(testQuantity.Add(listTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + + isAppend = false + break + } + } + if isAppend { + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + ReportTestQuantity: finalReport.ReportTestQuantity, + ReportPassQuantity: finalReport.ReportPassQuantity, + ReportPassProbability: finalReport.ReportPassProbability, + TestTime: report.TestTime, + Step: "CP", + StackingMaterials: report.StackingMaterials, + }) + } + } + for _, reportlist := range reportList { + var testQuantityDiffLabel, passQuantityDiffLabel, returnProbabilityLabel bool + testQuantityDecimal, _ := decimal.NewFromString(reportlist.TestQuantity) + reportTestQuantityDecimal, _ := decimal.NewFromString(reportlist.ReportTestQuantity) + firstPassQuantityDecimal, _ := decimal.NewFromString(reportlist.FirstPassQuantity) + passQuantityDecimal, _ := decimal.NewFromString(reportlist.PassQuantity) + reportPassQuantityDecimal, _ := decimal.NewFromString(reportlist.ReportPassQuantity) + if !testQuantityDecimal.IsZero() { + diff := reportTestQuantityDecimal.Sub(testQuantityDecimal).Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if reportTestQuantityDecimal.Sub(testQuantityDecimal).LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(diff) { + testQuantityDiffLabel = true + } + reportlist.TestQuantityDiff = diff.String() + "%" + reportlist.TestQuantityDiffLabel = testQuantityDiffLabel + probability := passQuantityDecimal.Sub(firstPassQuantityDecimal).Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if probability.LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(probability) { + returnProbabilityLabel = true + } + reportlist.ReturnProbability = probability.String() + "%" + reportlist.ReturnProbabilityLabel = returnProbabilityLabel + } + if !reportPassQuantityDecimal.IsZero() { + diff := passQuantityDecimal.Sub(reportPassQuantityDecimal).Div(reportPassQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if passQuantityDecimal.Sub(reportPassQuantityDecimal).LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(diff) { + passQuantityDiffLabel = true + } + reportlist.PassQuantityDiff = diff.String() + "%" + reportlist.PassQuantityDiffLabel = passQuantityDiffLabel + } + } + } else if r.QueryType == "Bin" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "CP").Where(sql). + Preload("BinFail", func(db *gorm.DB) *gorm.DB { + return db.Where("report_site_id = ?", "0") + }).Preload("Site", func(db *gorm.DB) *gorm.DB { + return db.Preload("BinFail") + }).Order("pbi").Find(&reports) + for _, report := range reports { + isAppend := true + for _, list := range reportList { + if list.PBI == report.PBI { + //reportTestQuantity, _ := decimal.NewFromString(report.TestQuantity) + //reportPassQuantity, _ := decimal.NewFromString(report.PassQuantity) + //listTestQuantity, _ := decimal.NewFromString(list.TestQuantity) + //listPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + //list.TestQuantity = reportTestQuantity.Add(listTestQuantity).String() + //list.PassQuantity = reportPassQuantity.Add(listPassQuantity).String() + //list.PassProbability = reportPassQuantity.Add(listPassQuantity).Div(reportTestQuantity.Add(listTestQuantity)). + // Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + isAppend = false + + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + list.SoftBinFailMap[binFail.SoftBin] += quantity + list.HardBinFailMap[binFail.HardBin] += quantity + } + for _, site := range report.Site { + for _, reportSite := range list.Site { + if reportSite.Site == site.Site { + siteTestQuantity, _ := decimal.NewFromString(site.TestQuantity) + sitePassQuantity, _ := decimal.NewFromString(site.PassQuantity) + reportSiteTestQuantity, _ := decimal.NewFromString(reportSite.TestQuantity) + reportSitePassQuantity, _ := decimal.NewFromString(reportSite.PassQuantity) + reportSite.TestQuantity = siteTestQuantity.Add(reportSiteTestQuantity).String() + reportSite.PassQuantity = sitePassQuantity.Add(reportSitePassQuantity).String() + reportSite.PassProbability = sitePassQuantity.Add(reportSitePassQuantity).Div(siteTestQuantity.Add(reportSiteTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + reportSite.SoftBinFailMap[binFail.SoftBin] += quantity + reportSite.HardBinFailMap[binFail.HardBin] += quantity + } + break + } + } + } + break + } + } + if isAppend { + softBinFail, hardBinFail := make(map[string]float64), make(map[string]float64) + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + softBinFail[binFail.SoftBin] += quantity + hardBinFail[binFail.HardBin] += quantity + } + var reportListSites []*model.ReportListSites + for _, site := range report.Site { + siteSoftBinFail, siteHardBinFail := make(map[string]float64), make(map[string]float64) + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + siteSoftBinFail[binFail.SoftBin] += quantity + siteHardBinFail[binFail.HardBin] += quantity + } + reportListSites = append(reportListSites, &model.ReportListSites{ + ID: site.ID, + ReportID: site.ReportID, + Site: site.Site, + TestQuantity: site.TestQuantity, + PassQuantity: site.PassQuantity, + PassProbability: site.PassProbability, + SoftBinFailMap: siteSoftBinFail, + HardBinFailMap: siteHardBinFail, + }) + } + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + TestTime: report.TestTime, + Step: report.Step, + SoftBinFailMap: softBinFail, + HardBinFailMap: hardBinFail, + Site: reportListSites, + }) + } + } + for _, list := range reportList { + testQuantityDecimal, _ := decimal.NewFromString(list.TestQuantity) + var softBinFail, hardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range list.SoftBinFailMap { + softBinQuantityDecimal := decimal.NewFromFloat(softBinQuantity) + softBinFail = append(softBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + Proportion: softBinQuantityDecimal.Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(softBinFail, func(i, j int) bool { + return softBinFail[i].Quantity > softBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range list.HardBinFailMap { + hardBinQuantityDecimal := decimal.NewFromFloat(hardBinQuantity) + hardBinFail = append(hardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + Proportion: hardBinQuantityDecimal.Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(hardBinFail, func(i, j int) bool { + return hardBinFail[i].Quantity > hardBinFail[j].Quantity + }) + for _, site := range list.Site { + var siteSoftBinFail, siteHardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range site.SoftBinFailMap { + siteSoftBinFail = append(siteSoftBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + }) + } + sort.Slice(siteSoftBinFail, func(i, j int) bool { + return siteSoftBinFail[i].Quantity > siteSoftBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range site.HardBinFailMap { + siteHardBinFail = append(siteHardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + }) + } + sort.Slice(siteHardBinFail, func(i, j int) bool { + return siteHardBinFail[i].Quantity > siteHardBinFail[j].Quantity + }) + site.SoftBinFail = siteSoftBinFail + site.HardBinFail = siteHardBinFail + } + sort.Slice(list.Site, func(i, j int) bool { + iDecimal, _ := decimal.NewFromString(list.Site[i].PassProbability[:len(list.Site[i].PassProbability)-1]) + jDecimal, _ := decimal.NewFromString(list.Site[j].PassProbability[:len(list.Site[j].PassProbability)-1]) + return jDecimal.LessThan(iDecimal) + }) + list.SoftBinFail = softBinFail + list.HardBinFail = hardBinFail + } + } else if r.QueryType == "WaferID" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "CP").Where(sql). + Preload("BinFail", func(db *gorm.DB) *gorm.DB { + return db.Where("report_site_id = ?", "0") + }).Preload("Site", func(db *gorm.DB) *gorm.DB { + return db.Preload("BinFail") + }).Order("pbi").Find(&reports) + for _, report := range reports { + softBinFailMap, hardBinFailMap := make(map[string]float64), make(map[string]float64) + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + softBinFailMap[binFail.SoftBin] += quantity + hardBinFailMap[binFail.HardBin] += quantity + } + var reportListSites []*model.ReportListSites + for _, site := range report.Site { + siteSoftBinFailMap, siteHardBinFailMap := make(map[string]float64), make(map[string]float64) + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + siteSoftBinFailMap[binFail.SoftBin] += quantity + siteHardBinFailMap[binFail.HardBin] += quantity + } + var siteSoftBinFail, siteHardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range siteSoftBinFailMap { + siteSoftBinFail = append(siteSoftBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + }) + } + sort.Slice(siteSoftBinFail, func(i, j int) bool { + return siteSoftBinFail[i].Quantity > siteSoftBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range siteHardBinFailMap { + siteHardBinFail = append(siteHardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + }) + } + sort.Slice(siteHardBinFail, func(i, j int) bool { + return siteHardBinFail[i].Quantity > siteHardBinFail[j].Quantity + }) + reportListSites = append(reportListSites, &model.ReportListSites{ + ID: site.ID, + ReportID: site.ReportID, + Site: site.Site, + TestQuantity: site.TestQuantity, + PassQuantity: site.PassQuantity, + PassProbability: site.PassProbability, + SoftBinFailMap: siteSoftBinFailMap, + HardBinFailMap: siteHardBinFailMap, + SoftBinFail: siteSoftBinFail, + HardBinFail: siteHardBinFail, + }) + } + testQuantityDecimal, _ := decimal.NewFromString(report.TestQuantity) + var softBinFail, hardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range softBinFailMap { + softBinQuantityDecimal := decimal.NewFromFloat(softBinQuantity) + softBinFail = append(softBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + Proportion: softBinQuantityDecimal.Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(softBinFail, func(i, j int) bool { + return softBinFail[i].Quantity > softBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range hardBinFailMap { + hardBinQuantityDecimal := decimal.NewFromFloat(hardBinQuantity) + hardBinFail = append(hardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + Proportion: hardBinQuantityDecimal.Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(hardBinFail, func(i, j int) bool { + return hardBinFail[i].Quantity > hardBinFail[j].Quantity + }) + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + SubBatch: report.SubBatch, + WaferID: report.WaferID, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + TestTime: report.TestTime, + Step: report.Step, + StackingMaterials: report.StackingMaterials, + SoftBinFailMap: softBinFailMap, + HardBinFailMap: hardBinFailMap, + SoftBinFail: softBinFail, + HardBinFail: hardBinFail, + Site: reportListSites, + }) + } + } + sort.Slice(reportList, func(i, j int) bool { + iDecimal, _ := decimal.NewFromString(reportList[i].PassProbability[:len(reportList[i].PassProbability)-1]) + jDecimal, _ := decimal.NewFromString(reportList[j].PassProbability[:len(reportList[j].PassProbability)-1]) + return jDecimal.LessThan(iDecimal) + }) + return reportList, total +} + +func FTList(r *request.FTList) ([]*model.ReportList, int64) { + var sql string + if r.Product != "" { + sql += "product = '" + r.Product + "'" + } + if r.Lot != "" { + if sql == "" { + sql += "lot ='" + r.Lot + "'" + } else { + sql += " AND lot = '" + r.Lot + "'" + } + } + if r.Factory != "" { + if sql == "" { + sql += "factory ='" + r.Factory + "'" + } else { + sql += " AND factory = '" + r.Factory + "'" + } + } + if r.TestProgram != "" { + if sql == "" { + sql += "test_program ='" + r.TestProgram + "'" + } else { + sql += " AND test_program = '" + r.TestProgram + "'" + } + } + if r.PBI != "" { + if sql == "" { + sql += "pbi ='" + r.PBI + "'" + } else { + sql += " AND pbi = '" + r.PBI + "'" + } + } + if r.OrderDate != "" { + if sql == "" { + sql += "order_date ='" + r.OrderDate + "'" + } else { + sql += " AND order_date = '" + r.OrderDate + "'" + } + } + if r.Seal != "" { + if sql == "" { + sql += "seal ='" + r.Seal + "'" + } else { + sql += " AND seal = '" + r.Seal + "'" + } + } + if r.Page > 0 { + r.Page-- + } + var reportList []*model.ReportList + var total int64 + if r.QueryType == "List" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "FT").Order("pbi").Find(&reports).Count(&total). + Offset(r.Page * r.PageSize).Limit(r.PageSize).Find(&reports) + for _, report := range reports { + var finalReport *model.FinalReport + global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND step = ?", + report.PBI, report.Product, report.Lot, "FT").Find(&finalReport) + isAppend := true + for _, list := range reportList { + if list.PBI == report.PBI { + firstPassQuantity, _ := decimal.NewFromString(report.FirstPassQuantity) + listFirstPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + testQuantity, _ := decimal.NewFromString(report.TestQuantity) + passQuantity, _ := decimal.NewFromString(report.PassQuantity) + listTestQuantity, _ := decimal.NewFromString(list.TestQuantity) + listPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + list.TestQuantity = testQuantity.Add(listTestQuantity).String() + list.PassQuantity = passQuantity.Add(listPassQuantity).String() + list.PassProbability = passQuantity.Add(listPassQuantity).Div(testQuantity.Add(listTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + + list.FirstPassQuantity = firstPassQuantity.Add(listFirstPassQuantity).String() + list.PassProbability = firstPassQuantity.Add(listFirstPassQuantity).Div(testQuantity.Add(listTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + + //reportTestQuantity, _ := decimal.NewFromString(finalReport.ReportTestQuantity) + //reportPassQuantity, _ := decimal.NewFromString(finalReport.ReportPassQuantity) + //listReportTestQuantity, _ := decimal.NewFromString(list.ReportTestQuantity) + //listReportPassQuantity, _ := decimal.NewFromString(list.ReportPassQuantity) + //if !reportTestQuantity.Add(listReportTestQuantity).IsZero() { + // list.ReportTestQuantity = reportTestQuantity.Add(listReportTestQuantity).String() + // list.ReportPassQuantity = reportPassQuantity.Add(listReportPassQuantity).String() + // list.PassProbability = reportPassQuantity.Add(listReportPassQuantity).Div(reportTestQuantity.Add(listReportTestQuantity)). + // Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + //} + isAppend = false + break + } + } + if isAppend { + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + ReportTestQuantity: finalReport.ReportTestQuantity, + ReportPassQuantity: finalReport.ReportPassQuantity, + ReportPassProbability: finalReport.ReportPassProbability, + TestTime: report.TestTime, + Step: "FT", + StackingMaterials: report.StackingMaterials, + }) + } + } + for _, reportlist := range reportList { + var testQuantityDiffLabel, passQuantityDiffLabel, returnProbabilityLabel bool + testQuantityDecimal, _ := decimal.NewFromString(reportlist.TestQuantity) + reportTestQuantityDecimal, _ := decimal.NewFromString(reportlist.ReportTestQuantity) + firstPassQuantityDecimal, _ := decimal.NewFromString(reportlist.FirstPassQuantity) + passQuantityDecimal, _ := decimal.NewFromString(reportlist.PassQuantity) + reportPassQuantityDecimal, _ := decimal.NewFromString(reportlist.ReportPassQuantity) + if !testQuantityDecimal.IsZero() { + diff := reportTestQuantityDecimal.Sub(testQuantityDecimal).Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if reportTestQuantityDecimal.Sub(testQuantityDecimal).LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(diff) { + testQuantityDiffLabel = true + } + reportlist.TestQuantityDiff = diff.String() + "%" + reportlist.TestQuantityDiffLabel = testQuantityDiffLabel + probability := passQuantityDecimal.Sub(firstPassQuantityDecimal).Div(testQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if probability.LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(probability) { + returnProbabilityLabel = true + } + reportlist.ReturnProbability = probability.String() + "%" + reportlist.ReturnProbabilityLabel = returnProbabilityLabel + } + if !reportPassQuantityDecimal.IsZero() { + diff := passQuantityDecimal.Sub(reportPassQuantityDecimal).Div(reportPassQuantityDecimal).Round(4). + Mul(decimal.NewFromInt(100)) + if passQuantityDecimal.Sub(reportPassQuantityDecimal).LessThan(decimal.NewFromInt(0)) || + decimal.NewFromInt(5).LessThanOrEqual(diff) { + passQuantityDiffLabel = true + } + reportlist.PassQuantityDiff = diff.String() + "%" + reportlist.PassQuantityDiffLabel = passQuantityDiffLabel + } + } + } else if r.QueryType == "Bin" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "FT").Where(sql). + Preload("BinFail", func(db *gorm.DB) *gorm.DB { + return db.Where("report_site_id = ?", "0") + }).Preload("Site", func(db *gorm.DB) *gorm.DB { + return db.Preload("BinFail") + }).Order("pbi").Find(&reports) + for _, report := range reports { + isAppend := true + for _, list := range reportList { + if list.PBI == report.PBI { + reportTestQuantity, _ := decimal.NewFromString(report.TestQuantity) + reportPassQuantity, _ := decimal.NewFromString(report.PassQuantity) + listTestQuantity, _ := decimal.NewFromString(list.TestQuantity) + listPassQuantity, _ := decimal.NewFromString(list.PassQuantity) + list.TestQuantity = reportTestQuantity.Add(listTestQuantity).String() + list.PassQuantity = reportPassQuantity.Add(listPassQuantity).String() + list.PassProbability = reportPassQuantity.Add(listPassQuantity).Div(reportTestQuantity.Add(listTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + isAppend = false + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + list.SoftBinFailMap[binFail.SoftBin] += quantity + list.HardBinFailMap[binFail.HardBin] += quantity + } + for _, site := range report.Site { + for _, reportSite := range list.Site { + if reportSite.Site == site.Site { + siteTestQuantity, _ := decimal.NewFromString(site.TestQuantity) + sitePassQuantity, _ := decimal.NewFromString(site.PassQuantity) + reportSiteTestQuantity, _ := decimal.NewFromString(reportSite.TestQuantity) + reportSitePassQuantity, _ := decimal.NewFromString(reportSite.PassQuantity) + reportSite.TestQuantity = siteTestQuantity.Add(reportSiteTestQuantity).String() + reportSite.PassQuantity = sitePassQuantity.Add(reportSitePassQuantity).String() + reportSite.PassProbability = sitePassQuantity.Add(reportSitePassQuantity).Div(siteTestQuantity.Add(reportSiteTestQuantity)). + Round(4).Mul(decimal.NewFromInt(100)).String() + "%" + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + reportSite.SoftBinFailMap[binFail.SoftBin] += quantity + reportSite.HardBinFailMap[binFail.HardBin] += quantity + } + break + } + } + } + break + } + } + if isAppend { + softBinFail, hardBinFail := make(map[string]float64), make(map[string]float64) + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + softBinFail[binFail.SoftBin] += quantity + hardBinFail[binFail.HardBin] += quantity + } + var reportListSites []*model.ReportListSites + for _, site := range report.Site { + siteSoftBinFail, siteHardBinFail := make(map[string]float64), make(map[string]float64) + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + siteSoftBinFail[binFail.SoftBin] += quantity + siteHardBinFail[binFail.HardBin] += quantity + } + reportListSites = append(reportListSites, &model.ReportListSites{ + ID: site.ID, + ReportID: site.ReportID, + Site: site.Site, + TestQuantity: site.TestQuantity, + PassQuantity: site.PassQuantity, + PassProbability: site.PassProbability, + SoftBinFailMap: siteSoftBinFail, + HardBinFailMap: siteHardBinFail, + }) + } + //var finalReport *model.FinalReport + //if errors.Is(global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ?", + // report.PBI, report.Product, report.Lot).Find(&finalReport).Error, gorm.ErrRecordNotFound) { + // //finalReport.ReportTestQuantity = "" + // //finalReport.ReportPassQuantity = "" + // //finalReport.ReportPassProbability = "" + //} + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + //ReportTestQuantity: finalReport.ReportTestQuantity, + //ReportPassQuantity: finalReport.ReportPassQuantity, + //ReportPassProbability: finalReport.ReportPassProbability, + TestTime: report.TestTime, + Step: report.Step, + SoftBinFailMap: softBinFail, + HardBinFailMap: hardBinFail, + Site: reportListSites, + }) + } + } + for _, list := range reportList { + testQuantity, _ := decimal.NewFromString(list.TestQuantity) + + var softBinFail, hardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range list.SoftBinFailMap { + softBinQuantityDecimal := decimal.NewFromFloat(softBinQuantity) + softBinFail = append(softBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + Proportion: softBinQuantityDecimal.Div(testQuantity).Round(4).Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(softBinFail, func(i, j int) bool { + return softBinFail[i].Quantity > softBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range list.HardBinFailMap { + hardBinQuantityDecimal := decimal.NewFromFloat(hardBinQuantity) + hardBinFail = append(hardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + Proportion: hardBinQuantityDecimal.Div(testQuantity).Round(4).Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(hardBinFail, func(i, j int) bool { + return hardBinFail[i].Quantity > hardBinFail[j].Quantity + }) + for _, site := range list.Site { + var siteSoftBinFail, siteHardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range site.SoftBinFailMap { + siteSoftBinFail = append(siteSoftBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + }) + } + sort.Slice(siteSoftBinFail, func(i, j int) bool { + return siteSoftBinFail[i].Quantity > siteSoftBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range site.HardBinFailMap { + siteHardBinFail = append(siteHardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + }) + } + sort.Slice(siteHardBinFail, func(i, j int) bool { + return siteHardBinFail[i].Quantity > siteHardBinFail[j].Quantity + }) + site.SoftBinFail = siteSoftBinFail + site.HardBinFail = siteHardBinFail + } + sort.Slice(list.Site, func(i, j int) bool { + iDecimal, _ := decimal.NewFromString(list.Site[i].PassProbability[:len(list.Site[i].PassProbability)-1]) + jDecimal, _ := decimal.NewFromString(list.Site[j].PassProbability[:len(list.Site[j].PassProbability)-1]) + return jDecimal.LessThan(iDecimal) + }) + list.SoftBinFail = softBinFail + list.HardBinFail = hardBinFail + } + } else if r.QueryType == "SubBatch" { + var reports []*model.Report + global.PostGreSQL.Where("step = ?", "FT").Where(sql). + Preload("BinFail", func(db *gorm.DB) *gorm.DB { + return db.Where("report_site_id = ?", "0") + }).Preload("Site", func(db *gorm.DB) *gorm.DB { + return db.Preload("BinFail") + }).Order("pbi").Find(&reports) + for _, report := range reports { + softBinFailMap, hardBinFailMap := make(map[string]float64), make(map[string]float64) + for _, binFail := range report.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + softBinFailMap[binFail.SoftBin] += quantity + hardBinFailMap[binFail.HardBin] += quantity + } + var reportListSites []*model.ReportListSites + for _, site := range report.Site { + siteSoftBinFailMap, siteHardBinFailMap := make(map[string]float64), make(map[string]float64) + for _, binFail := range site.BinFail { + quantityDecimal, _ := decimal.NewFromString(binFail.Quantity) + quantity, _ := quantityDecimal.Float64() + siteSoftBinFailMap[binFail.SoftBin] += quantity + siteHardBinFailMap[binFail.HardBin] += quantity + } + var siteSoftBinFail, siteHardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range siteSoftBinFailMap { + siteSoftBinFail = append(siteSoftBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + }) + } + sort.Slice(siteSoftBinFail, func(i, j int) bool { + return siteSoftBinFail[i].Quantity > siteSoftBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range siteHardBinFailMap { + siteHardBinFail = append(siteHardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + }) + } + sort.Slice(siteHardBinFail, func(i, j int) bool { + return siteHardBinFail[i].Quantity > siteHardBinFail[j].Quantity + }) + reportListSites = append(reportListSites, &model.ReportListSites{ + ID: site.ID, + ReportID: site.ReportID, + Site: site.Site, + TestQuantity: site.TestQuantity, + PassQuantity: site.PassQuantity, + PassProbability: site.PassProbability, + SoftBinFailMap: siteSoftBinFailMap, + HardBinFailMap: siteHardBinFailMap, + SoftBinFail: siteSoftBinFail, + HardBinFail: siteHardBinFail, + }) + } + sort.Slice(reportListSites, func(i, j int) bool { + iDecimal, _ := decimal.NewFromString(reportListSites[i].PassProbability[:len(reportListSites[i].PassProbability)-1]) + jDecimal, _ := decimal.NewFromString(reportListSites[j].PassProbability[:len(reportListSites[j].PassProbability)-1]) + return jDecimal.LessThan(iDecimal) + }) + testQuantityDecimal, _ := decimal.NewFromString(report.TestQuantity) + var softBinFail, hardBinFail []*model.ReportBinFail + for softBin, softBinQuantity := range softBinFailMap { + softBinQuantityDecimal := decimal.NewFromFloat(softBinQuantity) + softBinFail = append(softBinFail, &model.ReportBinFail{ + Bin: softBin, + Quantity: softBinQuantity, + Proportion: softBinQuantityDecimal.Div(testQuantityDecimal).Round(4).Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(softBinFail, func(i, j int) bool { + return softBinFail[i].Quantity > softBinFail[j].Quantity + }) + for hardBin, hardBinQuantity := range hardBinFailMap { + hardBinQuantityDecimal := decimal.NewFromFloat(hardBinQuantity) + hardBinFail = append(hardBinFail, &model.ReportBinFail{ + Bin: hardBin, + Quantity: hardBinQuantity, + Proportion: hardBinQuantityDecimal.Div(testQuantityDecimal).Round(4).Mul(decimal.NewFromInt(100)).String() + "%", + }) + } + sort.Slice(hardBinFail, func(i, j int) bool { + return hardBinFail[i].Quantity > hardBinFail[j].Quantity + }) + reportList = append(reportList, &model.ReportList{ + Product: report.Product, + Lot: report.Lot, + SubBatch: report.SubBatch, + Factory: report.Factory, + TestMachine: report.TestMachine, + TestProgram: report.TestProgram, + PBI: report.PBI, + OrderDate: report.OrderDate, + Seal: report.Seal, + TestQuantity: report.TestQuantity, + FirstPassQuantity: report.FirstPassQuantity, + FirstPassProbability: report.FirstPassProbability, + PassQuantity: report.PassQuantity, + PassProbability: report.PassProbability, + TestTime: report.TestTime, + Step: report.Step, + SoftBinFailMap: softBinFailMap, + HardBinFailMap: hardBinFailMap, + StackingMaterials: report.StackingMaterials, + SoftBinFail: softBinFail, + HardBinFail: hardBinFail, + Site: reportListSites, + }) + } + sort.Slice(reportList, func(i, j int) bool { + iDecimal, _ := decimal.NewFromString(reportList[i].PassProbability[:len(reportList[i].PassProbability)-1]) + jDecimal, _ := decimal.NewFromString(reportList[j].PassProbability[:len(reportList[j].PassProbability)-1]) + return jDecimal.LessThan(iDecimal) + }) + } + return reportList, total +} diff --git a/repository/test.data/upload.go b/repository/test.data/upload.go new file mode 100644 index 0000000..0e37693 --- /dev/null +++ b/repository/test.data/upload.go @@ -0,0 +1,21 @@ +package test_data + +import ( + "errors" + "testData/model" + "testData/repository" +) + +func HandleUploadFiles(fileTexts []*model.FileText, step, machine string) error { + if step == "" { + return errors.New("未输入工序") + } + for _, fileText := range fileTexts { + if machine == "STS8200" { + repository.HandleSTS8200Excel(fileText, step) + } else if machine == "TQT601" { + repository.HandlerTQT601Excel(fileText, step) + } + } + return nil +} diff --git a/repository/user.go b/repository/user.go new file mode 100644 index 0000000..0e033ed --- /dev/null +++ b/repository/user.go @@ -0,0 +1,19 @@ +package repository + +import ( + "errors" + "testData/global" + "testData/model" +) + +// 用户中心 通过ID获取用户信息 +func GetUserByID(id uint) (err error, user *model.User) { + var u model.User + if err = global.BaseDB.Preload("Department").Preload("Departments").Preload("Position").Preload("Role").First(&u, id).Error; err != nil { + return errors.New("用户不存在"), &u + } + if !u.Active { + return errors.New("账号已被取消激活,若有疑问请联系管理员"), nil + } + return nil, &u +} diff --git a/repository/xinde.go b/repository/xinde.go new file mode 100644 index 0000000..dd67d3b --- /dev/null +++ b/repository/xinde.go @@ -0,0 +1,29 @@ +package repository + +import ( + "path" + "strings" + "testData/global" + "testData/model" +) + +// XinDe 芯德 +func XinDe() { + var fileTexts []*model.FileText + global.PostGreSQL. + Where("factory = ?", "xinde").Order("mod_time").Find(&fileTexts) + for _, fileText := range fileTexts { + //fileText.Name = strings.ToLower(fileText.Name) + //if path.Ext(fileText.Name) != ".csv" && path.Ext(fileText.Name) != ".xls" && path.Ext(fileText.Name) != ".xlsx" { + // continue + //} + if strings.ToLower(path.Ext(fileText.Name)) != ".csv" && + strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" { + continue + } + if fileText.ProductName == "" || fileText.Lot == "" { + continue + } + HandleSTS8200Excel(fileText, "") + } +} diff --git a/request/casbin.go b/request/casbin.go new file mode 100644 index 0000000..3eb875e --- /dev/null +++ b/request/casbin.go @@ -0,0 +1,15 @@ +package request + +// Casbin info structure +type CasbinInfo struct { + //ApiId uint `json:"api_id" validate:"required" label:"API—ID"` // API ID + Path string `json:"path" validate:"required" label:"路径"` // 路径 + Method string `json:"method" validate:"required" label:"方法"` // 方法 +} + +// Casbin structure for input parameters +type CasbinInReceive struct { + AuthorityId string `json:"role_id" validate:"required" label:"权限id"` // 权限id + KeyWord string `json:"key_word"` + CasbinInfos []CasbinInfo `json:"apis"` +} diff --git a/request/chart.go b/request/chart.go new file mode 100644 index 0000000..a274835 --- /dev/null +++ b/request/chart.go @@ -0,0 +1,146 @@ +package request + +// QuerySelection 查询参数 +type QuerySelection struct { + Product string `json:"product"` // 产品型号 + Lot string `json:"lot"` // 批号 + PBI string `json:"pbi"` // PBI + SubBatch string `json:"sub_batch"` // 子批号 + Step string `json:"step"` // 工序 + WaferID string `json:"wafer_id"` // 片号 +} + +// Histogram 直方图 +type Histogram struct { + Selections []string `json:"selections"` // 参数 + Product string `json:"product"` // 产品型号 + Lot string `json:"lot"` // 批号 + PBI string `json:"pbi"` // PBI + SubBatch []string `json:"sub_batch"` // 子批号 + WaferID []string `json:"wafer_id"` // 片号 + Step string `json:"step"` // 工序 + Site []string `json:"site"` + Bin []string `json:"bin"` + Offset float64 `json:"offset"` // 偏移量 + Average float64 `json:"average"` + StandardDeviation float64 `json:"standard_deviation"` + SpliteSubBatch bool `json:"splite_sub_batch"` + OnlyPass bool `json:"only_pass"` + SpliteSite bool `json:"splite_site"` + XMax string `json:"x_max"` + XMin string `json:"x_min"` +} + +// Scatter 散点图 +type Scatter struct { + //X string `json:"x"` + //Y string `json:"y"` + //Selections []string `json:"selections"` // 参数 + XYSelection []XYSelection `json:"xy_selection"` + Product string `json:"product"` // 产品型号 + Lot string `json:"lot"` // 批号 + PBI string `json:"pbi"` // PBI + SubBatch []string `json:"sub_batch"` // 子批号 + WaferID []string `json:"wafer_id"` + Step string `json:"step"` // 工序 + Site []string `json:"site"` + Bin []string `json:"bin"` + SpliteSubBatch bool `json:"splite_sub_batch"` + OnlyPass bool `json:"only_pass"` + SpliteSite bool `json:"splite_site"` +} + +type XYSelection struct { + X string `json:"x"` + Y string `json:"y"` +} + +type Pie struct { + Selection string `json:"selection"` // 参数 + Product string `json:"product"` // 产品型号 + Lot string `json:"lot"` // 批号 + PBI string `json:"pbi"` // PBI + SubBatch string `json:"sub_batch"` // 子批号 + Max string `json:"max"` // 最大值 + Min string `json:"min"` // 最小值 + Step string `json:"step"` // 工序 + Site []string `json:"site"` + Bin []string `json:"bin"` + PieInterval []PieInterval `json:"pie_interval"` // 分区间 +} + +type PieInterval struct { + Name string `json:"name"` // 区间名称 + Max string `json:"max"` // 最大值 + Min string `json:"min"` // 最小值 +} + +type Line struct { + Selection string `json:"selection"` // 参数 + Product string `json:"product"` // 产品型号 + Lot string `json:"lot"` // 批号 + PBI string `json:"pbi"` // PBI + SubBatch string `json:"sub_batch"` // 子批号 + Step string `json:"step"` // 工序 + Site []string `json:"site"` + Bin []string `json:"bin"` + Offset string `json:"offset"` // 偏移量 +} + +type CPMap struct { + PBI string `json:"pbi"` + Selection []string `json:"selection"` // 参数 + Product string `json:"product"` // 产品型号 + SubBatch string `json:"sub_batch"` // 子批号 + Lot string `json:"lot"` // 批号 + WaferID string `json:"wafer_id"` // 片号 + Step string `json:"step"` // 工序 + Site []string `json:"site"` + SBin []string `json:"sbin"` + HBin []string `json:"hbin"` + SBinColor []CPMapColor `json:"sbin_color"` + HBinColor []CPMapColor `json:"hbin_color"` + SelectionColor []SelectionColor `json:"selection_color"` +} + +type LogSiteChart struct { + Product string `json:"product"` + Lot string `json:"lot"` + PBI string `json:"pbi"` + SubBatch string `json:"sub_batch"` // 子批 + Step string `json:"step"` // 工序 + Site []string `json:"site"` + Selection string `json:"selection"` + ContentType string `json:"content_type"` // 内容类型 + Bin []string `json:"bin"` +} + +type ProductInInterval struct { + Product string `json:"product"` + Bin []string `json:"bin"` +} + +type CPMapColor struct { + Color string `json:"color"` // Bin颜色 + Name string `json:"name"` // Bin名称 +} + +type SelectionColor struct { + Name string `json:"name"` // 参数名称 + Color string `json:"color"` // 参数颜色 + Max string `json:"max"` // 参数范围最大值 + Min string `json:"min"` // 参数范围最小值 +} + +type SelectionLimit struct { + PBI string `json:"pbi"` + Product string `json:"product"` + Lot string `json:"lot"` + SubBatch string `json:"sub_batch"` // 子批 + WaferID string `json:"wafer_id"` + Step string `json:"step"` // 工序 + Selection string `json:"selection"` + Site []string `json:"site"` + SBin []string `json:"sbin"` + HBin []string `json:"hbin"` +} diff --git a/request/report.chart.go b/request/report.chart.go new file mode 100644 index 0000000..31e94bb --- /dev/null +++ b/request/report.chart.go @@ -0,0 +1,22 @@ +package request + +type PackagePassProbabilityLine struct { + Product []string `json:"product"` // 成品型号 + Lot []string `json:"lot"` // 晶圆批次 + Package []string `json:"package"` // 封装形式 + Factory []string `json:"factory"` // 封装厂 + OrderDateStart string `json:"order_date_start"` // 下单日期开始时间 + OrderDateEnd string `json:"order_date_end"` // 下单日期结束时间 + DateSize string `json:"date_size"` // 时间大小 +} + +type PassProbabilityByFactory struct { + Factory string `json:"factory"` // 封装厂 + Type string `json:"type" validate:"required"` +} + +type PassProbabilityByProduct struct { + Product string `json:"product" validate:"required"` // 成品型号 + Factory string `json:"factory"` // 封装厂 + Type string `json:"type" validate:"required"` +} diff --git a/request/report.list.go b/request/report.list.go new file mode 100644 index 0000000..515ed25 --- /dev/null +++ b/request/report.list.go @@ -0,0 +1,59 @@ +package request + +type WaferList struct { + OrderDate string `json:"order_date"` // 下单日期 + PBI string `json:"pbi"` // 订单号 + Product string `json:"product"` // 晶圆型号 + Factory string `json:"factory"` // 晶圆厂 + WaferSize string `json:"wafer_size"` // 晶圆尺寸 + Quantity string `json:"quantity"` // 投片数量 + OnlineQuantity string `json:"online_quantity"` // 在线数量 + ReturnDate string `json:"return_date"` // 回货日期 + Lot string `json:"lot"` // 批号 + ReturnQuantity string `json:"return_quantity"` // 回货数量 +} + +type ABList struct { + OrderDate string `json:"order_date"` // 下单日期 + PBI string `json:"pbi"` // 订单号 + Product string `json:"product"` // 成品型号 + WaferProduct string `json:"wafer_product"` // 晶圆型号 + Package string `json:"package"` // 封装 + Factory string `json:"factory"` // 封装厂 + Lot string `json:"lot"` // 批号 + Seal string `json:"seal"` // 丝印 + WaferID string `json:"wafer_id"` // 片号 + Quantity string `json:"quantity"` // 订单数量 + OnlineQuantity string `json:"online_quantity"` // 在线数量 + IsFinish string `json:"is_finish"` // 是否已完成 + PassProbability string `json:"pass_probability"` // 良率 + StockOutQuantity string `json:"stock_out_quantity"` // 出库数 + StockInQuantity string `json:"stock_in_quantity"` // 入库数 + FailQuantity string `json:"fail_quantity"` // 封装不良品 +} + +type CPList struct { + WaferProduct string `json:"wafer_product"` // 晶圆型号 + Lot string `json:"lot"` // 晶圆批号 + Factory string `json:"factory"` // CP厂 + PBI string `json:"pbi"` + OrderDate string `json:"order_date"` // 下单日期 + TestMachine string `json:"test_machine"` // 测试机台 + QueryType string `json:"query_type"` // 查询类型 + Page int `json:"page"` + PageSize int `json:"page_size"` +} + +type FTList struct { + Product string `json:"product"` // 成品型号 + Lot string `json:"lot"` // 晶圆批号 + //SubBatch string `json:"sub_batch"` // 子批次 + Factory string `json:"factory"` // 测试厂 + TestProgram string `json:"test_program"` // 测试程序 + PBI string `json:"pbi"` + OrderDate string `json:"order_date"` // 下单日期 + Seal string `json:"seal"` // 丝印 + QueryType string `json:"query_type"` // 查询类型 + Page int `json:"page"` + PageSize int `json:"page_size"` +} diff --git a/router/chart.go b/router/chart.go new file mode 100644 index 0000000..37320cd --- /dev/null +++ b/router/chart.go @@ -0,0 +1,24 @@ +package router + +import ( + "github.com/gin-gonic/gin" + test_data "testData/api/test.data" +) + +func InitChartRouter(R *gin.RouterGroup) { + chartService := test_data.InitTestService() + chartGroup := R.Group("") + { + chartGroup.POST("selection", chartService.Selection) + chartGroup.POST("histogram", chartService.Histogram) + chartGroup.POST("scatter", chartService.Scatter) + chartGroup.POST("pie", chartService.Pie) + chartGroup.POST("line", chartService.Line) + chartGroup.POST("cpMap", chartService.CPMap) + chartGroup.POST("cpMap/export", chartService.CPMapExport) + chartGroup.POST("ftHistogram/export", chartService.ExportHistogram) + chartGroup.POST("scatter/export", chartService.ExportScatter) + chartGroup.POST("logSite", chartService.LogSite) + chartGroup.POST("selection/limit", chartService.SelectionLimit) + } +} diff --git a/router/report.chart.go b/router/report.chart.go new file mode 100644 index 0000000..12570fa --- /dev/null +++ b/router/report.chart.go @@ -0,0 +1,17 @@ +package router + +import ( + "github.com/gin-gonic/gin" + test_data "testData/api/test.data" +) + +func InitReportChartRouter(R *gin.RouterGroup) { + reportChartService := test_data.InitReportChartService() + reportChartGroup := R.Group("") + { + reportChartGroup.POST("report/packagePassProbabilityLine", reportChartService.PackagePassProbabilityLine) + reportChartGroup.POST("report/packageOrderNumberBar", reportChartService.PackageOrderNumberBar) + reportChartGroup.POST("report/fTPassProbabilityByFactory", reportChartService.FTPassProbabilityByFactory) + reportChartGroup.POST("report/fTPassProbabilityByProduct", reportChartService.FTPassProbabilityByProduct) + } +} diff --git a/router/report.list.go b/router/report.list.go new file mode 100644 index 0000000..e0c2dac --- /dev/null +++ b/router/report.list.go @@ -0,0 +1,17 @@ +package router + +import ( + "github.com/gin-gonic/gin" + test_data "testData/api/test.data" +) + +func InitReportListRouter(R *gin.RouterGroup) { + reportListService := test_data.InitReportService() + reportListGroup := R.Group("") + { + reportListGroup.POST("report/wafer", reportListService.WaferList) + reportListGroup.POST("report/cp", reportListService.CPList) + reportListGroup.POST("report/ab", reportListService.ABList) + reportListGroup.POST("report/ft", reportListService.FTList) + } +} diff --git a/service/casbin.go b/service/casbin.go new file mode 100644 index 0000000..213a3f9 --- /dev/null +++ b/service/casbin.go @@ -0,0 +1,105 @@ +package service + +import ( + "errors" + "github.com/casbin/casbin/v2" + "github.com/casbin/casbin/v2/model" + gormadapter "github.com/casbin/gorm-adapter/v3" + _ "github.com/go-sql-driver/mysql" + "sync" + "testData/global" + Model "testData/model" + "testData/request" +) + +type CasbinService struct{} + +var CasbinServiceApp = new(CasbinService) + +func (ca *CasbinService) UpdateCasbin(roleId string, casbinInReceive *request.CasbinInReceive) error { + var api []*Model.Api + global.BaseDB.Where("api_group LIKE '%" + casbinInReceive.KeyWord + + "%' OR description LIKE '%" + casbinInReceive.KeyWord + "%' OR path LIKE '%" + casbinInReceive.KeyWord + "%'").Find(&api) + var casBin []*Model.Casbin + var path []string + for i := 0; i < len(api); i++ { + path = append(path, api[i].Path) + } + global.BaseDB.Table("casbin_rule").Where("v0 = ? AND v1 NOT IN ?", roleId, path).Find(&casBin) + var rules [][]string + for i := 0; i < len(casBin); i++ { + rules = append(rules, []string{casBin[i].AuthorityId, casBin[i].Path, casBin[i].Method, casBin[i].ApiId}) + } + + ok, err := ca.ClearCasbin(0, roleId) + if err != nil { + return errors.New("清理原api出错:" + err.Error()) + } + for _, v := range casbinInReceive.CasbinInfos { + cm := Model.Casbin{ + Ptype: "p", + AuthorityId: roleId, + Path: v.Path, + Method: v.Method, + } + rules = append(rules, []string{cm.AuthorityId, cm.Path, cm.Method, cm.ApiId}) + } + e := ca.Casbin() + ok, err = e.AddPolicies(rules) + if !ok { + return errors.New("添加失败,请联系管理员:" + err.Error()) + } + return nil +} + +func (ca *CasbinService) UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error { + return global.BaseDB.Table("casbin_rule").Model(&Model.Casbin{}).Where("v1 = ? AND v2 = ?", oldPath, oldMethod).Updates(map[string]interface{}{ + "v1": newPath, + "v2": newMethod, + }).Error +} + +func (ca *CasbinService) GetPolicyPathByAuthorityId(authorityId string) (pathMaps []request.CasbinInfo) { + e := ca.Casbin() + list := e.GetFilteredPolicy(0, authorityId) + for _, v := range list { + pathMaps = append(pathMaps, request.CasbinInfo{ + Path: v[1], + Method: v[2], + }) + } + return pathMaps +} + +func (ca *CasbinService) ClearCasbin(v int, p ...string) (bool, error) { + e := ca.Casbin() + return e.RemoveFilteredPolicy(v, p...) + +} + +var ( + syncedEnforcer *casbin.SyncedEnforcer + once sync.Once +) + +func (ca *CasbinService) Casbin() *casbin.SyncedEnforcer { + once.Do(func() { + a, _ := gormadapter.NewAdapterByDB(global.BaseDB) + m, _ := model.NewModelFromString(` +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = r.sub == p.sub && r.obj == p.obj && r.act == p.act +`) + syncedEnforcer, _ = casbin.NewSyncedEnforcer(m, a) + }) + _ = syncedEnforcer.LoadPolicy() + return syncedEnforcer +} diff --git a/utils/excel.go b/utils/excel.go new file mode 100644 index 0000000..7c2ee10 --- /dev/null +++ b/utils/excel.go @@ -0,0 +1,36 @@ +package utils + +import ( + "fmt" + "github.com/shopspring/decimal" + "os/exec" + "strconv" +) + +func NumToRow(str string) (res string) { + strDecimal, _ := decimal.NewFromString(str) + for { + left := strDecimal.Div(decimal.NewFromInt(26)).RoundDown(0) + right := strDecimal.Mod(decimal.NewFromInt(26)).RoundDown(0) + if right.IsZero() && !left.IsZero() { + left = left.Sub(decimal.NewFromInt(1)) + right = decimal.NewFromInt(26) + } + rightInt, _ := strconv.Atoi(right.String()) + res = fmt.Sprintf("%c", rightInt+64) + res + if left.Equal(decimal.NewFromInt(0)) { + break + } + strDecimal = left + } + return res +} + +func ToXlsx(fileType, oldFilePath string) { + c := exec.Command("python3", "./toXlsx.py", fileType, oldFilePath) // /usr/local/bin/python3.11 + //c := exec.Command("nohup", "./toXlsx", fileType, oldFilePath, newFilePath) + _, err := c.CombinedOutput() + if err != nil { + fmt.Println(err) + } +} diff --git a/utils/file.go b/utils/file.go new file mode 100644 index 0000000..4d816c2 --- /dev/null +++ b/utils/file.go @@ -0,0 +1,60 @@ +package utils + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strconv" + "time" +) + +// FormatFileSize +/* +@Description: 转换文件单位 +@param fileSize 文件大小 +@return size 字符串 +*/ +func FormatFileSize(fileSize float64) (size string) { + units := []string{"B", "KB", "MB", "GB", "TB"} + var unitIndex int + for fileSize >= 1024 && unitIndex < len(units)-1 { + fileSize /= 1024 + unitIndex++ + } + return fmt.Sprintf("%.2f %s", fileSize, units[unitIndex]) +} + +func FillData(num int) []string { + return make([]string, num) +} + +func MakeDir(filePath string) { + _, err := os.Stat(filePath) + if os.IsNotExist(err) { + err = os.MkdirAll(filePath, os.ModePerm) + if err != nil { + log.Println("创建文件夹失败:", err) + } + } +} + +// DecodeToUnicode unicode中文解码 +func DecodeToUnicode(name string) (string, error) { + // 使用 strconv.Unquote 解码 + decodedStr, err := strconv.Unquote(`"` + name + `"`) + if err != nil { + return "", err + } + + return decodedStr, nil +} + +func MakeSavePath(s string) string { + //wd, _ := os.Getwd()wd, + folderPath := filepath.Join("files", time.Now().Format("2006-01"), s) + if _, err := os.Stat(folderPath); os.IsNotExist(err) { + _ = os.MkdirAll(folderPath, os.ModePerm) + } + return folderPath +} diff --git a/utils/jwt.get.user.go b/utils/jwt.get.user.go new file mode 100644 index 0000000..a9f920b --- /dev/null +++ b/utils/jwt.get.user.go @@ -0,0 +1,19 @@ +package utils + +import ( + "errors" + "github.com/gin-gonic/gin" + "testData/model" +) + +func JWTGetUser(c *gin.Context) (*model.User, error) { + claims, exists := c.Get("claims") + if !exists { + return nil, errors.New("token中未找到claims") + } + useUser, ok := claims.(*model.User) + if !ok { + return nil, errors.New("token中断言User失败") + } + return useUser, nil +} diff --git a/utils/jwt.go b/utils/jwt.go new file mode 100644 index 0000000..f6db77e --- /dev/null +++ b/utils/jwt.go @@ -0,0 +1,67 @@ +package utils + +import ( + "errors" + "github.com/golang-jwt/jwt/v4" + "github.com/spf13/viper" +) + +type JWT struct { + SigningKey []byte +} + +var ( + TokenExpired = errors.New("token已过期") + TokenNotValidYet = errors.New("token未生效") + TokenMalformed = errors.New("token非法") + TokenInvalid = errors.New("无法处理此token") +) + +func NewJWT() *JWT { + return &JWT{ + []byte(viper.GetString("signingKey")), + } +} + +// CreateToken 创建一个token +func (j *JWT) CreateToken(claims CustomClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// ParseToken 解析 token +func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) { + return j.SigningKey, nil + }) + if err != nil { + if ve, ok := err.(*jwt.ValidationError); ok { + if ve.Errors&jwt.ValidationErrorMalformed != 0 { + return nil, TokenMalformed + } else if ve.Errors&jwt.ValidationErrorExpired != 0 { + // Token is expired + return nil, TokenExpired + } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { + return nil, TokenNotValidYet + } else { + return nil, TokenInvalid + } + } + } + if token != nil { + if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + } else { + return nil, TokenInvalid + } +} + +type CustomClaims struct { + ID uint + Name string + Uuid string + BufferTime int64 + jwt.StandardClaims +} diff --git a/utils/validator.go b/utils/validator.go new file mode 100644 index 0000000..f9eb440 --- /dev/null +++ b/utils/validator.go @@ -0,0 +1,45 @@ +package utils + +import ( + "github.com/gin-gonic/gin" + "github.com/go-playground/locales/zh" + ut "github.com/go-playground/universal-translator" + "github.com/go-playground/validator/v10" + zhTranslations "github.com/go-playground/validator/v10/translations/zh" + "reflect" +) + +// ValidateInfo2CN 翻译validator为中文,并通过struct tag 中的label将字段名变成中文反馈在response错误信息中 +func ValidateInfo2CN(req interface{}) (string, bool) { + var validateErr string + uni := ut.New(zh.New()) + trans, _ := uni.GetTranslator("zh") + validate := validator.New() + validate.RegisterTagNameFunc(func(field reflect.StructField) string { + name := field.Tag.Get("label") + return name + }) + _ = zhTranslations.RegisterDefaultTranslations(validate, trans) + err := validate.Struct(req) + if err != nil { + if _, ok := err.(validator.ValidationErrors); !ok { + return err.Error(), false + } + for i := 0; i < len(err.(validator.ValidationErrors)); i++ { + if len(err.(validator.ValidationErrors))-1 == i { + validateErr += err.(validator.ValidationErrors)[i].Translate(trans) + } else { + validateErr += err.(validator.ValidationErrors)[i].Translate(trans) + "," + } + } + return validateErr, false + } + return validateErr, true +} + +type BaseRequestHttpHandlerInterface interface { + Create(c *gin.Context) + Show(c *gin.Context) + Update(c *gin.Context) + Delete(c *gin.Context) +}