package ai_predict_model import ( "encoding/json" "eta/eta_api/controllers" "eta/eta_api/models" aiPredictModel "eta/eta_api/models/ai_predict_model" "eta/eta_api/models/system" "eta/eta_api/services" "eta/eta_api/utils" "fmt" "github.com/rdlucklib/rdluck_tools/paging" "github.com/tealeg/xlsx" "os" "strconv" "strings" "time" ) // AiPredictModelIndexController AI预测模型标的 type AiPredictModelIndexController struct { controllers.BaseAuthController } // List // @Title 标的列表 // @Description 标的列表 // @Param PageSize query int true "每页数据条数" // @Param CurrentIndex query int true "当前页页码,从1开始" // @Param ClassifyId query int false "分类id" // @Param Keyword query string false "搜索关键词" // @Success 200 {object} data_manage.ChartListResp // @router /index/list [get] func (this *AiPredictModelIndexController) List() { br := new(models.BaseResponse).Init() defer func() { this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } pageSize, _ := this.GetInt("PageSize") currentIndex, _ := this.GetInt("CurrentIndex") classifyId, _ := this.GetInt("ClassifyId") keyword := this.GetString("KeyWord") keyword = strings.TrimSpace(keyword) resp := new(aiPredictModel.AiPredictModelIndexPageListResp) // 分页 var startSize int if pageSize <= 0 { pageSize = utils.PageSize20 } if currentIndex <= 0 { currentIndex = 1 } startSize = paging.StartIndex(currentIndex, pageSize) // 分类 classifyIdName := make(map[int]string) { classifyOb := new(aiPredictModel.AiPredictModelClassify) list, e := classifyOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "") if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e) return } for _, v := range list { classifyIdName[v.AiPredictModelClassifyId] = v.ClassifyName } } // 筛选条件 indexOb := new(aiPredictModel.AiPredictModelIndex) var cond string var pars []interface{} { if classifyId > 0 { cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId) pars = append(pars, classifyId) } if keyword != "" { cond += fmt.Sprintf(" AND %s LIKE ?", indexOb.Cols().IndexName) pars = append(pars, fmt.Sprint("%", keyword, "%")) } } // 获取列表 total, e := indexOb.GetCountByCondition(cond, pars) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取标的总数失败, %v", e) return } list, e := indexOb.GetPageItemsByCondition(cond, pars, []string{}, "", startSize, pageSize) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取分页列表失败, %v", e) return } pageList := make([]*aiPredictModel.AiPredictModelIndexItem, 0) for _, v := range list { t := v.Format2Item() t.ClassifyName = classifyIdName[v.ClassifyId] pageList = append(pageList, t) } page := paging.GetPaging(currentIndex, pageSize, total) resp.Paging = page resp.List = pageList br.Data = resp br.Ret = 200 br.Success = true br.Msg = "获取成功" } // Import // @Title 导入标的和数据 // @Description 导入标的和数据 // @Param IndexFile query file true "标的文件" // @Success 200 Ret=200 录入成功 // @router /index/import [post] func (this *AiPredictModelIndexController) Import() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } file, _, e := this.GetFile("IndexFile") if e != nil { br.Msg = "导入失败" br.ErrMsg = fmt.Sprintf("获取文件失败, %v", e) return } path := "./static/ai_predict_model_temp_" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx" defer func() { _ = file.Close() _ = os.Remove(path) }() if e = this.SaveToFile("IndexFile", path); e != nil { br.Msg = "导入失败" br.ErrMsg = fmt.Sprintf("保存文件失败, %v", e) return } xlFile, e := xlsx.OpenFile(path) if e != nil { br.Msg = "导入失败" br.ErrMsg = fmt.Sprintf("打开excel文件失败, %v", e) return } // 获取分类和用户,遍历时校验 classifyNameId := make(map[string]int) adminNameId := make(map[string]int) { classifyOb := new(aiPredictModel.AiPredictModelClassify) classifyCond := fmt.Sprintf(` AND %s = ?`, classifyOb.Cols().ParentId) classifyPars := make([]interface{}, 0) classifyPars = append(classifyPars, 0) // 只取一级分类(临时过渡方案,业务端只会加一级) classifies, e := classifyOb.GetItemsByCondition(classifyCond, classifyPars, []string{}, "") if e != nil { br.Msg = "导入失败" br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e) return } for _, v := range classifies { classifyNameId[v.ClassifyName] = v.AiPredictModelClassifyId } admins, e := system.GetSysAdminList(``, make([]interface{}, 0), []string{}, "") if e != nil { br.Msg = "导入失败" br.ErrMsg = fmt.Sprintf("获取用户失败, %v", e) return } for _, v := range admins { adminNameId[v.RealName] = v.AdminId } } // 遍历sheet页 // 列表页:预测标的|分类|模型框架|创建人|预测日期|预测值|预测频度|方向准确率|绝对偏差 type ImportDataColKey struct { IndexName string ColKey int DataDate time.Time } imports := make(map[string]*aiPredictModel.AiPredictModelImportData) importsData := make(map[string]map[time.Time]*aiPredictModel.AiPredictModelData) importsDailyData := make(map[string]map[time.Time]*aiPredictModel.AiPredictModelData) for sheetKey, sheet := range xlFile.Sheets { maxRow := sheet.MaxRow // 列表页 if sheetKey == 0 { for i := 0; i < maxRow; i++ { // 忽略首行标题 if i < 1 { continue } row := sheet.Row(i) cells := row.Cells if len(cells) < 9 { continue } // 标的名称 indexName := strings.TrimSpace(cells[0].String()) if indexName == "" { continue } if imports[indexName] == nil { imports[indexName] = new(aiPredictModel.AiPredictModelImportData) imports[indexName].Index = new(aiPredictModel.AiPredictModelIndex) imports[indexName].Data = make([]*aiPredictModel.AiPredictModelData, 0) } imports[indexName].Index.IndexName = indexName imports[indexName].Index.CreateTime = time.Now() imports[indexName].Index.ModifyTime = time.Now() // 分类 classifyName := strings.TrimSpace(cells[1].String()) if classifyNameId[classifyName] <= 0 { br.Msg = fmt.Sprintf("分类:%s不存在", classifyName) return } imports[indexName].Index.ClassifyId = classifyNameId[classifyName] // 创建人 adminName := strings.TrimSpace(cells[3].String()) if adminNameId[adminName] <= 0 { br.Msg = fmt.Sprintf("创建人:%s不存在", adminName) return } imports[indexName].Index.SysUserId = adminNameId[adminName] imports[indexName].Index.SysUserRealName = adminName // 其余信息 imports[indexName].Index.ModelFramework = strings.TrimSpace(cells[2].String()) strDate := strings.TrimSpace(cells[4].String()) predictDate, _ := time.Parse("2006/01/02", strDate) if predictDate.IsZero() { predictDate, _ = time.Parse("01-02-06", strDate) if predictDate.IsZero() { predictDate, _ = time.Parse("2006/1/2", strDate) } } imports[indexName].Index.PredictDate = predictDate strVal := strings.TrimSpace(cells[5].String()) if strVal == "" { continue } predictVal, _ := strconv.ParseFloat(strVal, 64) imports[indexName].Index.PredictValue = predictVal imports[indexName].Index.PredictFrequency = strings.TrimSpace(cells[6].String()) imports[indexName].Index.DirectionAccuracy = strings.TrimSpace(cells[7].String()) imports[indexName].Index.AbsoluteDeviation = strings.TrimSpace(cells[8].String()) } } // 月度数据页 if sheetKey == 1 { // 每五列为一个指标的数据 colKeys := make(map[int]*ImportDataColKey) // 每一列对应的指标名称以及对应的字段序号 for i := 0; i < maxRow; i++ { // 首行为指标名称 if i == 0 { nameCol := 0 row := sheet.Row(i) for ck, cell := range row.Cells { nameCol += 1 if nameCol > 5 { nameCol = 1 } if nameCol == 1 { // nameCol=1时为指标/数据行则为日期 indexName := strings.TrimSpace(cell.String()) if indexName == "" { continue } importsData[indexName] = make(map[time.Time]*aiPredictModel.AiPredictModelData) colKeys[ck] = &ImportDataColKey{ ColKey: 1, IndexName: indexName, } // 后面四列分别对应: 实际值|预测值|方向|偏差率, 这里直接加无须考虑是否会越界 colKeys[ck+1] = &ImportDataColKey{ ColKey: 2, IndexName: indexName, } colKeys[ck+2] = &ImportDataColKey{ ColKey: 3, IndexName: indexName, } colKeys[ck+3] = &ImportDataColKey{ ColKey: 4, IndexName: indexName, } colKeys[ck+4] = &ImportDataColKey{ ColKey: 5, IndexName: indexName, } continue } } continue } // 第二行为标题,跳过 if i == 1 { continue } // 剩余为数据行 row := sheet.Row(i) for ck, cell := range row.Cells { if colKeys[ck] == nil { continue } if colKeys[ck].IndexName == "" { continue } switch colKeys[ck].ColKey { case 1: // 日期列 strDate := strings.TrimSpace(cell.String()) dataDate, _ := time.Parse("2006/01/02", strDate) if dataDate.IsZero() { dataDate, _ = time.Parse("01-02-06", strDate) if dataDate.IsZero() { dataDate, _ = time.Parse("2006/1/2", strDate) if dataDate.IsZero() { continue } } } colKeys[ck].DataDate = dataDate colKeys[ck+1].DataDate = dataDate colKeys[ck+2].DataDate = dataDate colKeys[ck+3].DataDate = dataDate colKeys[ck+4].DataDate = dataDate importRow := imports[colKeys[ck].IndexName] if importRow == nil { continue } // 新增当前日期数据 importsData[colKeys[ck].IndexName][dataDate] = new(aiPredictModel.AiPredictModelData) importsData[colKeys[ck].IndexName][dataDate].DataTime = dataDate importsData[colKeys[ck].IndexName][dataDate].CreateTime = time.Now() importsData[colKeys[ck].IndexName][dataDate].ModifyTime = time.Now() importsData[colKeys[ck].IndexName][dataDate].Source = aiPredictModel.ModelDataSourceMonthly case 2, 3: // 实际值和预测值, 可能为空 dataDate := colKeys[ck].DataDate if importsData[colKeys[ck].IndexName][dataDate] == nil { continue } strVal := strings.TrimSpace(cell.String()) if strVal == "" { continue } val, _ := strconv.ParseFloat(strVal, 64) if colKeys[ck].ColKey == 2 { importsData[colKeys[ck].IndexName][dataDate].Value.Valid = true importsData[colKeys[ck].IndexName][dataDate].Value.Float64 = val } else { importsData[colKeys[ck].IndexName][dataDate].PredictValue.Valid = true importsData[colKeys[ck].IndexName][dataDate].PredictValue.Float64 = val } case 4, 5: // 方向/偏差率 dataDate := colKeys[ck].DataDate if importsData[colKeys[ck].IndexName][dataDate] == nil { continue } str := strings.TrimSpace(cell.String()) if str == "" { continue } if colKeys[ck].ColKey == 4 { importsData[colKeys[ck].IndexName][dataDate].Direction = str } else { importsData[colKeys[ck].IndexName][dataDate].DeviationRate = str } default: continue } } } } // 日度数据页 if sheetKey == 2 { // 每3列为一个指标的数据 colKeys := make(map[int]*ImportDataColKey) // 每一列对应的指标名称以及对应的字段序号 for i := 0; i < maxRow; i++ { // 首行为指标名称 if i == 0 { nameCol := 0 row := sheet.Row(i) for ck, cell := range row.Cells { nameCol += 1 if nameCol > 3 { nameCol = 1 } if nameCol == 1 { // nameCol=1时为指标/数据行则为日期 indexName := strings.TrimSpace(cell.String()) if indexName == "" { continue } importsDailyData[indexName] = make(map[time.Time]*aiPredictModel.AiPredictModelData) colKeys[ck] = &ImportDataColKey{ ColKey: 1, IndexName: indexName, } // 后面两列分别对应: 实际值|预测值, 这里直接加无须考虑是否会越界 colKeys[ck+1] = &ImportDataColKey{ ColKey: 2, IndexName: indexName, } colKeys[ck+2] = &ImportDataColKey{ ColKey: 3, IndexName: indexName, } continue } } continue } // 第二行为标题,遇到"预测值"单元格,需要取出其中的值作为预测图例名称 if i == 1 { row := sheet.Row(i) for ck, cell := range row.Cells { if colKeys[ck] == nil { continue } if colKeys[ck].IndexName == "" { continue } if colKeys[ck].ColKey != 3 { continue } if imports[colKeys[ck].IndexName] != nil && imports[colKeys[ck].IndexName].Index != nil { var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig extraConfig.DailyChart.PredictLegendName = strings.TrimSpace(cell.String()) b, _ := json.Marshal(extraConfig) imports[colKeys[ck].IndexName].Index.ExtraConfig = string(b) } } continue } // 剩余为数据行 row := sheet.Row(i) for ck, cell := range row.Cells { if colKeys[ck] == nil { continue } if colKeys[ck].IndexName == "" { continue } switch colKeys[ck].ColKey { case 1: // 日期列 strDate := strings.TrimSpace(cell.String()) dataDate, _ := time.Parse("2006/01/02", strDate) if dataDate.IsZero() { dataDate, _ = time.Parse("01-02-06", strDate) if dataDate.IsZero() { dataDate, _ = time.Parse("2006/1/2", strDate) if dataDate.IsZero() { continue } } } colKeys[ck].DataDate = dataDate colKeys[ck+1].DataDate = dataDate colKeys[ck+2].DataDate = dataDate importRow := imports[colKeys[ck].IndexName] if importRow == nil { continue } // 新增当前日期数据 importsDailyData[colKeys[ck].IndexName][dataDate] = new(aiPredictModel.AiPredictModelData) importsDailyData[colKeys[ck].IndexName][dataDate].DataTime = dataDate importsDailyData[colKeys[ck].IndexName][dataDate].CreateTime = time.Now() importsDailyData[colKeys[ck].IndexName][dataDate].ModifyTime = time.Now() importsDailyData[colKeys[ck].IndexName][dataDate].Source = aiPredictModel.ModelDataSourceDaily case 2, 3: // 实际值和预测值, 可能为空 dataDate := colKeys[ck].DataDate if importsDailyData[colKeys[ck].IndexName][dataDate] == nil { continue } strVal := strings.TrimSpace(cell.String()) if strVal == "" { continue } val, _ := strconv.ParseFloat(strVal, 64) if colKeys[ck].ColKey == 2 { importsDailyData[colKeys[ck].IndexName][dataDate].Value.Valid = true importsDailyData[colKeys[ck].IndexName][dataDate].Value.Float64 = val } else { importsDailyData[colKeys[ck].IndexName][dataDate].PredictValue.Valid = true importsDailyData[colKeys[ck].IndexName][dataDate].PredictValue.Float64 = val } default: continue } } } } } for indexName, v := range importsData { if imports[indexName] == nil { continue } for _, dateData := range v { imports[indexName].Data = append(imports[indexName].Data, dateData) } } for indexName, v := range importsDailyData { if imports[indexName] == nil { continue } for _, dateData := range v { imports[indexName].Data = append(imports[indexName].Data, dateData) } } importIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0) for _, v := range imports { importIndexes = append(importIndexes, v) } // 导入指标 if e = services.ImportAiPredictModelIndexAndData(importIndexes); e != nil { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("导入指标数据失败, %v", e) return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // Detail // @Title 标的详情 // @Description 标的详情 // @Param IndexId query int true "标的ID" // @Success 200 {object} data_manage.ChartListResp // @router /index/detail [get] func (this *AiPredictModelIndexController) Detail() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } indexId, _ := this.GetInt("IndexId") if indexId <= 0 { br.Msg = "参数有误" br.ErrMsg = fmt.Sprintf("参数有误, IndexId: %d", indexId) return } resp := new(aiPredictModel.AiPredictModelDetailResp) indexOb := new(aiPredictModel.AiPredictModelIndex) indexItem, e := indexOb.GetItemById(indexId) if e != nil { if e.Error() == utils.ErrNoRow() { br.Msg = "标的已被删除,请刷新页面" return } br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e) return } // 获取标的数据 monthData, dailyData := make([]*aiPredictModel.AiPredictModelData, 0), make([]*aiPredictModel.AiPredictModelData, 0) { tableData := make([]*aiPredictModel.AiPredictModelDataItem, 0) dataOb := new(aiPredictModel.AiPredictModelData) dataCond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode) dataPars := make([]interface{}, 0) dataPars = append(dataPars, indexItem.IndexCode) list, e := dataOb.GetItemsByCondition(dataCond, dataPars, []string{}, fmt.Sprintf("%s DESC", dataOb.Cols().DataTime)) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取标的数据失败, %v", e) return } // tableData取月度数据,最多显示10条 count, limit := 0, 10 for _, v := range list { // 日度数据 if v.Source == aiPredictModel.ModelDataSourceDaily { dailyData = append(dailyData, v) continue } // 月度数据 if count < limit { tableData = append(tableData, v.Format2Item()) count += 1 } monthData = append(monthData, v) } resp.TableData = tableData } // 月度图表 if len(monthData) > 0 { chartDetail, e := services.GetAiPredictChartDetailByData(indexItem, monthData, aiPredictModel.ModelDataSourceMonthly) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取月度图表失败, %v", e) return } resp.ChartView = chartDetail } // 日度图表 if len(dailyData) > 0 { dailyChartDetail, e := services.GetAiPredictChartDetailByData(indexItem, dailyData, aiPredictModel.ModelDataSourceDaily) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取日度图表失败, %v", e) return } resp.DailyChartView = dailyChartDetail } br.Data = resp br.Ret = 200 br.Success = true br.Msg = "获取成功" } // Save // @Title 保存标的 // @Description 保存标的 // @Param request body aiPredictModel.AiPredictModelIndexSaveReq true "type json string" // @Success 200 Ret=200 保存成功 // @router /index/save [post] func (this *AiPredictModelIndexController) Save() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req aiPredictModel.AiPredictModelIndexSaveReq if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil { br.Msg = "参数解析异常" br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e) return } if req.IndexId < 0 { br.Msg = "参数有误" br.ErrMsg = fmt.Sprintf("标的ID有误, IndexId: %d", req.IndexId) return } indexOb := new(aiPredictModel.AiPredictModelIndex) indexItem, e := indexOb.GetItemById(req.IndexId) if e != nil { if e.Error() == utils.ErrNoRow() { br.Msg = "标的已被删除,请刷新页面" return } br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e) return } var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig if indexItem.ExtraConfig != "" { if e = json.Unmarshal([]byte(indexItem.ExtraConfig), &extraConfig); e != nil { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("标的配置解析失败, %v", e) return } } if req.MonthlyChart != nil { extraConfig.MonthlyChart.LeftMin = req.MonthlyChart.LeftMin extraConfig.MonthlyChart.LeftMax = req.MonthlyChart.LeftMax extraConfig.MonthlyChart.Unit = req.MonthlyChart.Unit } if req.DailyChart != nil { extraConfig.DailyChart.LeftMin = req.DailyChart.LeftMin extraConfig.DailyChart.LeftMax = req.DailyChart.LeftMax extraConfig.DailyChart.Unit = req.DailyChart.Unit } configByte, _ := json.Marshal(extraConfig) indexItem.ExtraConfig = string(configByte) indexItem.ModifyTime = time.Now() updateCols := []string{indexOb.Cols().ExtraConfig, indexOb.Cols().ModifyTime} if e = indexItem.Update(updateCols); e != nil { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("保存标的失败, %v", e) return } br.Ret = 200 br.Msg = "操作成功" br.Success = true } // DashboardSave // @Title 保存看板 // @Description 保存看板 // @Param request body aiPredictModel.AiPredictModelDashboardSaveReq true "type json string" // @Success 200 Ret=200 新增成功 // @router /index/dashboard/save [post] func (this *AiPredictModelIndexController) DashboardSave() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req aiPredictModel.AiPredictModelDashboardSaveReq if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil { br.Msg = "参数解析异常" br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e) return } if req.IndexId <= 0 { br.Msg = "参数有误" br.ErrMsg = fmt.Sprintf("参数有误, %d", req.IndexId) return } req.DashboardName = strings.TrimSpace(req.DashboardName) indexOb := new(aiPredictModel.AiPredictModelIndex) _, e := indexOb.GetItemById(req.IndexId) if e != nil { if e.Error() == utils.ErrNoRow() { br.Msg = "标的已被删除,请刷新页面" return } br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e) return } // 获取看板 var isUpdate bool var updateCols []string dashboardItem := new(aiPredictModel.AiPredictModelDashboard) if req.IndexId > 0 { cond := fmt.Sprintf(" AND %s = ?", dashboardItem.Cols().AiPredictModelIndexId) pars := make([]interface{}, 0) pars = append(pars, req.IndexId) item, e := dashboardItem.GetItemByCondition(cond, pars, "") if e != nil && e.Error() != utils.ErrNoRow() { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("获取标的看板失败, %v", e) return } if item != nil { isUpdate = true dashboardItem = item dashboardItem.DashboardName = req.DashboardName dashboardItem.ModifyTime = time.Now() updateCols = append(updateCols, dashboardItem.Cols().DashboardName, dashboardItem.Cols().ModifyTime) } } if !isUpdate { dashboardItem.AiPredictModelIndexId = req.IndexId dashboardItem.DashboardName = req.DashboardName dashboardItem.SysUserId = sysUser.AdminId dashboardItem.SysUserRealName = sysUser.RealName dashboardItem.CreateTime = time.Now() dashboardItem.ModifyTime = time.Now() } // 详情 dashboardDetails := make([]*aiPredictModel.AiPredictModelDashboardDetail, 0) for i, v := range req.List { t := &aiPredictModel.AiPredictModelDashboardDetail{ Type: v.Type, UniqueCode: v.UniqueCode, Sort: i + 1, CreateTime: time.Now(), ModifyTime: time.Now(), } dashboardDetails = append(dashboardDetails, t) } // 保存 if e := dashboardItem.SaveIndexDashboard(dashboardItem, dashboardDetails, isUpdate, updateCols); e != nil { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("保存标的看板失败, %v", e) return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // DashboardDetail // @Title 看板详情 // @Description 看板详情 // @Param IndexId query int true "标的ID" // @Success 200 {object} aiPredictModel.AiPredictModelDashboardDetailResp // @router /index/dashboard/detail [get] func (this *AiPredictModelIndexController) DashboardDetail() { br := new(models.BaseResponse).Init() defer func() { if br.ErrMsg == "" { br.IsSendEmail = false } this.Data["json"] = br this.ServeJSON() }() sysUser := this.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } indexId, _ := this.GetInt("IndexId") resp := new(aiPredictModel.AiPredictModelDashboardDetailResp) indexOb := new(aiPredictModel.AiPredictModelIndex) indexItem, e := indexOb.GetItemById(indexId) if e != nil { if e.Error() == utils.ErrNoRow() { br.Msg = "标的已被删除,请刷新页面" return } br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e) return } resp.CreateUserId = indexItem.SysUserId resp.CreateUserRealName = indexItem.SysUserRealName // 获取标的看板 dashboardOb := new(aiPredictModel.AiPredictModelDashboard) dashboardItem := new(aiPredictModel.AiPredictModelDashboardItem) { cond := fmt.Sprintf(" AND %s = ?", dashboardOb.Cols().AiPredictModelIndexId) pars := make([]interface{}, 0) pars = append(pars, indexId) item, e := dashboardOb.GetItemByCondition(cond, pars, "") if e != nil && e.Error() != utils.ErrNoRow() { br.Msg = "操作失败" br.ErrMsg = fmt.Sprintf("获取标的看板失败, %v", e) return } if item != nil { dashboardItem = item.Format2Item() } } // 获取看板详情 dashboardDetails := make([]*aiPredictModel.AiPredictModelDashboardDetailItem, 0) if dashboardItem.DashboardId > 0 { detailOb := new(aiPredictModel.AiPredictModelDashboardDetail) cond := fmt.Sprintf(" AND %s = ?", detailOb.Cols().AiPredictModelDashboardId) pars := make([]interface{}, 0) pars = append(pars, dashboardItem.DashboardId) list, e := detailOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", detailOb.Cols().Sort)) if e != nil { br.Msg = "获取失败" br.ErrMsg = fmt.Sprintf("获取看板详情失败, %v", e) return } for _, v := range list { dashboardDetails = append(dashboardDetails, v.Format2Item()) } } resp.AiPredictModelDashboardItem = dashboardItem resp.List = dashboardDetails br.Data = resp br.Ret = 200 br.Success = true br.Msg = "获取成功" }