package service import ( "bytes" "context" "encoding/base64" "encoding/json" "fmt" "git.hpds.cc/Component/logging" "hpds-iot-web/internal/proto" "hpds-iot-web/model" "hpds-iot-web/mq" "image" "net/http" "strconv" "xorm.io/xorm" "github.com/360EntSecGroup-Skylar/excelize" ) type ReportService interface { ReportList(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error) GenerateReport(ctx context.Context, req proto.ReportRequest) (rsp *excelize.File, err error) } func NewReportService(engine *xorm.Engine, logger *logging.Logger) ReportService { return &repo{ engine: engine, logger: logger, } } func (rp *repo) ReportList(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error) { rsp = new(proto.BaseResponse) select { case <-ctx.Done(): err = fmt.Errorf("超时/取消") rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Message = "超时/取消" rsp.Err = ctx.Err() return rsp, ctx.Err() default: data := make([]model.Report, 0) count, err := rp.engine. Where("(? = 0 or m.report_id = ?)", req.ReportId, req.ReportId). And("t.status > 0").Limit(int(req.Size), int(((req.Page)-1)*req.Size)). FindAndCount(&data) if err != nil { goto ReturnPoint } rsp.Code = http.StatusOK rsp.Status = http.StatusText(http.StatusOK) rsp.Message = "成功" rsp = FillPaging(count, req.Page, req.Size, data, rsp) rsp.Err = err return rsp, err } ReturnPoint: if err != nil { rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Err = err rsp.Message = "失败" } return rsp, err } func (rp *repo) GenerateReport(ctx context.Context, req proto.ReportRequest) (rsp *excelize.File, err error) { //rsp = new(proto.BaseResponse) select { case <-ctx.Done(): err = fmt.Errorf("超时/取消") //rsp.Code = http.StatusInternalServerError //rsp.Status = http.StatusText(http.StatusInternalServerError) //rsp.Message = "超时/取消" //rsp.Err = ctx.Err() return rsp, ctx.Err() default: taskResultList := make([]model.TaskResult, 0) err = rp.engine.Where("task_id = ?", req.TaskId). Find(&taskResultList) if err != nil { err = fmt.Errorf("未能找到对应的结果") goto ReturnPoint } list := make([]proto.TaskResultItem, 0) for _, v := range taskResultList { var h bool file := new(model.FileManager) h, err = rp.engine.ID(v.FileId).Get(file) if err != nil || !h { continue } md := new(model.Model) h, err = rp.engine.ID(v.ModelId).Get(md) if err != nil || !h { continue } var ( mr mq.ModelResult mrList []string fileDiscern string memo string diseaseType int64 diseaseLevel int length float64 area float64 width float64 diseaseTypeName string diseaseLevelName string ) if len(v.Result) > 0 && v.Result[0] == '[' { mrList = make([]string, 0) if err := json.Unmarshal([]byte(v.Result), &mrList); err != nil { continue } for _, str := range mrList { if err := json.Unmarshal([]byte(str), &mr); err != nil { continue } switch mr.Code { case 0: //轻量化模型返回 lr := new(mq.LightweightResult) if err := json.Unmarshal([]byte(v.Result), lr); err != nil { continue } //for _, val := range lrList { if lr.Crack || lr.Pothole { if lr.Crack { memo = "检测到裂缝" } else { memo = "检测到坑洼" } fileDiscern = lr.ImgDiscern diseaseLevel = 3 diseaseLevelName = "重度" switch md.BizType { case 2: diseaseType = 8 diseaseTypeName = "结构裂缝" case 3: diseaseType = 15 diseaseTypeName = "衬砌裂缝" default: diseaseType = 4 diseaseTypeName = "横向裂缝" } } fn, _ := base64.StdEncoding.DecodeString(fileDiscern) buff := bytes.NewBuffer(fn) _, imgType, _ := image.Decode(buff) fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern) item := proto.TaskResultItem{ FileId: v.FileId, FileName: v.SrcPath, SrcFile: file.AccessUrl, DistFile: fileDiscern, DiseaseType: int(diseaseType), DiseaseTypeName: diseaseTypeName, DiseaseLevel: diseaseLevel, DiseaseLevelName: diseaseLevelName, KPile: "", UpDown: 0, LineNum: 0, Length: length, Width: width, Area: area, HorizontalPositions: 0, Memo: memo, Stat: false, } list = append(list, item) //} case 2000: ir := new(mq.InsigmaResult) if err := json.Unmarshal([]byte(str), &ir); err != nil { continue } fileDiscern = ir.Image fn, _ := base64.StdEncoding.DecodeString(fileDiscern) buff := bytes.NewBuffer(fn) _, imgType, _ := image.Decode(buff) fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern) item := proto.TaskResultItem{ FileId: v.FileId, FileName: v.SrcPath, SrcFile: file.AccessUrl, DistFile: fileDiscern, DiseaseType: int(diseaseType), DiseaseTypeName: diseaseTypeName, DiseaseLevel: diseaseLevel, DiseaseLevelName: diseaseLevelName, KPile: "", UpDown: 0, LineNum: 0, Length: length, Width: width, Area: area, HorizontalPositions: 0, Memo: memo, Stat: false, } list = append(list, item) case 2001: ir := new(mq.InsigmaResult) if err := json.Unmarshal([]byte(str), &ir); err != nil { continue } fileDiscern = ir.Image for _, value := range ir.Diseases { diseaseType = model.GetDiseaseType(value.Type, md.BizType) if len(value.Param.MaxWidth) > 0 && width == 0 { width, _ = strconv.ParseFloat(value.Param.MaxWidth, 64) } length = value.Param.Length area = value.Param.Area diseaseLevelName = value.Level diseaseTypeName = value.Type switch value.Level { case "重度": diseaseLevel = 3 case "中度": diseaseLevel = 2 case "轻度": diseaseLevel = 1 } memo += fmt.Sprintf("发现[%s],等级[%s],长度[%f],最大宽度[%s],面积[%f];\n", value.Type, value.Level, value.Param.Length, value.Param.MaxWidth, value.Param.Area) } fn, _ := base64.StdEncoding.DecodeString(fileDiscern) buff := bytes.NewBuffer(fn) _, imgType, _ := image.Decode(buff) fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern) item := proto.TaskResultItem{ FileId: v.FileId, FileName: v.SrcPath, SrcFile: file.AccessUrl, DistFile: fileDiscern, DiseaseType: int(diseaseType), DiseaseTypeName: diseaseTypeName, DiseaseLevel: diseaseLevel, DiseaseLevelName: diseaseLevelName, KPile: "", UpDown: 0, LineNum: 0, Length: length, Width: width, Area: area, HorizontalPositions: 0, Memo: memo, Stat: false, } list = append(list, item) } } } else { if err := json.Unmarshal([]byte(v.Result), &mr); err != nil { continue } switch mr.Code { case 0: //轻量化模型返回 lr := new(mq.LightweightResult) if err := json.Unmarshal([]byte(v.Result), &lr); err != nil { continue } if lr.Crack || lr.Pothole { if lr.Crack { memo = "检测到裂缝" } else { memo = "检测到坑洼" } fileDiscern = lr.ImgDiscern diseaseLevel = 3 diseaseLevelName = "重度" switch md.BizType { case 2: diseaseType = 8 diseaseTypeName = "结构裂缝" case 3: diseaseType = 15 diseaseTypeName = "衬砌裂缝" default: diseaseType = 4 diseaseTypeName = "横向裂缝" } } // case 2000: //网新返回没有病害 ir := new(mq.InsigmaResult) if err := json.Unmarshal([]byte(v.Result), &ir); err != nil { continue } fileDiscern = ir.Image case 2001: //网新返回有病害 ir := new(mq.InsigmaResult) if err := json.Unmarshal([]byte(v.Result), &ir); err != nil { continue } fileDiscern = ir.Image for _, val := range ir.Diseases { diseaseType = model.GetDiseaseType(val.Type, md.BizType) if len(val.Param.MaxWidth) > 0 && width == 0 { width, _ = strconv.ParseFloat(val.Param.MaxWidth, 64) } length = val.Param.Length area = val.Param.Area diseaseLevelName = val.Level diseaseTypeName = val.Type switch val.Level { case "重度": diseaseLevel = 3 case "中度": diseaseLevel = 2 case "轻度": diseaseLevel = 1 } memo += fmt.Sprintf("发现[%s],等级[%s],长度[%f],最大宽度[%s],面积[%f];\n", val.Type, val.Level, val.Param.Length, val.Param.MaxWidth, val.Param.Area) } } fn, _ := base64.StdEncoding.DecodeString(fileDiscern) buff := bytes.NewBuffer(fn) _, imgType, _ := image.Decode(buff) fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern) item := proto.TaskResultItem{ FileId: v.FileId, FileName: v.SrcPath, SrcFile: file.AccessUrl, DistFile: fileDiscern, DiseaseType: int(diseaseType), DiseaseTypeName: diseaseTypeName, DiseaseLevel: diseaseLevel, DiseaseLevelName: diseaseLevelName, KPile: "", UpDown: 0, LineNum: 0, Length: length, Width: width, Area: area, HorizontalPositions: 0, Memo: memo, Stat: false, } list = append(list, item) } } disTypeList := make([]model.DiseaseType, 0) err = model.DB.Find(&disTypeList) if err != nil { goto ReturnPoint } diseaseTypeList := make(map[int64]string) for _, v := range disTypeList { diseaseTypeList[v.TypeId] = v.TypeName } diseaseLevelList := make(map[int]string) diseaseLevelList[1] = "轻度" diseaseLevelList[2] = "中度" diseaseLevelList[3] = "重度" xlsx := excelize.NewFile() xlsx.MergeCell("Sheet1", "A1", "L1") xlsx.MergeCell("Sheet1", "A2", "L2") xlsx.MergeCell("Sheet1", "A3", "L3") xlsx.MergeCell("Sheet1", "A4", "L4") xlsx.SetCellValue("Sheet1", "A4", "病害明细") //序号 路线编码 方向 桩号 车道 病害名称 程度 长度(m) 宽度(m) 面积(㎡) 横向位置 备注 xlsx.SetCellValue("Sheet1", "A5", "序号") xlsx.SetCellValue("Sheet1", "B5", "路线编码") xlsx.SetCellValue("Sheet1", "C5", "方向") xlsx.SetCellValue("Sheet1", "D5", "桩号") xlsx.SetCellValue("Sheet1", "E5", "车道") xlsx.SetCellValue("Sheet1", "F5", "病害名称") xlsx.SetCellValue("Sheet1", "G5", "程度") xlsx.SetCellValue("Sheet1", "H5", "长度(m)") xlsx.SetCellValue("Sheet1", "I5", "宽度(m)") xlsx.SetCellValue("Sheet1", "J5", "面积(㎡)") xlsx.SetCellValue("Sheet1", "K5", "横向位置") xlsx.SetCellValue("Sheet1", "L5", "备注") for k, v := range list { xlsx.SetCellValue("Sheet1", fmt.Sprintf("A%d", k+6), k+1) xlsx.SetCellValue("Sheet1", fmt.Sprintf("B%d", k+6), v.KPile) switch v.UpDown { case 1: xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", k+6), "上行") case 2: xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", k+6), "下行") } xlsx.SetCellValue("Sheet1", fmt.Sprintf("D%d", k+6), v.KPile) xlsx.SetCellValue("Sheet1", fmt.Sprintf("E%d", k+6), v.LineNum) xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", k+6), diseaseTypeList[int64(v.DiseaseType)]) xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", k+6), diseaseLevelList[v.DiseaseLevel]) xlsx.SetCellValue("Sheet1", fmt.Sprintf("H%d", k+6), v.Length) xlsx.SetCellValue("Sheet1", fmt.Sprintf("I%d", k+6), v.Width) xlsx.SetCellValue("Sheet1", fmt.Sprintf("J%d", k+6), v.Area) xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", k+6), v.HorizontalPositions) xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", k+6), v.Memo) } //rsp = xlsx //rsp.Code = http.StatusOK //rsp.Status = http.StatusText(http.StatusOK) //rsp.Message = "成功" //rsp.Data = xlsx //rsp.Err = err return xlsx, err } ReturnPoint: if err != nil { rsp = nil //rsp.Code = http.StatusInternalServerError //rsp.Status = http.StatusText(http.StatusInternalServerError) //rsp.Err = err //rsp.Message = "失败" } return rsp, err }