Переглянути джерело

Merge branch 'feature/forum4.1_ai_predict_model' into debug

# Conflicts:
#	controllers/sys_role.go
#	services/task.go
xyxie 3 днів тому
батько
коміт
13d3016c79

+ 159 - 17
controllers/data_manage/ai_predict_model/classify.go

@@ -146,7 +146,7 @@ func (this *AiPredictModelClassifyController) Add() {
 		br.Msg = "请选择上级分类"
 		return
 	}
-	if req.Level > 5 {
+	if req.Level > 6 {
 		br.Msg = "目前只支持6级目录"
 		return
 	}
@@ -212,10 +212,10 @@ func (this *AiPredictModelClassifyController) Add() {
 	}
 	if req.ParentId > 0 {
 		// 用英文逗号拼接方便查询
-		classifyOb.LevelPath = fmt.Sprintf("%s,%d", levelPath, classifyOb.AiPredictModelClassifyId)
+		classifyOb.LevelPath = fmt.Sprintf("%s%d,", levelPath, classifyOb.AiPredictModelClassifyId)
 		classifyOb.RootId = rootId
 	} else {
-		classifyOb.LevelPath = fmt.Sprint(classifyOb.AiPredictModelClassifyId)
+		classifyOb.LevelPath = fmt.Sprintf("%d,", classifyOb.AiPredictModelClassifyId)
 		classifyOb.RootId = classifyOb.AiPredictModelClassifyId
 	}
 	if e = classifyOb.Update([]string{classifyOb.Cols().LevelPath, classifyOb.Cols().RootId}); e != nil {
@@ -343,29 +343,52 @@ func (this *AiPredictModelClassifyController) RemoveCheck() {
 
 	var deleteStatus int
 	var tipsMsg string
+	var childClassifyIds []int
 	// 删除分类
 	if req.ClassifyId > 0 && req.IndexId == 0 {
-		count, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyId(req.ClassifyId)
+		classifyInfo, err := aiPredictModel.GetAiPredictModelClassifyById(req.ClassifyId)
+	    if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}else if err != nil && utils.IsErrNoRow(err) {
+			br.Msg = "分类不存在,请刷新页面"
+			return
+		}
+		childClassifyIds, err = aiPredictModel.GetAiPredictModelClassifyChildIdsByLevelPath(classifyInfo.LevelPath)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取子分类ID失败,Err:" + err.Error()
+			return
+		}
+		count, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyIds(childClassifyIds)
 		if err != nil {
 			br.Msg = "删除失败"
-			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
+			br.ErrMsg = "分类下是否含有预测标的失败,Err:" + err.Error()
 			return
 		}
 
 		if count > 0 {
 			deleteStatus = 1
-			tipsMsg = "该分类下关联图表不可删除"
+			tipsMsg = "该分类下关联预测标的不可删除"
+		}else {
+			// 判断分类下是否存在框架
+			frameworkCount, err := aiPredictModel.GetAiPredictModelFrameworkCountByClassifyIds(childClassifyIds)
+			if err != nil {
+				br.Msg = "删除失败"
+				br.ErrMsg = "分类下是否存在框架失败,Err:" + err.Error()
+				return
+			}
+			if frameworkCount > 0 {
+				deleteStatus = 3
+				tipsMsg = "该分类下关联模型框架不可删除"
+			}
 		}
 	}
 
+
 	if deleteStatus != 1 && req.IndexId == 0 {
-		classifyCount, err := aiPredictModel.GetAiPredictModelClassifyCountByClassifyId(req.ClassifyId)
-		if err != nil && !utils.IsErrNoRow(err) {
-			br.Msg = "删除失败"
-			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
-			return
-		}
-		if classifyCount > 0 {
+		if len(childClassifyIds) > 0 {
 			deleteStatus = 2
 			tipsMsg = "确认删除当前目录及包含的子目录吗"
 		}
@@ -408,21 +431,55 @@ func (this *AiPredictModelClassifyController) Remove() {
 		br.Msg = "参数错误"
 		return
 	}
+	
 
 	// 删除分类
 	if req.ClassifyId > 0 && req.IndexId == 0 {
-		count, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyId(req.ClassifyId)
+		classifyInfo, err := aiPredictModel.GetAiPredictModelClassifyById(req.ClassifyId)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}else if err != nil && utils.IsErrNoRow(err) {
+			br.Msg = "分类不存在,请刷新页面"
+			return
+		}
+		// 查询所有子分类
+		childClassifyIds, err := aiPredictModel.GetAiPredictModelClassifyChildIdsByLevelPath(classifyInfo.LevelPath)
 		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
 		}
-		if count > 0 {
-			br.Msg = "该目录下存在关联指标,不可删除"
+		
+		indexCount, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyIds(childClassifyIds)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否存在指标失败,Err:" + err.Error()
+			return
+		}
+		if indexCount > 0 {
+			br.Msg = "该目录下存在模型标的,不可删除"
 			br.IsSendEmail = false
 			return
 		}
-		err = aiPredictModel.RemoveAiPredictModelClassify(req.ClassifyId)
+
+		// 是都存在模型框架
+		frameworkCount, err := aiPredictModel.GetAiPredictModelFrameworkCountByClassifyIds(childClassifyIds)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否存在框架失败,Err:" + err.Error()
+			return
+		}
+		if frameworkCount > 0 {
+			br.Msg = "该目录下存在模型框架,不可删除"
+			br.IsSendEmail = false
+			return
+		}
+		
+		
+		// 删除分类和子分类
+		err = aiPredictModel.RemoveAiPredictModelClassifyByClassifyIds(childClassifyIds)
 		if err != nil {
 			br.Msg = "删除失败"
 			br.ErrMsg = "删除失败,Err:" + err.Error()
@@ -556,3 +613,88 @@ func (this *AiPredictModelClassifyController) Move() {
 	br.Success = true
 	br.Msg = "移动成功"
 }
+
+// List
+// @Title 分类列表
+// @Description 分类列表
+// @Param   ParentId   query   bool   false   "父级ID"
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /classify/framework/list [get]
+func (this *AiPredictModelClassifyController) FrameworkList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	parentId, _ := this.GetInt("ParentId")
+	resp := new(aiPredictModel.AiPredictModelClassifyFrameworkListResp)
+
+	// (懒加载)仅查询直属分类
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	{
+		cond := fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := classifyOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", classifyOb.Cols().Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取子分类失败, %v", e)
+			return
+		}
+		for _, v := range list {
+			resp.AllNodes = append(resp.AllNodes, &aiPredictModel.AiPredictModelClassifyFrameworkListItem{
+				NodeName:     v.ClassifyName,
+				ClassifyId:   v.AiPredictModelClassifyId,
+				ClassifyName: v.ClassifyName,
+				ParentId:     v.ParentId,
+				Level:        v.Level,
+				Sort:         v.Sort,
+				UniqueCode:   v.UniqueCode,
+			})
+		}
+	}
+
+	// 非顶级目录查询指标
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+	if parentId > 0 {
+		parentClassify, e := classifyOb.GetItemById(parentId)
+		if e != nil {
+			br.Msg = "父级分类不存在, 请刷新页面"
+			return
+		}
+
+		cond := fmt.Sprintf(" AND %s = ?", aiPredictModel.AiPredictModelFrameworkColumns.ClassifyId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := frameworkOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", aiPredictModel.AiPredictModelFrameworkColumns.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取分类下指标失败, %v", e)
+			return
+		}
+		for _, v := range list {
+			resp.AllNodes = append(resp.AllNodes, &aiPredictModel.AiPredictModelClassifyFrameworkListItem{
+				NodeType:     1,
+				NodeName:     v.FrameworkName,
+				ClassifyId:   parentClassify.AiPredictModelClassifyId,
+				ClassifyName: parentClassify.ClassifyName,
+				AiPredictModelFrameworkId:  v.AiPredictModelFrameworkId,
+				FrameworkImg:  v.FrameworkImg,
+				ParentId:     parentId,
+				Sort:         v.Sort,
+				UniqueCode:   v.FrameworkCode,
+			})
+		}
+	}
+	sort.Slice(resp.AllNodes, func(i, j int) bool {
+		return resp.AllNodes[i].Sort < resp.AllNodes[j].Sort
+	})
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 101 - 5
controllers/data_manage/ai_predict_model/framework.go

@@ -43,6 +43,7 @@ func (c *AiPredictModelFrameworkController) List() {
 
 	adminId, _ := c.GetInt("AdminId")
 	keyword := c.GetString("Keyword")
+	classifyId, _ := c.GetInt("ClassifyId")
 	keyword = strings.TrimSpace(keyword)
 
 	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
@@ -57,6 +58,23 @@ func (c *AiPredictModelFrameworkController) List() {
 		cond += fmt.Sprintf(` AND %s LIKE ?`, aiPredictModel.AiPredictModelFrameworkColumns.FrameworkName)
 		pars = append(pars, "%"+keyword+"%")
 	}
+	if classifyId > 0 {
+		classifyInfo, err := aiPredictModel.GetAiPredictModelClassifyById(classifyId)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}
+		// 查询所有子分类
+		childClassifyIds, err := aiPredictModel.GetAiPredictModelClassifyChildIdsByLevelPath(classifyInfo.LevelPath)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取子分类失败,Err:" + err.Error()
+			return
+		}
+		cond += fmt.Sprintf(` AND %s IN (%s)`, aiPredictModel.AiPredictModelFrameworkColumns.ClassifyId, utils.GetOrmInReplace(len(childClassifyIds)))
+		pars = append(pars, childClassifyIds)
+	}
 
 	orderRule := `sort ASC, create_time DESC`
 	list, e := frameworkOb.GetItemsByCondition(cond, pars, []string{}, orderRule)
@@ -67,7 +85,7 @@ func (c *AiPredictModelFrameworkController) List() {
 	}
 	resp := make([]*aiPredictModel.AiPredictModelFrameworkItem, 0)
 	for _, v := range list {
-		t := aiPredictModel.FormatAiPredictModelFramework2Item(v, make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0))
+		t := aiPredictModel.FormatAiPredictModelFramework2Item(v, make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0), make([]string, 0))
 		if t.AdminId == sysUser.AdminId || utils.IsAdminRole(sysUser.RoleTypeCode) {
 			t.Button.OpButton = true
 			t.Button.DeleteButton = true
@@ -116,7 +134,31 @@ func (c *AiPredictModelFrameworkController) Add() {
 		br.Msg = "框架名称不可为空"
 		return
 	}
-
+	if req.ClassifyId <= 0 {
+		br.Msg = "分类不可为空"
+		return
+	}
+	// 判断目录是否存在
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	classifyInfo, e := classifyOb.GetItemById(req.ClassifyId)
+	if e != nil {
+		br.Msg = "分类不存在"
+		br.ErrMsg = "分类不存在, Err: " + e.Error()
+		return
+	}
+	classifyLevels := make([]string, 0)
+	{
+		levelPath := strings.Split(classifyInfo.LevelPath, ",")
+		classifyList, e := classifyOb.GetItemsByIds(levelPath)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类失败, Err: " + e.Error()
+			return
+		}
+		for _, v := range classifyList {
+			classifyLevels = append(classifyLevels, v.UniqueCode)
+		}
+	}
 	// 重名校验
 	{
 		ob := new(aiPredictModel.AiPredictModelFramework)
@@ -135,6 +177,7 @@ func (c *AiPredictModelFrameworkController) Add() {
 		}
 	}
 
+	
 	now := time.Now().Local()
 	frameworkCode := utils.MD5(fmt.Sprint(now.UnixMilli()))
 	item := new(aiPredictModel.AiPredictModelFramework)
@@ -144,6 +187,7 @@ func (c *AiPredictModelFrameworkController) Add() {
 	item.FrameworkContent = req.FrameworkContent
 	item.AdminId = sysUser.AdminId
 	item.AdminName = sysUser.RealName
+	item.ClassifyId = req.ClassifyId
 	item.CreateTime = now
 	item.ModifyTime = now
 	nodes := make([]*aiPredictModel.AiPredictModelFrameworkNode, 0)
@@ -171,7 +215,8 @@ func (c *AiPredictModelFrameworkController) Add() {
 		br.ErrMsg = "新增框架及节点失败, Err: " + e.Error()
 		return
 	}
-	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+	
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes, classifyLevels)
 
 	br.Data = detail
 	br.Ret = 200
@@ -219,7 +264,32 @@ func (c *AiPredictModelFrameworkController) Edit() {
 		br.Msg = "框架名称不可为空"
 		return
 	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "分类不可为空"
+		return
+	}
 
+	// 判断目录是否存在
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	classifyInfo, e := classifyOb.GetItemById(req.ClassifyId)
+	if e != nil {
+		br.Msg = "分类不存在"
+		br.ErrMsg = "分类不存在, Err: " + e.Error()
+		return
+	}
+	classifyLevels := make([]string, 0)
+	{
+		levelPath := strings.Split(classifyInfo.LevelPath, ",")
+		classifyList, e := classifyOb.GetItemsByIds(levelPath)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类失败, Err: " + e.Error()
+			return
+		}
+		for _, v := range classifyList {
+			classifyLevels = append(classifyLevels, v.UniqueCode)
+		}
+	}
 	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
 	item, e := frameworkOb.GetItemById(req.AiPredictModelFrameworkId)
 	if e != nil {
@@ -288,7 +358,7 @@ func (c *AiPredictModelFrameworkController) Edit() {
 		br.ErrMsg = "编辑框架及节点失败, Err: " + e.Error()
 		return
 	}
-	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes, classifyLevels)
 
 	br.Data = detail
 	br.Ret = 200
@@ -500,7 +570,13 @@ func (c *AiPredictModelFrameworkController) Move() {
 		return
 	}
 
+
 	updateCols := make([]string, 0)
+	if item.ClassifyId != req.ClassifyId {
+		//更新父级分类
+		updateCols = append(updateCols, "ClassifyId")
+		item.ClassifyId = req.ClassifyId
+	}
 	// 上一个兄弟节点
 	if req.PrevAiPredictModelFrameworkId > 0 {
 		prev, e := frameworkOb.GetItemById(req.PrevAiPredictModelFrameworkId)
@@ -608,6 +684,26 @@ func (c *AiPredictModelFrameworkController) Detail() {
 		return
 	}
 
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	classifyInfo, e := classifyOb.GetItemById(item.ClassifyId)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取分类失败, Err: " + e.Error()
+		return
+	}
+	classifyLevels := make([]string, 0)
+	{
+		levelPath := strings.Split(classifyInfo.LevelPath, ",")
+		classifyList, e := classifyOb.GetItemsByIds(levelPath)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类失败, Err: " + e.Error()
+			return
+		}
+		for _, v := range classifyList {
+			classifyLevels = append(classifyLevels, v.UniqueCode)
+		}
+	}
 	// 获取节点
 	nodeOb := new(aiPredictModel.AiPredictModelFrameworkNode)
 	nodeCond := ` AND ai_predict_model_framework_id = ?`
@@ -659,7 +755,7 @@ func (c *AiPredictModelFrameworkController) Detail() {
 
 		itemNodes = append(itemNodes, aiPredictModel.FormatAiPredictModelFrameworkNode2Item(v, num, aiPredictModelIndexMap))
 	}
-	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes, classifyLevels)
 
 	br.Data = detail
 	br.Ret = 200

+ 290 - 8
controllers/data_manage/ai_predict_model/index.go

@@ -87,7 +87,7 @@ func (this *AiPredictModelIndexController) List() {
 			classifyIdName[v.AiPredictModelClassifyId] = v.ClassifyName
 		}
 	}
-
+	classifyIds := make([]int, 0)
 	// 筛选条件
 	highlightMap := make(map[int]string)
 	indexOb := new(aiPredictModel.AiPredictModelIndex)
@@ -99,8 +99,21 @@ func (this *AiPredictModelIndexController) List() {
 			pars = append(pars, indexId)
 		}
 		if classifyId > 0 {
-			cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
-			pars = append(pars, classifyId)
+			// 查询所有子分类
+			classifyInfo, err := aiPredictModel.GetAiPredictModelClassifyById(classifyId)
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.Msg = "查询失败"
+				br.ErrMsg = "查询失败,Err:" + err.Error()
+				return
+			}
+			classifyIds, err = aiPredictModel.GetAiPredictModelClassifyChildIdsByLevelPath(classifyInfo.LevelPath)
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.Msg = "查询失败"
+				br.ErrMsg = "查询子分类失败,Err:" + err.Error()
+				return
+			}
+			cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().ClassifyId, utils.GetOrmInReplace(len(classifyIds)))
+			pars = append(pars, classifyIds)
 		}
 		//if keyword != "" {
 		//	cond += fmt.Sprintf(" AND %s LIKE ?", indexOb.Cols().IndexName)
@@ -109,7 +122,7 @@ func (this *AiPredictModelIndexController) List() {
 
 		// 有关键词从es中搜索
 		if keyword != "" {
-			_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_AI_PREDICT_MODEL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
+			_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_AI_PREDICT_MODEL, 0, classifyIds, []int{}, []string{}, startSize, pageSize)
 			if e != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = fmt.Sprintf("ES-搜索AI预测模型列表失败, %v", e)
@@ -216,20 +229,39 @@ func (this *AiPredictModelIndexController) Import() {
 
 	// 获取分类和用户,遍历时校验
 	classifyNameId := make(map[string]int)
+	classifyMap := make(map[int]string)
 	adminNameId := make(map[string]int)
 	{
 		classifyOb := new(aiPredictModel.AiPredictModelClassify)
-		classifyCond := fmt.Sprintf(` AND %s = ?`, classifyOb.Cols().ParentId)
+		classifyCond := ``
 		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 {
+			if this.Lang == utils.EnLangVersion {
+				classifyMap[v.AiPredictModelClassifyId] = v.ClassifyNameEn
+			} else {
+				classifyMap[v.AiPredictModelClassifyId] = v.ClassifyName
+			}
+		}
 		for _, v := range classifies {
-			classifyNameId[v.ClassifyName] = v.AiPredictModelClassifyId
+			levels := strings.Split(v.LevelPath, ",")
+			fullName := ""
+			for _, level := range levels {
+				if level == "" {
+					continue
+				}
+				cid, _ := strconv.Atoi(level)
+				fullName = fullName + "/" + classifyMap[cid]
+			}
+			fullName = strings.Trim(fullName, "/")
+			classifyNameId[fullName] = v.AiPredictModelClassifyId
 		}
 
 		admins, e := system.GetSysAdminList(``, make([]interface{}, 0), []string{}, "")
@@ -285,10 +317,11 @@ func (this *AiPredictModelIndexController) Import() {
 				imports[indexName].Index.TrainStatus = `训练成功`
 				imports[indexName].Index.RunStatus = `运行成功`
 
-				// 分类
+				// 分类改成多级用斜杠/区分例如:一级/二级/三级/四级/五级/六级
 				classifyName := strings.TrimSpace(cells[1].String())
 				if classifyNameId[classifyName] <= 0 {
 					br.Msg = fmt.Sprintf("分类:%s不存在", classifyName)
+					br.ErrMsg = fmt.Sprintf("分类:%s不存在,请先在系统中创建对应的分类", classifyName)
 					return
 				}
 				imports[indexName].Index.ClassifyId = classifyNameId[classifyName]
@@ -1462,3 +1495,252 @@ func getAllSearchDataSource(keyword string, source, subSource int) (list []*data
 
 	return
 }
+
+// DownloadTemplate
+// @Title 下载导入模版
+// @Description 下载导入模版
+// @Success 200 {object} models.EdbdataClassifyResp
+// @Param   Source   query   int  false       "来源:1:同花顺;2:wind;34:钢联"
+// @Param   IsApi   query   int  false       "是否api:1:是;0:否"
+// @router /index/download_template [get]
+func (c *AiPredictModelIndexController) DownloadTemplate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	c.Ctx.Output.Download("./static/template/AI预测模型导入模版.xlsx", "AI预测模型导入模版.xlsx")
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "下载成功"
+}
+
+// Export
+// @Title 导出AI预测模型
+// @Description 导出AI预测模型
+// @Success 200 {object} models.EdbdataClassifyResp
+// @Param   IndexId   query   int  false       "预测标的ID"
+// @router /index/export [get]
+func (c *AiPredictModelIndexController) Export() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	indexId, _ := c.GetInt("IndexId")
+	if indexId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, IndexId: %d", indexId)
+		return
+	}
+
+	// 获取标的信息
+	indexOb := new(aiPredictModel.AiPredictModelIndex)
+	indexItem, e := indexOb.GetItemById(indexId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "标的已被删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
+		return
+	}
+
+	// 获取分类名称
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	classifies, e := classifyOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
+	if e != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
+		return
+	}
+
+	// 构建分类ID到完整路径的映射
+	classifyIdToFullPath := make(map[int]string)
+	classifyMap := make(map[int]string)
+	for _, v := range classifies {
+		if c.Lang == utils.EnLangVersion {
+			classifyMap[v.AiPredictModelClassifyId] = v.ClassifyNameEn
+		} else {
+			classifyMap[v.AiPredictModelClassifyId] = v.ClassifyName
+		}
+	}
+	for _, v := range classifies {
+		levels := strings.Split(v.LevelPath, ",")
+		fullPath := ""
+		for _, level := range levels {
+			if level == "" {
+				continue
+			}
+			cid, _ := strconv.Atoi(level)
+			if fullPath == "" {
+				fullPath = classifyMap[cid]
+			} else {
+				fullPath = fullPath + "/" + classifyMap[cid]
+			}
+		}
+		classifyIdToFullPath[v.AiPredictModelClassifyId] = fullPath
+	}
+
+	// 获取标的数据
+	dataOb := new(aiPredictModel.AiPredictModelData)
+	dataCond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode)
+	dataPars := make([]interface{}, 0)
+	dataPars = append(dataPars, indexItem.IndexCode)
+	dataList, 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
+	}
+
+	// 创建Excel文件
+	xlFile := xlsx.NewFile()
+
+	// 创建预测标的列表页
+	sheet1, err := xlFile.AddSheet("列表页")
+	if err != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = fmt.Sprintf("创建Excel sheet失败, %v", err)
+		return
+	}
+
+	// 添加标题行
+	titleRow := sheet1.AddRow()
+	titles := []string{"预测标的", "分类", "模型类别", "创建人", "预测日期", "预测值", "预测频度", "方向准确率", "绝对偏差"}
+	for _, title := range titles {
+		cell := titleRow.AddCell()
+		cell.Value = title
+	}
+
+	// 添加数据行
+	dataRow := sheet1.AddRow()
+	dataRow.AddCell().Value = indexItem.IndexName
+	dataRow.AddCell().Value = classifyIdToFullPath[indexItem.ClassifyId]
+	dataRow.AddCell().Value = indexItem.ModelFramework
+	dataRow.AddCell().Value = indexItem.SysUserRealName
+	dataRow.AddCell().Value = indexItem.PredictDate.Format("2006-01-02")
+	dataRow.AddCell().Value = fmt.Sprintf("%.4f", indexItem.PredictValue)
+	dataRow.AddCell().Value = indexItem.PredictFrequency
+	dataRow.AddCell().Value = indexItem.DirectionAccuracy
+	dataRow.AddCell().Value = indexItem.AbsoluteDeviation
+
+	// 创建月度数据页
+	sheet2, err := xlFile.AddSheet("详情页")
+	if err != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = fmt.Sprintf("创建Excel sheet失败, %v", err)
+		return
+	}
+
+	// 添加标的名称行
+	nameRow := sheet2.AddRow()
+	nameCell := nameRow.AddCell()
+	nameCell.Value = indexItem.IndexName
+
+	// 添加标题行
+	titleRow2 := sheet2.AddRow()
+	titles2 := []string{"指标日期", "实际值", "预测值", "方向", "偏差率"}
+	for _, title := range titles2 {
+		cell := titleRow2.AddCell()
+		cell.Value = title
+	}
+
+	// 添加月度数据
+	monthlyData := make([]*aiPredictModel.AiPredictModelData, 0)
+	for _, data := range dataList {
+		if data.Source == aiPredictModel.ModelDataSourceMonthly {
+			monthlyData = append(monthlyData, data)
+		}
+	}
+	for _, data := range monthlyData {
+		dataRow := sheet2.AddRow()
+		dataRow.AddCell().Value = data.DataTime.Format("2006-01-02")
+		if data.Value.Valid {
+			dataRow.AddCell().Value = fmt.Sprintf("%.4f", data.Value.Float64)
+		} else {
+			dataRow.AddCell().Value = ""
+		}
+		if data.PredictValue.Valid {
+			dataRow.AddCell().Value = fmt.Sprintf("%.4f", data.PredictValue.Float64)
+		} else {
+			dataRow.AddCell().Value = ""
+		}
+		dataRow.AddCell().Value = data.Direction
+		dataRow.AddCell().Value = data.DeviationRate
+	}
+
+	// 创建日度数据页
+	sheet3, err := xlFile.AddSheet("日度数据表")
+	if err != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = fmt.Sprintf("创建Excel sheet失败, %v", err)
+		return
+	}
+
+	// 添加标的名称行
+	nameRow3 := sheet3.AddRow()
+	nameCell3 := nameRow3.AddCell()
+	nameCell3.Value = indexItem.IndexName
+
+	// 添加标题行
+	titleRow3 := sheet3.AddRow()
+	titles3 := []string{"日期", "实际值", "预测值"}
+	for _, title := range titles3 {
+		cell := titleRow3.AddCell()
+		cell.Value = title
+	}
+
+	// 添加日度数据
+	dailyData := make([]*aiPredictModel.AiPredictModelData, 0)
+	for _, data := range dataList {
+		if data.Source == aiPredictModel.ModelDataSourceDaily {
+			dailyData = append(dailyData, data)
+		}
+	}
+	for _, data := range dailyData {
+		dataRow := sheet3.AddRow()
+		dataRow.AddCell().Value = data.DataTime.Format("2006-01-02")
+		if data.Value.Valid {
+			dataRow.AddCell().Value = fmt.Sprintf("%.4f", data.Value.Float64)
+		} else {
+			dataRow.AddCell().Value = ""
+		}
+		if data.PredictValue.Valid {
+			dataRow.AddCell().Value = fmt.Sprintf("%.4f", data.PredictValue.Float64)
+		} else {
+			dataRow.AddCell().Value = ""
+		}
+	}
+
+	// 文件名称:预测标的名称+年月日
+	fileName := fmt.Sprintf("%s_%s.xlsx", indexItem.IndexName, time.Now().Format(utils.FormatDateShortUnSpace))
+	filePath := "./static/" + fileName
+
+	// 保存Excel文件
+	if err := xlFile.Save(filePath); err != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = fmt.Sprintf("保存Excel文件失败, %v", err)
+		return
+	}
+
+	// 下载文件
+	defer os.Remove(filePath)
+	c.Ctx.Output.Download(filePath, fileName)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "导出成功"
+}

+ 2 - 0
controllers/sys_admin.go

@@ -603,6 +603,7 @@ func (this *SysAdminController) Add() {
 	go eta_forum.AdminSave(admin.AdminId)
 	br.Ret = 200
 	br.Success = true
+	br.IsAddLog = true
 	br.Msg = "新增成功"
 }
 
@@ -1107,6 +1108,7 @@ func (this *SysAdminController) SetConfig() {
 
 	br.Ret = 200
 	br.Success = true
+	br.IsAddLog = true
 	br.Msg = "设置成功"
 }
 

+ 8 - 2
controllers/sys_role.go

@@ -76,6 +76,7 @@ func (this *SysRoleController) Add() {
 
 	br.Ret = 200
 	br.Success = true
+	br.IsAddLog = true
 	br.Msg = "新增成功"
 }
 
@@ -651,6 +652,7 @@ func (this *SysRoleController) SysRoleMenuAuthSave() {
 		return
 	}
 
+	br.IsAddLog = true
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "设置成功"
@@ -745,12 +747,16 @@ func (this *SysRoleController) SystemConfig() {
 		ConfKey: "LoginUrl",
 		ConfVal: conf["LoginUrl"],
 	}, system.BusinessConf{
-		ConfKey: models.KnowledgeBaseName,
-		ConfVal: conf[models.KnowledgeBaseName],
+		ConfKey: "KnowledgeBaseName",
+		ConfVal: conf["KnowledgeBaseName"],
 	}, system.BusinessConf{
 		ConfKey: "NotBackendGenerate",
 		ConfVal: conf["NotBackendGenerate"],
+	}, system.BusinessConf{
+		ConfKey: models.KnowledgeBaseName,
+		ConfVal: conf[models.KnowledgeBaseName],
 	})
+		
 	osc := system.BusinessConf{
 		ConfKey: "ObjectStorageClient",
 		ConfVal: utils.ObjectStorageClient,

+ 50 - 0
models/ai_predict_model/ai_predict_model_classify.go

@@ -116,6 +116,13 @@ func (m *AiPredictModelClassify) GetItemById(id int) (item *AiPredictModelClassi
 	return
 }
 
+func (m *AiPredictModelClassify) GetItemsByIds(ids []string) (items []*AiPredictModelClassify, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	err = o.Raw(sql, ids).Find(&items).Error
+	return
+}
+
 func (m *AiPredictModelClassify) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *AiPredictModelClassify, err error) {
 	o := global.DbMap[utils.DbNameIndex]
 	order := ``
@@ -238,6 +245,25 @@ type AiPredictModelClassifyListItem struct {
 	Children     []*AiPredictModelClassifyListItem `description:"子分类"`
 }
 
+// 模型框架下的目录列表
+type AiPredictModelClassifyFrameworkListResp struct {
+	AllNodes []*AiPredictModelClassifyFrameworkListItem `description:"分类节点"`
+}
+
+type AiPredictModelClassifyFrameworkListItem struct {
+	NodeType             int                               `description:"节点类型: 0-分类; 1-模型框架"`
+	NodeName             string                            `description:"节点名称"`
+	ClassifyId           int                               `description:"分类ID"`
+	ClassifyName         string                            `description:"分类名称"`
+	ClassifyNameEn       string                            `description:"英文分类名称"`
+	AiPredictModelFrameworkId int       `description:"模型框架ID"`
+	FrameworkImg              string    `description:"框架图片"`
+	ParentId     int                               `description:"父级ID"`
+	Level        int                               `description:"层级"`
+	Sort         int                               `description:"排序"`
+	UniqueCode   string                            `description:"唯一编码, 指标为IndexCode"`
+	Children     []*AiPredictModelClassifyFrameworkListItem `description:"子分类"`
+}
 type AiPredictModelClassifyMoveReq struct {
 	ClassifyId       int `description:"分类ID"`
 	ParentClassifyId int `description:"父级分类ID"`
@@ -345,6 +371,13 @@ func GetAiPredictModelIndexCountByClassifyId(classifyId int) (count int, err err
 	return
 }
 
+func GetAiPredictModelIndexCountByClassifyIds(classifyIds []int) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT COUNT(1) AS count FROM ai_predict_model_index WHERE classify_id IN (` + utils.GetOrmInReplace(len(classifyIds)) + `)`
+	err = o.Raw(sql, classifyIds).Scan(&count).Error
+	return
+}
+
 // GetAiPredictModelClassifyCountByClassifyId 获取目录下子目录数量
 func GetAiPredictModelClassifyCountByClassifyId(chartClassifyId int) (count int, err error) {
 	o := global.DbMap[utils.DbNameIndex]
@@ -439,3 +472,20 @@ func GetAiPredictClassifyByParentIdAndName(parentId int, classifyName string, cl
 	err = global.DbMap[utils.DbNameIndex].Raw(sql, parentId, classifyName, classifyId).First(&item).Error
 	return
 }
+
+
+// 根据level_path获取子分类
+func GetAiPredictModelClassifyChildIdsByLevelPath(levelPath string) (items []int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT ai_predict_model_classify_id FROM ai_predict_model_classify WHERE level_path LIKE ?`
+	err = o.Raw(sql, levelPath+"%").Scan(&items).Error
+	return
+}
+
+// RemoveAiPredictModelClassifyByClassifyIds 根据分类ID删除分类和子分类
+func RemoveAiPredictModelClassifyByClassifyIds(classifyIds []int) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `DELETE FROM ai_predict_model_classify WHERE ai_predict_model_classify_id IN (` + utils.GetOrmInReplace(len(classifyIds)) + `)`
+	err = o.Exec(sql, classifyIds).Error
+	return
+}

+ 16 - 1
models/ai_predict_model/ai_predict_model_framework.go

@@ -22,6 +22,7 @@ type AiPredictModelFramework struct {
 	AdminName                 string    `description:"创建人姓名"`
 	CreateTime                time.Time `description:"创建时间"`
 	ModifyTime                time.Time `description:"更新时间"`
+	ClassifyId                int       `description:"分类ID"`
 }
 
 func (m *AiPredictModelFramework) TableName() string {
@@ -45,6 +46,7 @@ var AiPredictModelFrameworkColumns = struct {
 	AdminName                 string
 	CreateTime                string
 	ModifyTime                string
+	ClassifyId                string
 }{
 	AiPredictModelFrameworkId: "ai_predict_model_framework_id",
 	FrameworkCode:             "framework_code",
@@ -58,6 +60,7 @@ var AiPredictModelFrameworkColumns = struct {
 	AdminName:                 "admin_name",
 	CreateTime:                "create_time",
 	ModifyTime:                "modify_time",
+	ClassifyId:                "classify_id",
 }
 
 func (m *AiPredictModelFramework) Create() (err error) {
@@ -236,6 +239,7 @@ type AiPredictModelFrameworkAddReq struct {
 	FrameworkName    string                           `description:"框架名称"`
 	FrameworkImg     string                           `description:"框架图片"`
 	FrameworkContent string                           `description:"框架内容"`
+	ClassifyId       int                              `description:"分类ID"`
 	Nodes            []AiPredictModelFrameworkNodeReq `description:"框架节点"`
 }
 
@@ -274,6 +278,7 @@ type AiPredictModelFrameworkMoveReq struct {
 	AiPredictModelFrameworkId     int `description:"图库框架ID"`
 	PrevAiPredictModelFrameworkId int `description:"上一个框架ID"`
 	NextAiPredictModelFrameworkId int `description:"下一个框架ID"`
+	ClassifyId                  int `description:"分类ID"`
 }
 
 // UpdateAiPredictModelFrameworkSort 更新我的图库框架排序
@@ -311,6 +316,7 @@ type AiPredictModelFrameworkItem struct {
 	ModifyTime                string                             `description:"更新时间"`
 	Nodes                     []*AiPredictModelFrameworkNodeItem `description:"框架节点" gorm:"-"`
 	Button                    AiPredictModelFrameworkItemButton  `description:"操作按钮" gorm:"-"`
+	ClassifyLevels            []string                           `description:"分类层级" gorm:"-"`
 }
 
 // AiPredictModelFrameworkItemButton 操作按钮
@@ -321,7 +327,7 @@ type AiPredictModelFrameworkItemButton struct {
 }
 
 // FormatAiPredictModelFramework2Item 格式化框架信息
-func FormatAiPredictModelFramework2Item(origin *AiPredictModelFramework, nodes []*AiPredictModelFrameworkNodeItem) (item *AiPredictModelFrameworkItem) {
+func FormatAiPredictModelFramework2Item(origin *AiPredictModelFramework, nodes []*AiPredictModelFrameworkNodeItem, classifyLevels []string) (item *AiPredictModelFrameworkItem) {
 	if origin == nil {
 		return
 	}
@@ -338,6 +344,7 @@ func FormatAiPredictModelFramework2Item(origin *AiPredictModelFramework, nodes [
 	item.AdminName = origin.AdminName
 	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
 	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	item.ClassifyLevels = classifyLevels
 	item.Nodes = nodes
 	return
 }
@@ -348,3 +355,11 @@ type AiPredictModelFrameworkPublicMenuItem struct {
 	MenuName   string                         `description:"目录名称"`
 	Frameworks []*AiPredictModelFrameworkItem `description:"框架列表"`
 }
+
+// GetAiPredictModelFrameworkCountByClassifyIds 获取分类下框架数量
+func GetAiPredictModelFrameworkCountByClassifyIds(classifyIds []int) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT COUNT(1) AS count FROM ai_predict_model_framework WHERE classify_id IN (?)`
+	err = o.Raw(sql, classifyIds).Scan(&count).Error
+	return
+}

+ 27 - 0
routers/commentsRouter.go

@@ -439,6 +439,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelClassifyController"],
+        beego.ControllerComments{
+            Method: "FrameworkList",
+            Router: `/classify/framework/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelClassifyController"],
         beego.ControllerComments{
             Method: "List",
@@ -628,6 +637,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"],
+        beego.ControllerComments{
+            Method: "DownloadTemplate",
+            Router: `/index/download_template`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"],
+        beego.ControllerComments{
+            Method: "Export",
+            Router: `/index/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/ai_predict_model:AiPredictModelIndexController"],
         beego.ControllerComments{
             Method: "Import",

+ 1 - 1
services/ai_predict_model_classify.go

@@ -190,7 +190,7 @@ func moveAiPredictModelClassify(parentClassify, edbClassifyInfo, prevClassify, n
 			edbClassifyInfo.Level = parentClassify.Level + 1
 			edbClassifyInfo.ModifyTime = time.Now()
 			// 更改层级路径
-			edbClassifyInfo.LevelPath = fmt.Sprintf("%s,%d", parentClassify.LevelPath, edbClassifyInfo.AiPredictModelClassifyId)
+			edbClassifyInfo.LevelPath = fmt.Sprintf("%s%d,", parentClassify.LevelPath, edbClassifyInfo.AiPredictModelClassifyId)
 			updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime", "LevelPath")
 		} else if edbClassifyInfo.ParentId != parentClassifyId && parentClassifyId == 0 {
 			errMsg = "移动失败"

+ 6 - 1
services/data/stl/stl.go

@@ -161,6 +161,12 @@ func GenerateStlEdbData(req *request.StlConfigReq, adminId int) (resp *response.
 	defer os.Remove(loadFilePath)
 
 	saveFilePath := exPath + "/" + strconv.Itoa(adminId) + "_" + time.Now().Format(utils.FormatDateTimeUnSpace) + "_res" + ".xlsx"
+	// 文件生成成功的话,那么计算完之后就删除吧
+	defer func() {
+		if utils.FileIsExist(saveFilePath) {
+			os.Remove(saveFilePath)
+		}
+	}()
 	result, err := execStlPythonCode(loadFilePath, saveFilePath, confReq.Period, confReq.Seasonal, confReq.Trend, confReq.TrendDeg, confReq.SeasonalDeg, confReq.LowPassDeg, confReq.Fraction, confReq.Robust)
 	if err != nil {
 		msg = "计算失败,请重新选择指标和参数后计算"
@@ -171,7 +177,6 @@ func GenerateStlEdbData(req *request.StlConfigReq, adminId int) (resp *response.
 		msg = "解析Excel失败"
 		return
 	}
-	defer os.Remove(saveFilePath)
 	trendName := fmt.Sprintf("%sTrend/F%g", edbInfo.EdbName, confReq.Fraction)
 	seasonalName := fmt.Sprintf("%sSeasonal/F%g", edbInfo.EdbName, confReq.Fraction)
 	residualName := fmt.Sprintf("%sResidual/F%g", edbInfo.EdbName, confReq.Fraction)

+ 1 - 1
services/elastic/elastic.go

@@ -2039,7 +2039,7 @@ func SearchDataSourceIndex(indexName, keyword string, source, subSource int, cla
 	// 分类
 	if len(classifyIds) > 0 {
 		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
+			"terms": map[string]interface{}{
 				"ClassifyId": classifyIds,
 			},
 		})

+ 3 - 2
services/task.go

@@ -87,11 +87,12 @@ func Task() {
 	// 权益报告监听入库
 	go AutoInsertRaiReport()
 
-	go llm.DealHistoryArticleDafTags()
 
+	go StartGenerateReportPDF()
 	// 巡检信息发送
 	go AutoCheckWebsocketMessageList()
-	go StartGenerateReportPDF()
+
+	go llm.DealHistoryArticleDafTags()
 
 	// TODO:数据修复
 	//FixNewEs()

BIN
static/template/AI预测模型导入模版.xlsx


+ 2 - 1
utils/constants.go

@@ -11,7 +11,8 @@ const (
 	FormatTimeHm               = "15:04"                     //时间格式
 	FormatDate                 = "2006-01-02"                //日期格式
 	FormatDateUnSpace          = "20060102"                  //日期格式
-	ormatDateUnSpace           = "2006.01.02"                //日期格式
+	FormatDateShortUnSpace     = "060102"                    //日期格式
+	FormatDateUnSpaceDot       = "2006.01.02"                //日期格式
 	FormatDateTime             = "2006-01-02 15:04:05"       //完整时间格式
 	HlbFormatDateTime          = "2006-01-02_15:04:05.999"   //完整时间格式
 	FormatDateTimeUnSpace      = "20060102150405"            //完整时间格式