Browse Source

Merge branch 'master' into feature/pool294_fa_calendar

xyxie 3 weeks ago
parent
commit
0bd88e0116
100 changed files with 17635 additions and 1563 deletions
  1. 2 1
      .gitignore
  2. 93 0
      cache/llm.go
  3. 4 4
      controllers/ai/ai.go
  4. 3 3
      controllers/ai/ai_file.go
  5. 4 4
      controllers/ai/ai_pormpt.go
  6. 30 24
      controllers/ai/ai_summary.go
  7. 15 6
      controllers/banner.go
  8. 31 3
      controllers/base_auth.go
  9. 1315 0
      controllers/bi_dashboard.go
  10. 2 2
      controllers/business_conf.go
  11. 50 8
      controllers/classify.go
  12. 4 4
      controllers/cloud_disk.go
  13. 2 2
      controllers/commodity_trade_base_index.go
  14. 4 4
      controllers/company_seller.go
  15. 558 0
      controllers/data_manage/ai_predict_model/classify.go
  16. 668 0
      controllers/data_manage/ai_predict_model/framework.go
  17. 1132 0
      controllers/data_manage/ai_predict_model/index.go
  18. 5 5
      controllers/data_manage/baiinfo_data.go
  19. 3 2
      controllers/data_manage/base_from_ly_index_controller.go
  20. 1152 0
      controllers/data_manage/base_from_radish_research.go
  21. 518 0
      controllers/data_manage/base_from_radish_research_classify.go
  22. 708 0
      controllers/data_manage/base_from_rzd_index_controller.go
  23. 105 75
      controllers/data_manage/base_from_ths_hf.go
  24. 2 2
      controllers/data_manage/base_from_ths_hf_classify.go
  25. 78 15
      controllers/data_manage/bloomberg_data.go
  26. 45 19
      controllers/data_manage/business_data.go
  27. 912 21
      controllers/data_manage/ccf_data.go
  28. 458 176
      controllers/data_manage/chart_classify.go
  29. 193 1
      controllers/data_manage/chart_common.go
  30. 2 2
      controllers/data_manage/chart_edb_config.go
  31. 38 16
      controllers/data_manage/chart_framework.go
  32. 343 88
      controllers/data_manage/chart_info.go
  33. 14 8
      controllers/data_manage/chart_theme.go
  34. 1653 0
      controllers/data_manage/clarksons_data.go
  35. 5 5
      controllers/data_manage/com_trade.go
  36. 38 31
      controllers/data_manage/correlation/correlation_chart_classify.go
  37. 52 31
      controllers/data_manage/correlation/correlation_chart_info.go
  38. 46 25
      controllers/data_manage/cross_variety/chart_info.go
  39. 10 10
      controllers/data_manage/cross_variety/classify.go
  40. 5 5
      controllers/data_manage/cross_variety/tag.go
  41. 5 5
      controllers/data_manage/cross_variety/variety.go
  42. 2 2
      controllers/data_manage/data_manage_permission/message.go
  43. 183 17
      controllers/data_manage/edb_classify.go
  44. 188 105
      controllers/data_manage/edb_info.go
  45. 12 7
      controllers/data_manage/edb_info_calculate.go
  46. 50 23
      controllers/data_manage/edb_info_refresh.go
  47. 42 14
      controllers/data_manage/edb_info_relation.go
  48. 3 2
      controllers/data_manage/eia_steo.go
  49. 21 10
      controllers/data_manage/excel/balance_table.go
  50. 20 9
      controllers/data_manage/excel/custom_analysis.go
  51. 1 1
      controllers/data_manage/excel/custom_analysis_edb.go
  52. 24 15
      controllers/data_manage/excel/excel_classify.go
  53. 524 39
      controllers/data_manage/excel/excel_info.go
  54. 2 2
      controllers/data_manage/factor_edb_series.go
  55. 52 29
      controllers/data_manage/fenwei_data.go
  56. 15 0
      controllers/data_manage/fix.go
  57. 19 16
      controllers/data_manage/future_good/future_good_chart_classify.go
  58. 152 100
      controllers/data_manage/future_good/future_good_chart_info.go
  59. 6 6
      controllers/data_manage/future_good/future_good_edb_info.go
  60. 9 9
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  61. 59 10
      controllers/data_manage/gl_data.go
  62. 1045 0
      controllers/data_manage/gpr_risk_data.go
  63. 22 0
      controllers/data_manage/jiayue_edb_source.go
  64. 21 18
      controllers/data_manage/line_equation/line_chart_classify.go
  65. 45 24
      controllers/data_manage/line_equation/line_chart_info.go
  66. 100 64
      controllers/data_manage/line_feature/chart_info.go
  67. 21 18
      controllers/data_manage/line_feature/classify.go
  68. 11 13
      controllers/data_manage/manual.go
  69. 55 11
      controllers/data_manage/manual_edb.go
  70. 25 14
      controllers/data_manage/multiple_graph_config.go
  71. 94 60
      controllers/data_manage/my_chart.go
  72. 61 18
      controllers/data_manage/mysteel_chemical_data.go
  73. 14 5
      controllers/data_manage/predict_edb_classify.go
  74. 211 95
      controllers/data_manage/predict_edb_info.go
  75. 1045 0
      controllers/data_manage/purang_data.go
  76. 22 13
      controllers/data_manage/range_analysis/chart_classify.go
  77. 30 23
      controllers/data_manage/range_analysis/chart_info.go
  78. 5 5
      controllers/data_manage/sci_data.go
  79. 56 20
      controllers/data_manage/sci_hq_data.go
  80. 50 25
      controllers/data_manage/smm_api.go
  81. 8 4
      controllers/data_manage/smm_data.go
  82. 225 0
      controllers/data_manage/stl/stl.go
  83. 8 8
      controllers/data_manage/supply_analysis/variety.go
  84. 15 11
      controllers/data_manage/supply_analysis/variety_edb.go
  85. 8 8
      controllers/data_manage/supply_analysis/variety_plant.go
  86. 1394 0
      controllers/data_manage/usda_fas_data.go
  87. 7 7
      controllers/data_manage/wind_data.go
  88. 10 8
      controllers/data_manage/yongyi_data.go
  89. 316 0
      controllers/data_source/data_source.go
  90. 7 8
      controllers/data_source/sci99.go
  91. 25 26
      controllers/data_stat/edb_source_stat.go
  92. 42 0
      controllers/data_stat/edb_terminal.go
  93. 5 3
      controllers/document_manage/document_manage_controller.go
  94. 398 0
      controllers/edb_monitor/edb_monitor.go
  95. 240 0
      controllers/edb_monitor/edb_monitor_classify.go
  96. 251 0
      controllers/edb_monitor/edb_monitor_message.go
  97. 14 2
      controllers/english_report/email.go
  98. 5 5
      controllers/english_report/en_permission.go
  99. 30 21
      controllers/english_report/english_classify.go
  100. 3 3
      controllers/english_report/english_company.go

+ 2 - 1
.gitignore

@@ -19,4 +19,5 @@ eta_api.exe
 eta_api.exe~
 /static/tmpFile/*
 etalogs/
-/.vscode
+/.vscode
+/fix

+ 93 - 0
cache/llm.go

@@ -0,0 +1,93 @@
+package cache
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+)
+
+type WechatArticleOp struct {
+	Source           string
+	WechatPlatformId int
+}
+
+// AddWechatArticleOpToCache
+// @Description: 将公众号文章操作加入缓存
+// @param wechatPlatformId
+// @param source
+// @return bool
+func AddWechatArticleOpToCache(wechatPlatformId int, source string) bool {
+	// 如果不在发布和调试模式,那么就不加入缓存
+	if !utils.InArrayByStr([]string{utils.BusinessCodeRelease, utils.BusinessCodeDebug}, utils.BusinessCode) {
+		return true
+	}
+
+	record := new(WechatArticleOp)
+	record.Source = source
+	record.WechatPlatformId = wechatPlatformId
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_WECHAT_PLATFORM_ARTICLE, record)
+
+		utils.FileLog.Info(fmt.Sprintf("将公众号文章操作 加入缓存 AddWechatArticleOpToCache LPush: 操作类型:%s,公众号id:%d", source, wechatPlatformId))
+		if err != nil {
+			fmt.Println("AddWechatArticleOpToCache LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}
+
+// AddWechatArticleLlmOpToCache
+// @Description: 将公众号文章llm操作加入缓存
+// @param wechatPlatformId
+// @param source
+// @return bool
+func AddWechatArticleLlmOpToCache(wechatPlatformId int, source string) bool {
+	// 如果不在发布和调试模式,那么就不加入缓存
+	if !utils.InArrayByStr([]string{utils.BusinessCodeRelease, utils.BusinessCodeDebug}, utils.BusinessCode) {
+		return true
+	}
+	record := new(WechatArticleOp)
+	record.Source = source
+	record.WechatPlatformId = wechatPlatformId
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_WECHAT_PLATFORM_ARTICLE_KNOWLEDGE, record)
+
+		utils.FileLog.Info(fmt.Sprintf("将公众号文章llm操作加入缓存 加入缓存 AddWechatArticleLlmOpToCache LPush: 操作类型:%s,公众号id:%d", source, wechatPlatformId))
+		if err != nil {
+			fmt.Println("AddWechatArticleOpToCache LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}
+
+type RagEtaReportOpOp struct {
+	Source          string
+	ReportId        int
+	ReportChapterId int
+}
+
+// RagEtaReportOpToCache
+// @Description: 将eta报告入知识库操作加入缓存
+// @author: Roc
+// @datetime 2025-04-07 15:05:22
+// @param reportId int
+// @param reportChapterId int
+// @param source string
+// @return bool
+func RagEtaReportOpToCache(reportId, reportChapterId int, source string) bool {
+	record := new(RagEtaReportOpOp)
+	record.Source = source
+	record.ReportId = reportId
+	record.ReportChapterId = reportChapterId
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_ETA_REPORT_KNOWLEDGE, record)
+
+		utils.FileLog.Info(fmt.Sprintf("将eta报告入知识库操作加入缓存 加入缓存 RagEtaReportOpToCache LPush: 操作类型:%s,报告id:%d,章节id:%d", source, reportId, reportChapterId))
+		if err != nil {
+			fmt.Println("RagEtaReportOpToCache LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}

+ 4 - 4
controllers/ai/ai.go

@@ -71,7 +71,7 @@ func (this *AiController) List() {
 	//根据提问,获取信息
 	askUuid := utils.MD5(req.Ask)
 	chatMode, err := aimod.GetAiChatByAsk(askUuid)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取数据失败!"
 		br.ErrMsg = "获取数据失败,GetAiChatByAsk,Err:" + err.Error()
 		return
@@ -88,7 +88,7 @@ func (this *AiController) List() {
 		//获取主题下的所有信息
 		//AiChatTopicId
 		historyList, err := aimod.GetAiChatList(req.AiChatTopicId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取主题历史数据失败!"
 			br.ErrMsg = "获取主题历史数据失败,Err:" + err.Error()
 			return
@@ -317,12 +317,12 @@ func (this *AiController) TopicEdit() {
 		return
 	}
 	topic, err := aimod.GetAiChatTopicByTopicName(req.TopicName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "编辑失败!"
 		br.ErrMsg = "获取数据失败!Err:" + err.Error()
 		return
 	}
-	if topic != nil && topic.AiChatTopicId != req.AiChatTopicId {
+	if topic != nil && topic.AiChatTopicId != req.AiChatTopicId && topic.AiChatTopicId > 0 {
 		br.Msg = "话题名称已存在,请重新修改!"
 		return
 	}

+ 3 - 3
controllers/ai/ai_file.go

@@ -110,7 +110,7 @@ func (this *AiFileController) FileUpload() {
 		aiChatTopicObj.AiChatTopicId = aiChatTopicId
 		topic, err := aiChatTopicObj.GetAiChatTopicById()
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "获取数据失败!"
 				br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
 				return
@@ -283,7 +283,7 @@ func (this *AiFileController) FileRetrieve() {
 		aiChatTopicObj.AiChatTopicId = req.AiChatTopicId
 		topic, err := aiChatTopicObj.GetAiChatTopicById()
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "获取数据失败!"
 				br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
 				return
@@ -301,7 +301,7 @@ func (this *AiFileController) FileRetrieve() {
 	//获取主题下的所有信息
 	//AiChatTopicId
 	historyList, err := aimod.GetAiChatList(req.AiChatTopicId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取主题历史数据失败!"
 		br.ErrMsg = "获取主题历史数据失败,Err:" + err.Error()
 		return

+ 4 - 4
controllers/ai/ai_pormpt.go

@@ -302,7 +302,7 @@ func (this *AiController) MoveAiPrompt() {
 
 	prompt, err := ai_summary.GetAiPromptById(req.AiPromptId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "当前提示词不存在"
 			br.ErrMsg = "当前提示词不存在"
 			return
@@ -321,7 +321,7 @@ func (this *AiController) MoveAiPrompt() {
 	if req.PrevAiPromptId > 0 {
 		prevPrompt, err = ai_summary.GetAiPromptById(req.PrevAiPromptId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				err = errors.New("目录下的提示词不存在")
 				return
 			}
@@ -334,7 +334,7 @@ func (this *AiController) MoveAiPrompt() {
 	if req.NextAiPromptId > 0 {
 		nextPrompt, err = ai_summary.GetAiPromptById(req.NextAiPromptId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				err = errors.New("目录下的提示词不存在")
 				return
 			}
@@ -410,4 +410,4 @@ func (this *AiController) SharePrompt() {
 	br.Msg = "操作成功"
 
 	return
-}
+}

+ 30 - 24
controllers/ai/ai_summary.go

@@ -11,9 +11,10 @@ import (
 	"eta/eta_api/services/aiser"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // AiSummaryClassifyItems
@@ -40,6 +41,13 @@ func (this *AiController) AiSummaryClassifyItems() {
 			br.ErrMsg = err.Error()
 			return
 		}
+		nodeAll, err := aiSummaryService.GetAiSummaryClassifyByIsShowMe(resp.AllNodes, aiSummaryClassifyId, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp.AllNodes = nodeAll
 
 		br.Ret = 200
 		br.Success = true
@@ -50,7 +58,7 @@ func (this *AiController) AiSummaryClassifyItems() {
 	}
 
 	rootList, err := ai_summary.GetAiSummaryClassifyAndInfoByParentId(aiSummaryClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -60,7 +68,7 @@ func (this *AiController) AiSummaryClassifyItems() {
 	}
 
 	classifyAll, err := ai_summary.GetAiSummaryClassifyAndInfoByParentId(aiSummaryClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -235,7 +243,7 @@ func (this *AiController) DeleteSandboxClassifyCheck() {
 
 	if deleteStatus != 1 {
 		classifyCount, err := ai_summary.GetAiSummaryInfoCountByClassifyId(req.AiSummaryClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有沙盘失败,Err:" + err.Error()
 			return
@@ -296,7 +304,7 @@ func (this *AiController) DeleteAiSummaryClassify() {
 	if req.AiSummaryClassifyId > 0 && req.AiSummaryId == 0 {
 		//判断是否含有纪要
 		count, err := ai_summary.GetAiSummaryInfoCountByClassifyId(req.AiSummaryClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -320,7 +328,7 @@ func (this *AiController) DeleteAiSummaryClassify() {
 	if req.AiSummaryId > 0 {
 		summaryInfo, err := ai_summary.GetAiSummaryById(req.AiSummaryId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "纪要已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -573,7 +581,7 @@ func (this *AiController) AiSummaryClassifyMove() {
 		} else {
 			// prevId为0,也就是沙盘移到最前端
 			firstClassify, err := ai_summary.GetFirstAiSummaryByClassifyId(req.AiSummaryClassifyId)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "移动失败"
 				br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 				return
@@ -762,7 +770,7 @@ func (this *AiController) AiSummaryClassifyMove() {
 
 		} else {
 			firstClassify, err := ai_summary.GetFirstAiSummaryClassifyByParentId(aiSummaryClassifyInfo.ParentId)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "移动失败"
 				br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 				return
@@ -841,7 +849,7 @@ func (this *AiController) AiSummaryList() {
 
 	if aiSummaryClassifyId > 0 {
 		sandboxClassifyIds, err := ai_summary.GetAiSummaryClassify(aiSummaryClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
@@ -862,7 +870,7 @@ func (this *AiController) AiSummaryList() {
 
 	//获取图表信息
 	list, err := ai_summary.GetAiSummaryListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取纪要信息失败"
 		br.ErrMsg = "获取纪要信息失败,Err:" + err.Error()
@@ -879,7 +887,7 @@ func (this *AiController) AiSummaryList() {
 		list[i].ParentIds = ids
 	}
 	resp := new(ai_summary.AiSummaryListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*ai_summary.AiSummaryItems, 0)
 		resp.Paging = page
 		resp.List = items
@@ -890,7 +898,7 @@ func (this *AiController) AiSummaryList() {
 	}
 
 	dataCount, err := ai_summary.GetAiSummaryListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -926,7 +934,7 @@ func (this *AiController) AiSummaryDetail() {
 	aiSummaryId, _ := this.GetInt("AiSummaryId")
 
 	detail, err := ai_summary.GetAiSummaryItemById(aiSummaryId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取沙盘信息失败"
 		br.ErrMsg = "获取沙盘信息失败,Err:" + err.Error()
@@ -936,11 +944,11 @@ func (this *AiController) AiSummaryDetail() {
 		AiSummaryItems: detail,
 	}
 
-	if detail.SaDocId >0 {
+	if detail.SaDocId > 0 {
 		item := new(saModel.SaDoc)
 		e := item.GetItemById(detail.SaDocId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "文档已被删除, 请刷新页面"
 				return
 			}
@@ -952,7 +960,6 @@ func (this *AiController) AiSummaryDetail() {
 		resp.SaDocClassifyId = item.ClassifyId
 	}
 
-
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true
@@ -1017,7 +1024,7 @@ func (this *AiController) AddAiSummary() {
 		br.ErrMsg = "保存分类失败,Err:" + err.Error()
 		return
 	}
-	classify ,err := ai_summary.GetAiSummaryClassifyById(req.ClassifyId)
+	classify, err := ai_summary.GetAiSummaryClassifyById(req.ClassifyId)
 	if err != nil {
 		br.Msg = "获取分类信息失败"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
@@ -1130,7 +1137,7 @@ func (this *AiController) GenerateAiSummary() {
 		//获取主题下的所有信息
 		//AiChatTopicId
 		historyList, err := aimod.GetAiChatList(req.AiChatTopicId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取主题历史数据失败!"
 			br.ErrMsg = "获取主题历史数据失败,Err:" + err.Error()
 			return
@@ -1218,7 +1225,7 @@ func (this *AiController) GenerateAiSummary() {
 			aiChatTopicObj.AiChatTopicId = req.AiChatTopicId
 			topic, err := aiChatTopicObj.GetAiChatTopicById()
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "获取数据失败!"
 					br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
 					return
@@ -1454,7 +1461,7 @@ func (this *AiController) GenerateAiSummary() {
 //		aiChatTopicObj.AiChatTopicId = aiChatTopicId
 //		topic, err := aiChatTopicObj.GetAiChatTopicById()
 //		if err != nil {
-//			if err.Error() == utils.ErrNoRow() {
+//			if utils.IsErrNoRow(err) {
 //				br.Msg = "获取数据失败!"
 //				br.ErrMsg = "获取数据失败,主题不存在,Err:" + err.Error()
 //				return
@@ -1562,7 +1569,6 @@ func (this *AiController) GenerateAiSummary() {
 //	return
 //}
 
-
 // AiSummaryClassifyList
 // @Title 获取所有纪要分类接口-不包含沙盘
 // @Description 获取所有纪要分类接口-不包含沙盘
@@ -1579,14 +1585,14 @@ func (this *AiController) AiSummaryClassifyList() {
 	resp := new(ai_summary.AiSummaryClassifyListResp)
 
 	rootList, err := ai_summary.GetAiSummaryClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := ai_summary.GetAiSummaryClassifyAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -1604,4 +1610,4 @@ func (this *AiController) AiSummaryClassifyList() {
 	br.Success = true
 	br.Msg = "获取成功"
 	br.Data = resp
-}
+}

+ 15 - 6
controllers/banner.go

@@ -4,7 +4,6 @@ import (
 	"eta/eta_api/models"
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
-	"github.com/h2non/filetype"
 	"io/ioutil"
 	"os"
 	"path"
@@ -53,14 +52,24 @@ func (this *BannerController) Upload() {
 		br.ErrMsg = "读取文件失败, Err: " + e.Error()
 		return
 	}
-	pass := filetype.IsImage(fileData)
-	if !pass {
-		br.Msg = "文件格式有误"
-		br.ErrMsg = "文件格式有误"
+	//pass := filetype.IsImage(fileData)
+	//if !pass {
+	//	br.Msg = "文件格式有误"
+	//	br.ErrMsg = "文件格式有误"
+	//	return
+	//}
+	ext := path.Ext(h.Filename)
+	if !utils.IsValidType(fileData, []utils.SourceType{
+		utils.Image,
+	}, []string{
+		"jpg",
+		"png",
+	}, ext) {
+		br.Msg = "文件格式不支持"
+		br.ErrMsg = "文件格式不支持"
 		return
 	}
 
-	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
 	err = os.MkdirAll(uploadDir, utils.DIR_MOD)

+ 31 - 3
controllers/base_auth.go

@@ -119,7 +119,7 @@ func (c *BaseAuthController) Prepare() {
 
 			session, err := system.GetSysSessionByToken(token)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "Token 信息已变更:Token: " + token}, false, false)
 					c.StopRun()
 					return
@@ -148,7 +148,7 @@ func (c *BaseAuthController) Prepare() {
 			}
 			admin, err := system.GetSysUserById(session.SysUserId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "获取admin 信息失败 " + strconv.Itoa(session.SysUserId)}, false, false)
 					c.StopRun()
 					return
@@ -174,13 +174,40 @@ func (c *BaseAuthController) Prepare() {
 				loginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN, session.Id)
 				loginInfo, _ := utils.Rc.RedisString(loginKey)
 				if loginInfo == `` {
+					// 超时退出的时候,也记录下当前请求日志,避免数据丢失
+					requestBody, err := url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+					if err != nil {
+						requestBody = string(c.Ctx.Input.RequestBody)
+					}
+					if requestBody == "" {
+						requestBody = c.Ctx.Input.URI()
+					}
+					utils.ApiLog.Info("uri:%s, authorization:%s, requestBody:%s", c.Ctx.Input.URI(), authorization, requestBody)
+
 					c.JSON(models.BaseResponse{Ret: 408, Msg: "超时未操作,系统自动退出!", ErrMsg: "超时未操作,系统自动退出!"}, false, false)
 					c.StopRun()
 					return
 				}
 
 				if loginInfo != "1" {
-					msg := `该账号于` + admin.LastLoginTime + "在其他网络登录。此客户端已退出登录。"
+					// 超时退出的时候,也记录下当前请求日志,避免数据丢失
+					requestBody, err := url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+					if err != nil {
+						requestBody = string(c.Ctx.Input.RequestBody)
+					}
+					if requestBody == "" {
+						requestBody = c.Ctx.Input.URI()
+					}
+					utils.ApiLog.Info("uri:%s, authorization:%s, requestBody:%s", c.Ctx.Input.URI(), authorization, requestBody)
+
+					var lastLoginTimeStr string
+					lastLoginTime, err := time.ParseInLocation(utils.FormatDateWallWithLoc, admin.LastLoginTime, time.Local)
+					if err == nil {
+						lastLoginTimeStr = lastLoginTime.Format(utils.FormatDateTime)
+					} else {
+						lastLoginTimeStr = admin.LastLoginTime
+					}
+					msg := `该账号于` + lastLoginTimeStr + "在其他网络登录。此客户端已退出登录。"
 					c.JSON(models.BaseResponse{Ret: 408, Msg: msg, ErrMsg: msg}, false, false)
 					c.StopRun()
 					return
@@ -213,6 +240,7 @@ func (c *BaseAuthController) Prepare() {
 					api += v.Api + "&"
 				}
 			}
+			api += "&" + models.BusinessConfMap["PublicApi"]
 			//处理uri请求,去除前缀和参数
 			api = strings.TrimRight(api, "&")
 			uri = strings.Replace(uri, "/adminapi", "", 1)

+ 1315 - 0
controllers/bi_dashboard.go

@@ -0,0 +1,1315 @@
+package controllers
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models"
+	"eta/eta_api/models/bi_dashboard"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type BIDaShboardController struct {
+	BaseAuthController
+}
+
+// GroupList
+// @Title 获取我的列表
+// @Description 获取我的列表接口
+// @Success 200 {object} models.RespGroupList
+// @router /my_list [get]
+func (this *BIDaShboardController) MyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 获取我的看板列表
+	privateCond := ` AND sys_admin_id = ? `
+	privatePars := []interface{}{this.SysUser.AdminId}
+	privateList, err := bi_dashboard.GetBiDashboardList(privateCond, privatePars)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = privateList
+	return
+}
+
+// AddDashboard
+// @Title 新增看板
+// @Description 新增看板接口
+// @Param	request	body models.AddDashboardReq true "type json string"
+// @Success 200 Ret=200 新增成功
+// @router /add [post]
+func (this *BIDaShboardController) AddDashboard() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.AddDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardName == "" {
+		br.Msg = "名称不能为空"
+		return
+	}
+	nameItem, err := bi_dashboard.GetDashboardByName(req.BiDashboardName, this.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "查询失败"
+		br.ErrMsg = "查询失败,Err:" + err.Error()
+		return
+	}
+	if nameItem != nil && nameItem.BiDashboardId > 0 {
+		br.Msg = "名称重复"
+		return
+	}
+
+	item := &bi_dashboard.BiDashboard{
+		//BiDashboardClassifyId: req.ClassifyId,
+		BiDashboardName: req.BiDashboardName,
+		SysAdminId:      this.SysUser.AdminId,
+		SysAdminName:    this.SysUser.RealName,
+		//Sort:                  0,
+		CreateTime: time.Now(),
+		ModifyTime: time.Now(),
+		State:      1,
+	}
+	id, e := bi_dashboard.AddBiDashboard(item)
+	if e != nil {
+		err = e
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + e.Error()
+		return
+	}
+	detailList := make([]*bi_dashboard.BiDashboardDetail, 0)
+	for i, v := range req.List {
+		item := &bi_dashboard.BiDashboardDetail{
+			BiDashboardId: int(id),
+			Type:          v.Type,
+			UniqueCode:    v.UniqueCode,
+			Sort:          i + 1,
+			CreateTime:    time.Now(),
+			ModifyTime:    time.Now(),
+		}
+		detailList = append(detailList, item)
+	}
+	err = bi_dashboard.AddBiDashboardDetailMulti(detailList)
+	if err != nil {
+		br.Msg = "新增详情失败"
+		br.ErrMsg = "新增详情失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+	//br.Data =
+}
+
+// EditPpt
+// @Title 编辑看板
+// @Description 编辑看板接口
+// @Param	request	body bi_dashboard.EditDashboardReq true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /edit [post]
+func (this *BIDaShboardController) EditDashboard() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.EditDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardName == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+
+	// 修改
+	item.BiDashboardName = req.BiDashboardName
+	item.ModifyTime = time.Now()
+
+	err = bi_dashboard.EditDashboard(item)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	err = bi_dashboard.DeleteBiDashboardDetail(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "删除详情失败"
+		br.ErrMsg = "删除详情失败,Err:" + err.Error()
+		return
+	}
+
+	detailList := make([]*bi_dashboard.BiDashboardDetail, 0)
+	for _, v := range req.List {
+		item := &bi_dashboard.BiDashboardDetail{
+			BiDashboardId: req.BiDashboardId,
+			Type:          v.Type,
+			UniqueCode:    v.UniqueCode,
+			Sort:          v.Sort,
+			CreateTime:    time.Now(),
+			ModifyTime:    time.Now(),
+		}
+		detailList = append(detailList, item)
+	}
+	err = bi_dashboard.AddBiDashboardDetailMulti(detailList)
+	if err != nil {
+		br.Msg = "新增详情失败"
+		br.ErrMsg = "新增详情失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// DeleteDashboard
+// @Title 删除看板
+// @Description 删除看板接口
+// @Param	request	body bi_dashboard.DelDashboardReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /delete [post]
+func (this *BIDaShboardController) DeleteDashboard() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.DelDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+	if item.SysAdminId != this.SysUser.AdminId {
+		br.Msg = "无权删除"
+		return
+	}
+	err = bi_dashboard.DelDashboard(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	//如果该看板存在共享记录,则删除共享
+	err = bi_dashboard.DeleteDashboardGrant(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "删除成功"
+}
+
+// DeleteDashboard
+// @Title 删除看板详情
+// @Description 删除看板详情接口
+// @Param	request	body bi_dashboard.DelDashboardDetailReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /detail/delete [post]
+func (this *BIDaShboardController) DeleteDashboardDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.DelDashboardDetailReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardDetailId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	err = bi_dashboard.DeleteBiDashboardDetailByDetailId(req.BiDashboardDetailId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "删除成功"
+}
+
+// DetailDashboard
+// @Title 获取看板详情
+// @Description 获取看板详情接口
+// @Param   PptId   query   int  true       "PptId"
+// @Success 200 {object} models.PptV2
+// @router /detail [get]
+func (this *BIDaShboardController) DetailDashboard() {
+	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
+	}
+	dashboardId, _ := this.GetInt("DashboardId")
+	resp := new(bi_dashboard.DashboardDetailResp)
+	dashboardItem, err := bi_dashboard.GetDashboardById(dashboardId)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		br.Msg = "我的看板列表查询出错"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	grantInfoList, err := bi_dashboard.GetDashboardGrantInfo(dashboardId)
+	if err != nil {
+		br.Msg = "信息获取失败"
+		br.ErrMsg = "共享信息获取失败,Err:" + err.Error()
+		return
+	}
+	if len(grantInfoList) > 0 {
+		resp.IsGrant = 1
+	}
+
+	detailList, err := bi_dashboard.GetBiDashboardDetailById(dashboardId)
+	if err != nil {
+		br.Msg = "详情获取失败"
+		br.ErrMsg = "详情获取失败,Err:" + err.Error()
+		return
+	}
+
+	editor, e := services.UpdateBiDashboardEditing(dashboardId, 0, sysUser.AdminId, sysUser.RealName)
+	if e != nil {
+		br.Msg = "编辑状态更新失败"
+		br.ErrMsg = "编辑状态更新失败,Err:" + e.Error()
+		return
+	}
+
+	resp.Editor = editor
+	resp.BiDashboard = dashboardItem
+	resp.List = detailList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// MoveDashboard
+// @Title 移动看板详情
+// @Description 移动看板详情接口
+// @Param	request	body bi_dashboard.MoveDashboardDetailReq true "type json string"
+// @Success 200 Ret=200 移动成功
+// @router /detail/move [post]
+func (this *BIDaShboardController) MoveDashboard() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.MoveDashboardDetailReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	if req.BiDashboardDetailId == req.OtherDetailId || req.BiDashboardDetailId <= 0 || req.OtherDetailId <= 0 {
+		br.Msg = "看板Id有误"
+		return
+	}
+	if req.Sort < 0 || req.OtherSort < 0 || req.Sort == req.OtherSort {
+		br.Msg = "排序有误"
+		return
+	}
+
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+
+	// 判断权限
+	if item.SysAdminId != this.SysUser.AdminId {
+		br.Msg = `无权移动`
+		return
+	}
+
+	// 修改
+	detailItem := &bi_dashboard.BiDashboardDetail{
+		BiDashboardDetailId: req.BiDashboardDetailId,
+		Sort:                req.OtherSort,
+		ModifyTime:          time.Now(),
+	}
+	err = bi_dashboard.EditBiDashboardDetail(detailItem)
+	if err != nil {
+		br.Msg = "编辑详情失败"
+		br.ErrMsg = "编辑详情失败,Err:" + err.Error()
+		return
+	}
+
+	otherItem := &bi_dashboard.BiDashboardDetail{
+		BiDashboardDetailId: req.OtherDetailId,
+		Sort:                req.Sort,
+		ModifyTime:          time.Now(),
+	}
+	err = bi_dashboard.EditBiDashboardDetail(otherItem)
+	if err != nil {
+		br.Msg = "编辑详情失败"
+		br.ErrMsg = "编辑详情失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// ShareList
+// @Title 获取共享列表
+// @Description 获取共享列表接口
+// @Success 200 {object} models.RespGroupList
+// @router /share_list [get]
+func (this *BIDaShboardController) ShareList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	//myPptList := make([]*bi_dashboard.BiDashboard, 0)
+	//otherPptList := make([]*bi_dashboard.BiDashboard, 0)
+	grantList := bi_dashboard.RespGroupList{}
+
+	// 获取我的看板列表
+	ShareList, err := bi_dashboard.GetAllMyShareList(this.SysUser.AdminId)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		br.ErrMsg = err.Error()
+		br.Msg = "查询失败"
+		return
+	}
+	grantList.MyList = ShareList
+
+	//dashboardMap := make(map[int]*bi_dashboard.BiDashboard)
+	adminIdList := make([]int, 0)   //需要查询的创建人admin_id列表集合
+	adminIdMap := make(map[int]int) //需要查询的创建人admin_id集合,用来去重的,避免重复id
+	grantDashboardList, err := bi_dashboard.GetAllGrantList(this.SysUser.AdminId)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		br.ErrMsg = err.Error()
+		br.Msg = "查询失败"
+		return
+	}
+
+	publicAdminIdList := make([]int, 0)
+	publicDashboardListMap := make(map[int][]*bi_dashboard.BiDashboard)
+	for _, v := range grantDashboardList {
+		publicDashboardList, ok := publicDashboardListMap[v.SysAdminId]
+		if !ok {
+			publicDashboardList = make([]*bi_dashboard.BiDashboard, 0)
+			publicAdminIdList = append(publicAdminIdList, v.SysAdminId)
+			if _, ok := adminIdMap[v.SysAdminId]; !ok {
+				adminIdList = append(adminIdList, v.SysAdminId) //需要查询的创建人admin_id列表集合
+				adminIdMap[v.SysAdminId] = v.SysAdminId         //需要查询的创建人admin_id集合,用来去重的,避免重复id
+			}
+		}
+
+		tmp := &bi_dashboard.BiDashboard{
+			BiDashboardId:   v.BiDashboardId,
+			BiDashboardName: v.BiDashboardName,
+			CreateTime:      v.CreateTime,
+			ModifyTime:      v.ModifyTime,
+			Sort:            v.Sort,
+			State:           v.State,
+			SysAdminId:      v.SysAdminId,
+			SysAdminName:    v.SysAdminName,
+		}
+		publicDashboardList = append(publicDashboardList, tmp)
+		publicDashboardListMap[v.SysAdminId] = publicDashboardList
+	}
+	// 创建人信息
+	systemAdminMap := make(map[int]*system.Admin)
+	systemAdminList, err := system.GetAdminListByIdList(adminIdList)
+	if err != nil {
+		return
+	}
+	for _, v := range systemAdminList {
+		systemAdminMap[v.AdminId] = v
+	}
+
+	for _, v := range publicAdminIdList {
+		systemAdmin, ok := systemAdminMap[v]
+		if !ok {
+			continue
+		}
+
+		// 看板 列表信息
+		respGroupNameListItemList, ok := publicDashboardListMap[v]
+		if !ok {
+			respGroupNameListItemList = make([]*bi_dashboard.BiDashboard, 0)
+		}
+
+		// ppt 分组信息
+		tmpRespGroupListItem := &bi_dashboard.RespOtherGroupListItem{
+			GroupId:       int64(systemAdmin.AdminId),
+			GroupName:     systemAdmin.RealName,
+			AdminId:       systemAdmin.AdminId,
+			DashboardList: respGroupNameListItemList,
+		}
+		grantList.OtherList = append(grantList.OtherList, tmpRespGroupListItem)
+	}
+	//if len(dashboradIds) > 0 {
+	//	// 通过dashboradIds列表字段获取所有的看板信息
+	//	dashboradList, tmpErr := bi_dashboard.GetDashboradByIds(dashboradIds)
+	//	if tmpErr != nil {
+	//		err = errors.New("查询dashborad详情出错:" + err.Error())
+	//		br.Msg = "查询dashborad详情出错"
+	//		br.ErrMsg = err.Error()
+	//		return
+	//	}
+	//	for _, v := range dashboradList {
+	//		dashboardMap[v.BiDashboardId] = v
+	//	}
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = grantList
+	return
+}
+
+// PublicList
+// @Title 获取公共列表
+// @Description 获取公共列表接口
+// @Success 200 {object} models.RespGroupList
+// @router /public_list [get]
+func (this *BIDaShboardController) PublicList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	resp := make([]*bi_dashboard.RespPublicGroupListItem, 0)
+	// 获取公共看板列表
+	publicCond := ` AND state = 6 `
+	publicPars := make([]interface{}, 0)
+	publicList, err := bi_dashboard.GetBiDashboardList(publicCond, publicPars)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		return
+	}
+
+	//dashboardMap := make(map[int]*bi_dashboard.BiDashboard)
+	adminIdList := make([]int, 0)   //需要查询的创建人admin_id列表集合
+	adminIdMap := make(map[int]int) //需要查询的创建人admin_id集合,用来去重的,避免重复id
+
+	publicAdminIdList := make([]int, 0)
+	publicDashboardListMap := make(map[int][]*bi_dashboard.BiDashboard)
+	publicDashboardClassifyIdMap := make(map[int]int)
+	for _, v := range publicList {
+		publicDashboardList, ok := publicDashboardListMap[v.SysAdminId]
+		if !ok {
+			publicDashboardList = make([]*bi_dashboard.BiDashboard, 0)
+			publicAdminIdList = append(publicAdminIdList, v.SysAdminId)
+			if _, ok := adminIdMap[v.SysAdminId]; !ok {
+				adminIdList = append(adminIdList, v.SysAdminId) //需要查询的创建人admin_id列表集合
+				adminIdMap[v.SysAdminId] = v.SysAdminId         //需要查询的创建人admin_id集合,用来去重的,避免重复id
+			}
+		}
+
+		tmp := &bi_dashboard.BiDashboard{
+			BiDashboardId:         v.BiDashboardId,
+			BiDashboardClassifyId: v.BiDashboardClassifyId,
+			BiDashboardName:       v.BiDashboardName,
+			CreateTime:            v.CreateTime,
+			ModifyTime:            v.ModifyTime,
+			Sort:                  v.Sort,
+			State:                 v.State,
+			SysAdminId:            v.SysAdminId,
+			SysAdminName:          v.SysAdminName,
+		}
+		publicDashboardList = append(publicDashboardList, tmp)
+		publicDashboardListMap[v.SysAdminId] = publicDashboardList
+		publicDashboardClassifyIdMap[v.BiDashboardClassifyId] = v.BiDashboardClassifyId
+	}
+	// 创建人信息
+	systemAdminMap := make(map[int]*system.Admin)
+	systemAdminList, err := system.GetAdminListByIdList(adminIdList)
+	if err != nil {
+		return
+	}
+	for _, v := range systemAdminList {
+		systemAdminMap[v.AdminId] = v
+	}
+
+	for _, v := range adminIdList {
+		systemAdmin, ok := systemAdminMap[v]
+		if !ok {
+			continue
+		}
+
+		// 看板 列表信息
+		respGroupNameListItemList, ok := publicDashboardListMap[v]
+		if !ok {
+			respGroupNameListItemList = make([]*bi_dashboard.BiDashboard, 0)
+		}
+
+		// ppt 分组信息
+		tmpRespGroupListItem := &bi_dashboard.RespPublicGroupListItem{
+			GroupId:       int64(systemAdmin.AdminId),
+			GroupName:     systemAdmin.RealName,
+			AdminId:       systemAdmin.AdminId,
+			DashboardList: make([]*bi_dashboard.BiDashboard, 0),
+		}
+
+		for _, vv := range respGroupNameListItemList {
+			tmpRespGroupListItem.DashboardList = append(tmpRespGroupListItem.DashboardList, vv)
+		}
+		resp = append(resp, tmpRespGroupListItem)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = resp
+	return
+}
+
+// AddDashboardClassify
+// @Title 新增看板分类
+// @Description 新增看板分类接口
+// @Param	request	body bi_dashboard.AddDashboardClassifyReq true "type json string"
+// @Success 200 Ret=200 新增成功
+// @router /classify/add [post]
+func (this *BIDaShboardController) AddDashboardClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.AddDashboardClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "名称不能为空"
+		return
+	}
+	maxSort, err := bi_dashboard.GetBiDashboardClassifyMaxSort()
+	if err != nil {
+		br.Msg = "获取最大排序值失败"
+		br.ErrMsg = "获取最大排序值失败,Err:" + err.Error()
+		return
+	}
+	count, err := bi_dashboard.GetBiDashboardClassifyByName(req.ClassifyName)
+	if err != nil {
+		br.Msg = "获取分类名称失败"
+		br.ErrMsg = "获取分类名称失败,Err:" + err.Error()
+		return
+	}
+	if count > 0 {
+		br.Msg = "分类名称已存在"
+		return
+	}
+
+	item := &bi_dashboard.BiDashboardClassify{
+		BiDashboardClassifyName: req.ClassifyName,
+		Sort:                    maxSort + 1,
+		CreateTime:              time.Now(),
+		ModifyTime:              time.Now(),
+	}
+	_, e := bi_dashboard.AddBiDashboardClassify(item)
+	if e != nil {
+		err = e
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+	//br.Data =
+}
+
+// EditDashboardClassify
+// @Title 编辑看板分类
+// @Description 编辑看板分类接口
+// @Param	request	body bi_dashboard.EditDashboardReq true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /classify/edit [post]
+func (this *BIDaShboardController) EditDashboardClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.EditDashboardClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+	if req.BiDashboardClassifyId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, BiDashboardClassifyId: %d", req.BiDashboardClassifyId)
+		return
+	}
+	item, err := bi_dashboard.GetBiDashboardClassifyById(req.BiDashboardClassifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+
+	// 修改
+	item.BiDashboardClassifyName = req.ClassifyName
+	item.ModifyTime = time.Now()
+
+	err = bi_dashboard.EditDashboardClassify(item)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// Grant
+// @Title 分配看板权限
+// @Description 分配看板权限接口
+// @Param	request	body models.GrantPptReq true "type json string"
+// @Success 200 Ret=200 分配成功
+// @router /grant [post]
+func (this *BIDaShboardController) Grant() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.GrantDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.AdminIdStr == "" {
+		br.Msg = "参数错误"
+		return
+	}
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	dashboardItem, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		br.Msg = "我的看板列表查询出错"
+		br.ErrMsg = err.Error()
+		return
+	}
+	if dashboardItem.SysAdminId != this.SysUser.AdminId {
+		br.Msg = "无权配置"
+		return
+	}
+
+	list := make([]*bi_dashboard.BiDashboardGrant, 0)
+
+	grantAdminIdStrList := strings.Split(req.AdminIdStr, ",")
+	lenGrantAdminIdStrList := len(grantAdminIdStrList) //指定用户的人数
+	for _, v := range grantAdminIdStrList {
+		grantAdminId, tmpErr := strconv.Atoi(v)
+		if tmpErr != nil {
+			br.Msg = "参数有误"
+			br.ErrMsg = fmt.Sprintf("参数有误,Err:%s", tmpErr.Error())
+			return
+		}
+
+		//如果只选择了自己作为指定的人,那么就提示他报错。如果多人,那么就过滤自己
+		if grantAdminId == this.SysUser.AdminId {
+			if lenGrantAdminIdStrList == 1 {
+				br.Msg = "不能指定自己为权限用户"
+				br.ErrMsg = fmt.Sprintf("参数有误,Err:%s", tmpErr.Error())
+				return
+			}
+			continue
+		}
+		tmpV := &bi_dashboard.BiDashboardGrant{
+			BiDashboardId: req.BiDashboardId,
+			GrantAdminId:  grantAdminId,
+			CreateTime:    time.Now(),
+		}
+		list = append(list, tmpV)
+	}
+
+	if len(list) <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误,Err:%s", "指定用户为空")
+		return
+	}
+
+	err = bi_dashboard.MultiAddDashboardGrant(req.BiDashboardId, list)
+	if err != nil {
+		br.Msg = "分配失败"
+		br.ErrMsg = fmt.Sprintf("分配失败,Err:%s", err.Error())
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "分配成功"
+}
+
+// Public
+// @Title
+// @Description 设置公共看板
+// @Param	request	body models.GrantPptReq true "type json string"
+// @Success 200 Ret=200 分配成功
+// @router /public [post]
+func (this *BIDaShboardController) Public() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.PublicDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+
+	item.State = 6
+
+	err = bi_dashboard.EditDashboard(item)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "分配成功"
+}
+
+// GroupList
+// @Title 获取分类列表
+// @Description 获取分类列表接口
+// @Success 200 {object} models.RespGroupList
+// @router /classify/list [get]
+func (this *BIDaShboardController) ClassifyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	classifyList, err := bi_dashboard.GetBiDashboardClassifyAllList()
+	if err != nil {
+		br.Msg = "查询失败"
+		br.ErrMsg = "查询失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = classifyList
+	return
+}
+
+// CancelGrant
+// @Title 取消分配看板权限
+// @Description 取消分配看板权限
+// @Param	request	body bi_dashboard.DelDashboardReq true "type json string"
+// @Success 200 Ret=200 分配成功
+// @router /grant/cancel [post]
+func (this *BIDaShboardController) CancelGrant() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.DelDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "数据不存在"
+		br.ErrMsg = "数据不存在,Err:" + err.Error()
+		return
+	}
+	if item.SysAdminId != this.SysUser.AdminId {
+		br.Msg = "无权配置"
+		return
+	}
+
+	// 分配
+	err = bi_dashboard.DeleteDashboardGrant(req.BiDashboardId)
+	if err != nil {
+		br.Msg = "取消失败"
+		br.ErrMsg = "取消失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "取消成功"
+}
+
+// GrantInfo
+// @Title 获取分配ppt权限详情
+// @Description 获取分配ppt权限详情接口
+// @Param    BiDashboardId   query   int  true       "看板的id"
+// @Success 200 {object} models.GrantInfoResp
+// @router /grant/info [get]
+func (this *BIDaShboardController) GrantInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	biDashboardId, _ := this.GetInt("BiDashboardId")
+	if biDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	item, err := bi_dashboard.GetDashboardById(biDashboardId)
+	if err != nil {
+		br.Msg = "数据不存在"
+		br.ErrMsg = "数据不存在,Err:" + err.Error()
+		return
+	}
+	if item.SysAdminId != this.SysUser.AdminId {
+		br.Msg = "无权配置"
+		return
+	}
+
+	grantInfoList, err := bi_dashboard.GetDashboardGrantInfo(biDashboardId)
+	if err != nil {
+		br.Msg = "信息获取失败"
+		br.ErrMsg = "信息获取失败,Err:" + err.Error()
+		return
+	}
+
+	if len(grantInfoList) <= 0 {
+		br.Msg = "未配置"
+		br.IsSendEmail = false
+		br.Success = true
+		br.Ret = 200
+		return
+	}
+
+	var adminIdStr string
+
+	adminIdsList := make([]string, 0)
+	for _, v := range grantInfoList {
+		adminIdsList = append(adminIdsList, strconv.Itoa(int(v.GrantAdminId)))
+	}
+	adminIdStr = strings.Join(adminIdsList, ",")
+
+	br.Ret = 200
+	br.Success = true
+	br.Data = adminIdStr
+	br.Msg = "查询成功"
+}
+
+// Public
+// @Title
+// @Description 撤销公共看板
+// @Param	request	body models.GrantPptReq true "type json string"
+// @Success 200 Ret=200 分配成功
+// @router /public/cancel [post]
+func (this *BIDaShboardController) PublicCancel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.DelDashboardReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	item, err := bi_dashboard.GetDashboardById(req.BiDashboardId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据异常!"
+		br.ErrMsg = "获取数据异常,Err:" + err.Error()
+		return
+	}
+
+	item.State = 1
+
+	err = bi_dashboard.EditDashboard(item)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "撤销成功"
+}
+
+// GroupList
+// @Title 获取我的首页看板
+// @Description 获取我的首页看板接口
+// @Success 200 {object} models.RespGroupList
+// @router /home_page [get]
+func (this *BIDaShboardController) HomePage() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	item, err := bi_dashboard.GetBiDashboardHomePageById(this.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "数据不存在"
+		br.ErrMsg = "数据不存在,Err:" + err.Error()
+		return
+	}
+
+	publicCond := ` AND state = 6 AND bi_dashboard_classify_id > 0 `
+	publicPars := []interface{}{this.SysUser.AdminId}
+	publicList, err := bi_dashboard.GetBiDashboardList(publicCond, publicPars)
+	if err != nil {
+		err = errors.New("我的看板列表查询出错:" + err.Error())
+		return
+	}
+
+	if item.BiDashboardHomePageId == 0 && len(publicList) > 0 {
+		item = &bi_dashboard.BiDashboardHomePage{
+			AdminId:       publicList[0].SysAdminId,
+			BiDashboardId: publicList[0].BiDashboardId,
+			FromType:      3,
+		}
+	}
+
+	if item.BiDashboardId == 0 {
+		item = nil
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = item
+	return
+}
+
+// GroupList
+// @Title 保存我的看板首页
+// @Description保存我的看板首页接口
+// @Success 200 {object} models.RespGroupList
+// @router /home_page/save [post]
+func (this *BIDaShboardController) HomePageSave() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req bi_dashboard.SaveHomePageReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	item, err := bi_dashboard.GetBiDashboardHomePageById(this.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "首页看板查询失败"
+		br.ErrMsg = "首页看板查询失败,Err:" + err.Error()
+		return
+	}
+
+	homePageItem := &bi_dashboard.BiDashboardHomePage{
+		BiDashboardId: req.BiDashboardId,
+		AdminId:       this.SysUser.AdminId,
+		CreateTime:    time.Now(),
+		ModifyTime:    time.Now(),
+		FromType:      req.FromType,
+	}
+
+	if item.BiDashboardHomePageId > 0 {
+		homePageItem.BiDashboardHomePageId = item.BiDashboardHomePageId
+	}
+
+	err = bi_dashboard.SaveBiDashboardHomePage(homePageItem)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	return
+}
+
+// Editing
+// @Title 标记/查询编辑状态
+// @Description 标记/查询编辑状态
+// @Param	request	body models.PPTEditingReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /editing [post]
+func (this *BIDaShboardController) Editing() {
+	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 bi_dashboard.BiDashboardEditingReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BiDashboardId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+	if req.Status < 0 {
+		br.Msg = "标记状态异常"
+		return
+	}
+
+	editor, e := services.UpdateBiDashboardEditing(req.BiDashboardId, req.Status, sysUser.AdminId, sysUser.RealName)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新编辑状态失败, err: " + e.Error()
+		return
+	}
+
+	br.Data = editor
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// GroupList
+// @Title 获取我拥有的图库表格菜单权限
+// @Description 获取我拥有的图库表格菜单权限接口
+// @Success 200 {object} models.RespGroupList
+// @router /chart_excel_permission [get]
+func (this *BIDaShboardController) ChartExcelPermission() {
+	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
+	}
+
+	roleId := sysUser.RoleId
+	//roleId=1
+	if roleId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	roleIds := strconv.Itoa(roleId)
+	//查询账号绑定的其他角色
+	otherRoles, err := system.GetRoleIdsByAdminId(sysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取其他角色失败"
+		br.ErrMsg = "获取其他角色失败,Err:" + err.Error()
+		return
+	}
+	if len(otherRoles) > 0 {
+		for _, v := range otherRoles {
+			roleIds += "," + strconv.Itoa(v.RoleId)
+		}
+	}
+	groupId := 0
+	if utils.RunMode == "release" {
+		groupId = 37
+	} else {
+		groupId = 61
+	}
+	//共享客户组下的用户
+	shareSellerMap := make(map[int]bool, 0)
+	subAdmins, err := system.GetAdminByGroupId(groupId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取销售失败"
+		br.ErrMsg = "获取销售失败,Err:" + err.Error()
+		return
+	}
+	for _, admin := range subAdmins {
+		shareSellerMap[admin.AdminId] = true
+	}
+
+	list, err := system.GetMenuByRoleIds(roleIds)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	lenList := len(list)
+
+	menuList := make([]*system.SysMenuSimple, 0)
+
+	chartExcelTypes, e := models.GetBusinessConfByKey("ChartExcelType")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家配置失败, Err: " + e.Error()
+		return
+	}
+	types := strings.Split(chartExcelTypes.ConfVal, ",")
+	typeMap := map[string]bool{}
+	for _, v := range types {
+		typeMap[v] = true
+	}
+
+	for i := 0; i < lenList; i++ {
+		item := list[i]
+		if !typeMap[item.LevelPath] && !typeMap[item.Path] {
+			continue
+		}
+		newItem := &system.SysMenuSimple{
+			MenuId:   item.MenuId,
+			ParentId: item.ParentId,
+			Name:     item.Name,
+			Sort:     item.Sort,
+			Path:     item.Path,
+			NameEn:   item.NameEn,
+		}
+		if item.IsLevel == 1 {
+			newItem.Path = item.LevelPath
+		}
+		menuList = append(menuList, newItem)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "查询成功"
+	br.Data = menuList
+	return
+}

+ 2 - 2
controllers/business_conf.go

@@ -326,7 +326,7 @@ func (this *BusinessConfController) SingleSave() {
 	// 获取配置信息
 	confOb, e := models.GetBusinessConfByKey(req.ConfKey)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "配置不存在"
 			return
 		}
@@ -419,7 +419,7 @@ func (this *BusinessConfController) GetSingle() {
 	// 获取配置信息
 	confOb, e := models.GetBusinessConfByKey(confKey)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "配置不存在"
 			return
 		}

+ 50 - 8
controllers/classify.go

@@ -204,10 +204,6 @@ func (this *ClassifyController) Delete() {
 		return
 	}
 
-	br.Msg = "报告分类不允许删除"
-	br.IsSendEmail = false
-	return
-
 	item, err := models.GetClassifyById(req.ClassifyId)
 	if err != nil {
 		br.Msg = "获取信息失败"
@@ -218,7 +214,46 @@ func (this *ClassifyController) Delete() {
 		br.Msg = "分类不存在"
 		return
 	}
-	err = models.DeleteClassify(req.ClassifyId)
+	classifyList := &models.ClassifyList{Id: item.Id}
+	err = services.MarkEnableDeleteClassify([]*models.ClassifyList{classifyList})
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "标记失败,Err:" + err.Error()
+		return
+	}
+	if classifyList.IsEnableDelete == 0 {
+		br.Msg = "该分类有关联报告或审批流,不允许删除"
+		return
+	}
+
+	var childClassifyIds []int
+	if item.HasChild == 1 {
+		// 获取所有子分类
+		subClassifyMap := make(map[int][]int)
+		allClassify, err := models.GetAllClassifyWithDesc()
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		for _, classify := range allClassify {
+			v, ok := subClassifyMap[classify.Id]
+			if !ok {
+				subClassifyMap[classify.Id] = []int{}
+			}
+			pv, pok := subClassifyMap[classify.ParentId]
+			if pok {
+				subClassifyMap[classify.ParentId] = append(pv, classify.Id)
+			} else {
+				subClassifyMap[classify.ParentId] = []int{classify.Id}
+			}
+			if ok {
+				subClassifyMap[classify.ParentId] = append(subClassifyMap[classify.ParentId], v...)
+			}
+		}
+		childClassifyIds = subClassifyMap[item.Id]
+	}
+	err = item.Delete(childClassifyIds)
 	if err != nil {
 		br.Msg = "删除失败"
 		br.ErrMsg = "删除失败,Err:" + err.Error()
@@ -320,7 +355,7 @@ func (this *ClassifyController) ParentClassify() {
 	parentMenus, e := models.GetClassifyMenuList(menuCond, menuPars)
 	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取一级分类子目录列表失败"
+		br.ErrMsg = fmt.Sprintf("获取一级分类子目录列表失败, %v", e)
 		return
 	}
 	for i := range parentMenus {
@@ -459,7 +494,7 @@ func (this *ClassifyController) ListClassify() {
 	parentMenus, e := models.GetClassifyMenuList(menuCond, menuPars)
 	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取一级分类子目录列表失败"
+		br.ErrMsg = fmt.Sprintf("获取一级分类子目录列表失败, %v", e)
 		return
 	}
 	for i := range parentMenus {
@@ -505,6 +540,12 @@ func (this *ClassifyController) ListClassify() {
 		}
 	}
 
+	err = services.MarkEnableDeleteClassify(list)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "标记可删除分类失败,Err:" + err.Error()
+		return
+	}
 	// 先将分类列表排序
 	services.SortClassifyListBySortAndCreateTime(list)
 	// 接着转换结构
@@ -636,6 +677,7 @@ func (this *ClassifyController) TelListClassify() {
 		condition += ` AND classify_name <> '晨报' AND classify_name <> '周报' `
 	}
 	telList, e := models.GetClassifyByCondition(condition, orderRule, pars)
+
 	if e != nil {
 		return
 	}
@@ -725,7 +767,7 @@ func (this *ClassifyController) SetEnabled() {
 	}
 	item, err := models.GetClassifyById(req.ClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			return
 		}

+ 4 - 4
controllers/cloud_disk.go

@@ -64,7 +64,7 @@ func (this *CloudDiskController) MenuCreate() {
 	existCond := ` AND menu_name = ? AND parent_id = ? `
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, req.MenuName, req.ParentId)
-	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && e.Error() != utils.ErrNoRow() {
+	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名目录失败, Err: " + e.Error()
 		return
@@ -144,7 +144,7 @@ func (this *CloudDiskController) MenuRename() {
 	existCond := ` AND menu_name = ? AND parent_id = ? AND menu_id <> ? `
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, req.MenuName, menuItem.ParentId, menuItem.MenuId)
-	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && e.Error() != utils.ErrNoRow() {
+	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名目录失败, Err: " + e.Error()
 		return
@@ -578,7 +578,7 @@ func (this *CloudDiskController) ResourceUpload() {
 	existCond := ` AND resource_name = ? AND menu_id = ? `
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, fileName, menuId)
-	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && e.Error() != utils.ErrNoRow() {
+	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名文件失败, Err: " + e.Error()
 		return
@@ -729,7 +729,7 @@ func (this *CloudDiskController) ResourceRename() {
 	existCond := ` AND resource_name = ? AND menu_id = ? AND resource_id <> ? `
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, req.ResourceName, resourceItem.MenuId, resourceItem.ResourceId)
-	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && e.Error() != utils.ErrNoRow() {
+	if e := existItem.GetItemByCondition(existCond, existPars); e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名文件失败, Err: " + e.Error()
 		return

+ 2 - 2
controllers/commodity_trade_base_index.go

@@ -2639,7 +2639,7 @@ func (this *TradeCommonController) MtjhData() {
 		product.CreateTime = v.CreateTime
 
 		modifyTime, err := data_manage.GetMtjhIndexLatestDate(v.IndexCode)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取更新时间失败"
 			br.ErrMsg = "获取更新时间失败,Err:" + err.Error()
 			return
@@ -2741,7 +2741,7 @@ func (this *TradeCommonController) MtjhSingleData() {
 	}
 
 	modifyTime, err := data_manage.GetMtjhIndexLatestDate(indexCode)
-	if err != nil {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取更新时间失败"
 		br.ErrMsg = "获取更新时间失败,Err:" + err.Error()
 		return

+ 4 - 4
controllers/company_seller.go

@@ -41,9 +41,9 @@ func (this *CompanySellerController) CheckListV2() {
 	productId := services.GetProductId(sysUser.RoleTypeCode)
 	switch productId {
 	case 1:
-		roleCodeTypeStr = `"` + utils.ROLE_TYPE_CODE_FICC_SELLER + `","` + utils.ROLE_TYPE_CODE_FICC_GROUP + `","` + utils.ROLE_TYPE_CODE_FICC_TEAM + `"`
+		roleCodeTypeStr = `'` + utils.ROLE_TYPE_CODE_FICC_SELLER + `','` + utils.ROLE_TYPE_CODE_FICC_GROUP + `','` + utils.ROLE_TYPE_CODE_FICC_TEAM + `'`
 	case 2:
-		roleCodeTypeStr = `"` + utils.ROLE_TYPE_CODE_RAI_SELLER + `","` + utils.ROLE_TYPE_CODE_RAI_GROUP + `"`
+		roleCodeTypeStr = `'` + utils.ROLE_TYPE_CODE_RAI_SELLER + `','` + utils.ROLE_TYPE_CODE_RAI_GROUP + `'`
 	}
 
 	// ficc管理员,不要只查销售
@@ -51,7 +51,7 @@ func (this *CompanySellerController) CheckListV2() {
 		roleCodeTypeStr = ``
 	} else if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_ADMIN {
 		// 权益管理员,查看所有权益的账号
-		roleCodeTypeStr = `"` + utils.ROLE_TYPE_CODE_RAI_SELLER + `","` + utils.ROLE_TYPE_CODE_RAI_GROUP + `","` + utils.ROLE_TYPE_CODE_RAI_RESEARCHR + `","` + utils.ROLE_TYPE_CODE_RAI_ADMIN + `"`
+		roleCodeTypeStr = `'` + utils.ROLE_TYPE_CODE_RAI_SELLER + `','` + utils.ROLE_TYPE_CODE_RAI_GROUP + `','` + utils.ROLE_TYPE_CODE_RAI_RESEARCHR + `','` + utils.ROLE_TYPE_CODE_RAI_ADMIN + `'`
 	}
 
 	getAllSeller, _ := this.GetBool("AllSeller", false)
@@ -1726,7 +1726,7 @@ func (this *CompanySellerController) CheckListV2() {
 
 	// 海外销售部-目前无权限, 均可见
 	seaDepartment, e := system.GetSysDepartmentByName("海外销售部")
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取海外销售部失败, Err: " + e.Error()
 		return

+ 558 - 0
controllers/data_manage/ai_predict_model/classify.go

@@ -0,0 +1,558 @@
+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/data_manage"
+	dataSourceModel "eta/eta_api/models/data_source"
+	"eta/eta_api/services"
+	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
+	"eta/eta_api/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// AiPredictModelClassifyController AI预测模型-分类
+type AiPredictModelClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 分类列表
+// @Description 分类列表
+// @Param   ParentId   query   bool   false   "父级ID"
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /classify/list [get]
+func (this *AiPredictModelClassifyController) List() {
+	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.AiPredictModelClassifyListResp)
+
+	// (懒加载)仅查询直属分类
+	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.AiPredictModelClassifyListItem{
+				NodeName:     v.ClassifyName,
+				ClassifyId:   v.AiPredictModelClassifyId,
+				ClassifyName: v.ClassifyName,
+				ParentId:     v.ParentId,
+				Level:        v.Level,
+				Sort:         v.Sort,
+				UniqueCode:   v.UniqueCode,
+			})
+		}
+	}
+
+	// 非顶级目录查询指标
+	indexOb := new(aiPredictModel.AiPredictModelIndex)
+	if parentId > 0 {
+		parentClassify, e := classifyOb.GetItemById(parentId)
+		if e != nil {
+			br.Msg = "父级分类不存在, 请刷新页面"
+			return
+		}
+
+		cond := fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := indexOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", indexOb.Cols().Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取分类下指标失败, %v", e)
+			return
+		}
+		for _, v := range list {
+			resp.AllNodes = append(resp.AllNodes, &aiPredictModel.AiPredictModelClassifyListItem{
+				NodeType:     1,
+				NodeName:     v.IndexName,
+				ClassifyId:   parentClassify.AiPredictModelClassifyId,
+				ClassifyName: parentClassify.ClassifyName,
+				IndexId:      v.AiPredictModelIndexId,
+				IndexCode:    v.IndexCode,
+				IndexName:    v.IndexName,
+				ParentId:     parentId,
+				Sort:         v.Sort,
+				UniqueCode:   v.IndexCode,
+			})
+		}
+	}
+	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 = "获取成功"
+}
+
+// Add
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body aiPredictModel.AiPredictModelClassifyAddReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /classify/add [post]
+func (this *AiPredictModelClassifyController) Add() {
+	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.AiPredictModelClassifyAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "请选择上级分类"
+		return
+	}
+	if req.Level > 5 {
+		br.Msg = "目前只支持6级目录"
+		return
+	}
+
+	// 校验分类名称
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	{
+		cond := fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ParentId)
+		if this.Lang == utils.EnLangVersion {
+			cond += fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ClassifyNameEn)
+		} else {
+			cond += fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ClassifyName)
+		}
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ParentId, req.ClassifyName)
+		count, e := classifyOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取分类名称重复数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在"
+			return
+		}
+	}
+
+	// 层级路径
+	var levelPath string
+	var rootId int
+	if req.ParentId > 0 {
+		parent, e := classifyOb.GetItemById(req.ParentId)
+		if e != nil {
+			br.Msg = "上级分类有误"
+			br.ErrMsg = fmt.Sprintf("获取上级分类失败, %v", e)
+			return
+		}
+		levelPath = parent.LevelPath
+		rootId = parent.RootId
+	}
+
+	sortMax, e := classifyOb.GetSortMax(req.ParentId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取分类最大排序失败, %v", e)
+		return
+	}
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	classifyOb.ParentId = req.ParentId
+	classifyOb.ClassifyName = req.ClassifyName
+	classifyOb.ClassifyNameEn = req.ClassifyName
+	classifyOb.Level = req.Level + 1
+	classifyOb.Sort = sortMax + 1
+	classifyOb.SysUserId = sysUser.AdminId
+	classifyOb.SysUserRealName = sysUser.RealName
+	classifyOb.UniqueCode = utils.MD5(classifyOb.TableName() + "_" + timestamp)
+	classifyOb.CreateTime = time.Now().Local()
+	classifyOb.ModifyTime = time.Now().Local()
+	if e = classifyOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("新增分类失败, %v", e)
+		return
+	}
+	if req.ParentId > 0 {
+		// 用英文逗号拼接方便查询
+		classifyOb.LevelPath = fmt.Sprintf("%s,%d", levelPath, classifyOb.AiPredictModelClassifyId)
+		classifyOb.RootId = rootId
+	} else {
+		classifyOb.LevelPath = fmt.Sprint(classifyOb.AiPredictModelClassifyId)
+		classifyOb.RootId = classifyOb.AiPredictModelClassifyId
+	}
+	if e = classifyOb.Update([]string{classifyOb.Cols().LevelPath, classifyOb.Cols().RootId}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新分类失败, %v", e)
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "操作成功"
+	br.Success = true
+}
+
+// Edit
+// @Title 修改分类
+// @Description 修改分类
+// @Param	request	body aiPredictModel.AiPredictModelClassifyEditReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /classify/edit [post]
+func (this *AiPredictModelClassifyController) Edit() {
+	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.AiPredictModelClassifyEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId < 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+
+	classifyOb := new(aiPredictModel.AiPredictModelClassify)
+	classifyItem, e := classifyOb.GetItemById(req.ClassifyId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "分类不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
+		return
+	}
+
+	// 校验分类名称
+	{
+		cond := fmt.Sprintf(" AND %s <> ?", classifyOb.Cols().PrimaryId)
+		if this.Lang == utils.EnLangVersion {
+			cond += fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ClassifyNameEn)
+		} else {
+			cond += fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ClassifyName)
+		}
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ClassifyId, req.ClassifyName)
+		count, e := classifyOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取分类名称重复数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在"
+			return
+		}
+	}
+	classifyItem.ClassifyName = req.ClassifyName
+	classifyItem.ClassifyNameEn = req.ClassifyName
+	classifyItem.ModifyTime = time.Now().Local()
+	updateCols := []string{classifyOb.Cols().ClassifyName, classifyOb.Cols().ClassifyNameEn, classifyOb.Cols().ModifyTime}
+	if e = classifyItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新分类失败, %v", e)
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "操作成功"
+	br.Success = true
+}
+
+// RemoveCheck
+// @Title 删除校验
+// @Description 删除校验
+// @Param	request	body aiPredictModel.AiPredictModelClassifyRemoveReq true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /classify/remove_check [post]
+func (this *AiPredictModelClassifyController) RemoveCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req aiPredictModel.AiPredictModelClassifyRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId < 0 && req.IndexId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	var deleteStatus int
+	var tipsMsg string
+	// 删除分类
+	if req.ClassifyId > 0 && req.IndexId == 0 {
+		count, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyId(req.ClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
+			return
+		}
+
+		if count > 0 {
+			deleteStatus = 1
+			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 {
+			deleteStatus = 2
+			tipsMsg = "确认删除当前目录及包含的子目录吗"
+		}
+	}
+	if deleteStatus == 0 {
+		tipsMsg = "可删除,进行删除操作"
+	}
+
+	resp := new(data_manage.ChartClassifyDeleteCheckResp)
+	resp.DeleteStatus = deleteStatus
+	resp.TipsMsg = tipsMsg
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// Remove
+// @Title 删除分类/标的
+// @Description 删除分类/标的
+// @Param	request	body aiPredictModel.AiPredictModelClassifyRemoveReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /classify/remove [post]
+func (this *AiPredictModelClassifyController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req aiPredictModel.AiPredictModelClassifyRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId < 0 && req.IndexId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	// 删除分类
+	if req.ClassifyId > 0 && req.IndexId == 0 {
+		count, err := aiPredictModel.GetAiPredictModelIndexCountByClassifyId(req.ClassifyId)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "删除失败"
+			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "该目录下存在关联指标,不可删除"
+			br.IsSendEmail = false
+			return
+		}
+		err = aiPredictModel.RemoveAiPredictModelClassify(req.ClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	// 删除标的
+	if req.IndexId > 0 {
+		indexOb := new(aiPredictModel.AiPredictModelIndex)
+		aiIndex, e := indexOb.GetItemById(req.IndexId)
+		if e != nil {
+			if utils.IsErrNoRow(e) {
+				br.Ret = 200
+				br.Msg = "删除成功"
+				br.Success = true
+				return
+			}
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取标的信息失败, %v", e)
+			return
+		}
+		if aiIndex != nil && aiIndex.AiPredictModelIndexId <= 0 {
+			br.Ret = 200
+			br.Msg = "删除成功"
+			br.Success = true
+			return
+		}
+
+		// 获取指标图表
+		var chartIds []int
+		chartTypes := []int{utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY, utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY}
+		for _, v := range chartTypes {
+			ct, e := data_manage.GetAiPredictChartInfoByIndexId(v, req.IndexId)
+			if e != nil && !utils.IsErrNoRow(e) {
+				br.Msg = "操作失败"
+				br.ErrMsg = fmt.Sprintf("获取标的图表信息失败, %v", e)
+				return
+			}
+			if ct != nil && ct.ChartInfoId > 0 {
+				chartIds = append(chartIds, ct.ChartInfoId)
+			}
+		}
+
+		// 删除标的及数据
+		if e = indexOb.RemoveIndexAndData(req.IndexId, chartIds); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("删除标的及数据失败, %v", e)
+			return
+		}
+
+		// ES标记标的/图表删除
+		go func() {
+			indexItem := new(dataSourceModel.SearchDataSource)
+			indexItem.PrimaryId = aiIndex.AiPredictModelIndexId
+			indexItem.IndexName = aiIndex.IndexName
+			indexItem.IndexCode = aiIndex.IndexCode
+			indexItem.ClassifyId = aiIndex.ClassifyId
+			indexItem.Source = utils.DATA_SOURCE_AI_PREDICT_MODEL
+			indexItem.SourceName = "AI预测模型"
+			indexItem.IsDeleted = 1
+			indexItem.CreateTime = utils.TimeTransferString(utils.FormatDateTime, aiIndex.CreateTime)
+			indexItem.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, aiIndex.ModifyTime)
+
+			docId := fmt.Sprintf("%d-%d", indexItem.Source, indexItem.PrimaryId)
+			if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
+				utils.FileLog.Info("AI预测模型-标记删除es失败, %v", e)
+				return
+			}
+
+			if len(chartIds) == 0 {
+				return
+			}
+			for _, v := range chartIds {
+				data.EsDeleteChartInfo(v)
+			}
+		}()
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// Move
+// @Title 移动
+// @Description 移动
+// @Success 200 {object} aiPredictModel.AiPredictModelClassifyMoveReq
+// @router /classify/move [post]
+func (this *AiPredictModelClassifyController) Move() {
+	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.AiPredictModelClassifyMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId <= 0 && req.ItemId <= 0 {
+		br.Msg = "请选择分类或指标"
+		return
+	}
+
+	err, errMsg := services.AiPredictModelMoveClassify(req, sysUser)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}

+ 668 - 0
controllers/data_manage/ai_predict_model/framework.go

@@ -0,0 +1,668 @@
+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/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+// AiPredictModelFrameworkController 模型框架
+type AiPredictModelFrameworkController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 列表
+// @Description 列表
+// @Param   AdminId		query	int		false	"创建人ID"
+// @Param   Visibility	query	int		false	"范围: 0-所有; 1-私有; 2-公开"
+// @Param   Keyword		query	string	false	"关键词"
+// @Success 200 Ret=200 获取成功
+// @router /framework/list [get]
+func (c *AiPredictModelFrameworkController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	adminId, _ := c.GetInt("AdminId")
+	keyword := c.GetString("Keyword")
+	keyword = strings.TrimSpace(keyword)
+
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+
+	cond := ``
+	pars := make([]interface{}, 0)
+	if adminId > 0 {
+		cond += fmt.Sprintf(` AND %s = ?`, aiPredictModel.AiPredictModelFrameworkColumns.AdminId)
+		pars = append(pars, adminId)
+	}
+	if keyword != "" {
+		cond += fmt.Sprintf(` AND %s LIKE ?`, aiPredictModel.AiPredictModelFrameworkColumns.FrameworkName)
+		pars = append(pars, "%"+keyword+"%")
+	}
+
+	orderRule := `sort ASC, create_time DESC`
+	list, e := frameworkOb.GetItemsByCondition(cond, pars, []string{}, orderRule)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取框架列表失败, Err: " + e.Error()
+		return
+	}
+	resp := make([]*aiPredictModel.AiPredictModelFrameworkItem, 0)
+	for _, v := range list {
+		t := aiPredictModel.FormatAiPredictModelFramework2Item(v, make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0))
+		if t.AdminId == sysUser.AdminId || utils.IsAdminRole(sysUser.RoleTypeCode) {
+			t.Button.OpButton = true
+			t.Button.DeleteButton = true
+			t.Button.MoveButton = true
+		}
+		resp = append(resp, t)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Add
+// @Title 新增框架
+// @Description 新增框架
+// @Param	request	body aiPredictModel.AiPredictModelFrameworkAddReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /framework/add [post]
+func (c *AiPredictModelFrameworkController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 参数校验
+	var req aiPredictModel.AiPredictModelFrameworkAddReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	req.FrameworkName = strings.TrimSpace(req.FrameworkName)
+	if req.FrameworkName == "" {
+		br.Msg = "框架名称不可为空"
+		return
+	}
+
+	// 重名校验
+	{
+		ob := new(aiPredictModel.AiPredictModelFramework)
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ?`, aiPredictModel.AiPredictModelFrameworkColumns.FrameworkName, aiPredictModel.AiPredictModelFrameworkColumns.AdminId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.FrameworkName, sysUser.AdminId)
+		exist, e := ob.GetItemByCondition(cond, pars)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil && exist.AiPredictModelFrameworkId > 0 {
+			br.Msg = "框架名称已存在,请重新输入"
+			return
+		}
+	}
+
+	now := time.Now().Local()
+	frameworkCode := utils.MD5(fmt.Sprint(now.UnixMilli()))
+	item := new(aiPredictModel.AiPredictModelFramework)
+	item.FrameworkName = req.FrameworkName
+	item.FrameworkCode = frameworkCode
+	item.FrameworkImg = req.FrameworkImg
+	item.FrameworkContent = req.FrameworkContent
+	item.AdminId = sysUser.AdminId
+	item.AdminName = sysUser.RealName
+	item.CreateTime = now
+	item.ModifyTime = now
+	nodes := make([]*aiPredictModel.AiPredictModelFrameworkNode, 0)
+	itemNodes := make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0)
+	if len(req.Nodes) > 0 {
+		for _, v := range req.Nodes {
+			if v.AiPredictModelIndexId <= 0 {
+				continue
+			}
+			t := new(aiPredictModel.AiPredictModelFrameworkNode)
+			t.FrameworkName = req.FrameworkName
+			t.NodeId = v.NodeId
+			t.NodeName = v.NodeName
+			t.AiPredictModelIndexId = v.AiPredictModelIndexId
+			t.CreateTime = now
+			nodes = append(nodes, t)
+			num := 1
+			// 响应节点数据
+			td := aiPredictModel.FormatAiPredictModelFrameworkNode2Item(t, num, map[int]*aiPredictModel.AiPredictModelIndex{})
+			itemNodes = append(itemNodes, td)
+		}
+	}
+	if e := item.CreateFrameworkAndNodes(item, nodes); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增框架及节点失败, Err: " + e.Error()
+		return
+	}
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	br.IsAddLog = true
+}
+
+// Edit
+// @Title 编辑框架
+// @Description 编辑框架
+// @Param	request	body aiPredictModel.AiPredictModelFrameworkEditReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /framework/edit [post]
+func (c *AiPredictModelFrameworkController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 参数校验
+	var req aiPredictModel.AiPredictModelFrameworkEditReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.AiPredictModelFrameworkId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, AiPredictModelFrameworkId: %d", req.AiPredictModelFrameworkId)
+		return
+	}
+	req.FrameworkName = strings.TrimSpace(req.FrameworkName)
+	if req.FrameworkName == "" {
+		br.Msg = "框架名称不可为空"
+		return
+	}
+
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+	item, e := frameworkOb.GetItemById(req.AiPredictModelFrameworkId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "框架不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取框架失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作权限校验
+	if item.AdminId != sysUser.AdminId && !utils.IsAdminRole(sysUser.RoleTypeCode) {
+		br.Msg = "您没有权限操作该框架"
+		return
+	}
+
+	// 重名校验
+	{
+		ob := new(aiPredictModel.AiPredictModelFramework)
+		cond := fmt.Sprintf(` AND %s <> ? AND %s = ? AND %s = ?`, ob.PrimaryId(), aiPredictModel.AiPredictModelFrameworkColumns.FrameworkName, aiPredictModel.AiPredictModelFrameworkColumns.AdminId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.AiPredictModelFrameworkId, req.FrameworkName, sysUser.AdminId)
+		exist, e := ob.GetItemByCondition(cond, pars)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil && exist.AiPredictModelFrameworkId > 0 {
+			br.Msg = "框架名称已存在,请重新输入"
+			return
+		}
+	}
+
+	now := time.Now().Local()
+	item.FrameworkName = req.FrameworkName
+	item.FrameworkImg = req.FrameworkImg
+	item.FrameworkContent = req.FrameworkContent
+	item.ModifyTime = now
+	updateCols := []string{"FrameworkName", "FrameworkImg", "FrameworkContent", "ModifyTime"}
+	nodes := make([]*aiPredictModel.AiPredictModelFrameworkNode, 0)
+	itemNodes := make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0)
+	if len(req.Nodes) > 0 {
+		for _, v := range req.Nodes {
+			if v.AiPredictModelIndexId <= 0 {
+				continue
+			}
+			t := new(aiPredictModel.AiPredictModelFrameworkNode)
+			t.AiPredictModelFrameworkId = req.AiPredictModelFrameworkId
+			t.FrameworkName = req.FrameworkName
+			t.NodeId = v.NodeId
+			t.NodeName = v.NodeName
+			t.AiPredictModelIndexId = v.AiPredictModelIndexId
+			t.CreateTime = now
+			nodes = append(nodes, t)
+
+			// 响应节点数据
+			td := aiPredictModel.FormatAiPredictModelFrameworkNode2Item(t, 1, map[int]*aiPredictModel.AiPredictModelIndex{})
+			itemNodes = append(itemNodes, td)
+		}
+	}
+	if e := item.EditFrameworkAndNodes(item, updateCols, nodes); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "编辑框架及节点失败, Err: " + e.Error()
+		return
+	}
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	br.IsAddLog = true
+}
+
+// Remove
+// @Title 删除框架
+// @Description 删除视频
+// @Param	request	body aiPredictModel.AiPredictModelFrameworkRemoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /framework/remove [post]
+func (c *AiPredictModelFrameworkController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 参数校验
+	var req aiPredictModel.AiPredictModelFrameworkRemoveReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.AiPredictModelFrameworkId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, AiPredictModelFrameworkId: %d", req.AiPredictModelFrameworkId)
+		return
+	}
+
+	ob := new(aiPredictModel.AiPredictModelFramework)
+	item, e := ob.GetItemById(req.AiPredictModelFrameworkId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取框架失败, Err: " + e.Error()
+		return
+	}
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN && item.AdminId != sysUser.AdminId {
+		br.Msg = "无权操作"
+		return
+	}
+
+	if e := item.RemoveFrameworkAndNodes(req.AiPredictModelFrameworkId); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除框架失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	br.IsAddLog = true
+}
+
+// Rename
+// @Title 重命名框架
+// @Description 重命名框架
+// @Param	request	body aiPredictModel.AiPredictModelFrameworkRenameReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /framework/rename [post]
+func (c *AiPredictModelFrameworkController) Rename() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 参数校验
+	var req aiPredictModel.AiPredictModelFrameworkRenameReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.AiPredictModelFrameworkId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, AiPredictModelFrameworkId: %d", req.AiPredictModelFrameworkId)
+		return
+	}
+	req.FrameworkName = strings.TrimSpace(req.FrameworkName)
+	if req.FrameworkName == "" {
+		br.Msg = "框架名称不可为空"
+		return
+	}
+
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+	item, e := frameworkOb.GetItemById(req.AiPredictModelFrameworkId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "框架不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取框架失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作权限校验
+	if item.AdminId != sysUser.AdminId && !utils.IsAdminRole(sysUser.RoleTypeCode) {
+		br.Msg = "您没有权限操作该框架"
+		return
+	}
+
+	// 重名校验
+	{
+		ob := new(aiPredictModel.AiPredictModelFramework)
+		cond := fmt.Sprintf(` AND %s <> ? AND %s = ? AND %s = ?`, ob.PrimaryId(), aiPredictModel.AiPredictModelFrameworkColumns.FrameworkName, aiPredictModel.AiPredictModelFrameworkColumns.AdminId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.AiPredictModelFrameworkId, req.FrameworkName, sysUser.AdminId)
+		exist, e := ob.GetItemByCondition(cond, pars)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil && exist.AiPredictModelFrameworkId > 0 {
+			br.Msg = "框架名称已存在,请重新输入"
+			return
+		}
+	}
+
+	now := time.Now().Local()
+	item.FrameworkName = req.FrameworkName
+	item.ModifyTime = now
+	updateCols := []string{"FrameworkName", "ModifyTime"}
+	if e := item.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "框架重命名失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Move
+// @Title 移动排序
+// @Description 移动排序
+// @Param	request	body aiPredictModel.AiPredictModelFrameworkMoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /framework/move [post]
+func (c *AiPredictModelFrameworkController) Move() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 参数校验
+	var req aiPredictModel.AiPredictModelFrameworkMoveReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.AiPredictModelFrameworkId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, AiPredictModelFrameworkId: %d", req.AiPredictModelFrameworkId)
+		return
+	}
+
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+	item, e := frameworkOb.GetItemById(req.AiPredictModelFrameworkId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "框架不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取框架失败, Err: " + e.Error()
+		return
+	}
+
+	updateCols := make([]string, 0)
+	// 上一个兄弟节点
+	if req.PrevAiPredictModelFrameworkId > 0 {
+		prev, e := frameworkOb.GetItemById(req.PrevAiPredictModelFrameworkId)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取上一个兄弟节点失败, Err: " + e.Error()
+			return
+		}
+
+		// 两个兄弟节点之间
+		if req.NextAiPredictModelFrameworkId > 0 {
+			next, e := frameworkOb.GetItemById(req.PrevAiPredictModelFrameworkId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取下一个兄弟节点失败, Err: " + e.Error()
+				return
+			}
+			// 如果上一个与下一个排序权重是一致的, 那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2, 自己变成上一个兄弟的排序权重+1
+			if prev.Sort == next.Sort || prev.Sort == item.Sort {
+				strUpdate := `sort + 2`
+				_ = aiPredictModel.UpdateAiPredictModelFrameworkSort(sysUser.AdminId, prev.AiPredictModelFrameworkId, prev.Sort, strUpdate)
+			} else {
+				// 如果下一个排序权重正好是上一个节点的下一层, 那么需要再加一层了
+				if next.Sort-prev.Sort == 1 {
+					//变更兄弟节点的排序
+					strUpdate := `sort + 1`
+					_ = aiPredictModel.UpdateAiPredictModelFrameworkSort(sysUser.AdminId, 0, prev.Sort, strUpdate)
+				}
+			}
+		}
+
+		// 上一个兄弟节点sort+1
+		item.Sort = prev.Sort + 1
+		item.ModifyTime = time.Now()
+		updateCols = append(updateCols, "Sort", "ModifyTime")
+	} else {
+		first, err := aiPredictModel.GetFirstAiPredictModelFramework()
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取我的模型框架排首位的数据失败, Err:" + err.Error()
+			return
+		}
+		if first != nil && first.Sort == 0 {
+			strUpdate := ` sort + 1 `
+			_ = aiPredictModel.UpdateAiPredictModelFrameworkSort(sysUser.AdminId, first.AiPredictModelFrameworkId-1, 0, strUpdate)
+		}
+
+		// 排首位
+		item.Sort = 0
+		item.ModifyTime = time.Now()
+		updateCols = append(updateCols, "Sort", "ModifyTime")
+	}
+
+	if len(updateCols) > 0 {
+		if e := item.Update(updateCols); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "更新框架排序失败, Err: " + e.Error()
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Detail
+// @Title 框架详情
+// @Description 框架详情
+// @Param   AiPredictModelFrameworkId  query  int  true  "框架ID"
+// @Success 200 Ret=200 操作成功
+// @router /framework/detail [get]
+func (c *AiPredictModelFrameworkController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	frameworkId, _ := c.GetInt("AiPredictModelFrameworkId")
+	if frameworkId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, AiPredictModelFrameworkId: %d", frameworkId)
+		return
+	}
+
+	frameworkOb := new(aiPredictModel.AiPredictModelFramework)
+	item, e := frameworkOb.GetItemById(frameworkId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "框架不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取框架失败, Err: " + e.Error()
+		return
+	}
+
+	// 获取节点
+	nodeOb := new(aiPredictModel.AiPredictModelFrameworkNode)
+	nodeCond := ` AND ai_predict_model_framework_id = ?`
+	nodePars := make([]interface{}, 0)
+	nodePars = append(nodePars, frameworkId)
+	nodes, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取框架节点失败, Err: " + e.Error()
+		return
+	}
+
+	// 模型标的map
+	aiPredictModelIndexMap := make(map[int]*aiPredictModel.AiPredictModelIndex)
+	{
+		aiPredictModelIndexIdList := make([]interface{}, 0)
+		for _, v := range nodes {
+			if v.AiPredictModelIndexId > 0 {
+				aiPredictModelIndexIdList = append(aiPredictModelIndexIdList, v.AiPredictModelIndexId)
+			}
+		}
+
+		indexIdNum := len(aiPredictModelIndexIdList)
+		if indexIdNum > 0 {
+			indexObj := aiPredictModel.AiPredictModelIndex{}
+			indexList, e := indexObj.GetItemsByCondition(` AND ai_predict_model_index_id in (`+utils.GetOrmInReplace(indexIdNum)+`)`, []interface{}{aiPredictModelIndexIdList}, []string{}, "")
+			if e != nil {
+				if utils.IsErrNoRow(e) {
+					br.Msg = "框架不存在, 请刷新页面"
+					return
+				}
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取标的列表失败, Err: " + e.Error()
+				return
+			}
+			for _, v := range indexList {
+				aiPredictModelIndexMap[v.AiPredictModelIndexId] = v
+			}
+		}
+	}
+
+	// 格式化响应数据
+	itemNodes := make([]*aiPredictModel.AiPredictModelFrameworkNodeItem, 0)
+	for _, v := range nodes {
+		if v.NodeId == "" {
+			continue
+		}
+		num := 1
+
+		itemNodes = append(itemNodes, aiPredictModel.FormatAiPredictModelFrameworkNode2Item(v, num, aiPredictModelIndexMap))
+	}
+	detail := aiPredictModel.FormatAiPredictModelFramework2Item(item, itemNodes)
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 1132 - 0
controllers/data_manage/ai_predict_model/index.go

@@ -0,0 +1,1132 @@
+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/data_manage"
+	dataSourceModel "eta/eta_api/models/data_source"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services"
+	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
+	"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   IndexId   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")
+	indexId, _ := this.GetInt("IndexId")
+	keyword := this.GetString("KeyWord")
+	if keyword == "" {
+		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
+		}
+	}
+
+	// 筛选条件
+	highlightMap := make(map[int]string)
+	indexOb := new(aiPredictModel.AiPredictModelIndex)
+	var cond string
+	var pars []interface{}
+	{
+		if indexId > 0 {
+			cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().PrimaryId)
+			pars = append(pars, indexId)
+		}
+		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, "%"))
+		//}
+
+		// 有关键词从es中搜索
+		if keyword != "" {
+			_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_AI_PREDICT_MODEL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("ES-搜索手工指标列表失败, %v", e)
+				return
+			}
+			if len(list) == 0 {
+				resp.List = make([]*aiPredictModel.AiPredictModelIndexItem, 0)
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				br.Data = resp
+				return
+			}
+			var ids []int
+			for _, v := range list {
+				ids = append(ids, v.PrimaryId)
+				highlightMap[v.PrimaryId] = v.SearchText
+			}
+			cond += fmt.Sprintf(` AND %s IN (%s)`, indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+			pars = append(pars, ids)
+		}
+	}
+
+	// 获取列表
+	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]
+		// 搜索高亮
+		t.SearchText = v.IndexName
+		s := highlightMap[v.AiPredictModelIndexId]
+		if s != "" {
+			t.SearchText = s
+		}
+		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, _ := utils.GetExcelDate(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, _ := utils.GetExcelDate(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, _ := utils.GetExcelDate(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, sysUser.AdminId, sysUser.RealName); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("导入指标数据失败, %v", e)
+		return
+	}
+
+	// 写入es
+	go func() {
+		for _, v := range importIndexes {
+			indexItem := new(dataSourceModel.SearchDataSource)
+			indexItem.PrimaryId = v.Index.AiPredictModelIndexId
+			indexItem.IndexName = v.Index.IndexName
+			indexItem.IndexCode = v.Index.IndexCode
+			indexItem.ClassifyId = v.Index.ClassifyId
+			indexItem.Source = utils.DATA_SOURCE_AI_PREDICT_MODEL
+			indexItem.SourceName = "AI预测模型"
+			indexItem.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.Index.CreateTime)
+			indexItem.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, v.Index.ModifyTime)
+
+			docId := fmt.Sprintf("%d-%d", indexItem.Source, indexItem.PrimaryId)
+			if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
+				utils.FileLog.Info("AI预测模型-写入es失败, %v", e)
+				continue
+			}
+		}
+	}()
+
+	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 utils.IsErrNoRow(e) {
+			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 utils.IsErrNoRow(e) {
+			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 utils.IsErrNoRow(e) {
+			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 && !utils.IsErrNoRow(e) {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取标的看板失败, %v", e)
+			return
+		}
+		if item != nil && item.AiPredictModelIndexId > 0 {
+			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 utils.IsErrNoRow(e) {
+			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 && !utils.IsErrNoRow(e) {
+			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 = "获取成功"
+}
+
+// SearchByEs
+// @Title 图表模糊搜索(从es获取)
+// @Description  图表模糊搜索(从es获取)
+// @Param   Keyword   query   string  true       "图表名称"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Param   Source   query   int  true       "来源,14:日度预测,15:月度预测,默认0:全部14+15"
+// @Success 200 {object} data_manage.ChartInfo
+// @router /chart/search_by_es [get]
+func (this *AiPredictModelIndexController) SearchByEs() {
+	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
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	keyword := this.GetString("Keyword")
+	keyword = strings.TrimSpace(keyword)
+	if keyword == "" {
+		keyword = this.GetString("KeyWord")
+		keyword = strings.TrimSpace(keyword)
+	}
+
+	//只看我的
+	isShowMe, _ := this.GetBool("IsShowMe")
+	showSysId := 0
+	if isShowMe {
+		showSysId = sysUser.AdminId
+	}
+
+	source, _ := this.GetInt("Source")
+	sourceList := make([]int, 0)
+	if source <= 0 {
+		sourceList = append(sourceList, utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY, utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY)
+	} else {
+		sourceList = append(sourceList, source)
+	}
+
+	var searchList []*data_manage.ChartInfoMore
+	var total int64
+	var err error
+
+	// 获取当前账号的不可见指标(AI预测的指标为标的均可见)
+	noPermissionChartIdList := make([]int, 0)
+	//{
+	//	obj := data_manage.EdbInfoNoPermissionAdmin{}
+	//	confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	for _, v := range confList {
+	//		noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
+	//	}
+	//}
+
+	if keyword != "" {
+		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+	} else {
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	finalList := make([]*data_manage.ChartInfoMore, 0)
+	if len(searchList) > 0 {
+		chartInfoIds := ""
+		chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
+		for _, v := range searchList {
+			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
+		}
+		if chartInfoIds != "" {
+			chartInfoIds = strings.Trim(chartInfoIds, ",")
+			//判断是否需要展示英文标识
+			edbList, e := data_manage.GetChartEdbMappingListByChartInfoIds(chartInfoIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + e.Error()
+				return
+			}
+			for _, v := range edbList {
+				chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
+			}
+		}
+
+		for _, v := range searchList {
+			tmp := new(data_manage.ChartInfoMore)
+			tmp.ChartInfo = v.ChartInfo
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
+			//判断是否需要展示英文标识
+			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
+				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
+			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
+			finalList = append(finalList, tmp)
+		}
+	}
+	//新增搜索词记录
+	{
+		searchKeyword := new(data_manage.SearchKeyword)
+		searchKeyword.KeyWord = keyword
+		searchKeyword.CreateTime = time.Now()
+		go data_manage.AddSearchKeyword(searchKeyword)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+	resp := data_manage.ChartInfoListByEsResp{
+		Paging: page,
+		List:   finalList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 5 - 5
controllers/data_manage/baiinfo_data.go

@@ -36,14 +36,14 @@ func (this *EdbInfoController) BaiinfoClassify() {
 	}
 
 	rootList, err := data_manage.GetBaseFromBaiinfoClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromBaiinfoClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -52,7 +52,7 @@ func (this *EdbInfoController) BaiinfoClassify() {
 	baseFromBaiinfoIndexMap := make(map[int][]*data_manage.BaseFromBaiinfoClassifyItems)
 
 	allBaseFromBaiinfoIndex, err := data_manage.GetBaiinfoIndexAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
@@ -144,14 +144,14 @@ func (this *EdbInfoController) BaiinfoClassifyName() {
 	}
 
 	rootList, err := data_manage.GetBaseFromBaiinfoClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromBaiinfoClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return

+ 3 - 2
controllers/data_manage/base_from_ly_index_controller.go

@@ -114,8 +114,9 @@ func (this *BaseFromLyIndexController) LyIndexDataList() {
 	if currentIndex <= 0 {
 		currentIndex = 1
 	}
+	startSize := utils.StartIndex(currentIndex, pageSize)
 
-	indexDataList, err := data.GetIndexDataPage(indexId, currentIndex, pageSize)
+	indexDataList, err := data.GetIndexDataPage(indexId, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取指标数据列表失败"
 		br.ErrMsg = "获取指标数据列表失败,Err:" + err.Error()
@@ -459,7 +460,7 @@ func (this *BaseFromLyIndexController) LyIndexDataExport() {
 
 			var lyDataList []*data_manage.BaseFromLyData
 			lyDataList, err = data_manage.GetBaseFromLyDataByIndexCode(v.IndexCode)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.ErrMsg = "GetBaseFromLyDataByIndexCode,Err:" + err.Error()
 				br.Msg = "获取数据失败"
 				return

+ 1152 - 0
controllers/data_manage/base_from_radish_research.go

@@ -0,0 +1,1152 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	dataSourceModel "eta/eta_api/models/data_source"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BaseFromRadishResearchController 萝卜投研
+type BaseFromRadishResearchController struct {
+	controllers.BaseAuthController
+}
+
+// IndexPageList
+// @Title 指标列表-分页
+// @Description 指标列表-分页
+// @Success 200 {object} data_manage.RadishResearchIndexPageListResp
+// @router /radish_research/index/page_list [get]
+func (this *BaseFromRadishResearchController) IndexPageList() {
+	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 params data_manage.RadishResearchIndexListForm
+	if e := this.ParseForm(&params); e != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = fmt.Sprintf("参数解析失败, err: %v", e)
+		return
+	}
+	resp := new(data_manage.RadishResearchIndexPageListResp)
+	resp.List = make([]*data_manage.BaseFromRadishResearchIndexItem, 0)
+	classifyId, _ := this.GetInt("ClassifyId", -1)
+
+	// 分页查询
+	var startSize int
+	if params.PageSize <= 0 {
+		params.PageSize = utils.PageSize20
+	}
+	if params.CurrentIndex <= 0 {
+		params.CurrentIndex = 1
+	}
+	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
+
+	// 筛选项
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	var (
+		cond        string
+		pars        []interface{}
+		classifyIds []int
+	)
+	// 未分类
+	if classifyId == 0 {
+		cond += fmt.Sprintf(` AND %s = ?`, indexOb.Cols().ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	// 包含所有子分类的指标
+	if classifyId > 0 {
+		classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+		classifies, e := classifyOb.GetItemsByCondition(fmt.Sprintf(" AND FIND_IN_SET(%d, %s)", classifyId, classifyOb.Cols().LevelPath), make([]interface{}, 0), []string{classifyOb.Cols().PrimaryId}, fmt.Sprintf("%s ASC, %s ASC", classifyOb.Cols().ParentId, classifyOb.Cols().Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取子分类IDs失败, %v", e)
+			return
+		}
+		for _, v := range classifies {
+			if v.BaseFromRadishResearchClassifyId <= 0 {
+				continue
+			}
+			classifyIds = append(classifyIds, v.BaseFromRadishResearchClassifyId)
+		}
+		if len(classifyIds) > 0 {
+			cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().ClassifyId)
+			pars = append(pars, classifyIds)
+		}
+	}
+	// 分类多选
+	params.ClassifyIds = strings.TrimSpace(params.ClassifyIds)
+	if params.ClassifyIds != "" {
+		idsArr := strings.Split(params.ClassifyIds, ",")
+		for _, v := range idsArr {
+			id, _ := strconv.Atoi(v)
+			if id > 0 {
+				classifyIds = append(classifyIds, id)
+			}
+		}
+		if len(classifyIds) > 0 {
+			cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().ClassifyId)
+			pars = append(pars, classifyIds)
+		}
+	}
+	// 频度多选
+	params.Frequencies = strings.TrimSpace(params.Frequencies)
+	if params.Frequencies != "" {
+		freArr := strings.Split(params.Frequencies, ",")
+		if len(freArr) > 0 {
+			cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().Frequency)
+			pars = append(pars, freArr)
+		}
+	}
+	// 关键词
+	params.Keyword = strings.TrimSpace(params.Keyword)
+	if params.Keyword != "" {
+		kw := fmt.Sprint("%", params.Keyword, "%")
+		cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexOb.Cols().IndexName, indexOb.Cols().IndexCode)
+		pars = append(pars, kw, kw)
+	}
+	// 是否忽略已加入指标库的
+	if params.IgnoreEdbExist {
+		cond += fmt.Sprintf(` AND %s = 0`, indexOb.Cols().EdbExist)
+	}
+
+	// 列表合计
+	total, e := indexOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标总数失败, %v", e)
+		return
+	}
+	if total <= 0 {
+		page := paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
+		resp.Paging = page
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	items, e := indexOb.GetPageItemsByCondition(cond, pars, []string{}, "", startSize, params.PageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标列表失败, %v", e)
+		return
+	}
+	for _, v := range items {
+		t := v.Format2Item()
+		resp.List = append(resp.List, t)
+	}
+
+	page := paging.GetPaging(params.CurrentIndex, params.PageSize, total)
+	resp.Paging = page
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// IndexDetail
+// @Title 指标详情
+// @Description 指标详情
+// @Param   IndexId  query  string  true  "指标ID"
+// @Success 200 {object} data_manage.BaseFromRadishResearchIndexDetail
+// @router /radish_research/index/detail [get]
+func (this *BaseFromRadishResearchController) IndexDetail() {
+	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(data_manage.BaseFromRadishResearchIndexDetail)
+
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	item, e := indexOb.GetItemById(indexId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "指标不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取指标失败, %v", e)
+		return
+	}
+	if item != nil && item.BaseFromRadishResearchIndexId <= 0 {
+		br.Msg = "指标不存在, 请刷新页面"
+		return
+	}
+	resp.BaseFromRadishResearchIndexItem = item.Format2Item()
+	resp.DataList = make([]*data_manage.BaseFromRadishResearchDataItem, 0)
+
+	dataOb := new(data_manage.BaseFromRadishResearchData)
+	cond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode)
+	pars := make([]interface{}, 0)
+	pars = append(pars, item.IndexCode)
+	dataList, e := dataOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s DESC", dataOb.Cols().DataTime))
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标数据失败, %v", e)
+		return
+	}
+	for _, v := range dataList {
+		resp.DataList = append(resp.DataList, v.Format2Item())
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// IndexEdit
+// @Title 编辑指标
+// @Description 编辑指标
+// @Success 200 {object} data_manage.RadishResearchIndexEditReq
+// @router /radish_research/index/edit [post]
+func (this *BaseFromRadishResearchController) IndexEdit() {
+	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 data_manage.RadishResearchIndexEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.IndexId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, IndexId: %d", req.IndexId)
+		return
+	}
+
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	item, e := indexOb.GetItemById(req.IndexId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "指标不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取指标失败, %v", e)
+		return
+	}
+	if item != nil && item.BaseFromRadishResearchIndexId <= 0 {
+		br.Msg = "指标不存在, 请刷新页面"
+		return
+	}
+
+	// 更新指标(这里不多限制,允许移到未分类)
+	item.ClassifyId = req.ClassifyId
+	item.ModifyTime = time.Now().Local()
+	updateCols := []string{indexOb.Cols().ClassifyId, indexOb.Cols().ModifyTime}
+	if e = item.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新指标分类失败, %v", e)
+		return
+	}
+
+	// 更新ES
+	go func() {
+		indexItem := new(dataSourceModel.SearchDataSource)
+		indexItem.PrimaryId = item.BaseFromRadishResearchIndexId
+		indexItem.IndexCode = item.IndexCode
+		indexItem.IndexName = item.IndexName
+		indexItem.ClassifyId = item.ClassifyId
+		indexItem.Unit = item.Unit
+		indexItem.Frequency = item.Frequency
+		indexItem.StartDate = item.StartDate.Format(utils.FormatDate)
+		indexItem.EndDate = item.EndDate.Format(utils.FormatDate)
+		indexItem.LatestValue = fmt.Sprint(item.LatestValue)
+		indexItem.Source = utils.DATA_SOURCE_RADISH_RESEARCH
+		indexItem.SourceName = utils.DATA_SOURCE_NAME_RADISH_RESEARCH
+		indexItem.IsDeleted = 0
+		indexItem.CreateTime = item.CreateTime.Format(utils.FormatDateTime)
+		indexItem.ModifyTime = item.ModifyTime.Format(utils.FormatDateTime)
+
+		docId := fmt.Sprintf("%d-%d", utils.DATA_SOURCE_RADISH_RESEARCH, item.BaseFromRadishResearchIndexId)
+		if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
+			utils.FileLog.Warning("RadishResearch-写入指标ES失败, %v", e)
+			return
+		}
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// IndexRemove
+// @Title 删除指标
+// @Description 删除指标
+// @Success 200 {object} data_manage.RadishResearchIndexRemoveReq
+// @router /radish_research/index/remove [post]
+func (this *BaseFromRadishResearchController) IndexRemove() {
+	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 data_manage.RadishResearchIndexRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.IndexId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, IndexId: %d", req.IndexId)
+		return
+	}
+
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	item, e := indexOb.GetItemById(req.IndexId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "指标不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取指标失败, %v", e)
+		return
+	}
+	if item != nil && item.BaseFromRadishResearchIndexId <= 0 {
+		br.Msg = "指标不存在, 请刷新页面"
+		return
+	}
+	if item.EdbExist == 1 {
+		br.Msg = "指标已被引用, 不允许删除"
+		return
+	}
+	if e = indexOb.RemoveIndexAndData(item.IndexCode); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("删除指标和数据失败, %v", e)
+		return
+	}
+
+	// 更新ES
+	go func() {
+		indexItem := new(dataSourceModel.SearchDataSource)
+		indexItem.PrimaryId = item.BaseFromRadishResearchIndexId
+		indexItem.IndexCode = item.IndexCode
+		indexItem.IndexName = item.IndexName
+		indexItem.ClassifyId = item.ClassifyId
+		indexItem.Unit = item.Unit
+		indexItem.Frequency = item.Frequency
+		indexItem.StartDate = item.StartDate.Format(utils.FormatDate)
+		indexItem.EndDate = item.EndDate.Format(utils.FormatDate)
+		indexItem.LatestValue = fmt.Sprint(item.LatestValue)
+		indexItem.Source = utils.DATA_SOURCE_RADISH_RESEARCH
+		indexItem.SourceName = utils.DATA_SOURCE_NAME_RADISH_RESEARCH
+		indexItem.IsDeleted = 1 // 标记已删除
+		indexItem.CreateTime = item.CreateTime.Format(utils.FormatDateTime)
+		indexItem.ModifyTime = item.ModifyTime.Format(utils.FormatDateTime)
+
+		docId := fmt.Sprintf("%d-%d", utils.DATA_SOURCE_RADISH_RESEARCH, item.BaseFromRadishResearchIndexId)
+		if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
+			utils.FileLog.Warning("RadishResearch-写入指标ES失败, %v", e)
+			return
+		}
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// IndexExport
+// @Title 导出指标数据
+// @Description 导出指标数据
+// @Param   ClassifyId  query  int  false  "分类Id"
+// @Success 200  导出成功
+// @router /radish_research/index/export [get]
+func (this *BaseFromRadishResearchController) IndexExport() {
+	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
+	}
+	classifyId, _ := this.GetInt("ClassifyId", -1)
+
+	var (
+		cond        string
+		pars        []interface{}
+		classifyIds []int
+	)
+	// 未分类
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	if classifyId == 0 {
+		cond += fmt.Sprintf(` AND %s = ?`, indexOb.Cols().ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	// 包含所有子分类的指标
+	if classifyId > 0 {
+		classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+		classifies, e := classifyOb.GetItemsByCondition(fmt.Sprintf(" AND FIND_IN_SET(%d, %s)", classifyId, classifyOb.Cols().LevelPath), make([]interface{}, 0), []string{classifyOb.Cols().PrimaryId}, fmt.Sprintf("%s ASC, %s ASC", classifyOb.Cols().ParentId, classifyOb.Cols().Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取子分类IDs失败, %v", e)
+			return
+		}
+		for _, v := range classifies {
+			if v.BaseFromRadishResearchClassifyId <= 0 {
+				continue
+			}
+			classifyIds = append(classifyIds, v.BaseFromRadishResearchClassifyId)
+		}
+		if len(classifyIds) > 0 {
+			cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().ClassifyId)
+			pars = append(pars, classifyIds)
+		}
+	}
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downFile := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	// 获取指标数据
+	indexes, e := indexOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s ASC", indexOb.Cols().Sort, indexOb.Cols().PrimaryId))
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标失败, %v", e)
+		return
+	}
+	if len(indexes) == 0 {
+		// 无数据返回空文件
+		if e := xlsxFile.Save(downFile); e != nil {
+			sheet, e := xlsxFile.AddSheet("无数据")
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("新增Sheet失败, %v", e)
+				return
+			}
+			rowSecName := sheet.AddRow()
+			celSecName := rowSecName.AddCell()
+			celSecName.SetValue("")
+			if e = xlsxFile.Save(downFile); e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("保存文件失败, %v", e)
+				return
+			}
+		}
+		fileName := fmt.Sprintf("%s%s%s", utils.DATA_SOURCE_NAME_RADISH_RESEARCH, time.Now().Format("06.01.02"), ".xlsx")
+		this.Ctx.Output.Download(downFile, fileName)
+		defer func() {
+			_ = os.Remove(downFile)
+		}()
+		return
+	}
+
+	// 划分指标频度
+	frequencyIndex := make(map[string][]*data_manage.BaseFromRadishResearchIndex)
+	frequencyIndexIds := make(map[string][]int)
+	for _, v := range indexes {
+		if frequencyIndex[v.Frequency] == nil {
+			frequencyIndex[v.Frequency] = make([]*data_manage.BaseFromRadishResearchIndex, 0)
+		}
+		if frequencyIndexIds[v.Frequency] == nil {
+			frequencyIndexIds[v.Frequency] = make([]int, 0)
+		}
+		frequencyIndexIds[v.Frequency] = append(frequencyIndexIds[v.Frequency], v.BaseFromRadishResearchIndexId)
+		frequencyIndex[v.Frequency] = append(frequencyIndex[v.Frequency], v)
+	}
+
+	frequencyArr := []string{"日度", "周度", "旬度", "月度", "季度", "半年度", "年度"}
+	//frequencyMap := map[string]string{
+	//	"日度":  "Daily",
+	//	"周度":  "Weekly",
+	//	"旬度":  "ten-day",
+	//	"月度":  "Monthly",
+	//	"季度":  "Quarterly",
+	//	"半年度": "Semi-annual",
+	//	"年度":  "Annual",
+	//}
+	dataOb := new(data_manage.BaseFromRadishResearchData)
+	for _, frequency := range frequencyArr {
+		// 获取对应频度指标
+		secNameList := frequencyIndex[frequency]
+		if len(secNameList) == 0 {
+			continue
+		}
+
+		//sheetName := fmt.Sprintf("%s(%s)", frequency, frequencyMap[frequency])
+		sheetNew, e := xlsxFile.AddSheet(frequency)
+		if e != nil {
+			utils.FileLog.Warning(fmt.Sprintf("萝卜投研导出-AddSheet err: %v", e))
+			continue
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		updateTimeRow := sheetNew.AddRow()
+
+		// 指标日期序列
+		indexIds := frequencyIndexIds[frequency]
+		dataTimeList, e := dataOb.GetDataTimeByIndexIds(indexIds)
+		if e != nil {
+			utils.FileLog.Warning(fmt.Sprintf("萝卜投研导出-GetDataTimeByIndexIds err: %v", e))
+			continue
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+		}
+		for k, sv := range secNameList {
+			// 获取数据
+			dataCond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode)
+			dataPars := make([]interface{}, 0)
+			dataPars = append(dataPars, sv.IndexCode)
+			dataList, e := dataOb.GetItemsByCondition(dataCond, dataPars, []string{}, fmt.Sprintf("%s DESC", dataOb.Cols().DataTime))
+			if e != nil {
+				utils.FileLog.Warning(fmt.Sprintf("萝卜投研导出-GetIndexDataByCondition err: %v", e))
+				continue
+			}
+
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称")
+				frequencyRow.AddCell().SetValue("频度")
+				unitRow.AddCell().SetValue("单位")
+				updateTimeRow.AddCell().SetValue("更新时间")
+				minCol := k * 3
+				sheetNew.SetColWidth(minCol, minCol, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(sv.IndexName)
+			frequencyRow.AddCell().SetValue(sv.Frequency)
+			unitRow.AddCell().SetValue(sv.Unit)
+
+			updateTimeRow.AddCell().SetValue(sv.ModifyTime)
+			dataInfoMap := make(map[string]*data_manage.BaseFromRadishResearchData)
+			for _, v := range dataList {
+				dt := v.DataTime.Format(utils.FormatDate)
+				dataInfoMap[dt] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	// 保存文件出错返回空文件
+	if e := xlsxFile.Save(downFile); e != nil {
+		sheet, e := xlsxFile.AddSheet("无数据")
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("新增Sheet失败, %v", e)
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		if e = xlsxFile.Save(downFile); e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("保存文件失败, %v", e)
+			return
+		}
+	}
+	fileName := fmt.Sprintf("%s%s%s", utils.DATA_SOURCE_NAME_RADISH_RESEARCH, time.Now().Format("06.01.02"), ".xlsx")
+	this.Ctx.Output.Download(downFile, fileName)
+	defer func() {
+		_ = os.Remove(downFile)
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+
+}
+
+// IndexSelect
+// @Title 批量加入指标库-选择指标
+// @Description 批量加入指标库-选择指标
+// @Success 200 {object} data_manage.BaseFromRadishResearchIndexItem
+// @router /radish_research/index/select [post]
+func (this *BaseFromRadishResearchController) IndexSelect() {
+	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 data_manage.RadishResearchIndexSelectReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	resp := make([]*data_manage.BaseFromRadishResearchIndexItem, 0)
+
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	var (
+		cond string
+		pars []interface{}
+	)
+	// 忽略已加入指标库的
+	cond += fmt.Sprintf(` AND %s = 0`, indexOb.Cols().EdbExist)
+	if len(req.ClassifyIds) > 0 {
+		cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().ClassifyId)
+		pars = append(pars, req.ClassifyIds)
+	}
+	if len(req.Frequencies) > 0 {
+		cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().Frequency)
+		pars = append(pars, req.Frequencies)
+	}
+	req.Keyword = strings.TrimSpace(req.Keyword)
+	if req.Keyword != "" {
+		kw := fmt.Sprint("%", req.Keyword, "%")
+		cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexOb.Cols().IndexName, indexOb.Cols().IndexCode)
+		pars = append(pars, kw, kw)
+	}
+	// 列表全选-SelectAll-true: IndexCodes为排除的指标, SelectAll-false: IndexCodes为选择的指标
+	if len(req.IndexCodes) > 0 {
+		if req.SelectAll {
+			cond += fmt.Sprintf(` AND %s NOT IN ?`, indexOb.Cols().IndexCode)
+		} else {
+			cond += fmt.Sprintf(` AND %s IN ?`, indexOb.Cols().IndexCode)
+		}
+		pars = append(pars, req.IndexCodes)
+	}
+
+	items, e := indexOb.GetItemsByCondition(cond, pars, []string{}, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标列表失败, %v", e)
+		return
+	}
+	if len(items) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range items {
+		t := v.Format2Item()
+		resp = append(resp, t)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// EdbAdd
+// @Title 加入指标库
+// @Description 加入指标库
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /radish_research/edb/add [post]
+func (this *BaseFromRadishResearchController) EdbAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := fmt.Sprintf("CACHE_EDB_INFO_ADD_%d_%d", utils.DATA_SOURCE_RADISH_RESEARCH, sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	var req data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析失败, %v", e)
+		return
+	}
+	req.EdbCode = strings.TrimSpace(req.EdbCode)
+	req.EdbName = strings.TrimSpace(req.EdbName)
+	if req.EdbCode == "" {
+		br.Msg = "指标编码不能为空"
+		return
+	}
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	// 是否加入过指标库
+	exist, e := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_RADISH_RESEARCH, req.EdbCode)
+	if e != nil && !utils.IsErrNoRow(e) {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("校验是否加入过指标库失败, %v", e)
+		return
+	}
+	if exist != nil && exist.EdbInfoId > 0 {
+		br.Msg = "指标库已存在,请刷新页面"
+		return
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_RADISH_RESEARCH, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 刷新指标数据
+	refreshRes, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, "")
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("刷新指标数据失败, %v", e)
+		return
+	}
+	if refreshRes != nil && refreshRes.Ret != 200 {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("刷新指标数据失败, Ret: %d, Msg: %s, ErrMsg: %s", refreshRes.Ret, refreshRes.Msg, refreshRes.ErrMsg)
+		return
+	}
+
+	// 更新指标EdbExist
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	if e := indexOb.UpdateEdbExists(1, []string{req.EdbCode}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新数据源EdbExist失败, %v", e)
+		return
+	}
+
+	//新增操作日志
+	{
+		edbLog := new(data_manage.EdbInfoLog)
+		edbLog.EdbInfoId = edbInfo.EdbInfoId
+		edbLog.SourceName = edbInfo.SourceName
+		edbLog.Source = edbInfo.Source
+		edbLog.EdbCode = edbInfo.EdbCode
+		edbLog.EdbName = edbInfo.EdbName
+		edbLog.ClassifyId = edbInfo.ClassifyId
+		edbLog.SysUserId = sysUser.AdminId
+		edbLog.SysUserRealName = sysUser.RealName
+		edbLog.CreateTime = time.Now()
+		edbLog.Content = string(this.Ctx.Input.RequestBody)
+		edbLog.Status = "新增指标"
+		edbLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddEdbInfoLog(edbLog)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	// 试用平台更新用户累计新增指标数
+	if utils.BusinessCode == utils.BusinessCodeSandbox {
+		go func() {
+			adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+			if e != nil {
+				return
+			}
+			if adminItem != nil && adminItem.AdminId <= 0 {
+				return
+			}
+			if adminItem.DepartmentName != "ETA试用客户" {
+				return
+			}
+
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// EdbNameCheck
+// @Title 批量加入指标库-重名校验
+// @Description 批量加入指标库-重名校验
+// @Success 200 {object} data_manage.EdbNameCheckResult
+// @router /radish_research/edb/name_check [post]
+func (this *BaseFromRadishResearchController) EdbNameCheck() {
+	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 []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	nameCount := make(map[string]int)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		nameCount[v.EdbName] += 1
+
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+	}
+	// 本次提交的名称中也不允许重复
+	for _, v := range resp {
+		if nameCount[v.EdbName] > 1 {
+			v.Exist = true
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// EdbMultiAdd
+// @Title 批量加入指标库
+// @Description 批量加入指标库
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /radish_research/edb/multi_add [post]
+func (this *BaseFromRadishResearchController) EdbMultiAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := fmt.Sprintf("CACHE_EDB_INFO_BATCH_ADD_%d_%d", utils.DATA_SOURCE_RADISH_RESEARCH, sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	var successCodes []string
+	for _, v := range req {
+		// 是否加入过指标库
+		exist, e := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_RADISH_RESEARCH, v.EdbCode)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("校验是否加入过指标库失败, %v", e)
+			return
+		}
+		if exist != nil && exist.EdbInfoId > 0 {
+			// 加入过指标库这里直接忽略掉
+			continue
+		}
+
+		// 指标入库
+		edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_RADISH_RESEARCH, utils.DATA_SUB_SOURCE_EDB, v.ClassifyId, v.EdbCode, v.EdbName, v.Frequency, v.Unit, v.StartDate, v.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+		if err != nil {
+			br.Msg = "保存失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = err.Error()
+			br.IsSendEmail = isSendEmail
+			return
+		}
+		successCodes = append(successCodes, v.EdbCode)
+
+		// 刷新指标数据
+		refreshRes, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, "")
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("刷新指标数据失败, %v", e)
+			return
+		}
+		if refreshRes != nil && refreshRes.Ret != 200 {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("刷新指标数据失败, Ret: %d, Msg: %s, ErrMsg: %s", refreshRes.Ret, refreshRes.Msg, refreshRes.ErrMsg)
+			return
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+
+		// 更新es
+		go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+	}
+
+	// 更新指标EdbExist
+	if len(successCodes) > 0 {
+		indexOb := new(data_manage.BaseFromRadishResearchIndex)
+		if e := indexOb.UpdateEdbExists(1, successCodes); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("更新数据源EdbExist失败, %v", e)
+			return
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}

+ 518 - 0
controllers/data_manage/base_from_radish_research_classify.go

@@ -0,0 +1,518 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/services/data"
+	"eta/eta_api/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// ClassifyList
+// @Title 分类列表-含指标
+// @Description 分类列表-含指标
+// @Param   ParentId  query  int  false  "父级ID"
+// @Success 200 {object} data_manage.RadishResearchSearchEdbResp
+// @router /radish_research/classify/list [get]
+func (this *BaseFromRadishResearchController) ClassifyList() {
+	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
+	}
+	parentId, _ := this.GetInt("ParentId", -1)
+
+	resp := make([]*data_manage.BaseFromRadishResearchClassifyListItem, 0)
+
+	// 默认查询未分类及一级分类
+	var classifyId int
+	if parentId == -1 {
+		resp = append(resp, &data_manage.BaseFromRadishResearchClassifyListItem{
+			ClassifyName: "未分类",
+			Level:        1,
+			Sort:         -100,
+			UniqueCode:   "unclassified",
+		})
+	}
+	// 查询未分类下的指标
+	if parentId == 0 {
+		classifyId = -1
+	}
+	if parentId > 0 {
+		classifyId = parentId
+	}
+
+	// 查询分类
+	classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+	{
+		cond := fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, classifyId)
+		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 = append(resp, &data_manage.BaseFromRadishResearchClassifyListItem{
+				ClassifyId:   v.BaseFromRadishResearchClassifyId,
+				ClassifyName: v.ClassifyName,
+				ParentId:     v.ParentId,
+				Level:        v.Level,
+				Sort:         v.Sort,
+				UniqueCode:   v.UniqueCode,
+			})
+		}
+	}
+
+	// 查询指标
+	if parentId > -1 {
+		indexOb := new(data_manage.BaseFromRadishResearchIndex)
+		{
+			cond := fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
+			pars := make([]interface{}, 0)
+			pars = append(pars, parentId)
+			list, e := indexOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", indexOb.Cols().Sort))
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("获取分类下指标失败, %v", e)
+				return
+			}
+			for _, v := range list {
+				resp = append(resp, &data_manage.BaseFromRadishResearchClassifyListItem{
+					NodeType:   1,
+					IndexId:    v.BaseFromRadishResearchIndexId,
+					IndexCode:  v.IndexCode,
+					IndexName:  v.IndexName,
+					ParentId:   parentId,
+					Sort:       v.Sort,
+					UniqueCode: v.IndexCode,
+				})
+			}
+		}
+	}
+	sort.Slice(resp, func(i, j int) bool {
+		return resp[i].Sort < resp[j].Sort
+	})
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// ClassifyTree
+// @Title 分类树
+// @Description 分类树
+// @Success 200 {object} data_manage.RadishResearchSearchEdbResp
+// @router /radish_research/classify/tree [get]
+func (this *BaseFromRadishResearchController) ClassifyTree() {
+	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
+	}
+
+	// 获取所有分类
+	classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+	list, e := classifyOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", classifyOb.Cols().ParentId, classifyOb.Cols().Sort))
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取分类列表失败, %v", e)
+		return
+	}
+	items := make([]*data_manage.BaseFromRadishResearchClassifyItem, 0)
+	for _, v := range list {
+		items = append(items, v.Format2Item())
+	}
+	tree := data.GetRadishResearchClassifyTreeRecursive(items, 0)
+
+	// 未分类置顶
+	resp := make([]*data_manage.BaseFromRadishResearchClassifyItem, 0)
+	resp = append(resp, &data_manage.BaseFromRadishResearchClassifyItem{
+		ClassifyName: "未分类",
+		Level:        1,
+		Sort:         -100,
+		UniqueCode:   "unclassified",
+	})
+	resp = append(resp, tree...)
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// ClassifyAdd
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body data_manage.RadishResearchClassifyAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /radish_research/classify/add [post]
+func (this *BaseFromRadishResearchController) ClassifyAdd() {
+	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 data_manage.RadishResearchClassifyAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "请选择上级分类"
+		return
+	}
+	if req.Level > 6 {
+		br.Msg = "目前只支持6级目录"
+		return
+	}
+
+	// 校验分类名称
+	classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+	{
+		cond := fmt.Sprintf(" AND %s = ? AND %s = ?", classifyOb.Cols().ParentId, classifyOb.Cols().ClassifyName)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ParentId, req.ClassifyName)
+		count, e := classifyOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取分类名称重复数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在"
+			return
+		}
+	}
+
+	// 层级路径
+	var levelPath string
+	var rootId int
+	if req.ParentId > 0 {
+		parent, e := classifyOb.GetItemById(req.ParentId)
+		if e != nil {
+			br.Msg = "上级分类有误"
+			br.ErrMsg = fmt.Sprintf("获取上级分类失败, %v", e)
+			return
+		}
+		levelPath = parent.LevelPath
+		rootId = parent.RootId
+	}
+
+	sortMax, e := classifyOb.GetSortMax(req.ParentId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取分类最大排序失败, %v", e)
+		return
+	}
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	classifyOb.ParentId = req.ParentId
+	classifyOb.ClassifyName = req.ClassifyName
+	classifyOb.Level = req.Level + 1
+	classifyOb.Sort = sortMax + 1
+	classifyOb.SysUserId = sysUser.AdminId
+	classifyOb.SysUserRealName = sysUser.RealName
+	classifyOb.UniqueCode = utils.MD5(classifyOb.TableName() + "_" + timestamp)
+	classifyOb.CreateTime = time.Now().Local()
+	classifyOb.ModifyTime = time.Now().Local()
+	if e = classifyOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("新增分类失败, %v", e)
+		return
+	}
+	if req.ParentId > 0 {
+		// 用英文逗号拼接方便查询
+		classifyOb.LevelPath = fmt.Sprintf("%s,%d", levelPath, classifyOb.BaseFromRadishResearchClassifyId)
+		classifyOb.RootId = rootId
+	} else {
+		classifyOb.LevelPath = fmt.Sprint(classifyOb.BaseFromRadishResearchClassifyId)
+		classifyOb.RootId = classifyOb.BaseFromRadishResearchClassifyId
+	}
+	if e = classifyOb.Update([]string{classifyOb.Cols().LevelPath, classifyOb.Cols().RootId}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新分类失败, %v", e)
+		return
+	}
+
+	br.Data = classifyOb.BaseFromRadishResearchClassifyId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// ClassifyEdit
+// @Title 编辑分类
+// @Description 编辑分类
+// @Param	request	body data_manage.RadishResearchClassifyEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /radish_research/classify/edit [post]
+func (this *BaseFromRadishResearchController) ClassifyEdit() {
+	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 data_manage.RadishResearchClassifyEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId < 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+
+	classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+	classifyItem, e := classifyOb.GetItemById(req.ClassifyId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Msg = "分类不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
+		return
+	}
+	if classifyItem != nil && classifyItem.BaseFromRadishResearchClassifyId <= 0 {
+		br.Msg = "分类不存在, 请刷新页面"
+		return
+	}
+
+	// 校验分类名称
+	{
+		cond := fmt.Sprintf(" AND %s <> ? AND %s = ?", classifyOb.Cols().PrimaryId, classifyOb.Cols().ClassifyName)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ClassifyId, req.ClassifyName)
+		count, e := classifyOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取分类名称重复数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在"
+			return
+		}
+	}
+	classifyItem.ClassifyName = req.ClassifyName
+	classifyItem.ModifyTime = time.Now().Local()
+	updateCols := []string{classifyOb.Cols().ClassifyName, classifyOb.Cols().ModifyTime}
+	if e = classifyItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("更新分类失败, %v", e)
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// ClassifyRemove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body data_manage.RadishResearchClassifyRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /radish_research/classify/remove [post]
+func (this *BaseFromRadishResearchController) ClassifyRemove() {
+	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 data_manage.RadishResearchClassifyRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId < 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+	classifyItem, e := classifyOb.GetItemById(req.ClassifyId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
+		return
+	}
+	if classifyItem != nil && classifyItem.BaseFromRadishResearchClassifyId <= 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+
+	// 查询子分类
+	{
+		cond := fmt.Sprintf(" AND %s = ?", classifyOb.Cols().ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ClassifyId)
+		count, e := classifyOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取子分类数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类下含有子分类, 不允许删除"
+			return
+		}
+	}
+
+	// 查询指标
+	indexOb := new(data_manage.BaseFromRadishResearchIndex)
+	{
+		cond := fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.ClassifyId)
+		count, e := indexOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("获取分类下指标数失败, %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "该分类下含有指标, 不允许删除"
+			return
+		}
+	}
+
+	if e := classifyItem.Remove(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("删除分类失败, %v", e)
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// ClassifyMove
+// @Title 移动分类
+// @Description 移动分类
+// @Param	request	body data_manage.BaseFromRadishResearchClassifyMoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /radish_research/classify/move [post]
+func (this *BaseFromRadishResearchController) ClassifyMove() {
+	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 data_manage.BaseFromRadishResearchClassifyMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
+		return
+	}
+	if req.ClassifyId <= 0 && req.ItemId <= 0 {
+		br.Msg = "请选择分类或指标"
+		return
+	}
+
+	err, errMsg := data.RadishResearchMoveClassify(req, sysUser)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 708 - 0
controllers/data_manage/base_from_rzd_index_controller.go

@@ -0,0 +1,708 @@
+// Package data_manage
+// @Author gmy 2024/8/12 14:31:00
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BaseFromRzdIndexController 睿姿得数据控制器
+type BaseFromRzdIndexController struct {
+	controllers.BaseAuthController
+}
+
+// RzdClassify
+// @Title 睿姿得数据分类
+// @Description 汾渭数据分类接口
+// @Success 200 {object} data_manage.BaseFromRzdClassifyResponse
+// @router /rzd/classify [get]
+func (this *BaseFromRzdIndexController) RzdClassify() {
+	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
+	}
+
+	classifies, e := data.RzdClassifyList()
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取睿姿得数据分类失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = classifies
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// RzdIndexData
+// @Title 获取睿姿得数据
+// @Description 获取睿姿得数据
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Param   Frequency   query   string  true       "频率"
+// @Success 200
+// @router /rzd/index/data [get]
+func (this *BaseFromRzdIndexController) RzdIndexData() {
+	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
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	frequency := this.GetString("Frequency")
+
+	resultList, err := data.RzdIndexData(classifyId, frequency, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// RzdIndexDetail
+// @Title 获取睿姿得数据指标详情
+// @Description 获取睿姿得数据指标详情
+// @Param   IndexCode   query   string  true       "查询参数 指标id"
+// @Success 200
+// @router /rzd/index/detail [get]
+func (this *BaseFromRzdIndexController) RzdIndexDetail() {
+	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
+	}
+
+	indexCode := this.GetString("IndexCode")
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	indexDetail, err := data.GetRzdIndexDetail(indexCode, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexDetail
+}
+
+// RzdIndexList
+// @Title 获取睿姿得数据指标列表
+// @Description 获取睿姿得数据指标详情
+// @Param   searchParams   query   string  true       "查询参数 指标id/指标名称"
+// @Success 200
+// @router /rzd/index/list [get]
+func (this *BaseFromRzdIndexController) RzdIndexList() {
+	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
+	}
+
+	searchParams := this.GetString("SearchParams")
+
+	indexList, err := data.GetRzdIndexList(searchParams)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexList
+}
+
+// GetRzdFrequencyList
+// @Title 查询频率列表
+// @Description 查询频率列表
+// @Param   classifyId   query  int  false   "指标唯一编码"
+// @Success 200 {object} []string
+// @router /rzd/frequency/list [get]
+func (this *BaseFromRzdIndexController) GetRzdFrequencyList() {
+	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
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	frequencyList, err := data.GetRzdIndexFrequency(classifyId)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+}
+
+// RzdIndexAddValidate
+// @Title 新增加入到指标库校验
+// @Description 新增加入到指标库校验
+// @Param   req    body   data_manage.BaseFromFenWeiIndexBatchAddCheckReq     true        "请求参数"
+// @Success 200 {object} []data_manage.IndexCheckData
+// @router /rzd/index/add/validate [post]
+func (this *BaseFromRzdIndexController) RzdIndexAddValidate() {
+	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 *data_manage.BaseFromRzdIndexBatchAddCheckReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	// 校验指标编码是否存在
+	addValidate, err := data.RzdIndexAddValidate(req)
+	if err != nil {
+		br.Ret = 403
+		br.Success = false
+		br.Msg = err.Error()
+		return
+	}
+	br.Data = addValidate
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RzdIndexAdd
+// @Title 指标添加到指标库
+// @Description 指标添加到指标库
+// @Param   req    body   []data_manage.AddEdbInfoReq     true        "请求参数"
+// @Success 200 string "操作成功"
+// @router /rzd/index/add [post]
+func (this *BaseFromRzdIndexController) RzdIndexAdd() {
+	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
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_RZD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过" + strconv.Itoa(30) + "个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.RzdNameCheckResult, 0)
+	for _, index := range req {
+		index.EdbCode = strings.TrimSpace(index.EdbCode)
+		if index.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		index.EdbName = strings.TrimSpace(index.EdbName)
+		if index.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		index.Frequency = strings.TrimSpace(index.Frequency)
+		if index.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		index.Unit = strings.TrimSpace(index.Unit)
+		if index.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if index.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+		indexNames = append(indexNames, index.EdbName)
+		resp = append(resp, &data_manage.RzdNameCheckResult{
+			IndexCode: index.EdbCode,
+			IndexName: index.EdbName,
+			Exist:     false,
+		})
+	}
+
+	// 指标名称重复校验
+	nameCheck, err := data.RzdIndexNameCheck(indexNames, resp)
+	if err != nil {
+		br.Msg = err.Error()
+		br.ErrMsg = err.Error()
+		return
+	}
+	for _, v := range nameCheck {
+		if v.Exist {
+			br.Msg = "指标名称重复"
+			br.Data = nameCheck
+			br.Ret = 200
+			br.Success = true
+			return
+		}
+	}
+
+	for _, v := range req {
+		var rzdIndexAddReq data_manage.RzdIndexAddReq
+		rzdIndexAddReq.EdbCode = v.EdbCode
+		rzdIndexAddReq.EdbName = v.EdbName
+		rzdIndexAddReq.Frequency = v.Frequency
+		rzdIndexAddReq.Unit = v.Unit
+		rzdIndexAddReq.ClassifyId = v.ClassifyId
+		rzdIndexAddReq.AdminId = sysUser.AdminId
+		rzdIndexAddReq.AdminRealName = sysUser.RealName
+
+		// 新增指标到指标库
+		edbInfo, e, errMsg, skip := data.RzdIndexAdd(rzdIndexAddReq, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// todo 下面两段代码能否抽离出来???
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// RzdIndexDataExport
+// @Title 导出指标数据
+// @Description 导出指标数据
+// @Param  IndexCode     query   string     false        "指标编码"
+// @Param  ClassifyId     query   int     false        "分类ID"
+// @Success 200 string "操作成功"
+// @router /rzd/index/data/export [get]
+func (this *BaseFromRzdIndexController) RzdIndexDataExport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId") //分类
+	indexCode := this.GetString("IndexCode")   //指标唯一编码
+
+	if classifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downLoadFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	classifyIdList, err := data.RzdClassifyRecursiveQuery(classifyId)
+	if err != nil {
+		br.Msg = "查询分类失败"
+		br.ErrMsg = "查询分类失败"
+		return
+	}
+	classifyIdList = append(classifyIdList, classifyId)
+
+	frequencies, err := data_manage.GetRzdIndexFrequency(classifyIdList)
+	if err != nil {
+		br.Msg = "查询频度失败"
+		br.ErrMsg = "查询频度失败"
+		return
+	}
+
+	fileName := `睿姿得数据`
+	if classifyId > 0 && indexCode == "" {
+		fenWeiClassify, err := data_manage.GetRzdClassifyItemByClassifyId(classifyId)
+		if err != nil {
+			return
+		}
+		fileName = fenWeiClassify.ClassifyName
+	}
+	if frequencies == nil {
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+	}
+
+	for _, frequency := range frequencies {
+		fenWeiIndices, err := data_manage.GetRzdIndexByCodeAndClassify(indexCode, classifyIdList, frequency)
+		if err != nil {
+			return
+		}
+		var sheet *xlsx.Sheet
+		if len(fenWeiIndices) > 0 {
+			sheetName := *frequency
+			if sheetName == "" {
+				sheetName = "无频度"
+			}
+			sheet, err = xlsxFile.AddSheet(sheetName)
+			if err != nil {
+				br.Msg = "新增Sheet失败"
+				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			continue
+		}
+
+		if indexCode != "" {
+			fileName = fenWeiIndices[0].IndexName
+		}
+
+		//获取指标数据
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("指标名称/Metric Nome")
+		rowFrequency := sheet.AddRow()
+		celFrequency := rowFrequency.AddCell()
+		celFrequency.SetValue("频率/Frequency")
+		rowUnit := sheet.AddRow()
+		celUnit := rowUnit.AddCell()
+		celUnit.SetValue("单位/Unit")
+		rowModifyDate := sheet.AddRow()
+		rowModifyCell := rowModifyDate.AddCell()
+		rowModifyCell.SetValue("更新时间/Update Time")
+
+		dataMap := make(map[string]map[string]*data_manage.BaseFromRzdData)
+		var tradeCodeList []string
+		for _, v := range fenWeiIndices {
+			cellSenName := rowSecName.AddCell()
+			cellSenName.SetValue(v.IndexName)
+			celFrequency := rowFrequency.AddCell()
+			celFrequency.SetValue(v.Frequency)
+			celUnit := rowUnit.AddCell()
+			celUnit.SetValue(v.Unit)
+			rowModifyCell := rowModifyDate.AddCell()
+			updateTimeStr := utils.FormatDateString(v.ModifyTime)
+			rowModifyCell.SetValue(updateTimeStr)
+			tradeCodeList = append(tradeCodeList, v.IndexCode)
+
+			var dataList []*data_manage.BaseFromRzdData
+			dataList, err = data_manage.GetBaseFormRzdDataByIndexCode(v.IndexCode)
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.ErrMsg = "GetBaseFormRzdDataByIndexCode,Err:" + err.Error()
+				br.Msg = "获取数据失败"
+				return
+			}
+			for _, item := range dataList {
+				if dataMap[item.IndexCode] == nil {
+					dataMap[item.IndexCode] = make(map[string]*data_manage.BaseFromRzdData)
+				}
+				dataMap[item.IndexCode][item.DataTime] = item
+			}
+		}
+
+		tradeCodeStr := strings.Join(tradeCodeList, "','")
+		tradeCodeStr = "'" + tradeCodeStr + "'"
+		dataTimeList, err := data_manage.GetRzdDataListByIndexCodes(tradeCodeStr)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		for _, dataTime := range dataTimeList {
+			rowData := sheet.AddRow()
+			celDate := rowData.AddCell()
+			celDate.SetValue(dataTime)
+
+			for _, m := range fenWeiIndices {
+				celData := rowData.AddCell()
+				if dataMap[m.IndexCode][dataTime] != nil {
+					celData.SetValue(dataMap[m.IndexCode][dataTime].Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		err = xlsxFile.Save(downLoadFilePath)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downLoadFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}
+
+// GetRzdIndexInfo
+// @Title 添加指标-根据条件获取指标信息
+// @Description 添加指标-根据条件获取指标信息
+// @Param   KeyWord   query   string  false       "关键字"
+// @Param   ClassifyIds   query   string  false       "分类id"
+// @Param   Frequencies   query   string  false       "频率"
+// @Param   PageSize   query   int  false       "每页数据条数"
+// @Param   CurrentIndex   query   int  false       "当前页页码,从1开始"
+// @Success 200 {object} data_manage.BaseFromRzdIndexPage
+// @router /rzd/get/index/info [get]
+func (this *BaseFromRzdIndexController) GetRzdIndexInfo() {
+	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
+	}
+
+	keyWord := this.GetString("KeyWord")
+	classifyIds := this.GetString("ClassifyIds")
+	frequencies := this.GetString("Frequencies")
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var classifyIdList []string
+	var frequencyList []string
+	if classifyIds != "" {
+		classifyIdList = strings.Split(classifyIds, ",")
+	}
+	if frequencies != "" {
+		frequencyList = strings.Split(frequencies, ",")
+	}
+	indexInfoPage, err := data.GetRzdIndexInfo(keyWord, classifyIdList, frequencyList, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexInfoPage
+}

+ 105 - 75
controllers/data_manage/base_from_ths_hf.go

@@ -5,8 +5,10 @@ import (
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	dataSourceModel "eta/eta_api/models/data_source"
 	"eta/eta_api/models/mgo"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -296,6 +298,7 @@ func (this *BaseFromThsHfController) List() {
 		br.ErrMsg = fmt.Sprintf("参数有误, SortType: %d", params.SortType)
 		return
 	}
+	params.Keywords = strings.TrimSpace(params.Keywords)
 	resp := new(data_manage.ThsHfIndexPageListResp)
 	resp.List = make([]*data_manage.BaseFromThsHfIndexItem, 0)
 
@@ -316,18 +319,30 @@ func (this *BaseFromThsHfController) List() {
 		//classifies = list
 	}
 
+	// 分页查询
+	var startSize int
+	if params.PageSize <= 0 {
+		params.PageSize = utils.PageSize20
+	}
+	if params.CurrentIndex <= 0 {
+		params.CurrentIndex = 1
+	}
+	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
+
 	// 筛选项
 	var (
-		cond      string
-		pars      []interface{}
-		listOrder string
+		cond         string
+		pars         []interface{}
+		listOrder    string
+		classifyIds  []int
+		adminIds     []int
+		frequencyArr []string
 	)
 	indexOb := new(data_manage.BaseFromThsHfIndex)
 	{
 		// 分类
 		if params.ClassifyId != "" {
 			classifyIdArr := strings.Split(params.ClassifyId, ",")
-			classifyIds := make([]int, 0)
 			for _, v := range classifyIdArr {
 				t, _ := strconv.Atoi(v)
 				if t > 0 {
@@ -344,65 +359,23 @@ func (this *BaseFromThsHfController) List() {
 			}
 			cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().BaseFromThsHfClassifyId, utils.GetOrmInReplace(len(classifyIds)))
 			pars = append(pars, classifyIds)
-
-			//// 不包含子分类
-			//if len(classifyIds) > 0 && !params.IncludeChild {
-			//	cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().BaseFromThsHfClassifyId, utils.GetOrmInReplace(len(classifyIds)))
-			//	pars = append(pars, classifyIds)
-			//}
-			//
-			//// 包含子分类
-			//if len(classifyIds) > 0 && params.IncludeChild {
-			//	queryClassifyIds := make([]int, 0)
-			//	queryClassifyExist := make(map[int]bool)
-			//
-			//	for _, v := range classifyIds {
-			//		// 遍历所有分类从LevelPath中找含有查询分类ID的...=_=!
-			//		for _, cv := range classifies {
-			//			if queryClassifyExist[cv.BaseFromThsHfClassifyId] {
-			//				continue
-			//			}
-			//			if cv.LevelPath == "" {
-			//				continue
-			//			}
-			//			strArr := strings.Split(cv.LevelPath, ",")
-			//			if len(strArr) == 0 {
-			//				continue
-			//			}
-			//			for _, sv := range strArr {
-			//				tv, _ := strconv.Atoi(sv)
-			//				if tv == v {
-			//					queryClassifyIds = append(queryClassifyIds, cv.BaseFromThsHfClassifyId)
-			//					queryClassifyExist[cv.BaseFromThsHfClassifyId] = true
-			//					break
-			//				}
-			//			}
-			//		}
-			//	}
-			//
-			//	if len(queryClassifyIds) == 0 {
-			//		page := paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
-			//		resp.Paging = page
-			//		br.Ret = 200
-			//		br.Success = true
-			//		br.Msg = "获取成功"
-			//		return
-			//	}
-			//	cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().BaseFromThsHfClassifyId, utils.GetOrmInReplace(len(queryClassifyIds)))
-			//	pars = append(pars, queryClassifyIds)
-			//}
 		}
 
 		if params.Frequency != "" {
-			frequencyArr := strings.Split(params.Frequency, ",")
-			if len(frequencyArr) > 0 {
-				cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().Frequency, utils.GetOrmInReplace(len(frequencyArr)))
-				pars = append(pars, frequencyArr)
+			frequencyArr = strings.Split(params.Frequency, ",")
+			if len(frequencyArr) == 0 {
+				page := paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
+				resp.Paging = page
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
 			}
+			cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().Frequency, utils.GetOrmInReplace(len(frequencyArr)))
+			pars = append(pars, frequencyArr)
 		}
 		if params.SysAdminId != "" {
 			adminIdArr := strings.Split(params.SysAdminId, ",")
-			adminIds := make([]int, 0)
 			for _, v := range adminIdArr {
 				t, _ := strconv.Atoi(v)
 				if t > 0 {
@@ -410,15 +383,60 @@ func (this *BaseFromThsHfController) List() {
 				}
 			}
 			if len(adminIds) > 0 {
-				cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().SysUserId, utils.GetOrmInReplace(len(adminIds)))
-				pars = append(pars, adminIds)
+				page := paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
+				resp.Paging = page
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
 			}
+			cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().SysUserId, utils.GetOrmInReplace(len(adminIds)))
+			pars = append(pars, adminIds)
 		}
-		params.Keywords = strings.TrimSpace(params.Keywords)
+
+		// 关键词空格拆分
 		if params.Keywords != "" {
-			cond += fmt.Sprintf(" AND (%s LIKE ? OR %s LIKE ?)", indexOb.Cols().IndexCode, indexOb.Cols().IndexName)
-			kw := fmt.Sprint("%", params.Keywords, "%")
-			pars = append(pars, kw, kw)
+			indexCodeCol := indexOb.Cols().IndexCode
+			indexNameCol := indexOb.Cols().IndexName
+			keywordArr := strings.Split(params.Keywords, " ")
+			if len(keywordArr) > 1 {
+				sliceArr := make([]string, 0)
+				sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+				pars = utils.GetLikeKeywordPars(pars, params.Keywords, 2)
+				for _, v := range keywordArr {
+					if v == ` ` || v == `` {
+						continue
+					}
+					sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+					pars = utils.GetLikeKeywordPars(pars, v, 2)
+				}
+				cond += ` AND (` + strings.Join(sliceArr, " OR ") + `)`
+			} else {
+				cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexCodeCol, indexNameCol)
+				pars = utils.GetLikeKeywordPars(pars, params.Keywords, 2)
+			}
+
+			// ES关键词搜索
+			//_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, params.Keywords, utils.DATA_SOURCE_THS, utils.DATA_SUB_SOURCE_HIGH_FREQUENCY, []int{}, []int{}, []string{}, startSize, params.PageSize)
+			//if e != nil {
+			//	br.Msg = "获取失败"
+			//	br.ErrMsg = fmt.Sprintf("ES-搜索高频数据指标失败, %v", e)
+			//	return
+			//}
+			//if len(list) == 0 {
+			//	page := paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
+			//	resp.Paging = page
+			//	br.Ret = 200
+			//	br.Success = true
+			//	br.Msg = "获取成功"
+			//	return
+			//}
+			//var indexIds []int
+			//for _, v := range list {
+			//	indexIds = append(indexIds, v.PrimaryId)
+			//}
+			//cond += fmt.Sprintf(" AND %s IN (%s)", indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(indexIds)))
+			//pars = append(pars, indexIds)
 		}
 
 		// 排序
@@ -446,15 +464,6 @@ func (this *BaseFromThsHfController) List() {
 		return
 	}
 
-	// 分页查询
-	var startSize int
-	if params.PageSize <= 0 {
-		params.PageSize = utils.PageSize20
-	}
-	if params.CurrentIndex <= 0 {
-		params.CurrentIndex = 1
-	}
-	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
 	items, e := indexOb.GetPageItemsByCondition(cond, pars, []string{}, listOrder, startSize, params.PageSize)
 	if e != nil {
 		br.Msg = "获取失败"
@@ -719,7 +728,7 @@ func (this *BaseFromThsHfController) Edit() {
 	indexOb := new(data_manage.BaseFromThsHfIndex)
 	item, e := indexOb.GetItemById(params.IndexId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "指标不存在, 请刷新页面"
 			return
 		}
@@ -810,7 +819,7 @@ func (this *BaseFromThsHfController) Detail() {
 	indexOb := new(data_manage.BaseFromThsHfIndex)
 	item, e := indexOb.GetItemById(indexId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "指标不存在, 请刷新页面"
 			return
 		}
@@ -890,7 +899,7 @@ func (this *BaseFromThsHfController) Refresh() {
 	indexOb := new(data_manage.BaseFromThsHfIndex)
 	_, e := indexOb.GetItemById(params.IndexId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "指标不存在, 请刷新页面"
 			return
 		}
@@ -950,7 +959,7 @@ func (this *BaseFromThsHfController) Remove() {
 	indexOb := new(data_manage.BaseFromThsHfIndex)
 	item, e := indexOb.GetItemById(params.IndexId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "操作成功"
@@ -1004,6 +1013,27 @@ func (this *BaseFromThsHfController) Remove() {
 		}
 	}
 
+	// ES标记删除
+	go func() {
+		indexItem := new(dataSourceModel.SearchDataSource)
+		indexItem.PrimaryId = item.BaseFromThsHfIndexId
+		indexItem.IndexName = item.IndexName
+		indexItem.IndexCode = item.IndexCode
+		indexItem.ClassifyId = item.BaseFromThsHfClassifyId
+		indexItem.Source = utils.DATA_SOURCE_THS
+		indexItem.SubSource = utils.DATA_SUB_SOURCE_HIGH_FREQUENCY
+		indexItem.SourceName = "同花顺高频"
+		indexItem.IsDeleted = 1
+		indexItem.CreateTime = utils.TimeTransferString(utils.FormatDateTime, item.CreateTime)
+		indexItem.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, item.ModifyTime)
+
+		docId := fmt.Sprintf("%d-%d", indexItem.Source, indexItem.PrimaryId)
+		if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
+			utils.FileLog.Info("同花顺高频-标记删除es失败, %v", e)
+			return
+		}
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"

+ 2 - 2
controllers/data_manage/base_from_ths_hf_classify.go

@@ -301,7 +301,7 @@ func (this *BaseFromThsHfController) ClassifyEdit() {
 	classifyOb := new(data_manage.BaseFromThsHfClassify)
 	classifyItem, e := classifyOb.GetItemById(req.ClassifyId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "分类不存在, 请刷新页面"
 			return
 		}
@@ -382,7 +382,7 @@ func (this *BaseFromThsHfController) ClassifyRemove() {
 	classifyOb := new(data_manage.BaseFromThsHfClassify)
 	classifyItem, e := classifyOb.GetItemById(req.ClassifyId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "获取成功"

+ 78 - 15
controllers/data_manage/bloomberg_data.go

@@ -57,16 +57,70 @@ func (this *BloombergDataController) List() {
 		return
 	}
 
+	var startSize int
+	if params.PageSize <= 0 {
+		params.PageSize = utils.PageSize20
+	}
+	if params.CurrentIndex <= 0 {
+		params.CurrentIndex = 1
+	}
+	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
+	dataResp := new(data_manage.BloombergSourceListResp)
+
 	cond := ``
 	pars := make([]interface{}, 0)
 	// 筛选项
 	{
 		params.Keywords = strings.TrimSpace(params.Keywords)
 		if params.Keywords != "" {
-			cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, data_manage.BaseFromBloombergIndexCols.IndexCode, data_manage.BaseFromBloombergIndexCols.IndexName)
-			kw := fmt.Sprint("%", params.Keywords, "%")
-			pars = append(pars, kw, kw)
+			// 空格分词搜
+			indexCodeCol := data_manage.BaseFromBloombergIndexCols.IndexCode
+			indexNameCol := data_manage.BaseFromBloombergIndexCols.IndexName
+			//keywordArr := strings.Split(params.Keywords, " ")
+			//if len(keywordArr) > 1 {
+			//	sliceArr := make([]string, 0)
+			//	sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+			//	pars = utils.GetLikeKeywordPars(pars, params.Keywords, 2)
+			//
+			//	for _, v := range keywordArr {
+			//		if v == ` ` || v == `` {
+			//			continue
+			//		}
+			//		sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+			//		pars = utils.GetLikeKeywordPars(pars, v, 2)
+			//	}
+			//	cond += ` AND (` + strings.Join(sliceArr, " OR ") + `)`
+			//} else {
+			//	cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexCodeCol, indexNameCol)
+			//	pars = utils.GetLikeKeywordPars(pars, params.Keywords, 2)
+			//}
+			cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexCodeCol, indexNameCol)
+			pars = utils.GetLikeKeywordPars(pars, params.Keywords, 2)
+
+			// ES搜
+			//_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, params.Keywords, utils.DATA_SOURCE_BLOOMBERG, 0, []int{}, []int{}, []string{}, startSize, params.PageSize)
+			//if e != nil {
+			//	br.Msg = "获取失败"
+			//	br.ErrMsg = fmt.Sprintf("ES-搜索Bloomberg指标失败, %v", e)
+			//	return
+			//}
+			//if len(list) == 0 {
+			//	dataResp.Paging = paging.GetPaging(params.CurrentIndex, params.PageSize, 0)
+			//	dataResp.List = make([]*data_manage.BaseFromBloombergIndexItem, 0)
+			//	br.Data = dataResp
+			//	br.Ret = 200
+			//	br.Success = true
+			//	br.Msg = "获取成功"
+			//	return
+			//}
+			//var indexIds []int
+			//for _, v := range list {
+			//	indexIds = append(indexIds, v.PrimaryId)
+			//}
+			//cond += fmt.Sprintf(" AND %s IN (%s)", data_manage.BaseFromBloombergIndexCols.BaseFromBloombergIndexId, utils.GetOrmInReplace(len(indexIds)))
+			//pars = append(pars, indexIds)
 		}
+
 		if params.Frequency != "" {
 			cond += fmt.Sprintf(` AND %s = ?`, data_manage.BaseFromBloombergIndexCols.Frequency)
 			pars = append(pars, params.Frequency)
@@ -81,14 +135,6 @@ func (this *BloombergDataController) List() {
 		br.ErrMsg = "获取Bloomberg原始指标列表总数失败, Err: " + e.Error()
 		return
 	}
-	var startSize int
-	if params.PageSize <= 0 {
-		params.PageSize = utils.PageSize20
-	}
-	if params.CurrentIndex <= 0 {
-		params.CurrentIndex = 1
-	}
-	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
 
 	// 排序, 默认创建时间倒序
 	orderFields := map[int]string{
@@ -143,7 +189,6 @@ func (this *BloombergDataController) List() {
 		respList = append(respList, t)
 	}
 	page := paging.GetPaging(params.CurrentIndex, params.PageSize, total)
-	dataResp := new(data_manage.BloombergSourceListResp)
 	dataResp.Paging = page
 	dataResp.List = respList
 
@@ -479,9 +524,27 @@ func (this *BloombergDataController) AddCheck() {
 	// 筛选项
 	req.Keywords = strings.TrimSpace(req.Keywords)
 	if req.Keywords != "" {
-		cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, data_manage.BaseFromBloombergIndexCols.IndexCode, data_manage.BaseFromBloombergIndexCols.IndexName)
-		kw := fmt.Sprint("%", req.Keywords, "%")
-		pars = append(pars, kw, kw)
+		// 空格分词搜
+		indexCodeCol := data_manage.BaseFromBloombergIndexCols.IndexCode
+		indexNameCol := data_manage.BaseFromBloombergIndexCols.IndexName
+		keywordArr := strings.Split(req.Keywords, " ")
+		if len(keywordArr) > 1 {
+			sliceArr := make([]string, 0)
+			sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+			pars = utils.GetLikeKeywordPars(pars, req.Keywords, 2)
+
+			for _, v := range keywordArr {
+				if v == ` ` || v == `` {
+					continue
+				}
+				sliceArr = append(sliceArr, fmt.Sprintf(` %s LIKE ? OR %s LIKE ? `, indexCodeCol, indexNameCol))
+				pars = utils.GetLikeKeywordPars(pars, v, 2)
+			}
+			cond += ` AND (` + strings.Join(sliceArr, " OR ") + `)`
+		} else {
+			cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ?)`, indexCodeCol, indexNameCol)
+			pars = utils.GetLikeKeywordPars(pars, req.Keywords, 2)
+		}
 	}
 	if req.Frequency != "" {
 		cond += fmt.Sprintf(` AND %s = ?`, data_manage.BaseFromBloombergIndexCols.Frequency)

+ 45 - 19
controllers/data_manage/business_data.go

@@ -8,6 +8,7 @@ import (
 	"eta/eta_api/models/data_manage/request"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
@@ -37,7 +38,7 @@ func (c *EdbBusinessController) SourceList() {
 
 	obj := data_manage.EdbBusinessSource{}
 	list, err := obj.GetAllList()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -90,26 +91,51 @@ func (c *EdbBusinessController) List() {
 	var condition string
 	var pars []interface{}
 
+	keywords = strings.TrimSpace(keywords)
 	if keywords != "" {
-		keywordSlice := strings.Split(keywords, " ")
-		if len(keywordSlice) > 0 {
-			tmpConditionSlice := make([]string, 0)
-			tmpConditionSlice = append(tmpConditionSlice, ` a.index_name like ? or a.index_code like ? `)
-			pars = utils.GetLikeKeywordPars(pars, keywords, 2)
-
-			for _, v := range keywordSlice {
-				if v == ` ` || v == `` {
-					continue
-				}
-				tmpConditionSlice = append(tmpConditionSlice, ` a.index_name like ? or a.index_code like ? `)
-				pars = utils.GetLikeKeywordPars(pars, v, 2)
+		//keywordSlice := strings.Split(keywords, " ")
+		//if len(keywordSlice) > 0 {
+		//	tmpConditionSlice := make([]string, 0)
+		//	tmpConditionSlice = append(tmpConditionSlice, ` a.index_name like ? or a.index_code like ? `)
+		//	pars = utils.GetLikeKeywordPars(pars, keywords, 2)
+		//
+		//	for _, v := range keywordSlice {
+		//		if v == ` ` || v == `` {
+		//			continue
+		//		}
+		//		tmpConditionSlice = append(tmpConditionSlice, ` a.index_name like ? or a.index_code like ? `)
+		//		pars = utils.GetLikeKeywordPars(pars, v, 2)
+		//	}
+		//	condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`
+		//
+		//} else {
+		//	condition += ` a.index_name like ? or a.index_code like ? `
+		//	pars = utils.GetLikeKeywordPars(pars, keywords, 2)
+		//}
+
+		// ES搜
+		_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keywords, utils.DATA_SOURCE_BUSINESS, 0, []int{}, []int{}, []string{}, startSize, req.PageSize)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("ES-搜索自有数据指标失败, %v", e)
+			return
+		}
+		if len(list) == 0 {
+			br.Data = data_manage.BusinessIndexListResp{
+				List:   make([]*data_manage.BaseFromBusinessIndexItem, 0),
+				Paging: paging.GetPaging(req.CurrentIndex, req.PageSize, 0),
 			}
-			condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`
-
-		} else {
-			condition += ` a.index_name like ? or a.index_code like ? `
-			pars = utils.GetLikeKeywordPars(pars, keywords, 2)
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			return
+		}
+		var indexIds []int
+		for _, v := range list {
+			indexIds = append(indexIds, v.PrimaryId)
 		}
+		condition += fmt.Sprintf(" AND a.base_from_business_index_id IN (%s)", utils.GetOrmInReplace(len(indexIds)))
+		pars = append(pars, indexIds)
 	}
 
 	if frequency != "" {
@@ -574,7 +600,7 @@ func (c *EdbBusinessController) DataList() {
 
 	// 获取分页数据
 	dataCount, dataList, err := data.GetPageBaseBusinessIndexData(req.IndexCode, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return

+ 912 - 21
controllers/data_manage/ccf_data.go

@@ -1,14 +1,19 @@
 package data_manage
 
 import (
+	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"github.com/tealeg/xlsx"
 	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -110,7 +115,8 @@ func (this *EdbInfoController) CCFIndexData() {
 		br.ErrMsg = "请选择分类"
 		return
 	}
-
+	// 增加频度请求入参
+	frequency := this.GetString("Frequency")
 	// 获取指标
 	var condition string
 	var pars []interface{}
@@ -118,7 +124,10 @@ func (this *EdbInfoController) CCFIndexData() {
 		condition += ` AND classify_id=? `
 		pars = append(pars, classifyId)
 	}
-
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
 	indexes, err := data_manage.GetCCFIndex(condition, pars)
 	if err != nil {
 		br.Msg = "获取数据失败"
@@ -130,7 +139,7 @@ func (this *EdbInfoController) CCFIndexData() {
 	for _, v := range indexes {
 		indexCodes = append(indexCodes, v.IndexCode)
 	}
-	indexCounts, e := data_manage.GetCCFIndexDataCountGroup(indexCodes)
+	/*indexCounts, e := data_manage.GetCCFIndexDataCountGroup(indexCodes)
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标数据总量失败, Err:" + err.Error()
@@ -139,7 +148,53 @@ func (this *EdbInfoController) CCFIndexData() {
 	countMap := make(map[string]int)
 	for _, v := range indexCounts {
 		countMap[v.IndexCode] = v.Count
+	}*/
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	dataMap := make(map[string][]*data_manage.BaseFromCCFData)
+	total := 0
+	if len(indexCodes) > 0 {
+		edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_CCF, indexCodes)
+		if err != nil {
+			br.Msg = "获取数据源失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbCode] = v
+		}
+		// 首先对分类下的指标按照日期进行分页,再针对日期,进行排序
+		dataTimes, err := data_manage.GetCCFIndexDataTimePageByCodes(indexCodes, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据日期信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataTimes) > 0 {
+			startDate := dataTimes[len(dataTimes)-1]
+			endDate := dataTimes[0]
+			// 把截止日往后加1天
+			endDateT, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+			endDate = endDateT.AddDate(0, 0, 1).Format(utils.FormatDate)
+			dataList, e := data_manage.GetCCFIndexDataByDataTime(indexCodes, startDate, endDate)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			//将数据按照指标进行分类
+			for _, v := range dataList {
+				dataMap[v.IndexCode] = append(dataMap[v.IndexCode], v)
+			}
+		}
+
+		total, err = data_manage.GetCCFIndexDataTimePageCount(indexCodes)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
 	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
 
 	resultList := make([]*data_manage.BaseFromCCFIndexList, 0)
 	for _, v := range indexes {
@@ -152,19 +207,24 @@ func (this *EdbInfoController) CCFIndexData() {
 		product.Frequency = v.Frequency
 		product.CreateTime = v.CreateTime
 		product.ModifyTime = v.ModifyTime
-
-		total := countMap[v.IndexCode]
+		if edb, ok := edbInfoMap[v.IndexCode]; ok {
+			product.EdbInfoId = edb.EdbInfoId
+			product.EdbExist = 1
+		}
+		/*total := countMap[v.IndexCode]
 		page := paging.GetPaging(currentIndex, pageSize, total)
 		dataList, e := data_manage.GetCCFIndexData(v.IndexCode, startSize, pageSize)
 		if e != nil {
 			br.Msg = "获取数据失败"
 			br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
 			return
+		}*/
+
+		dataListTmp, ok := dataMap[v.IndexCode]
+		if !ok {
+			dataListTmp = make([]*data_manage.BaseFromCCFData, 0)
 		}
-		if dataList == nil {
-			dataList = make([]*data_manage.BaseFromCCFData, 0)
-		}
-		product.DataList = dataList
+		product.DataList = dataListTmp
 		product.Paging = page
 		resultList = append(resultList, product)
 	}
@@ -267,9 +327,17 @@ func (this *EdbInfoController) CCFSingleData() {
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_CCF, indexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取指标库信息失败"
+		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
+		return
+	}
 	var ret data_manage.CCFSingleDataResp
 	var dataList []*data_manage.CCFSingleData
-
+	if edbInfo != nil {
+		ret.EdbInfoId = edbInfo.EdbInfoId
+	}
 	ret.ClassifyId = indexInfo.ClassifyId
 	ret.BaseFromCcfIndexId = indexInfo.BaseFromCcfIndexId
 	ret.IndexCode = indexInfo.IndexCode
@@ -350,27 +418,29 @@ func (this *EdbInfoController) ExportCCFList() {
 		br.Msg = "success"
 		return
 	}
-	sheetNew := new(xlsx.Sheet)
-	sheetNew, err = xlsxFile.AddSheet("CCF化纤")
+	//sheetNew := new(xlsx.Sheet)
+	//sheetNew, err = xlsxFile.AddSheet("CCF化纤")
 
 	//sheetNew.SetColWidth()
 	//获取指标数据
-	windRow := sheetNew.AddRow()
+	/*windRow := sheetNew.AddRow()
 	secNameRow := sheetNew.AddRow()
 	indexCodeRow := sheetNew.AddRow()
 	frequencyRow := sheetNew.AddRow()
 	unitRow := sheetNew.AddRow()
-	lastModifyDateRow := sheetNew.AddRow()
+	lastModifyDateRow := sheetNew.AddRow()*/
 	//获取分类下指标最大数据量
 	var dataMax int
-	setRowIndex := 6
-	indexCodeList := make([]string, 0)
+	//setRowIndex := 6
+	codeList := make([]string, 0)
+	frequenciesMap := make(map[string][]*data_manage.BaseFromCCFIndexList)
 	for _, v := range indexList {
-		indexCodeList = append(indexCodeList, v.IndexCode)
+		codeList = append(codeList, v.IndexCode)
+		frequenciesMap[v.Frequency] = append(frequenciesMap[v.Frequency], v)
 	}
 	dataListMap := make(map[string][]*data_manage.BaseFromCCFData)
 	if len(indexList) > 0 {
-		allDataList, e := data_manage.GetCCFIndexDataByCodes(indexCodeList)
+		allDataList, e := data_manage.GetCCFIndexDataByCodes(codeList)
 		if e != nil {
 			br.Msg = "获取数据失败"
 			br.ErrMsg = "获取数据失败,Err:" + e.Error()
@@ -385,8 +455,118 @@ func (this *EdbInfoController) ExportCCFList() {
 			}
 		}
 	}
+	// 按照频率分组排序
+	frequencies := []string{
+		"日度", "周度", "旬度", "月度", "季度", "半年度", "年度",
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		indexCodeList, ok := frequenciesMap[frequency]
+		if !ok {
+			continue
+		}
+		if len(indexCodeList) <= 0 {
+			fmt.Printf("sheet:%s, 不存在指标", frequency)
+			return
+		}
+		var sheetName string
+		switch frequency {
+		case "日度":
+			sheetName = "日度(Daily)"
+		case "周度":
+			sheetName = "周度(Weekly)"
+		case "旬度":
+			sheetName = "旬度(ten-day)"
+		case "月度":
+			sheetName = "月度(Monthly)"
+		case "季度":
+			sheetName = "季度(Quarterly)"
+		case "半年度":
+			sheetName = "半年度(Semi-annual)"
+		case "年度":
+			sheetName = "年度(Annual)"
+		default:
+			sheetName = "其他数据"
+		}
+		sheetNew, err := xlsxFile.AddSheet(sheetName)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, idx := range frequenciesMap[frequency] {
+			indexIdList = append(indexIdList, idx.BaseFromCcfIndexId)
+		}
+		dataTimeList, err := data_manage.GetCCFDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取数据时间失败,Err:" + err.Error()
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, icl := range indexCodeList {
+			// 获取数据
+			dataList, ok := dataListMap[icl.IndexCode]
+			if !ok {
+				continue
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称/Metric Name")
+				frequencyRow.AddCell().SetValue("频度/Frequency")
+				unitRow.AddCell().SetValue("单位/Unit")
+				lastModifyDateRow.AddCell().SetValue("更新时间/Update Time")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(icl.IndexName)
+			frequencyRow.AddCell().SetValue(icl.Frequency)
+			unitRow.AddCell().SetValue(icl.Unit)
 
-	for k, sv := range indexList {
+			timeDate, err := time.Parse(utils.FormatDateTime, dataList[0].ModifyTime)
+			if err != nil {
+				continue
+			}
+			lastModifyDateRow.AddCell().SetValue(timeDate.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromCCFData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+	/*for k, sv := range indexList {
 		//获取数据
 		dataList, ok := dataListMap[sv.IndexCode]
 		if !ok {
@@ -454,7 +634,7 @@ func (this *EdbInfoController) ExportCCFList() {
 				}
 			}
 		}
-	}
+	}*/
 
 	err = xlsxFile.Save(downFile)
 	if err != nil {
@@ -579,7 +759,7 @@ func (this *EdbInfoController) CCFStockTable() {
 	// 若无tableDate默认取最近的有数据的表格
 	item, e := excelOb.GetItemByCondition(cond, pars, fmt.Sprintf("%s DESC", excelOb.Cols().ExcelDate))
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "该日期暂无数据"
@@ -597,3 +777,714 @@ func (this *EdbInfoController) CCFStockTable() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
+
+// CCFIndexBatchSearch
+// @Title CCF化纤信息指标查询
+// @Description CCF化纤信息指标查询
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /ccf/batch_search [get]
+func (this *EdbInfoController) CCFIndexBatchSearch() {
+	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
+	}
+	classifyIdStr := this.GetString("ClassifyIds")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	resp := data_manage.BaseFromCCFIndexSearchList{}
+	total := 0
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	var list = make([]*data_manage.BaseFromCCFIndexList, 0)
+	var condition string
+	var pars []interface{}
+	classifyIds := strings.Split(classifyIdStr, ",")
+	if len(classifyIds) > 0 && classifyIds[0] != `` {
+		condition += " AND classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+		pars = append(pars, classifyIds)
+	}
+	keyword := this.GetString("Keyword")
+	if keyword != `` {
+		condition += " AND (index_name like ? OR index_code like ?) "
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+	frequencies := this.GetString("Frequencies")
+	if frequencies != "" {
+		frequencyList := strings.Split(frequencies, ",")
+		condition += " AND frequency IN (" + utils.GetOrmInReplace(len(frequencyList)) + " ) "
+		pars = append(pars, frequencyList)
+	}
+	condition += ` AND index_code not in (SELECT edb_code FROM edb_info WHERE source=?) `
+	pars = append(pars, utils.DATA_SOURCE_CCF)
+	list, err := data_manage.GetCCFIndexPage(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	// 获取最新值
+	endTimeList := make([]string, 0)
+	endValMap := make(map[int]string)
+	indexIds := make([]int, 0)
+	for _, v := range list {
+		endTimeList = append(endTimeList, v.EndDate)
+		indexIds = append(indexIds, v.BaseFromCcfIndexId)
+	}
+
+	if len(indexIds) > 0 {
+		dataTmpList, e := data_manage.GetCCFIndexDataByIndexIdAndDataTime(indexIds, endTimeList)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取指标最新值失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range dataTmpList {
+			endValMap[v.BaseFromCcfIndexId] = v.Value
+		}
+	}
+	for _, v := range list {
+		if val, ok := endValMap[v.BaseFromCcfIndexId]; ok {
+			v.EndValue = val
+		}
+	}
+	total, err = data_manage.GetCCFIndexPageCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// CCFIndexBatchAdd
+// @Title CCF化纤信息批量新增
+// @Description CCF化纤信息批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /ccf/batch_add [post]
+func (this *EdbInfoController) CCFIndexBatchAdd() {
+	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
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_CCF_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data_manage.CCFIndexSource2EdbReq
+		r.EdbCode = v.EdbCode
+		r.EdbName = v.EdbName
+		r.Frequency = v.Frequency
+		r.Unit = v.Unit
+		r.ClassifyId = v.ClassifyId
+		r.AdminId = sysUser.AdminId
+		r.AdminRealName = sysUser.RealName
+
+		edbInfo, e, errMsg, skip := data.CCFIndexSource2Edb(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// CCFIndexNameCheck
+// @Title 加入指标库的重名检测
+// @Description 加入指标库的重名检测
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} NameCheckResult
+// @router /ccf/edb_info/name_check [post]
+func (this *EdbInfoController) CCFIndexNameCheck() {
+	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 []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_CCF, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_CCF, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// CCFAddCheck
+// @Title 加入指标库指标Id检测
+// @Description 加入指标库指标Id检测
+// @Param	request	body request.BatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /ccf/edb_info/add_check [post]
+func (c *EdbInfoController) CCFAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req.IndexCodes)
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_CCF)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetCCFIndex(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromCCFIndexList, 0)
+	for _, v := range list {
+		if edb, ok := existMap[v.IndexCode]; ok {
+			v.EdbInfoId = edb.EdbInfoId
+			// todo 验证下面三个字段的用处
+			//v.EdbClassifyId = edb.ClassifyId
+			//v.EdbUniqueCode = edb.UniqueCode
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// CCFEdbInfoAdd
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /ccf/edb_info/add [post]
+func (this *EdbInfoController) CCFEdbInfoAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req data_manage.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	req.EdbCode = strings.Trim(req.EdbCode, " ")
+
+	if req.EdbCode == "" {
+		br.Msg = "指标ID不能为空"
+		return
+	}
+
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	count, err := data_manage.GetCCFIndexDataCount(req.EdbCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if count == 0 {
+		br.Msg = "指标不存在"
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_CCF, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 试用平台更新用户累计新增指标数
+	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+		return
+	}
+	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+		go func() {
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	//新增操作日志
+	{
+		edbLog := new(data_manage.EdbInfoLog)
+		edbLog.EdbInfoId = edbInfo.EdbInfoId
+		edbLog.SourceName = edbInfo.SourceName
+		edbLog.Source = edbInfo.Source
+		edbLog.EdbCode = edbInfo.EdbCode
+		edbLog.EdbName = edbInfo.EdbName
+		edbLog.ClassifyId = edbInfo.ClassifyId
+		edbLog.SysUserId = sysUser.AdminId
+		edbLog.SysUserRealName = sysUser.RealName
+		edbLog.CreateTime = time.Now()
+		edbLog.Content = string(this.Ctx.Input.RequestBody)
+		edbLog.Status = "新增指标"
+		edbLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddEdbInfoLog(edbLog)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// GetFrequency
+// @Title CCF化纤信息数据频度
+// @Description CCF化纤信息数据频度接口
+// @Param   ClassifyId   query   string  true       "分类Id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /ccf/frequency [get]
+func (this *EdbInfoController) GetCCFFrequency() {
+	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
+	}
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	frequencyList, err := data_manage.GetCCFFrequencyByClassifyId(classifyId)
+	if err != nil {
+		br.Msg = "获取频度失败"
+		br.ErrMsg = "获取频度失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+}
+
+// BatchAddEdbCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body data_manage.BatchManualEdbReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /ccf/batch/add/check [post]
+func (c *EdbInfoController) BatchAddEdbCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 最大批量添加的数量
+	codeMaxT := 31
+
+	var req data_manage.BatchCheckCCFEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,Err:" + err.Error()
+		return
+	}
+	req.Keyword = strings.TrimSpace(req.Keyword)
+	classifyIdStr := req.ClassifyIds
+
+	var list = make([]*data_manage.BaseFromCCFIndexList, 0)
+	var condition string
+	var pars []interface{}
+
+	if req.ListAll {
+		classifyIds := strings.Split(classifyIdStr, ",")
+		if len(classifyIds) > 0 && classifyIds[0] != `` {
+			condition += " AND classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+			pars = append(pars, classifyIds)
+		}
+		keyword := req.Keyword
+		if keyword != `` {
+			condition += " AND (index_name like ? OR index_code like ?) "
+			pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+		}
+		frequencies := req.Frequencies
+		if frequencies != "" {
+			frequencyList := strings.Split(frequencies, ",")
+			condition += " AND frequency IN (" + utils.GetOrmInReplace(len(frequencyList)) + " ) "
+			pars = append(pars, frequencyList)
+		}
+		codes := req.TradeCodeList
+		codeList := make([]string, 0)
+		if codes != "" {
+			codeList = strings.Split(codes, ",")
+		}
+		if len(codeList) > 0 {
+			condition += ` AND index_code not in (` + utils.GetOrmInReplace(len(codeList)) + `) `
+			pars = append(pars, codeList)
+		}
+	} else {
+		codes := req.TradeCodeList
+		codeList := make([]string, 0)
+		if codes != "" {
+			codeList = strings.Split(codes, ",")
+		}
+		if len(codeList) <= 0 {
+			br.Msg = "请选择指标"
+			br.ErrMsg = "请选择指标"
+			return
+		}
+		// 指标
+		condition += ` AND index_code in (` + utils.GetOrmInReplace(len(codeList)) + `) `
+		pars = append(pars, codeList)
+
+	}
+	condition += ` AND index_code not in (SELECT edb_code FROM edb_info WHERE source=?) `
+	pars = append(pars, utils.DATA_SOURCE_CCF)
+
+	list, err = data_manage.GetCCFIndexPage(condition, pars, 0, codeMaxT)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if len(list) >= codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	br.Data = list
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 458 - 176
controllers/data_manage/chart_classify.go

@@ -8,11 +8,18 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/data_manage_permission"
+	"eta/eta_api/services/eta_forum"
 	"eta/eta_api/utils"
 	"fmt"
 	"time"
 )
 
+const (
+	CHART_CLASSIFY_ADD_OR_EDIT = "chartLib:classifyOpt:add"
+	CHART_CLASSIFY_DELETE      = "chartLib:classifyOpt:delete"
+	CHART_CLASSIFY_MOVE        = "chartLib:classifyOpt:move"
+)
+
 // 数据管理-分类模块
 type ChartClassifyController struct {
 	controllers.BaseAuthController
@@ -76,7 +83,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -129,21 +136,21 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 	}
 
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_DEFAULT})
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -202,19 +209,19 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_DEFAULT}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -251,6 +258,7 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 // ChartClassifyItems
 // @Title 获取所有图表分类接口-不包含图表
 // @Description 获取所有图表分类接口-不包含图表
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
 // @Success 200 {object} data_manage.ChartClassifyListResp
 // @router /chart_classify/items [get]
 func (this *ChartClassifyController) ChartClassifyItems() {
@@ -259,6 +267,7 @@ func (this *ChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
+	isShowMe, _ := this.GetBool("IsShowMe")
 
 	level, _ := this.GetInt(`Level`)
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
@@ -290,6 +299,28 @@ func (this *ChartClassifyController) ChartClassifyItems() {
 		nodeAll = append(nodeAll, rootNode)
 	}
 
+	if isShowMe {
+		// 自己拥有的分类id列表
+		chartClassifyIdList, err := data_manage.GetChartClassifyIdListByAdminId(this.SysUser.AdminId, utils.CHART_SOURCE_DEFAULT)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		tmpNodeAll := nodeAll
+		nodeAll = make([]*data_manage.ChartClassifyItems, 0)
+		for _, node := range tmpNodeAll {
+			if node.Children == nil || len(node.Children) <= 0 {
+				continue
+			}
+			isSelf := data.RemoveNotChartClassifyItemsMakeTree(node, chartClassifyIdList)
+			if isSelf {
+				nodeAll = append(nodeAll, node)
+			}
+		}
+	}
+
 	language := `CN`
 	// 指标显示的语言
 	{
@@ -351,7 +382,7 @@ func (this *ChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_DEFAULT, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_DEFAULT, req.IsSelected, this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -396,18 +427,35 @@ func (this *ChartClassifyController) EditChartClassify() {
 	}
 
 	// 编辑图表分类
-	_, err, errMsg, isSendEmail := data.EditChartClassifyV2(req.ChartClassifyId, req.ParentId, utils.CHART_SOURCE_DEFAULT, req.ChartClassifyName, this.Lang)
+	classifyInfo, isDeleteForumChart, tipCode, err, errMsg, isSendEmail := data.EditChartClassifyV2(req.ChartClassifyId, req.ParentId, utils.CHART_SOURCE_DEFAULT, req.ChartClassifyName, req.IsSelected, this.Lang)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "保存分类失败,Err:" + err.Error()
 		br.IsSendEmail = isSendEmail
 		return
 	}
+	var ret data_manage.EditChartClassifyResp
+	if tipCode != "" {
+		br.Ret = 200
+		br.Msg = "该分类下存在已上架的图表,请先将图表从资源库下架,再关闭该精选资源分类。"
+		ret.TipCode = tipCode
+		ret.TipMsg = "该分类下存在已上架的图表,请先将图表从资源库下架,再关闭该精选资源分类。"
+		br.IsSendEmail = false
+		br.Success = true
+		br.Data = ret
+		return
+	}
+
+	// 移除精选后,删除所有的图表
+	if isDeleteForumChart {
+		go eta_forum.ChartInfoDeleteBatch(classifyInfo, this.SysUser)
+	}
 
 	br.Ret = 200
 	br.Msg = "保存成功"
 	br.Success = true
 	br.IsAddLog = true
+	br.Data = ret
 }
 
 // @Title 删除图表检测接口
@@ -479,7 +527,7 @@ func (this *ChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -493,6 +541,24 @@ func (this *ChartClassifyController) DeleteChartClassifyCheck() {
 		tipsMsg = "可删除,进行删除操作"
 	}
 
+	if req.ChartInfoId > 0 {
+		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "图表已删除,请刷新页面"
+				br.ErrMsg = "指标不存在,Err:" + err.Error()
+				return
+			}
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+			return
+		}
+		if chartInfo.ForumChartInfoId > 0 {
+			deleteStatus = 3
+			tipsMsg = "删除后,该图表将从ETA投研资源库同步删除,影响客户的查看权限,是否确认删除?"
+		}
+	}
+
 	resp := new(data_manage.ChartClassifyDeleteCheckResp)
 	resp.DeleteStatus = deleteStatus
 	resp.TipsMsg = tipsMsg
@@ -566,7 +632,7 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -584,13 +650,15 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 			br.ErrMsg = "删除失败,Err:" + err.Error()
 			return
 		}
+
+		go eta_forum.ChartClassifySaveBatch(item.Source)
 	}
 	resp := new(data_manage.AddChartInfoResp)
 	//删除图表
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -669,6 +737,10 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 			// 删除MY ETA 图表 es数据
 			//go data.EsDeleteMyChartInfoByChartInfoId(req.ChartInfoId)
 			go data.EsDeleteMyChartInfoByMyChartIds(myIds)
+			
+			if chartInfo.ForumChartInfoId > 0 {
+				go eta_forum.DeleteChartByForumChartInfoId(chartInfo.ForumChartInfoId)
+			}
 		}
 
 		var condition string
@@ -680,7 +752,7 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -700,14 +772,14 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -765,7 +837,6 @@ func (this *ChartClassifyController) ChartClassifyMove() {
 		br.Ret = 408
 		return
 	}
-
 	var req data_manage.MoveChartClassifyReq
 	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
 	if err != nil {
@@ -773,141 +844,197 @@ func (this *ChartClassifyController) ChartClassifyMove() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-
-	if req.ClassifyId <= 0 {
+	if req.ClassifyId <= 0 && req.ChartInfoId <= 0 {
 		br.Msg = "参数错误"
-		br.ErrMsg = "分类id小于等于0"
-		return
-	}
-	//判断分类是否存在
-	chartClassifyInfo, err := data_manage.GetChartClassifyById(req.ClassifyId)
-	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
-			br.Msg = "分类不存在,请刷新页面"
-			return
-		}
-		br.Msg = "移动失败"
-		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
-		return
-	}
-
-	// 校验移动的父级目录下是否有重名分类
-	exists, e := data_manage.GetChartClassifyByParentIdAndName(req.ParentClassifyId, chartClassifyInfo.ChartClassifyName, req.ClassifyId)
-	if e != nil && e.Error() != utils.ErrNoRow() {
-		br.Msg = "移动失败"
-		br.ErrMsg = "获取父级目录下的同名分类失败, Err: " + e.Error()
-		return
-	}
-	if exists != nil {
-		br.Msg = "移动失败,分类名称已存在"
+		br.ErrMsg = "请选择拖动目标,分类目录或者指标"
 		return
 	}
-	// 已授权分类id
-	permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, chartClassifyInfo.ChartClassifyId)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
-		return
-	}
-	// 权限校验
-	{
-		haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(chartClassifyInfo.IsJoinPermission, chartClassifyInfo.ChartClassifyId, permissionClassifyIdList)
 
-		button := data.GetChartClassifyOpButton(this.SysUser, chartClassifyInfo.SysUserId, haveOperaAuth)
-		if !button.OpButton {
-			br.Msg = "无操作权限"
+	err, errMsg := data.MoveChartClassify(req, sysUser, utils.CHART_SOURCE_DEFAULT)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
 			br.IsSendEmail = false
-			return
 		}
-	}
-
-	if chartClassifyInfo.Source != utils.CHART_SOURCE_DEFAULT {
-		br.Msg = "分类异常"
-		br.ErrMsg = "分类异常,不是ETA图库的分类"
 		return
 	}
-	updateCol := make([]string, 0)
-
-	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
-	if chartClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
-		parentChartClassifyInfo, err := data_manage.GetChartClassifyById(req.ParentClassifyId)
-		if err != nil {
-			br.Msg = "移动失败"
-			br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
-			return
-		}
-		chartClassifyInfo.ParentId = parentChartClassifyInfo.ChartClassifyId
-		chartClassifyInfo.Level = parentChartClassifyInfo.Level + 1
-		chartClassifyInfo.ModifyTime = time.Now()
-		updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
-	}
-
-	//如果有传入 上一个兄弟节点分类id
-	if req.PrevClassifyId > 0 {
-		//上一个兄弟节点
-		prevClassify, err := data_manage.GetChartClassifyById(req.PrevClassifyId)
-		if err != nil {
-			br.Msg = "移动失败"
-			br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
-			return
-		}
-
-		//如果是移动在两个兄弟节点之间
-		if req.NextClassifyId > 0 {
-			//下一个兄弟节点
-			nextClassify, err := data_manage.GetChartClassifyById(req.NextClassifyId)
-			if err != nil {
-				br.Msg = "移动失败"
-				br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
-				return
-			}
-			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
-			if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == chartClassifyInfo.Sort {
-				//变更兄弟节点的排序
-				updateSortStr := `sort + 2`
-				_ = data_manage.UpdateChartClassifySortByParentId(prevClassify.ParentId, prevClassify.ChartClassifyId, prevClassify.Sort, updateSortStr)
-			} else {
-				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
-				if nextClassify.Sort-prevClassify.Sort == 1 {
-					//变更兄弟节点的排序
-					updateSortStr := `sort + 1`
-					_ = data_manage.UpdateChartClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
-				}
-			}
-		}
-
-		chartClassifyInfo.Sort = prevClassify.Sort + 1
-		chartClassifyInfo.ModifyTime = time.Now()
-		updateCol = append(updateCol, "Sort", "ModifyTime")
-
-	} else {
-		firstClassify, err := data_manage.GetFirstChartClassifyByParentId(chartClassifyInfo.ParentId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
-			br.Msg = "移动失败"
-			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
-			return
-		}
-
-		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
-		if firstClassify != nil && firstClassify.Sort == 0 {
-			updateSortStr := ` sort + 1 `
-			_ = data_manage.UpdateChartClassifySortByParentId(firstClassify.ParentId, firstClassify.ChartClassifyId-1, 0, updateSortStr)
-		}
-
-		chartClassifyInfo.Sort = 0 //那就是排在第一位
-		chartClassifyInfo.ModifyTime = time.Now()
-		updateCol = append(updateCol, "Sort", "ModifyTime")
-	}
-
-	//更新
-	if len(updateCol) > 0 {
-		err = chartClassifyInfo.Update(updateCol)
-		if err != nil {
-			br.Msg = "移动失败"
-			br.ErrMsg = "修改失败,Err:" + err.Error()
-			return
-		}
-	}
+	// var req data_manage.MoveChartClassifyReq
+	// err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	// if err != nil {
+	// 	br.Msg = "参数解析异常!"
+	// 	br.ErrMsg = "参数解析失败,Err:" + err.Error()
+	// 	return
+	// }
+
+	// if req.ClassifyId <= 0 {
+	// 	br.Msg = "参数错误"
+	// 	br.ErrMsg = "分类id小于等于0"
+	// 	return
+	// }
+	// //判断分类是否存在
+	// chartClassifyInfo, err := data_manage.GetChartClassifyById(req.ClassifyId)
+	// if err != nil {
+	// 	if utils.IsErrNoRow(err) {
+	// 		br.Msg = "分类不存在,请刷新页面"
+	// 		return
+	// 	}
+	// 	br.Msg = "移动失败"
+	// 	br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+	// 	return
+	// }
+	// oldParentId := chartClassifyInfo.ParentId
+	// oldLevelPath := chartClassifyInfo.LevelPath
+	// oldSelected := chartClassifyInfo.IsSelected
+
+	// // 校验移动的父级目录下是否有重名分类
+	// exists, e := data_manage.GetChartClassifyByParentIdAndName(req.ParentClassifyId, chartClassifyInfo.ChartClassifyName, req.ClassifyId)
+	// if e != nil && !utils.IsErrNoRow(e) {
+	// 	br.Msg = "移动失败"
+	// 	br.ErrMsg = "获取父级目录下的同名分类失败, Err: " + e.Error()
+	// 	return
+	// }
+	// if exists != nil && exists.ChartClassifyId > 0 {
+	// 	br.Msg = "移动失败,分类名称已存在"
+	// 	return
+	// }
+	// // 已授权分类id
+	// permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, chartClassifyInfo.ChartClassifyId)
+	// if err != nil {
+	// 	br.Msg = "获取失败"
+	// 	br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+	// 	return
+	// }
+	// // 权限校验
+	// {
+	// 	haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(chartClassifyInfo.IsJoinPermission, chartClassifyInfo.ChartClassifyId, permissionClassifyIdList)
+
+	// 	button := data.GetChartClassifyOpButton(this.SysUser, chartClassifyInfo.SysUserId, haveOperaAuth)
+	// 	if !button.OpButton {
+	// 		br.Msg = "无操作权限"
+	// 		br.IsSendEmail = false
+	// 		return
+	// 	}
+	// }
+
+	// if chartClassifyInfo.Source != utils.CHART_SOURCE_DEFAULT {
+	// 	br.Msg = "分类异常"
+	// 	br.ErrMsg = "分类异常,不是ETA图库的分类"
+	// 	return
+	// }
+	// updateCol := make([]string, 0)
+
+	// var parentChartClassifyInfo *data_manage.ChartClassify
+	// if req.ParentClassifyId > 0 {
+	// 	parentChartClassifyInfo, err = data_manage.GetChartClassifyById(req.ParentClassifyId)
+	// 	if err != nil {
+	// 		br.Msg = "移动失败"
+	// 		br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
+	// 		return
+	// 	}
+	// }
+	// //判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
+	// if chartClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
+	// 	if chartClassifyInfo.Level != parentChartClassifyInfo.Level+1 { //禁止层级调整
+	// 		br.Msg = "移动失败"
+	// 		br.ErrMsg = "不支持目录层级变更"
+	// 		return
+	// 	}
+	// 	chartClassifyInfo.ParentId = parentChartClassifyInfo.ChartClassifyId
+	// 	chartClassifyInfo.Level = parentChartClassifyInfo.Level + 1
+	// 	chartClassifyInfo.ModifyTime = time.Now()
+	// 	updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
+	// }else if chartClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId == 0 {
+	// 	br.Msg = "移动失败"
+	// 	br.ErrMsg = "不支持目录层级变更"
+	// 	return
+	// }
+
+	// //如果有传入 上一个兄弟节点分类id
+	// if req.PrevClassifyId > 0 {
+	// 	//上一个兄弟节点
+	// 	prevClassify, err := data_manage.GetChartClassifyById(req.PrevClassifyId)
+	// 	if err != nil {
+	// 		br.Msg = "移动失败"
+	// 		br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+	// 		return
+	// 	}
+
+	// 	//如果是移动在两个兄弟节点之间
+	// 	if req.NextClassifyId > 0 {
+	// 		//下一个兄弟节点
+	// 		nextClassify, err := data_manage.GetChartClassifyById(req.NextClassifyId)
+	// 		if err != nil {
+	// 			br.Msg = "移动失败"
+	// 			br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+	// 			return
+	// 		}
+	// 		//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+	// 		if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == chartClassifyInfo.Sort {
+	// 			//变更兄弟节点的排序
+	// 			updateSortStr := `sort + 2`
+	// 			_ = data_manage.UpdateChartClassifySortByParentId(prevClassify.ParentId, prevClassify.ChartClassifyId, prevClassify.Sort, updateSortStr)
+	// 		} else {
+	// 			//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+	// 			if nextClassify.Sort-prevClassify.Sort == 1 {
+	// 				//变更兄弟节点的排序
+	// 				updateSortStr := `sort + 1`
+	// 				_ = data_manage.UpdateChartClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+	// 			}
+	// 		}
+	// 	}
+
+	// 	chartClassifyInfo.Sort = prevClassify.Sort + 1
+	// 	chartClassifyInfo.ModifyTime = time.Now()
+	// 	updateCol = append(updateCol, "Sort", "ModifyTime")
+
+	// } else {
+	// 	firstClassify, err := data_manage.GetFirstChartClassifyByParentId(chartClassifyInfo.ParentId)
+	// 	if err != nil && !utils.IsErrNoRow(err) {
+	// 		br.Msg = "移动失败"
+	// 		br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
+	// 		return
+	// 	}
+
+	// 	//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+	// 	if firstClassify != nil && firstClassify.Sort == 0 {
+	// 		updateSortStr := ` sort + 1 `
+	// 		_ = data_manage.UpdateChartClassifySortByParentId(firstClassify.ParentId, firstClassify.ChartClassifyId-1, 0, updateSortStr)
+	// 	}
+
+	// 	chartClassifyInfo.Sort = 0 //那就是排在第一位
+	// 	chartClassifyInfo.ModifyTime = time.Now()
+	// 	updateCol = append(updateCol, "Sort", "ModifyTime")
+	// }
+
+	// //更新
+	// if len(updateCol) > 0 {
+	// 	err = chartClassifyInfo.Update(updateCol)
+	// 	if err != nil {
+	// 		br.Msg = "移动失败"
+	// 		br.ErrMsg = "修改失败,Err:" + err.Error()
+	// 		return
+	// 	}
+	// }
+	// if oldParentId != req.ParentClassifyId {
+	// 	if err = data.UpdateChartClassifyLevelPathWithChildren(chartClassifyInfo, parentChartClassifyInfo, oldParentId, oldLevelPath); err != nil {
+	// 		br.Msg = "修改分类失败"
+	// 		br.ErrMsg = "更新分类level_path失败,Err:" + err.Error()
+	// 		return
+	// 	}
+	// }
+	// // 如果是精选目录,则需要同步到ETA资源库
+	// if chartClassifyInfo.Source == utils.CHART_SOURCE_DEFAULT {
+	// 	// 如果当前目录的精选标识发生变化,需要同步更新子目录的精选标识
+	// 	if err = data.UpdateChildClassifySelection(chartClassifyInfo, parentChartClassifyInfo, oldSelected); err != nil {
+	// 		br.Msg = "修改分类失败"
+	// 		br.ErrMsg = "更新子目录精选标识失败,Err:" + err.Error()
+	// 		return
+	// 	}
+	// 	go eta_forum.ChartClassifySaveBatch(chartClassifyInfo.Source)
+	// }
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "移动成功"
@@ -916,13 +1043,13 @@ func (this *ChartClassifyController) ChartClassifyMove() {
 // getChartClassifyListForMe 获取我创建的图表分类
 func getChartClassifyListForMeV2(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -981,7 +1108,7 @@ func (this *ChartClassifyController) ChartClassifyChartListV2() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -994,7 +1121,7 @@ func (this *ChartClassifyController) ChartClassifyChartListV2() {
 	isShowMe, _ := this.GetBool("IsShowMe")
 	if isShowMe {
 		allChartInfo, err := data_manage.GetChartInfoByAdminIdAndClassify([]int{utils.CHART_SOURCE_DEFAULT}, sysUser.AdminId, chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取全部数据失败,Err:" + err.Error()
 			return
@@ -1012,7 +1139,7 @@ func (this *ChartClassifyController) ChartClassifyChartListV2() {
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAllByClassifyId(utils.CHART_SOURCE_DEFAULT, chartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -1065,13 +1192,13 @@ func (this *ChartClassifyController) ChartClassifyChartListV3() {
 		br.Msg = "参数错误"
 		return
 	}
-
+	
 	// 获取当前账号的不可见指标
 	noPermissionChartIdMap := make(map[int]bool)
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1080,45 +1207,83 @@ func (this *ChartClassifyController) ChartClassifyChartListV3() {
 			noPermissionChartIdMap[v.ChartInfoId] = true
 		}
 	}
-
+	var allNodes []*data_manage.ChartClassifyItems
+	// 获取是否精选资源标识
+	isSelected, _ := this.GetInt("IsSelected")
+	if chartClassifyId > 0 {
+		chartClassifyInfo, err := data_manage.GetChartClassifyById(chartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}
+		isSelected = chartClassifyInfo.IsSelected
+	}
 	isShowMe, _ := this.GetBool("IsShowMe")
 	if isShowMe {
-		allChartInfo, err := data_manage.GetChartClassifyAndInfoByParentIdForMe(chartClassifyId, sysUser.AdminId)
+		allChartInfo, err := data_manage.GetChartClassifyAndInfoByParentIdForMe(chartClassifyId, sysUser.AdminId, isSelected)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		// 移除没有权限的图表
+		allNodes = data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
+		allNodes, err = data.GetChartClassifyByIsMe(sysUser.AdminId, chartClassifyId, utils.CHART_SOURCE_DEFAULT, allNodes)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		//resp.AllNodes = allNodes
+		//
+		//br.Ret = 200
+		//br.Success = true
+		//br.Msg = "获取成功"
+		//br.Data = resp
+		//fmt.Println("source my classify")
+		//return
+	} else {
+		allChartInfo, err := data_manage.GetChartClassifyAndInfoByParentId(chartClassifyId, isSelected)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
 		}
+		//allChartInfo, err := data_manage.GetChartInfoAllByClassifyId(utils.CHART_SOURCE_DEFAULT, chartClassifyId)
+		//if err != nil && err.Error() != utils.ErrNoRow() {
+		//	br.Msg = "获取失败"
+		//	br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		//	return
+		//}
 		// 移除没有权限的图表
-		allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
-		resp.AllNodes = allNodes
-
-		br.Ret = 200
-		br.Success = true
-		br.Msg = "获取成功"
-		br.Data = resp
-		fmt.Println("source my classify")
-		return
+		allNodes = data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
 	}
-
-	allChartInfo, err := data_manage.GetChartClassifyAndInfoByParentId(chartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	menulist, e := system.GetMenuButtonsByRoleId(this.SysUser.RoleId)
+	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		br.ErrMsg = "获取角色按钮权限失败, Err: " + e.Error()
 		return
 	}
-
-	//allChartInfo, err := data_manage.GetChartInfoAllByClassifyId(utils.CHART_SOURCE_DEFAULT, chartClassifyId)
-	//if err != nil && err.Error() != utils.ErrNoRow() {
-	//	br.Msg = "获取失败"
-	//	br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
-	//	return
-	//}
-	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
-
+	buttonList := make(map[string]int, 0)
+	for _, item := range menulist {
+		if item.MenuType == 1 {
+			buttonList[item.ButtonCode] = 1
+		}
+	}
+	var addOrEditRight, deleteRight, moveRight bool
+	if _, ok := buttonList[CHART_CLASSIFY_ADD_OR_EDIT]; ok {
+		addOrEditRight = true
+	}
+	if _, ok := buttonList[CHART_CLASSIFY_DELETE]; ok {
+		deleteRight = true
+	}
+	if _, ok := buttonList[CHART_CLASSIFY_MOVE]; ok {
+		moveRight = true
+	}
 	for k, item := range allNodes {
-		item.Button = data.GetChartOpButton(this.SysUser, item.SysUserId, item.HaveOperaAuth)
+		//item.Button = data.GetChartOpButton(this.SysUser, item.SysUserId, item.HaveOperaAuth)
+		item.Button = data.GetChartOpButtonV2(item.HaveOperaAuth, addOrEditRight, deleteRight, moveRight)
 		if item.ChartInfoId > 0 {
 			item.Button.AddButton = false
 			item.Button.OpButton = false
@@ -1136,4 +1301,121 @@ func (this *ChartClassifyController) ChartClassifyChartListV3() {
 	br.Success = true
 	br.Msg = "获取成功"
 	br.Data = resp
+}
+
+// SetChartClassifyResourceStatus
+// @Title 一键从资源库上架/下架
+// @Description 一键从资源库上架/下架
+// @Param   ChartClassifyId   query   bool  true       "图片分类id"
+// @Param   ResourceStatus   query   bool  true       "资源状态"
+// @Success 200 {object} models.BaseResponse
+// @router /chart_classify/resource_status [post]
+func (this *ChartClassifyController) SetChartClassifyResourceStatus() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req data_manage.SetChartClassifyResourceStatusReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	chartClassifyId := req.ChartClassifyId	
+	if chartClassifyId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	resourceStatus := req.ResourceStatus
+	if resourceStatus <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	chartClassifyInfo, err := data_manage.GetChartClassifyById(chartClassifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	if resourceStatus == utils.ChartClassifyResourceStatusDown {
+		errMsg, err := eta_forum.SetChartClassifyResourceStatusDown(chartClassifyInfo, this.SysUser)
+		if err != nil {
+			if errMsg != "" {
+				br.Msg = errMsg
+				br.ErrMsg = err.Error()
+				return
+			}
+			br.Msg = "操作失败"
+			br.ErrMsg = err.Error()
+			return
+		}
+	} else if resourceStatus == utils.ChartClassifyResourceStatusUp {
+		errMsg, err := eta_forum.SetChartClassifyResourceStatusUp(chartClassifyInfo, this.SysUser)
+		if err != nil {
+			if errMsg != "" {
+				br.Msg = errMsg
+				br.ErrMsg = err.Error()
+				return
+			}
+			br.Msg = "操作失败"
+			br.ErrMsg = err.Error()
+			return
+		}
+	}
+	
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+
+// 一键更新至资源库
+// @Title 一键更新至资源库
+// @Description 一键更新至资源库
+// @Param   ChartClassifyId   query   bool  true       "图片分类id"
+// @Success 200 {object} models.BaseResponse
+// @router /chart_classify/forum_chart/update [post]
+func (this *ChartClassifyController) UpdateChartClassifyResource() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req data_manage.ChartClassifyResourceUpdate
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	
+	chartClassifyInfo, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	if chartClassifyInfo.Source != utils.CHART_SOURCE_DEFAULT {
+		br.Msg = "分类来源错误"
+		return
+	}
+	if chartClassifyInfo.IsSelected != utils.ChartClassifyIsSelected {
+		br.Msg = "该分类不是精选分类"
+		return
+	}
+
+	err = eta_forum.ChartBatchUpdateAndUpload(chartClassifyInfo, this.SysUser)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+	
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
 }

+ 193 - 1
controllers/data_manage/chart_common.go

@@ -9,8 +9,10 @@ import (
 	"eta/eta_api/controllers/data_manage/line_feature"
 	"eta/eta_api/controllers/data_manage/range_analysis"
 	"eta/eta_api/models"
+	aiPredictModel "eta/eta_api/models/ai_predict_model"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
+	"eta/eta_api/services"
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/excel"
@@ -54,7 +56,7 @@ func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -289,6 +291,29 @@ func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
 		br.Success = true
 		br.Msg = "获取成功"
 		br.Data = resp
+	case utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY, utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY:
+		resp, isOk, msg, errMsg := GetAiPredictChartInfoDetailFromUniqueCode(chartInfo, isCache)
+		if !isOk {
+			if strings.Contains(errMsg, utils.ErrNoRow()) {
+				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
+				resp.EdbInfoList = endInfoList
+				resp.ChartInfo = chartInfo
+				resp.Status = false
+
+				br.Data = resp
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
+			}
+			br.Msg = msg
+			br.ErrMsg = errMsg
+			return
+		}
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
 	default:
 		br.Msg = "错误的图表"
 		br.ErrMsg = "错误的图表"
@@ -351,3 +376,170 @@ func getBalanceChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoVie
 
 	return
 }
+
+// GeneralChartToken
+// @Title 根据图表唯一code生成token
+// @Description 根据编码获取图表详情接口
+// @Param   UniqueCode   query   string  true       "图表/表格唯一编码"
+// @Param   Source   query   string  true       "来源,枚举值:chart、table"
+// @Success 200 {object} data_manage.ChartInfoDetailFromUniqueCodeResp
+// @router /chart_info/common/general_token [get]
+func (this *ChartInfoController) GeneralChartToken() {
+	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
+	}
+	uniqueCode := this.GetString("UniqueCode")
+	if uniqueCode == "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,uniqueCode is empty"
+		return
+	}
+	source := this.GetString("Source", "chart")
+
+	businessConf, err := models.GetBusinessConfByKey(models.BusinessConfIsOpenChartExpired)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取配置失败,Err:" + err.Error()
+		return
+	}
+
+	var token string
+	if businessConf.ConfVal == `true` {
+		// 缓存key
+		sourceType := source
+		if source == `table` {
+			sourceType = source
+		}
+		token, err = services.GeneralChartToken(sourceType, uniqueCode)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败"
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = token
+	return
+}
+
+// GetAiPredictChartInfoDetailFromUniqueCode 根据编码获取AI预测模型图表详情
+func GetAiPredictChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
+	var err error
+	msg = "获取成功"
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("UniqueCode获取图表详情失败, %v", err)
+			msg = "获取失败"
+			errMsg = fmt.Sprintf(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	if chartInfo == nil {
+		err = fmt.Errorf("图表信息不存在")
+		return
+	}
+	if chartInfo.Source != utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY && chartInfo.Source != utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY {
+		err = fmt.Errorf("图表来源有误, Source: %d", chartInfo.Source)
+		return
+	}
+	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
+
+	// 获取图表标的
+	edbMappings, e := data_manage.GetChartEdbMappingsByChartInfoId(chartInfo.ChartInfoId)
+	if e != nil {
+		err = fmt.Errorf("获取图表指标关联失败, %v", e)
+		return
+	}
+	if len(edbMappings) == 0 {
+		err = fmt.Errorf("图表指标关联不存在, %v", e)
+		return
+	}
+	indexId := edbMappings[0].EdbInfoId
+	if indexId <= 0 {
+		err = fmt.Errorf("图表标的有误")
+		return
+	}
+	indexOb := new(aiPredictModel.AiPredictModelIndex)
+	indexItem, e := indexOb.GetItemById(indexId)
+	if e != nil {
+		err = fmt.Errorf("获取图表标的失败, %v", e)
+		return
+	}
+	if indexItem != nil && indexItem.AiPredictModelIndexId <= 0 {
+		err = fmt.Errorf("图表标的不存在, IndexId: %d", indexId)
+		return
+	}
+
+	// 获取标的数据
+	indexData := make([]*aiPredictModel.AiPredictModelData, 0)
+	dataSource := aiPredictModel.ModelDataSourceDaily
+	if chartInfo.Source == utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY {
+		dataSource = aiPredictModel.ModelDataSourceMonthly
+	}
+	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 {
+		err = fmt.Errorf("获取标的数据失败, %v", e)
+		return
+	}
+	for _, v := range list {
+		if v.Source == dataSource {
+			indexData = append(indexData, v)
+			continue
+		}
+	}
+
+	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
+	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
+	if utils.Re == nil && isCache {
+		if utils.Re == nil && utils.Rc.IsExist(key) {
+			if chartData, e := utils.Rc.RedisBytes(key); e == nil {
+				e = json.Unmarshal(chartData, &resp)
+				if e != nil || resp == nil {
+					return
+				}
+				isOk = true
+				return
+			}
+		}
+	}
+
+	// 图表详情
+	chartDetail, e := services.GetAiPredictChartDetailByData(indexItem, indexData, dataSource)
+	if e != nil {
+		err = fmt.Errorf("获取图表详情失败, %v", e)
+		return
+	}
+	resp.ChartInfo = chartDetail.ChartInfo
+	resp.EdbInfoList = chartDetail.EdbInfoList
+	resp.XEdbIdValue = chartDetail.XEdbIdValue
+	resp.YDataList = chartDetail.YDataList
+	resp.XDataList = chartDetail.XDataList
+	resp.BarChartInfo = chartDetail.BarChartInfo
+	resp.CorrelationChartInfo = chartDetail.CorrelationChartInfo
+	resp.DataResp = chartDetail.DataResp
+	resp.Status = true
+
+	if utils.Re == nil {
+		jsonData, _ := json.Marshal(resp)
+		_ = utils.Rc.Put(key, jsonData, 10*time.Minute)
+	}
+	isOk = true
+	return
+}

+ 2 - 2
controllers/data_manage/chart_edb_config.go

@@ -148,7 +148,7 @@ func (this *EdbInfoController) ModifyNoPermissionAdmin() {
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
 		br.Msg = "修改失败"
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "找不到该指标"
 			br.IsSendEmail = false
 		}
@@ -208,7 +208,7 @@ func (this *EdbInfoController) DelNoPermissionAdmin() {
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
 		br.Msg = "删除失败"
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "找不到该指标"
 			br.IsSendEmail = false
 		}

+ 38 - 16
controllers/data_manage/chart_framework.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strings"
 	"time"
 )
@@ -43,6 +44,9 @@ func (this *ChartFrameworkController) List() {
 		return
 	}
 
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
 	adminId, _ := this.GetInt("AdminId")
 	visibility, _ := this.GetInt("Visibility")
 	if visibility == 1 && adminId <= 0 {
@@ -68,19 +72,37 @@ func (this *ChartFrameworkController) List() {
 		pars = append(pars, visibilityArr[visibility])
 	}
 
+	var total, startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	t, e := frameworkOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取框架列表总数失败, Err: " + e.Error()
+		return
+	}
+	total = t
 	orderRule := `sort ASC, create_time DESC`
-	list, e := frameworkOb.GetItemsByCondition(cond, pars, []string{}, orderRule)
+	list, e := frameworkOb.GetPageItemsByCondition(cond, pars, []string{}, orderRule, startSize, pageSize)
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取框架列表失败, Err: " + e.Error()
 		return
 	}
-	resp := make([]*data_manage.ChartFrameworkItem, 0)
+	resp := new(data_manage.ChartFrameworkListResp)
+	resp.List = make([]*data_manage.ChartFrameworkItem, 0)
 	for _, v := range list {
 		t := data_manage.FormatChartFramework2Item(v, make([]*data_manage.ChartFrameworkNodeItem, 0))
-		resp = append(resp, t)
+		resp.List = append(resp.List, t)
 	}
 
+	resp.Paging = paging.GetPaging(currentIndex, pageSize, total)
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true
@@ -205,12 +227,12 @@ func (this *ChartFrameworkController) Add() {
 		pars := make([]interface{}, 0)
 		pars = append(pars, req.FrameworkName, sysUser.AdminId)
 		exist, e := ob.GetItemByCondition(cond, pars)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "操作失败"
 			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
 			return
 		}
-		if exist != nil {
+		if exist != nil && exist.ChartFrameworkId > 0 {
 			br.Msg = "框架名称已存在"
 			return
 		}
@@ -315,7 +337,7 @@ func (this *ChartFrameworkController) Edit() {
 	frameworkOb := new(data_manage.ChartFramework)
 	item, e := frameworkOb.GetItemById(req.ChartFrameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "框架不存在, 请刷新页面"
 			return
 		}
@@ -331,12 +353,12 @@ func (this *ChartFrameworkController) Edit() {
 		pars := make([]interface{}, 0)
 		pars = append(pars, req.ChartFrameworkId, req.FrameworkName, sysUser.AdminId)
 		exist, e := ob.GetItemByCondition(cond, pars)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "操作失败"
 			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
 			return
 		}
-		if exist != nil {
+		if exist != nil && exist.ChartFrameworkId > 0 {
 			br.Msg = "框架名称已存在"
 			return
 		}
@@ -429,7 +451,7 @@ func (this *ChartFrameworkController) Remove() {
 	ob := new(data_manage.ChartFramework)
 	item, e := ob.GetItemById(req.ChartFrameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "操作成功"
@@ -499,7 +521,7 @@ func (this *ChartFrameworkController) Rename() {
 	frameworkOb := new(data_manage.ChartFramework)
 	item, e := frameworkOb.GetItemById(req.ChartFrameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "框架不存在, 请刷新页面"
 			return
 		}
@@ -515,12 +537,12 @@ func (this *ChartFrameworkController) Rename() {
 		pars := make([]interface{}, 0)
 		pars = append(pars, req.ChartFrameworkId, req.FrameworkName, sysUser.AdminId)
 		exist, e := ob.GetItemByCondition(cond, pars)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "操作失败"
 			br.ErrMsg = "获取重名框架失败, Err: " + e.Error()
 			return
 		}
-		if exist != nil {
+		if exist != nil && exist.ChartFrameworkId > 0 {
 			br.Msg = "框架名称已存在"
 			return
 		}
@@ -584,7 +606,7 @@ func (this *ChartFrameworkController) EditPublic() {
 	frameworkOb := new(data_manage.ChartFramework)
 	item, e := frameworkOb.GetItemById(req.ChartFrameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "框架不存在, 请刷新页面"
 			return
 		}
@@ -651,7 +673,7 @@ func (this *ChartFrameworkController) Move() {
 	frameworkOb := new(data_manage.ChartFramework)
 	item, e := frameworkOb.GetItemById(req.ChartFrameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "框架不存在, 请刷新页面"
 			return
 		}
@@ -698,7 +720,7 @@ func (this *ChartFrameworkController) Move() {
 		updateCols = append(updateCols, "Sort", "ModifyTime")
 	} else {
 		first, err := data_manage.GetFirstChartFramework(sysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "操作失败"
 			br.ErrMsg = "获取我的图库框架排首位的数据失败, Err:" + err.Error()
 			return
@@ -759,7 +781,7 @@ func (this *ChartFrameworkController) Detail() {
 	frameworkOb := new(data_manage.ChartFramework)
 	item, e := frameworkOb.GetItemById(frameworkId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "框架不存在, 请刷新页面"
 			return
 		}

+ 343 - 88
controllers/data_manage/chart_info.go

@@ -2,6 +2,7 @@ package data_manage
 
 import (
 	"encoding/json"
+	"errors"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
@@ -10,19 +11,21 @@ import (
 	"eta/eta_api/services"
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/area_graph"
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/data/excel"
 	"eta/eta_api/services/eta_forum"
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"os"
 	"os/exec"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // 图表管理
@@ -65,7 +68,7 @@ func (this *ChartInfoController) ChartInfoSave() {
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面!"
 			br.ErrMsg = "图表已被删除,请刷新页面,ChartInfoId:" + strconv.Itoa(req.ChartInfoId)
 			return
@@ -333,7 +336,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -356,7 +359,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表不存在!"
 				br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 				return
@@ -366,7 +369,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 				return
 			}
 		}
-		if edbInfo == nil {
+		if edbInfo == nil || edbInfo.EdbInfoId <= 0 {
 			br.Msg = "指标不存在!"
 			br.ErrMsg = "指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 			return
@@ -388,7 +391,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 
 			edbExist, err := data_manage.GetEdbInfoByCondition(edbCondition, edbPars)
 			if err != nil {
-				if err.Error() != utils.ErrNoRow() {
+				if !utils.IsErrNoRow(err) {
 					br.Msg = "判断英文指标名称是否存在失败"
 					br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + err.Error()
 					return
@@ -417,7 +420,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -446,7 +449,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表不存在!"
 				br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 				return
@@ -456,7 +459,7 @@ func (this *ChartInfoController) ChartEnInfoEdit() {
 				return
 			}
 		}
-		if edbInfo != nil {
+		if edbInfo != nil && edbInfo.EdbInfoId > 0 {
 			go data.AddOrEditEdbInfoToEs(edbInfoId)
 		}
 	}
@@ -525,7 +528,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -548,7 +551,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表不存在!"
 				br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 				return
@@ -583,7 +586,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 
 			edbExist, err := data_manage.GetEdbInfoByCondition(edbCondition, edbPars)
 			if err != nil {
-				if err.Error() != utils.ErrNoRow() {
+				if !utils.IsErrNoRow(err) {
 					br.Msg = "判断英文指标名称是否存在失败"
 					br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + err.Error()
 					return
@@ -615,7 +618,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -644,7 +647,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表不存在!"
 				br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 				return
@@ -654,7 +657,7 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 				return
 			}
 		}
-		if edbInfo != nil {
+		if edbInfo != nil && edbInfo.EdbInfoId > 0 {
 			go data.AddOrEditEdbInfoToEs(edbInfoId)
 		}
 	}
@@ -697,7 +700,7 @@ func (this *ChartInfoController) ChartInfoNewest() {
 		this.ServeJSON()
 	}()
 	item, err := data_manage.GetChartInfoByNewest(1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取最新图表失败"
 		br.ErrMsg = "获取最新图表失败,Err:" + err.Error()
 		return
@@ -780,17 +783,17 @@ func (this *ChartInfoController) ChartInfoMove() {
 			return
 		}
 	}
-
+	oldClassifyId := chartInfo.ChartClassifyId
 	//如果改变了分类,那么移动该图表数据
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
 		tmpChartInfo, tmpErr := data_manage.GetChartInfoByClassifyIdAndName(req.ChartClassifyId, chartInfo.ChartName)
-		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
 			return
 		}
-		if tmpChartInfo != nil {
+		if tmpChartInfo != nil && tmpChartInfo.ChartInfoId > 0 {
 			br.Msg = "移动失败,同一个分类下图表名称不允许重复"
 			br.ErrMsg = "移动失败,同一个分类下图表名称不允许重复"
 			return
@@ -844,14 +847,14 @@ func (this *ChartInfoController) ChartInfoMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
 		}
 
 		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
-		if firstClassify != nil && firstClassify.Sort == 0 {
+		if firstClassify != nil && firstClassify.ChartClassifyId > 0 && firstClassify.Sort == 0 {
 			updateSortStr := ` sort + 1 `
 			_ = data_manage.UpdateChartInfoSortByClassifyId(firstClassify.ChartClassifyId, 0, firstClassify.ChartInfoId-1, []int{chartInfo.Source}, updateSortStr)
 		}
@@ -871,6 +874,20 @@ func (this *ChartInfoController) ChartInfoMove() {
 		}
 		//添加es数据
 		go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
+
+		// 判断是否为精选目录
+			// 如果该目录不是精选目录,且该图表已经上架,则需撤回该图表
+			if oldClassifyId != req.ChartClassifyId {
+				parentChartClassifyInfo, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
+				if err != nil {
+					br.Msg = "移动失败"
+					br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
+					return
+				}
+				if parentChartClassifyInfo.IsSelected == 0 && chartInfo.ForumChartInfoId > 0 {
+					go eta_forum.DeleteChart(chartInfo.ChartInfoId)
+				}
+			}
 	}
 
 	if err != nil {
@@ -958,7 +975,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 	if chartInfoId > 0 {
 		chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "该图表已删除,自动查看下一图表"
 				br.ErrMsg = "该图表已删除,自动查看下一图表,Err:" + err.Error()
 				br.Ret = 406
@@ -1027,7 +1044,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 	extraConfigStr := chartInfo.ExtraConfig
 	// 柱方图的一些配置
 	var barConfig data_manage.BarChartInfoReq
-	if chartInfo != nil && chartInfo.ChartType == 7 {
+	if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == 7 {
 		if chartInfo.BarConfig == `` {
 			br.Msg = "柱方图未配置"
 			br.ErrMsg = "柱方图未配置"
@@ -1041,7 +1058,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 		}
 		extraConfigStr = chartInfo.BarConfig
 	}
-	yearMax := 0
+	var dateMax time.Time
 	if dateType == utils.DateTypeNYears {
 		for _, v := range mappingList {
 			if v.LatestDate != "" {
@@ -1051,14 +1068,18 @@ func (this *ChartInfoController) ChartInfoDetail() {
 					br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if lastDateT.After(dateMax) {
+					dateMax = lastDateT
 				}
 			}
 		}
 	}
+	if chartType == utils.CHART_TYPE_SEASON && dateType == utils.DateTypeNYears {
+		// 季度图,的至今N年,需要特殊处理,将日期范围扩大到下一年
+		dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+	}
 	// 开始/结束日期
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, dateMax)
 
 	if chartInfo.HaveOperaAuth {
 		// 获取图表中的指标数据
@@ -1123,7 +1144,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 		if len(warnEdbList) > 0 {
 			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
 		}
-		if chartInfoId > 0 && chartInfo != nil {
+		if chartInfoId > 0 && chartInfo != nil && chartInfo.ChartInfoId > 0 {
 			//判断是否加入我的图库
 			{
 				var myChartCondition string
@@ -1134,7 +1155,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1287,7 +1308,7 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
 		return
 	}
-	yearMax := 0
+	var dateMax time.Time
 	for k, v := range mappingList {
 		if tmpV, ok := edbInfoIdMapping[v.EdbInfoId]; ok {
 			v.EdbInfoType = tmpV.EdbInfoType
@@ -1311,8 +1332,8 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 					br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if lastDateT.After(dateMax) {
+					dateMax = lastDateT
 				}
 			}
 		}
@@ -1326,8 +1347,13 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 		mappingList[k] = v
 	}
 
+	if req.ChartType == utils.CHART_TYPE_SEASON && req.DateType == utils.DateTypeNYears {
+		// 季节性图表,要特殊处理起始日期, 最近N年
+		dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+	}
+
 	// 开始/结束日期
-	startDate, endDate := utils.GetDateByDateTypeV2(req.DateType, req.StartDate, req.EndDate, req.StartYear, yearMax)
+	startDate, endDate := utils.GetDateByDateTypeV2(req.DateType, req.StartDate, req.EndDate, req.StartYear, dateMax)
 	if startDate == "" {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败 时间格式错误"
@@ -1349,7 +1375,7 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 	extraConfigStr := chartInfo.ExtraConfig
 	// 柱方图的一些配置
 	var barConfig data_manage.BarChartInfoReq
-	if chartInfo != nil && chartInfo.ChartType == 7 {
+	if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == 7 {
 		if chartInfo.BarConfig == `` {
 			br.Msg = "柱方图未配置"
 			br.ErrMsg = "柱方图未配置"
@@ -1362,7 +1388,9 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 			return
 		}
 		extraConfigStr = chartInfo.BarConfig
-	} else if chartInfo != nil && chartInfo.ChartType == utils.CHART_TYPE_SECTION_COMBINE {
+	} else if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == utils.CHART_TYPE_SECTION_COMBINE {
+		extraConfigStr = req.ExtraConfig
+	} else if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == utils.CHART_TYPE_AREA {
 		extraConfigStr = req.ExtraConfig
 	}
 
@@ -1391,6 +1419,16 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
 	}
 
+	// 面积图 面积堆积 数据处理
+	if req.ChartType == utils.CHART_TYPE_AREA {
+		err, errMsg = fillAreaGraphData(extraConfigStr, edbList)
+		if err != nil {
+			br.Msg = "面积图处理失败"
+			br.ErrMsg = errMsg
+			return
+		}
+	}
+
 	//图表操作权限
 	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
@@ -1483,6 +1521,60 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 	br.Data = resp
 }
 
+func fillAreaGraphData(extraConfigStr string, edbDataList []*data_manage.ChartEdbInfoMapping) (err error, errMsg string) {
+
+	var tmpConfig data_manage.AreaExtraConf
+	if extraConfigStr != `` {
+		err = json.Unmarshal([]byte(extraConfigStr), &tmpConfig)
+		if err != nil {
+			errMsg = "面积图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		if tmpConfig.StandardEdbInfoId <= 0 {
+			utils.FileLog.Info("面积图未开启面积堆积")
+			return
+		}
+	}
+	if tmpConfig.IsHeap == 1 {
+		standardIndexMap := make(map[string]*data_manage.EdbDataList)
+		var startDate, endDate string
+		for _, v := range edbDataList {
+			// 判断是否为基准指标
+			if v.EdbInfoId == tmpConfig.StandardEdbInfoId {
+				if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
+					startDate = dataList[0].DataTime
+					endDate = dataList[len(dataList)-1].DataTime
+					for _, dataObject := range dataList {
+						standardIndexMap[dataObject.DataTime] = dataObject
+					}
+				}
+				break
+			}
+		}
+		strategy, err := area_graph.CreateStrategy(tmpConfig.NullDealWay)
+		if err != nil {
+			return err, "创建空值处理器失败"
+		}
+		err = strategy.Deal(tmpConfig, edbDataList, standardIndexMap, startDate, endDate)
+		if err != nil {
+			return err, err.Error()
+		}
+
+		// 时间戳处理
+		for _, mapping := range edbDataList {
+			if dataList, ok := mapping.DataList.([]*data_manage.EdbDataList); ok {
+				for _, dataInfo := range dataList {
+					toFormatTime := utils.StringToFormatTime(dataInfo.DataTime, utils.FormatDate)
+					dataInfo.DataTimestamp = toFormatTime.UnixMilli()
+				}
+			}
+		}
+	}
+
+	return nil, ""
+}
+
 // ChartInfoDetailV2
 // @Title 获取图表详情
 // @Description 获取图表详情接口
@@ -1511,7 +1603,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 	}
 	chartInfo, err := data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "该图表已删除,自动查看下一图表"
 			br.ErrMsg = "该图表已删除,自动查看下一图表,Err:" + err.Error()
 			br.Ret = 406
@@ -1523,6 +1615,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 	}
 
 	resp := new(data_manage.ChartInfoDetailResp)
+	isSelected := 0
 	// 图表数据权限
 	{
 		// 图表分类
@@ -1532,7 +1625,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 			br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
 			return
 		}
-
+		isSelected = chartClassify.IsSelected
 		// 已授权分类id
 		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
 		if err != nil {
@@ -1593,23 +1686,26 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 			dateType = 3
 		}
 	}
-	yearMax := 0
+	var dateMax time.Time
 	if dateType == utils.DateTypeNYears {
 		for _, v := range mappingList {
-			if v.LatestDate != "" {
+			if v.LatestDate != "" && v.LatestDate != "0000-00-00" {
 				lastDateT, tErr := time.Parse(utils.FormatDate, v.LatestDate)
 				if tErr != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if lastDateT.After(dateMax) {
+					dateMax = lastDateT
 				}
 			}
 		}
 	}
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+	if dateType == utils.DateTypeNYears && chartInfo.ChartType == utils.CHART_TYPE_SEASON {
+		dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+	}
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, dateMax)
 
 	if chartInfo.ChartType == 2 {
 		chartInfo.StartDate = startDate
@@ -1619,7 +1715,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 	extraConfigStr := chartInfo.ExtraConfig
 	// 柱方图的一些配置
 	var barConfig data_manage.BarChartInfoReq
-	if chartInfo != nil && chartInfo.ChartType == 7 {
+	if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == 7 {
 		if chartInfo.BarConfig == `` {
 			br.Msg = "柱方图未配置"
 			br.ErrMsg = "柱方图未配置"
@@ -1659,7 +1755,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 		if len(warnEdbList) > 0 {
 			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
 		}
-		if chartInfoId > 0 && chartInfo != nil {
+		if chartInfoId > 0 && chartInfo != nil && chartInfo.ChartInfoId > 0 {
 			//判断是否加入我的图库
 			{
 				var myChartCondition string
@@ -1670,7 +1766,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1737,6 +1833,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 	}
 
 	// 图表当前分类的分类树
+	
 	classifyLevels := make([]string, 0)
 	{
 		list, e := data_manage.GetChartClassifyAllBySource(utils.CHART_SOURCE_DEFAULT)
@@ -1755,7 +1852,8 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 	}
 
 	resp.ClassifyLevels = classifyLevels
-	
+	resp.IsSelected = isSelected
+
 	//图表操作权限
 	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, chartInfo.HaveOperaAuth)
 	chartInfo.Button = data_manage.ChartViewButton{
@@ -1891,13 +1989,13 @@ func (this *ChartInfoController) ChartInfoEdbInfoDetail() {
 		br.Msg = "获取失败,Err:" + err.Error()
 		return
 	}
-	maxYear := 0
+	var maxDate time.Time
 	if edbInfo.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 	if startDate == "" {
 		br.Msg = "参数错误"
 		br.Msg = "参数错误,无效的查询日期"
@@ -2103,7 +2201,7 @@ func (this *ChartInfoController) ChartInfoSearch() {
 	for _, v := range keyWordArr {
 		v = strings.Replace(v, " ", "%", -1)
 		newSearchList, err := data_manage.ChartInfoSearchByKeyWord(v, showSysId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -2214,7 +2312,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 		showSysId = sysUser.AdminId
 	}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -2223,7 +2321,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -2240,7 +2338,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 		isEs = true
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -2277,7 +2375,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 		}
 		// 当前列表中的分类map
 		chartClassifyMap := make(map[int]*data_manage.ChartClassify)
-
+		isSelectClassifyMap := make(map[int]bool)
 		// 图表分类
 		{
 			chartClassifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
@@ -2288,6 +2386,9 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 			}
 			for _, v := range chartClassifyList {
 				chartClassifyMap[v.ChartClassifyId] = v
+				if v.IsSelected == 1 {
+					isSelectClassifyMap[v.ChartClassifyId] = true
+				}
 			}
 		}
 		// 图表
@@ -2323,7 +2424,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
@@ -2333,7 +2434,13 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 			if currClassify, ok := chartClassifyMap[v.ChartClassifyId]; ok {
 				tmp.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.ChartInfoId, v.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
 			}
-
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
+			if _, ok := isSelectClassifyMap[v.ChartClassifyId]; ok {
+				tmp.IsSelected = 1
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -2391,7 +2498,7 @@ func (this *EdbInfoController) ChartInfoRefresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -2510,7 +2617,7 @@ func (this *ChartInfoController) ChartInfoDetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -2580,7 +2687,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -2733,7 +2840,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		return
 	}
 
-	yearMax := 0
+	var dateMax time.Time
 	if dateType == utils.DateTypeNYears {
 		for _, v := range mappingList {
 			if v.LatestDate != "" {
@@ -2743,18 +2850,22 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 					errMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if lastDateT.After(dateMax) {
+					dateMax = lastDateT
 				}
 			}
 		}
 	}
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+	if chartInfo.ChartType == utils.CHART_TYPE_SEASON && dateType == utils.DateTypeNYears {
+		// 季度图,的至今N年,需要特殊处理,将日期范围扩大到下一年
+		dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+	}
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, dateMax)
 
 	extraConfigStr := chartInfo.ExtraConfig //图表额外数据参数
 	var barConfig data_manage.BarChartInfoReq
 	// 柱方图的一些配置
-	if chartInfo != nil && chartInfo.ChartType == 7 {
+	if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == 7 {
 		if chartInfo.BarConfig == `` {
 			msg = "柱方图未配置"
 			errMsg = "柱方图未配置"
@@ -2800,11 +2911,22 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	*/
 
 	chartViewClassify, _ := data_manage.GetChartClassifyViewById(chartInfo.ChartClassifyId)
-	if chartViewClassify != nil {
+	if chartViewClassify != nil && chartViewClassify.ChartClassifyId > 0 {
 		chartClassifyParent, _ := data_manage.GetChartClassifyViewById(chartClassify.ParentId)
 		chartInfo.ChartClassify = append(chartInfo.ChartClassify, chartClassifyParent)
 	}
 	chartInfo.ChartClassify = append(chartInfo.ChartClassify, chartViewClassify)
+
+	// 面积图 面积堆积 数据处理
+	if chartType == utils.CHART_TYPE_AREA {
+		err, errMsg = fillAreaGraphData(extraConfigStr, edbList)
+		if err != nil {
+			msg = "获取失败"
+			errMsg = "获取面积图数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
 	resp.EdbInfoList = edbList
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
@@ -3089,7 +3211,7 @@ func (this *ChartInfoController) CopyChartInfo() {
 	}
 	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -3197,7 +3319,10 @@ func (this *ChartInfoController) CopyChartInfo() {
 	{
 		mapList := make([]*data_manage.ChartEdbMapping, 0)
 		for _, v := range edbMappingList {
+			// windows server环境这里得加个延时,不然生成时间戳都是一样的
+			time.Sleep(100 * time.Millisecond)
 			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			//utils.FileLog.Info("IndexCode: %s, UniqueCode: %s", v.EdbInfoId, utils.MD5(utils.CHART_PREFIX+"_"+timestamp))
 			mapItem := &data_manage.ChartEdbMapping{
 				//ChartEdbMappingId: 0,
 				ChartInfoId:   chartInfo.ChartInfoId,
@@ -3215,7 +3340,7 @@ func (this *ChartInfoController) CopyChartInfo() {
 				ChartStyle:    v.ChartStyle,
 				ChartColor:    v.ChartColor,
 				ChartWidth:    v.ChartWidth,
-				Source:        v.Source,
+				Source:        oldChartInfo.Source,
 				EdbAliasName:  v.EdbAliasName,
 				IsConvert:     v.IsConvert,
 				ConvertType:   v.ConvertType,
@@ -3752,10 +3877,6 @@ func (this *EdbInfoController) GetBatchChartRefreshResult() {
 //	fmt.Println("end")
 //}
 
-//func init() {
-//	data.AddAllChartInfo()
-//}
-
 // 截面散点示例数据
 //func init() {
 //
@@ -4061,7 +4182,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 	if chartInfoId > 0 {
 		chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "该图表已删除,自动查看下一图表"
 				br.ErrMsg = "该图表已删除,自动查看下一图表,Err:" + err.Error()
 				br.Ret = 406
@@ -4149,7 +4270,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 		extraConfigStr := chartInfo.ExtraConfig
 		// 柱方图的一些配置
 		var barConfig data_manage.BarChartInfoReq
-		if chartInfo != nil && chartInfo.ChartType == 7 {
+		if chartInfo != nil && chartInfo.ChartInfoId > 0 && chartInfo.ChartType == 7 {
 			if chartInfo.BarConfig == `` {
 				br.Msg = "柱方图未配置"
 				br.ErrMsg = "柱方图未配置"
@@ -4163,7 +4284,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 			}
 			extraConfigStr = chartInfo.BarConfig
 		}
-		yearMax := 0
+		var dateMax time.Time
 		if dateType == utils.DateTypeNYears {
 			for _, v := range mappingList {
 				if v.LatestDate != "" {
@@ -4173,14 +4294,18 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 						br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 						return
 					}
-					if lastDateT.Year() > yearMax {
-						yearMax = lastDateT.Year()
+					if lastDateT.After(dateMax) {
+						dateMax = lastDateT
 					}
 				}
 			}
 		}
+		if chartType == utils.CHART_TYPE_SEASON && dateType == utils.DateTypeNYears {
+			// 季节性图,最近N年需要特殊处理
+			dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+		}
 		// 开始/结束日期
-		startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+		startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, dateMax)
 
 		// 获取图表中的指标数据
 		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartConvertEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig, isAxis)
@@ -4206,7 +4331,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 		if len(warnEdbList) > 0 {
 			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
 		}
-		if chartInfoId > 0 && chartInfo != nil {
+		if chartInfoId > 0 && chartInfo != nil && chartInfo.ChartInfoId > 0 {
 			//判断是否加入我的图库
 			{
 				var myChartCondition string
@@ -4217,7 +4342,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -4347,6 +4472,9 @@ func (this *ChartInfoController) UpdateToForum() {
 		return
 	}
 
+	// 更新指标数据
+	utils.Rc.LPush(utils.CACHE_KEY_EDB_DATA_UPDATE_LOG, []byte("1"))
+	
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "保存成功"
@@ -4619,7 +4747,7 @@ func (this *ChartInfoController) ChartList() {
 	if len(chartClassifyIdsStr) > 0 {
 		if !subClassify {
 			chartClassifyId, err := data_manage.GetChartClassifyByIdsNoSubClassify(chartClassifyIds)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取图表信息失败"
 				br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 				return
@@ -4656,7 +4784,12 @@ func (this *ChartInfoController) ChartList() {
 		}
 	}
 	if keyWord != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyWord + `%' OR chart_name_en LIKE '%` + keyWord + `%' )`
+		keyWordArr := strings.Split(keyWord, " ")
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(chart_name,chart_name_en) LIKE '%` + v + `%'`
+			}
+		}
 	}
 	if sysUserIds != "" {
 		adminIds := strings.Split(sysUserIds, ",")
@@ -4694,7 +4827,7 @@ func (this *ChartInfoController) ChartList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -4712,7 +4845,7 @@ func (this *ChartInfoController) ChartList() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -4720,7 +4853,7 @@ func (this *ChartInfoController) ChartList() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -4812,7 +4945,7 @@ func (this *ChartInfoController) ChartList() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -4823,7 +4956,7 @@ func (this *ChartInfoController) ChartList() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -4891,7 +5024,7 @@ func (this *ChartInfoController) ModifyChartList() {
 		if len(chartClassifyIds) > 0 {
 			if !req.SubClassify {
 				chartClassifyId, err := data_manage.GetChartClassifyByIdsNoSubClassify(chartClassifyIds)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "获取图表信息失败"
 					br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 					return
@@ -5008,8 +5141,130 @@ func (this *ChartInfoController) ModifyChartList() {
 		br.ErrMsg = "更新图表分类失败,Err:" + err.Error()
 		return
 	}
+	
+	go eta_forum.ChartInfoDeleteBatchByChartInfoIds(chartIds, req.ChartClassifyId)
 
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
-}
+}
+
+// 查询图表简介列表
+// @Title 查询图表简介列表
+// @Description 查询图表简介列表
+// @Param   ChartInfoId   query   int  true       "图表id"
+// @Success 200 {object} models.ChartDescriptionListResponse
+// @router /chart_info/description/list [get]
+func (this *ChartInfoController) GetChartDescriptionList() {
+	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
+	}
+
+	chartInfoId, _ := this.GetInt("ChartInfoId")
+	if chartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+
+	chartDescriptionList, err := data_manage.GetChartDescriptionByChartInfoId(chartInfoId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表简介失败,Err:" + err.Error()
+		return
+	}
+	list := make([]*data_manage.ChartDescriptionList, 0)
+	response := new(data_manage.ChartDescriptionListResponse)
+	for _, v := range chartDescriptionList {
+		list = append(list, &data_manage.ChartDescriptionList{
+			Id:               v.Id,
+			Description:      v.Description,
+			ChartInfoId:      v.ChartInfoId,
+			SysUserId:        v.SysUserId,
+			SysUserRealName:  v.SysUserRealName,
+			CreateTime:       v.CreateTime.Format(utils.FormatDateTime),
+		})
+	}
+	response.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = response
+}
+
+// 添加图表简介
+// @Title 添加图表简介
+// @Description 添加图表简介
+// @Param   ChartInfoId   query   int  true       "图表id"
+// @Success 200 {object} models.ChartDescriptionListResponse
+// @router /chart_info/description/add [post]
+func (this *ChartInfoController) AddChartDescription() {
+	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
+	}	
+
+	var req data_manage.ChartDescriptionAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+	if req.Description == "" {
+		br.Msg = "请输入简介"
+		return
+	}
+	// 判断图表是否存在
+	_, err = data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if !utils.IsErrNoRow(err) {
+			br.Msg = "图表不存在"
+			return
+		}
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+	item := &data_manage.ChartDescription{
+		ChartInfoId: req.ChartInfoId,
+		Description: req.Description,
+		SysUserId: sysUser.AdminId,
+		SysUserRealName: sysUser.RealName,
+		ModifyTime: time.Now(),
+		CreateTime: time.Now(),
+	}
+	err = data_manage.AddChartDescription(item)
+	if err != nil {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加图表简介失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "添加成功"
+}
+

+ 14 - 8
controllers/data_manage/chart_theme.go

@@ -207,6 +207,9 @@ func (c *ChartThemeController) GetThemePreviewData() {
 		chartInfo.LeftMax = "4000"
 		extraConfigStr = `{"DateConfList":[],"IsHeap":0,"XDataList":[{"Name":"内销"},{"Name":"出口"},{"Name":"销量"},{"Name":"产量"}],"UnitList":{"LeftName":"万台","RightName":"%","RightTwoName":""},"BaseChartSeriesName":"增量","SortType":0,"SeriesList":[{"ChartSeriesId":0,"SeriesName":"增量","ChartStyle":"column","ChartColor":"rgba(0, 0, 255, 1)","ChartWidth":1,"IsPoint":0,"IsNumber":0,"IsAxis":1,"EdbInfoList":[{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":19,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":20,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":21,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":22,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}}]},{"ChartSeriesId":0,"SeriesName":"增速","ChartStyle":"spline","ChartColor":"rgba(255, 0, 200, 1)","ChartWidth":1,"IsPoint":0,"IsNumber":0,"IsAxis":0,"EdbInfoList":[{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":23,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":24,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":25,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}},{"ChartSeriesEdbMappingId":0,"ChartSeriesId":0,"EdbInfoId":26,"DateConfName":"","DateConfType":0,"DateConf":{"MoveForward":0,"DateChange":[]}}]}]}`
 		chartInfo.ChartName = "图表标题"
+	case utils.CHART_TYPE_AREA: // 曲线图
+		edbInfoIdList = []int{25, 26}
+		chartInfo.ChartName = "面积图"
 	default:
 		br.Msg = "暂不支持该类型"
 		br.IsSendEmail = false
@@ -231,7 +234,7 @@ func (c *ChartThemeController) GetThemePreviewData() {
 	chartInfo.Source = chartThemeType.ChartSource
 	chartInfo.ChartType = chartThemeType.ChartType
 
-	yearMax := 0
+	var dateMax time.Time
 	if dateType == utils.DateTypeNYears {
 		for _, v := range mappingList {
 			if v.LatestDate != "" {
@@ -241,14 +244,17 @@ func (c *ChartThemeController) GetThemePreviewData() {
 					br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if lastDateT.After(dateMax) {
+					dateMax = lastDateT
 				}
 			}
 		}
 	}
+	if chartType == utils.CHART_TYPE_SEASON && dateType == utils.DateTypeNYears {
+		dateMax = time.Date(dateMax.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+	}
 	// 开始/结束日期
-	startDate, endDate := utils.GetDateByDateTypeV2(dateType, tmpStartDate, tmpEndDate, startYear, yearMax)
+	startDate, endDate := utils.GetDateByDateTypeV2(dateType, tmpStartDate, tmpEndDate, startYear, dateMax)
 
 	// 获取图表中的指标数据
 	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetThemePreviewChartEdbData(chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
@@ -398,7 +404,7 @@ func (c *ChartThemeController) Edit() {
 	// 获取配置
 	chartTheme, err := chart_theme.GetChartThemeId(req.ChartThemeId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "主题不存在或已删除"
 			br.ErrMsg = "主题不存在或已删除"
 			br.IsSendEmail = false
@@ -468,7 +474,7 @@ func (c *ChartThemeController) Delete() {
 	// 获取配置
 	chartTheme, err := chart_theme.GetChartThemeId(req.ChartThemeId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "主题不存在或已删除"
 			br.ErrMsg = "主题不存在或已删除"
 			br.IsSendEmail = false
@@ -556,7 +562,7 @@ func (c *ChartThemeController) SetDefaultTheme() {
 	// 获取图表配置
 	chartTheme, err := chart_theme.GetChartThemeId(req.ChartThemeId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "主题不存在或已删除"
 			br.ErrMsg = "主题不存在或已删除"
 			br.IsSendEmail = false
@@ -570,7 +576,7 @@ func (c *ChartThemeController) SetDefaultTheme() {
 	// 获取图表类型
 	chartThemeType, err := chart_theme.GetChartThemeTypeById(req.ChartThemeTypeId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "获取图表类型不存在或已删除"
 			br.ErrMsg = "获取图表类型不存在或已删除"
 			br.IsSendEmail = false

+ 1653 - 0
controllers/data_manage/clarksons_data.go

@@ -0,0 +1,1653 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/request"
+	"eta/eta_api/models/data_manage/response"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/tealeg/xlsx"
+)
+
+type ClarksonsDataController struct {
+	controllers.BaseAuthController
+}
+
+// @Title 克拉克森数据分类
+// @Description 克拉克森数据分类接口
+// @Success 200 {object} data_manage.SciClassify
+// @router /clarksons/classify [get]
+func (this *ClarksonsDataController) Classify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	classifyList, err := data_manage.GetClarksonsClassifyAll()
+	if err != nil {
+		br.Msg = "查询失败"
+		br.ErrMsg = "查询失败, Err:" + err.Error()
+		return
+	}
+
+	initClassify := &data_manage.BaseFromClarksonsClassifyItem{
+		BaseFromClassifyId: 0,
+		ClassifyName:       "未分类",
+		ClassifyNameEn:     "Unclassified",
+		UniqueCode:         "0",
+		ParentId:           0,
+		Level:              1,
+		Sort:               0,
+		Children:           nil,
+	}
+	finalList := make([]*data_manage.BaseFromClarksonsClassifyItem, 0)
+	classifyTree := getClarksonsClassifyTree(classifyList, 0)
+	finalList = append(finalList, initClassify)
+	finalList = append(finalList, classifyTree...)
+
+	br.Msg = "查询成功"
+	br.Data = finalList
+	br.Success = true
+	br.Ret = 200
+}
+
+// AddSciClassify
+// @Title 新增分类
+// @Description 新增分类接口
+// @Param	request	body data_manage.AddBaseFromSciClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /clarksons/classify/add [post]
+func (this *ClarksonsDataController) AddClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.AddBaseFromClarksonsClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "操作异常"
+		return
+	}
+	ok, msg, err := data.AddClarksonsClassify(req.ClassifyName, req.ParentId)
+	if err != nil {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		return
+	}
+	if !ok {
+		if msg != "" {
+			br.Msg = msg
+			return
+		}
+		br.Msg = "添加失败"
+		return
+	}
+	br.Msg = "添加成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// DelClassify
+// @Title 新增分类
+// @Description 新增分类接口
+// @Param	request	body data_manage.AddBaseFromSciClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /clarksons/classify/del [post]
+func (this *ClarksonsDataController) DelClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.DelBaseFromClarksonsClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.BaseFromClassifyId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	err = data.DelClarksonsClassify(req.BaseFromClassifyId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// EditClassify
+// @Title 修改分类
+// @Description 修改分类接口
+// @Param	request	body data_manage.EditBaseFromMysteelChemicalClassifyReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /clarksons/classify/edit [post]
+func (this *ClarksonsDataController) EditClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.EditBaseFromClarksonsClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BaseFromClassifyId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		return
+	}
+	classify, err := data_manage.GetClarksonsClassifyById(req.BaseFromClassifyId)
+	if err != nil {
+		if utils.IsErrNoRow(err) {
+			br.Msg = "分类不存在"
+			return
+		}
+		br.Msg = "编辑失败"
+		br.ErrMsg = "获取分类失败,Err:" + err.Error()
+		return
+	}
+
+	if classify.ClassifyName != req.ClassifyName {
+		count, err := data_manage.GetClarksonsClassifyCountByName(req.ClassifyName)
+		if err != nil {
+			br.Msg = "编辑失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在"
+			return
+		}
+		classify.ClassifyName = req.ClassifyName
+		classify.ModifyTime = time.Now()
+		err = classify.Update([]string{"classify_name", "modify_time"})
+		if err != nil {
+			br.Msg = "编辑失败"
+			br.ErrMsg = "编辑失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	br.Msg = "编辑成功"
+	br.Success = true
+	br.Ret = 200
+	br.IsAddLog = true
+}
+
+// MoveClassify
+// @Title 分类移动接口
+// @Description 分类移动接口
+// @Success 200 {object} data_manage.MoveBaseFromMysteelChemicalClassifyReq
+// @router /clarksons/classify/move [post]
+func (this *ClarksonsDataController) MoveClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req request.MoveBaseFromClarksonsClassifyReq
+	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BaseFromClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "分类id小于等于0"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data.MoveClarksonsClassify(req.BaseFromClassifyId, req.ParentClassifyId, req.PrevClassifyId, req.NextClassifyId)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "移动成功"
+}
+
+// IndexList
+// @Title 克拉克森指标列表
+// @Description 克拉克森数据指标列表接口
+// @Param   BaseFromClassifyId   query   int  true       "分类id"
+// @Success 200 {object} data_manage.BaseFromMysteelChemicalIndexResp
+// @router /clarksons/index/list [get]
+func (this *ClarksonsDataController) IndexList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("BaseFromClassifyId", 0)
+	indexList, err := data_manage.GetClarksonsIndexBaseInfoByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexList
+}
+
+// GetClarksonsIndexInfo
+// @Title 添加指标-根据条件获取指标信息
+// @Description 添加指标-根据条件获取指标信息
+// @Param   KeyWord   query   string  false       "关键字"
+// @Param   ClassifyIds   query   string  false       "分类id"
+// @Param   Frequencies   query   string  false       "频率"
+// @Param   PageSize   query   int  false       "每页数据条数"
+// @Param   CurrentIndex   query   int  false       "当前页页码,从1开始"
+// @Success 200 {object} data_manage.BaseFromRzdIndexPage
+// @router /clarksons/get/index/info [post]
+func (this *ClarksonsDataController) GetClarksonsIndexInfo() {
+	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 request.ClarksonsDataBatchListReq
+	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	keyWord := req.KeyWord
+	classifyIds := req.ClassifyIds
+	frequencies := req.Frequencies
+
+	pageSize := req.PageSize
+	currentIndex := req.CurrentIndex
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var classifyIdList []string
+	var frequencyList []string
+	if classifyIds != "" {
+		classifyIdList = strings.Split(classifyIds, ",")
+	}
+	if frequencies != "" {
+		frequencyList = strings.Split(frequencies, ",")
+	}
+	indexInfoPage, err := data.GetClarksonsIndexInfo(keyWord, classifyIdList, frequencyList, currentIndex, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexInfoPage
+}
+
+// SearchList
+// @Title 克拉克森模糊搜索
+// @Description 克拉克森模糊搜索
+// @Param   Keyword   query   string  true       "关键字搜索"
+// @Success 200 {object} models.BaseResponse
+// @router /clarksons/search_list [get]
+func (this *ClarksonsDataController) SearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	//关键字
+	keyword := this.GetString("Keyword")
+	var condition string
+	var pars []interface{}
+	if keyword != "" {
+		condition += ` AND (index_code LIKE ? OR index_name LIKE ?)`
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	} else {
+		br.Msg = "请输入指标ID/指标名称"
+		return
+	}
+
+	list, err := data_manage.GetClarksonsIndexBaseInfoByCondition(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// SingleData
+// @Title 获取克拉克森据
+// @Description 获取克拉克森单条数据接口
+// @Param   BaseFromClarksonsIndexId   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /clarksons/single_data [get]
+func (this *ClarksonsDataController) SingleData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	baseFromClarksonsIndexId, _ := this.GetInt("BaseFromClarksonsIndexId")
+	indexInfo, err := data_manage.GetClarksonsIndexByIndexId(baseFromClarksonsIndexId)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_CLARKSONS, indexInfo.IndexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取指标数据失败"
+		br.ErrMsg = "获取指标库数据失败,Err:" + err.Error()
+		return
+	}
+	var edbInfoId int
+	if edbInfo != nil {
+		edbInfoId = edbInfo.EdbInfoId
+	}
+	dataList, err := data_manage.GetClarksonsDataByIndexId(baseFromClarksonsIndexId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	var ret response.ClarksonsSingleDataResp
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromClarksonsIndexId = indexInfo.BaseFromClarksonsIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.EdbInfoId = edbInfoId
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	ret.Data = dataList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// MoveClarksonsData
+// @Title 克拉克森指标移动接口
+// @Description 克拉克森指标移动接口
+// @Success 200 {object} request.MoveBaseFromClarksonsReq
+// @router /clarksons/move [post]
+func (this *ClarksonsDataController) MoveClarksonsData() {
+	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
+	}
+
+	var req request.MoveBaseFromClarksonsReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.BaseFromClarksonsIndexId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "指标id小于等于0"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.BaseFromClassifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data.MoveClarksonsData(req.BaseFromClarksonsIndexId, req.BaseFromClassifyId, req.PrevBaseFromClarksonsIndexId, req.NextBaseFromClarksonsIndexId)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+	br.Msg = "移动成功"
+}
+
+// ResetClarksonsIndex
+// @Title 指标数据清除分类
+// @Description 指标数据清除分类
+// @Param	request	body data_manage.DelBaseFromSciReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /clarksons/reset [post]
+//func (this *ClarksonsDataController) ResetClarksonsIndex() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//	var req request.ResetBaseFromClarksonsReq
+//	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+//	if err != nil {
+//		br.Msg = "参数解析异常!"
+//		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	if req.BaseFromClarksonsIndexId < 0 {
+//		br.Msg = "参数错误"
+//		br.IsSendEmail = false
+//		return
+//	}
+//
+//	err = data.ResetClarksonsIndex(req.BaseFromClarksonsIndexId)
+//	if err != nil {
+//		br.Msg = "移动失败"
+//		br.ErrMsg = "移动失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	br.Ret = 200
+//	br.Msg = "操作成功"
+//	br.Success = true
+//	br.IsAddLog = true
+//}
+
+// AddEdbInfo
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /clarksons/edb_info/add [post]
+//func (this *ClarksonsDataController) AddEdbInfo() {
+//	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
+//	}
+//	deleteCache := true
+//	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+//	defer func() {
+//		if deleteCache {
+//			utils.Rc.Delete(cacheKey)
+//		}
+//	}()
+//	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+//		deleteCache = false
+//		br.Msg = "系统处理中,请稍后重试!"
+//		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+//		return
+//	}
+//	var req data_manage.AddEdbInfoReq
+//	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+//	if err != nil {
+//		br.Msg = "参数解析异常!"
+//		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	req.EdbName = strings.Trim(req.EdbName, " ")
+//	req.EdbCode = strings.Trim(req.EdbCode, " ")
+//
+//	if req.EdbCode == "" {
+//		br.Msg = "指标ID不能为空"
+//		return
+//	}
+//
+//	if req.EdbName == "" {
+//		br.Msg = "指标名称不能为空"
+//		return
+//	}
+//
+//	if req.Frequency == "" {
+//		br.Msg = "频率不能为空"
+//		return
+//	}
+//
+//	if req.Unit == "" {
+//		br.Msg = "单位不能为空"
+//		return
+//	}
+//
+//	if req.ClassifyId <= 0 {
+//		br.Msg = "请选择分类"
+//		return
+//	}
+//
+//	_, err = data_manage.GetClarksonsIndexByIndexCode(req.EdbCode)
+//	if err != nil {
+//		if utils.IsErrNoRow(err) {
+//			br.Msg = "指标不存在"
+//			return
+//		}
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取失败,Err:" + err.Error()
+//		return
+//	}
+//	source := utils.DATA_SOURCE_CLARKSONS
+//	// 指标入库
+//	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+//	if err != nil {
+//		br.Msg = "保存失败"
+//		if errMsg != `` {
+//			br.Msg = errMsg
+//		}
+//		br.ErrMsg = err.Error()
+//		br.IsSendEmail = isSendEmail
+//		return
+//	}
+//
+//	// 试用平台更新用户累计新增指标数
+//	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+//	if e != nil {
+//		br.Msg = "操作失败"
+//		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+//		return
+//	}
+//	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+//		go func() {
+//			var r etaTrialService.EtaTrialUserReq
+//			r.Mobile = adminItem.Mobile
+//			_, _ = etaTrialService.UpdateUserIndexNum(r)
+//		}()
+//	}
+//
+//	//新增操作日志
+//	{
+//		// 添加钢联指标更新日志
+//		if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
+//			go data_stat.AddEdbInfoUpdateLog(edbInfo.EdbInfoId, 1, "", sysUser, 2)
+//		}
+//
+//		edbLog := new(data_manage.EdbInfoLog)
+//		edbLog.EdbInfoId = edbInfo.EdbInfoId
+//		edbLog.SourceName = edbInfo.SourceName
+//		edbLog.Source = edbInfo.Source
+//		edbLog.EdbCode = edbInfo.EdbCode
+//		edbLog.EdbName = edbInfo.EdbName
+//		edbLog.ClassifyId = edbInfo.ClassifyId
+//		edbLog.SysUserId = sysUser.AdminId
+//		edbLog.SysUserRealName = sysUser.RealName
+//		edbLog.CreateTime = time.Now()
+//		edbLog.Content = string(this.Ctx.Input.RequestBody)
+//		edbLog.Status = "新增指标"
+//		edbLog.Method = this.Ctx.Input.URI()
+//		go data_manage.AddEdbInfoLog(edbLog)
+//	}
+//
+//	// 更新es
+//	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+//
+//	resp := new(data_manage.AddEdbInfoResp)
+//	resp.EdbInfoId = edbInfo.EdbInfoId
+//	resp.UniqueCode = edbInfo.UniqueCode
+//	br.Ret = 200
+//	br.Success = true
+//	br.Msg = "保存成功"
+//	br.Data = resp
+//	br.IsAddLog = true
+//}
+
+// AddCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body request.BusinessDataBatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /clarksons/edb_info/add_check [post]
+func (this *ClarksonsDataController) AddCheck() {
+	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 *request.ClarksonsDataBatchAddCheckReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMax := 30
+	codeLen := len(req.IndexCodes)
+	if len(req.IndexCodes) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	if codeLen > codeMax {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
+		return
+	}
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_CLARKSONS)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetClarksonsIndexAndEdbInfoByCondition(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取克拉克森原始指标列表失败, Err: " + err.Error()
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromClarksonsIndexView, 0)
+	for _, v := range list {
+		if v.EdbInfoId > 0 {
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// NameCheck
+// @Title 重名校验
+// @Description 批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /clarksons/edb_info/name_check [post]
+func (c *ClarksonsDataController) NameCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req []*data_manage.NameCheckEdbInfoReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMax := 30
+	codeLen := len(req)
+	if codeLen > codeMax {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
+		return
+	}
+
+	type NameCheckResult struct {
+		EdbCode string
+		EdbName string
+		Exist   bool
+	}
+	indexNames := make([]string, 0)
+	resp := make([]*NameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &NameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_CLARKSONS, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取克拉克森已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_CLARKSONS, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// BatchAdd
+// @Title 批量新增
+// @Description 批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /clarksons/edb_info/batch_add [post]
+func (this *ClarksonsDataController) BatchAdd() {
+	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
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_CLARKSONS_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data.ClarksonsIndexSource2EdbReq
+		r.EdbCode = v.EdbCode
+		r.EdbName = v.EdbName
+		r.Frequency = v.Frequency
+		r.Unit = v.Unit
+		r.ClassifyId = v.ClassifyId
+		r.AdminId = sysUser.AdminId
+		r.AdminRealName = sysUser.RealName
+
+		edbInfo, errMsg, skip, e := data.ClarksonsIndexSource2Edb(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+
+		// 更新es
+		go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// BatchDelete
+// @Title 批量删除
+// @Description 批量删除
+// @Param	request	body []*request.DelBaseFromClarksonsReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /clarksons/edb_info/batch_delete [post]
+func (this *ClarksonsDataController) BatchDelete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req []*request.DelBaseFromClarksonsReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	var deleteIds []int
+	for _, v := range req {
+		if v.BaseFromClarksonsIndexId <= 0 {
+			continue
+		}
+		deleteIds = append(deleteIds, v.BaseFromClarksonsIndexId)
+	}
+	existList, err := data.BatchDelClarksonsData(deleteIds)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = existList
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// BatchEdit
+// @Title 批量编辑
+// @Description 批量编辑
+// @Param	request	body []*request.DelBaseFromClarksonsReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /clarksons/edb_info/batch_edit [post]
+func (this *ClarksonsDataController) BatchEdit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req []*request.EditBaseFromClarksonsReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	indexIds := make([]int, 0)
+	classifyIds := make([]int, 0)
+	indexIdToclassifyId := make(map[int]int)
+	for _, v := range req {
+		if v.BaseFromClarksonsIndexId <= 0 {
+			continue
+		}
+		if v.BaseFromClassifyId <= 0 {
+			continue
+		}
+		indexIds = append(indexIds, v.BaseFromClarksonsIndexId)
+		classifyIds = append(classifyIds, v.BaseFromClassifyId)
+		indexIdToclassifyId[v.BaseFromClarksonsIndexId] = v.BaseFromClassifyId
+	}
+	if len(indexIds) == 0 {
+		br.Msg = "请选择指标或指定正确的分类"
+		return
+	}
+	indexList, err := data_manage.GetClarksonsIndexListByIndexIds(indexIds)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "获取指标失败,Err:" + err.Error()
+		return
+	}
+	classifySort, err := data_manage.GetClarksonsClassifyMaxSortByClassifyIds(classifyIds)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "获取分类最大排序失败,Err:" + err.Error()
+		return
+	}
+	classifySortMap := make(map[int]int)
+	for _, v := range classifySort {
+		classifySortMap[v.BaseFromClassifyId] = v.MaxSort
+	}
+	classifyList, err := data_manage.GetClarksonsClassifyListByIds(classifyIds)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "获取分类失败,Err:" + err.Error()
+		return
+	}
+	existClassifyList := make(map[int]struct{})
+	for _, v := range classifyList {
+		existClassifyList[v.BaseFromClassifyId] = struct{}{}
+	}
+	//编辑指标
+	updateIndexList := make([]*data_manage.BaseFromClarksonsIndex, 0)
+	for _, v := range indexList {
+		tmpClassifyId := indexIdToclassifyId[v.BaseFromClarksonsIndexId]
+		if _, ok := existClassifyList[tmpClassifyId]; ok {
+			v.ClassifyId = tmpClassifyId
+			v.Sort = classifySortMap[tmpClassifyId] + 1
+			classifySortMap[tmpClassifyId] += 1
+			updateIndexList = append(updateIndexList, v)
+		}
+	}
+	err = data_manage.BatchModifyClarksonsIndexClassify(updateIndexList)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑指标失败,Err:" + err.Error()
+		return
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+
+}
+
+// EditClarksons
+// @Title 编辑克拉克森指标
+// @Description 编辑克拉克森指标接口
+// @Param	request	body data_manage.AddEdbClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /clarksons/edit [post]
+func (this *ClarksonsDataController) EditClarksons() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.EditBaseFromClarksonsReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.BaseFromClarksonsIndexId <= 0 {
+		br.Msg = "请选择指标"
+		br.IsSendEmail = false
+		return
+	}
+	if req.BaseFromClassifyId < 0 {
+		br.Msg = "请选择分类"
+		br.IsSendEmail = false
+		return
+	}
+
+	//编辑指标
+	sciIndexInfo, errMsg, err := data.EditClarksonsIndex(req.BaseFromClarksonsIndexId, req.BaseFromClassifyId)
+	if errMsg != `` {
+		br.Msg = errMsg
+		return
+	}
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑指标失败,Err:" + err.Error()
+		return
+	}
+
+	resp := response.EditClarksonsIndexInfoResp{
+		BaseFromClarksonsIndexId: sciIndexInfo.BaseFromClarksonsIndexId,
+		IndexCode:                sciIndexInfo.IndexCode,
+	}
+	br.Data = resp
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// DeleteClarksonsData
+// @Title 删除指标
+// @Description 删除指标接口
+// @Param	request	body data_manage.DelBaseFromSciReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /clarksons/del [post]
+func (this *ClarksonsDataController) DeleteClarksonsData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.DelBaseFromClarksonsReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.BaseFromClarksonsIndexId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data.DelClarksonsData(req.BaseFromClarksonsIndexId)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = errMsg + ";Err:" + err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// ExportClarksonsList
+// @Title 导出Sci数据
+// @Description 导出Sci数据
+// @Param   BaseFromClassifyId   query   int  true       "关键字搜索"
+// @Param   IndexCode   query   string  true       "指标编码"
+// @Success 200  导出成功
+// @router /export/clarksonsList [get]
+func (this *ClarksonsDataController) ExportClarksonsList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("BaseFromClassifyId")
+	indexCode := this.GetString("IndexCode")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	secNameList := make([]*data_manage.BaseFromClarksonsIndex, 0)
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var condition string
+	var pars []interface{}
+	if classifyId > 0 {
+		childClassify, err := data_manage.GetChildClarksonsClassifyListById(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		if len(childClassify) > 0 {
+			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			for _, child := range childClassify {
+				pars = append(pars, child.BaseFromClassifyId)
+			}
+		} else {
+			condition += ` AND classify_id=?`
+			pars = append(pars, classifyId)
+		}
+	} else {
+		condition += ` AND classify_id=?`
+		pars = append(pars, classifyId)
+	}
+	if indexCode != "" {
+		condition += ` AND index_code=? `
+		pars = append(pars, indexCode)
+	}
+	frequencies, err := data_manage.GetClarksonsFrequencyByCondition(condition, pars)
+	if err != nil {
+		fmt.Println("GetSciFrequency err:", err.Error())
+		utils.FileLog.Info("GetSciFrequency err:" + err.Error())
+		return
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		secNameList, err = data_manage.GetClarksonsIndexByConditionAndFrequency(condition, *frequency, pars)
+		if err != nil {
+			fmt.Println("获取数据失败,Err:" + err.Error())
+			return
+		}
+		if len(secNameList) <= 0 {
+			fmt.Println("secNameList长度为0")
+			return
+		}
+		sheetNew, err := xlsxFile.AddSheet(*frequency)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, sv := range secNameList {
+			indexIdList = append(indexIdList, sv.BaseFromClarksonsIndexId)
+		}
+		dataTimeList, err := data_manage.GetClarksonsDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, sv := range secNameList {
+			//获取数据
+			dataList, err := data_manage.GetClarksonsIndexDataByCode(sv.IndexCode)
+			if err != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取数据失败,Err:" + err.Error()
+				return
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称")
+				frequencyRow.AddCell().SetValue("频率")
+				unitRow.AddCell().SetValue("单位")
+				lastModifyDateRow.AddCell().SetValue("更新时间")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(sv.IndexName)
+			frequencyRow.AddCell().SetValue(sv.Frequency)
+			unitRow.AddCell().SetValue(sv.Unit)
+
+			lastModifyDateRow.AddCell().SetValue(sv.ModifyTime.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromClarksonsData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		err = xlsxFile.Save(downLoadnFilePath)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+	fileName := `克拉克森`
+	if indexCode != "" && len(secNameList) == 1 {
+		fileName = secNameList[0].IndexName
+	}
+	fileName += time.Now().Format("2006.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}
+
+// getClarksonsClassifyTree 返回卓创红旗的树形结构
+func getClarksonsClassifyTree(items []*data_manage.BaseFromClarksonsClassifyItem, parentId int) []*data_manage.BaseFromClarksonsClassifyItem {
+	res := make([]*data_manage.BaseFromClarksonsClassifyItem, 0)
+	for _, item := range items {
+		if item.ParentId == parentId {
+			t := new(data_manage.BaseFromClarksonsClassifyItem)
+			t.BaseFromClassifyId = item.BaseFromClassifyId
+			t.ClassifyName = item.ClassifyName
+			t.ParentId = item.ParentId
+			t.Level = item.Level
+			t.Sort = item.Sort
+			t.ModifyTime = item.ModifyTime
+			t.CreateTime = item.CreateTime
+			t.ClassifyNameEn = item.ClassifyNameEn
+			if item.UniqueCode == "" {
+				t.UniqueCode = strconv.Itoa(item.BaseFromClassifyId)
+			}
+			t.Children = getClarksonsClassifyTree(items, item.BaseFromClassifyId)
+			res = append(res, t)
+		}
+	}
+	return res
+}
+
+// @Title 获取克拉克森数据
+// @Description 获取克拉克森数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   BaseFromSci99ClassifyId   query   int  true       "分类id"
+// @Param   KeyWord   query   string  true       "关键词"
+// @Success 200 {object} data_source.BaseFromSci99IndexView
+// @router /clarksons/index/data [get]
+func (this *ClarksonsDataController) ClarksonsData() {
+	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")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	baseFromClarksonsClassifyId, _ := this.GetInt("BaseFromClarksonsClassifyId")
+	if baseFromClarksonsClassifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	keyword := this.GetString("KeyWord")
+
+	//获取指标
+	var condition string
+	var pars []interface{}
+
+	if baseFromClarksonsClassifyId > 0 {
+		condition += ` AND classify_id=? `
+		pars = append(pars, baseFromClarksonsClassifyId)
+	}
+
+	if keyword != "" {
+		condition += ` AND (index_code =? OR index_name LIKE ?)  `
+		pars = append(pars, keyword)
+		pars = append(pars, "%"+keyword+"%")
+	}
+
+	sci99List, err := data_manage.GetClarksonsIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	resultList := make([]*data_manage.BaseFromClarksonsIndexList, 0)
+	for _, v := range sci99List {
+		product := new(data_manage.BaseFromClarksonsIndexList)
+		product.BaseFromClarksonsIndexId = v.BaseFromClarksonsIndexId
+		product.ClassifyId = v.ClassifyId
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.Unit = v.Unit
+		product.ModifyTime = v.ModifyTime
+
+		modifyTime, err := data_manage.GetClarksonsIndexLatestDate(v.IndexCode)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取更新时间失败"
+			br.ErrMsg = "获取更新时间失败,Err:" + err.Error()
+			return
+		}
+		product.ModifyTime = modifyTime
+
+		total, err := data_manage.GetClarksonsIndexDataCount(v.IndexCode)
+		page := paging.GetPaging(currentIndex, pageSize, total)
+		dataList, err := data_manage.GetClarksonsIndexData(v.IndexCode, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		if dataList == nil {
+			dataList = make([]*data_manage.BaseFromClarksonsData, 0)
+		}
+		product.DataList = dataList
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// IndexPageList
+// @Title 克拉克森指标列表
+// @Description 克拉克森数据指标列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Param   IsListAll   query   int  true       "是否展示全部"
+// @Success 200 {object} data_manage.BaseFromMysteelChemicalIndexResp
+// @router /clarksons/index/page/list [get]
+func (this *ClarksonsDataController) IndexPageList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	pageSize, _ := this.GetInt("PageSize")
+	currrentIndex, _ := this.GetInt("CurrentIndex")
+	isListAll, _ := this.GetBool("IsListAll")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currrentIndex <= 0 {
+		currrentIndex = 1
+	}
+	startSize = utils.StartIndex(currrentIndex, pageSize)
+	var total int
+	var indexList []*data_manage.BaseFromClarksonsIndexView
+	if isListAll {
+		tmpTotal, err := data_manage.GetClarksonsIndexCount()
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+			return
+		}
+		total = tmpTotal
+		tmpIndexList, err := data_manage.GetClarksonsIndexByPage(startSize, pageSize)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+			return
+		}
+		indexList = tmpIndexList
+	} else {
+		var classifyIds []int
+		if classifyId > 0 {
+			tmpClassifyIds, err := data_manage.GetClarksonsChildClassifyIdsById(classifyId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+				return
+			}
+			if len(tmpClassifyIds) > 0 {
+				classifyIds = append(classifyIds, tmpClassifyIds...)
+			}
+		}
+		classifyIds = append(classifyIds, classifyId)
+		tmpTotal, err := data_manage.GetClarksonsIndexCountByClassifyId(classifyIds)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+			return
+		}
+		total = tmpTotal
+		tmpIndexList, err := data_manage.GetClarksonsIndexByClassifyId(classifyIds, startSize, pageSize)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+			return
+		}
+		indexList = tmpIndexList
+	}
+
+	page := paging.GetPaging(currrentIndex, pageSize, total)
+	resp := new(response.ClarksonsIndexPageListResp)
+	resp.List = indexList
+	resp.Paging = page
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 5 - 5
controllers/data_manage/com_trade.go

@@ -29,7 +29,7 @@ func (this *EdbInfoController) ComTradeCountryList() {
 	}
 
 	list, err := data_manage.GetComTradeCountryItemAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -161,14 +161,14 @@ func (this *EdbInfoController) ComTradeDataList() {
 	sortStr = fmt.Sprintf("%s %s,modify_time desc ", sortParam, sortType)
 
 	total, err := data_manage.GetComTradeListCount(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	list, err := data_manage.GetComTradeList(condition, pars, startSize, pageSize, sortStr)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -178,7 +178,7 @@ func (this *EdbInfoController) ComTradeDataList() {
 	lastUpdateTimeStr := ``
 	// 获取用到的指标信息
 	comTradeList, err := data_manage.GetAllComTradeIndexList()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -247,7 +247,7 @@ func (this *EdbInfoController) ComTradeList() {
 	}
 
 	list, err := data_manage.GetComTradeIndexList(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return

+ 38 - 31
controllers/data_manage/correlation/correlation_chart_classify.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/correlation"
 	correlationServ "eta/eta_api/services/data/correlation"
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
@@ -61,7 +62,7 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
 	// 查询分类节点
 	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_CORRELATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -135,6 +136,14 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 			return nodeAll[i].Sort < nodeAll[j].Sort
 		})
 	}
+	if isShowMe {
+		nodeAll, err = correlation.GetCorrelationClassifyByIsMe(this.SysUser.AdminId, parentId, source, nodeAll)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取我的分类失败,Err:" + err.Error()
+			return
+		}
+	}
 
 	resp.AllNodes = nodeAll
 	br.Ret = 200
@@ -146,19 +155,19 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CORRELATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_CORRELATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_CORRELATION}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -254,7 +263,7 @@ func (this *CorrelationChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_CORRELATION, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_CORRELATION, 0,this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -358,7 +367,7 @@ func (this *CorrelationChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -420,7 +429,7 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -440,11 +449,12 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 		}
 	}
 	resp := new(data_manage.AddChartInfoResp)
+
 	//删除图表
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -483,13 +493,23 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 		}
 
 		source := chartInfo.Source // 相关性图表(滚动相关性)
-		//删除图表及关联指标
+
+		// 删除图表及关联指标
 		err = data_manage.DeleteChartInfoAndData(chartInfo.ChartInfoId)
 		if err != nil {
 			br.Msg = "删除失败"
 			br.ErrMsg = "删除失败,Err:" + err.Error()
 			return
 		}
+
+		// 删除图表关联
+		e = correlationServ.RemoveCorrelationRelate(chartInfo.ChartInfoId)
+		if e != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = fmt.Sprintf("删除相关性图表关联失败, %v", e)
+			return
+		}
+
 		//删除ES
 		{
 			go data.EsDeleteChartInfo(chartInfo.ChartInfoId)
@@ -498,16 +518,14 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 			go data.EsDeleteMyChartInfoByMyChartIds(myIds)
 		}
 
+		// 删除后定位至其他图(不知道原需求具体定位到哪张...修复的时候只是多加上了个source条件)
 		var condition string
 		var pars []interface{}
-		condition += " AND chart_classify_id=? AND source = ? "
-		pars = append(pars, chartInfo.ChartClassifyId, source)
-
-		condition += " AND chart_info_id>? ORDER BY create_time ASC LIMIT 1 "
-		pars = append(pars, req.ChartInfoId)
+		condition += ` AND chart_classify_id = ? AND source = ? AND chart_info_id > ? ORDER BY create_time ASC LIMIT 1`
+		pars = append(pars, chartInfo.ChartClassifyId, source, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -520,21 +538,18 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 			var condition string
 			var pars []interface{}
 
-			condition += " AND level=1 "
-			//pars = append(pars, chartInfo.ChartClassifyId)
-
-			condition += " AND chart_classify_id>? ORDER BY chart_classify_id ASC LIMIT 1 "
-			pars = append(pars, chartInfo.ChartClassifyId)
+			condition += ` AND level = 1 AND chart_classify_id > ? AND source = ? ORDER BY chart_classify_id ASC LIMIT 1`
+			pars = append(pars, chartInfo.ChartClassifyId, source)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
-				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				nextItem, err = data_manage.GetNextChartByClassifyIdAndSource(chartInfo.ChartClassifyId, source)
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -546,14 +561,6 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 			}
 		}
 
-		// 删除图表关联
-		e = correlationServ.RemoveCorrelationRelate(chartInfo.ChartInfoId)
-		if e != nil {
-			br.Msg = "删除失败"
-			br.ErrMsg = fmt.Sprintf("删除相关性图表关联失败, %v", e)
-			return
-		}
-
 		//新增操作日志
 		{
 			chartLog := new(data_manage.ChartInfoLog)

+ 52 - 31
controllers/data_manage/correlation/correlation_chart_info.go

@@ -335,7 +335,7 @@ func (this *CorrelationChartInfoController) Move() {
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
 		tmpChartInfo, tmpErr := data_manage.GetChartInfoByClassifyIdAndName(req.ChartClassifyId, chartInfo.ChartName)
-		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
 			return
@@ -394,7 +394,7 @@ func (this *CorrelationChartInfoController) Move() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
@@ -510,15 +510,32 @@ func (this *CorrelationChartInfoController) List() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
 		}
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -533,7 +550,7 @@ func (this *CorrelationChartInfoController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -551,7 +568,7 @@ func (this *CorrelationChartInfoController) List() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -559,7 +576,7 @@ func (this *CorrelationChartInfoController) List() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -603,7 +620,7 @@ func (this *CorrelationChartInfoController) List() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -614,7 +631,7 @@ func (this *CorrelationChartInfoController) List() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -665,7 +682,7 @@ func (this *CorrelationChartInfoController) Detail() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -790,7 +807,7 @@ func (this *CorrelationChartInfoController) Detail() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -946,7 +963,7 @@ func (this *CorrelationChartInfoController) DetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -984,7 +1001,7 @@ func (this *CorrelationChartInfoController) DetailFromUniqueCode() {
 					myCond += ` AND a.chart_info_id=? `
 					myPars = append(myPars, chartInfo.ChartInfoId)
 					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
-					if err != nil && err.Error() != utils.ErrNoRow() {
+					if err != nil && !utils.IsErrNoRow(err) {
 						br.Msg = "获取失败"
 						br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 						return
@@ -1055,7 +1072,7 @@ func (this *CorrelationChartInfoController) Refresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -1174,7 +1191,7 @@ func (this *CorrelationChartInfoController) Copy() {
 
 		_, e = data_manage.GetChartClassifyById(req.ChartClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -1187,7 +1204,7 @@ func (this *CorrelationChartInfoController) Copy() {
 	// 图表信息
 	originChart, e := data_manage.GetChartInfoById(req.ChartInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "原图表不存在"
 			return
 		}
@@ -1204,7 +1221,7 @@ func (this *CorrelationChartInfoController) Copy() {
 	// 相关性图
 	originCorrelate := new(data_manage.ChartInfoCorrelation)
 	if e = originCorrelate.GetItemById(req.ChartInfoId); e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "原相关性图表不存在"
 			return
 		}
@@ -1217,7 +1234,7 @@ func (this *CorrelationChartInfoController) Copy() {
 	chartInfo := new(data_manage.ChartInfo)
 	if originCorrelate.AnalysisMode != 1 {
 		multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByChartId(req.ChartInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = `保存失败`
 			br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 			return
@@ -1486,7 +1503,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1707,7 +1724,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1823,7 +1840,7 @@ func (this *CorrelationChartInfoController) EnInfoEdit() {
 	pars = append(pars, req.ChartInfoId, req.ChartNameEn, utils.CHART_SOURCE_CORRELATION)
 	existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "判断英文图表名称是否存在失败"
 			br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 			return
@@ -1927,7 +1944,7 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 		sourceList = append(sourceList, source)
 	}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -1936,7 +1953,7 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1950,7 +1967,7 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -1980,13 +1997,17 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -2021,7 +2042,7 @@ func (this *CorrelationChartInfoController) Newest() {
 		this.ServeJSON()
 	}()
 	item, err := data_manage.GetChartInfoByNewest(utils.CHART_SOURCE_CORRELATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取最新图表失败"
 		br.ErrMsg = "获取最新图表失败,Err:" + err.Error()
 		return
@@ -2094,7 +2115,7 @@ func (this *CorrelationChartInfoController) BaseInfoEdit() {
 	pars = append(pars, req.ChartName)
 	existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "判断英文图表名称是否存在失败"
 			br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 			return
@@ -2286,7 +2307,7 @@ func (this *CorrelationChartInfoController) MultiFactorAdd() {
 
 		_, e = data_manage.GetChartClassifyById(req.ClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -2642,7 +2663,7 @@ func (this *CorrelationChartInfoController) MultiFactorEdit() {
 
 	chartInfo, e := data_manage.GetChartInfoById(req.ChartInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "图表已被删除, 请刷新页面"
 			return
 		}
@@ -2694,7 +2715,7 @@ func (this *CorrelationChartInfoController) MultiFactorEdit() {
 
 		_, e = data_manage.GetChartClassifyById(req.ClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -2895,7 +2916,7 @@ func (this *CorrelationChartInfoController) MultiFactorDetail() {
 
 	chartInfo, e := data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "图表已被删除, 请刷新页面"
 			return
 		}

+ 46 - 25
controllers/data_manage/cross_variety/chart_info.go

@@ -84,15 +84,32 @@ func (c *ChartInfoController) List() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
 		}
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -107,7 +124,7 @@ func (c *ChartInfoController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -125,7 +142,7 @@ func (c *ChartInfoController) List() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -133,7 +150,7 @@ func (c *ChartInfoController) List() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -177,7 +194,7 @@ func (c *ChartInfoController) List() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -188,7 +205,7 @@ func (c *ChartInfoController) List() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -474,7 +491,7 @@ func (c *ChartInfoController) Detail() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -567,7 +584,7 @@ func (c *ChartInfoController) Detail() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -686,7 +703,7 @@ func (c *ChartInfoController) Relation() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -956,7 +973,7 @@ func (c *ChartInfoController) Move() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(chartInfo.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
@@ -1058,7 +1075,7 @@ func (c *ChartInfoController) Refresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -1143,7 +1160,7 @@ func (c *ChartInfoController) EnInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -1262,7 +1279,7 @@ func (c *ChartInfoController) DeleteChart() {
 	//删除图表
 	chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已删除,请刷新页面"
 			br.ErrMsg = "指标不存在,Err:" + err.Error()
 			return
@@ -1325,7 +1342,7 @@ func (c *ChartInfoController) DeleteChart() {
 	pars = append(pars, req.ChartInfoId)
 
 	nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "删除失败"
 		br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 		return
@@ -1345,14 +1362,14 @@ func (c *ChartInfoController) DeleteChart() {
 		tmpPars = append(tmpPars, chartInfo.ChartClassifyId)
 
 		classifyItem, err := data_manage.GetChartClassifyByCondition(tmpCondition, tmpPars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 			return
 		}
 		if classifyItem != nil {
 			nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 				return
@@ -1434,7 +1451,7 @@ func (c *ChartInfoController) SearchByEs() {
 
 	sourceList := []int{utils.CHART_SOURCE_CROSS_HEDGING}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -1443,7 +1460,7 @@ func (c *ChartInfoController) SearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1457,7 +1474,7 @@ func (c *ChartInfoController) SearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -1487,13 +1504,17 @@ func (c *ChartInfoController) SearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -1537,7 +1558,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1680,7 +1701,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1775,7 +1796,7 @@ func (c *ChartInfoController) Save() {
 
 	chartItem, e := data_manage.GetChartInfoById(req.ChartInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "图表已被删除, 请刷新页面"
 			return
 		}
@@ -1862,7 +1883,7 @@ func (c *ChartInfoController) BaseInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return

+ 10 - 10
controllers/data_manage/cross_variety/classify.go

@@ -36,7 +36,7 @@ func (c *ClassifyController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -54,14 +54,14 @@ func (c *ClassifyController) List() {
 	}
 
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CROSS_HEDGING)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAll([]int{source})
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -195,7 +195,7 @@ func (c *ClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -257,7 +257,7 @@ func (c *ClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -281,7 +281,7 @@ func (c *ClassifyController) DeleteChartClassify() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -344,7 +344,7 @@ func (c *ClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -364,14 +364,14 @@ func (c *ClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -497,7 +497,7 @@ func (c *ClassifyController) ChartClassifyMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartClassifyByParentIdAndSource(chartClassifyInfo.ParentId, chartClassifyInfo.Source)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取跨品种分析图表分类排序第一条的分类信息失败,Err:" + err.Error()
 			return

+ 5 - 5
controllers/data_manage/cross_variety/tag.go

@@ -45,12 +45,12 @@ func (c *TagController) Add() {
 	}
 	TagName := utils.TrimStr(req.TagName)
 	item, err := cross_variety.GetTagByName(TagName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil {
+	if item != nil && item.ChartTagId > 0 {
 		br.Msg = "添加失败,标签名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -110,12 +110,12 @@ func (c *TagController) Edit() {
 	TagName := utils.TrimStr(req.TagName)
 
 	item, err := cross_variety.GetTagByName(TagName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil && item.ChartTagId != req.ChartTagId {
+	if item != nil && item.ChartTagId != req.ChartTagId && item.ChartTagId > 0 {
 		br.Msg = "添加失败,标签名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -248,7 +248,7 @@ func (c *TagController) Delete() {
 
 	varietyInfo, err := cross_variety.GetTagById(req.ChartTagId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "该标签不存在或已删除"
 			br.IsSendEmail = false
 		} else {

+ 5 - 5
controllers/data_manage/cross_variety/variety.go

@@ -44,12 +44,12 @@ func (c *VarietyController) Add() {
 	}
 	varietyName := utils.TrimStr(req.VarietyName)
 	item, err := cross_variety.GetVarietyByName(varietyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil {
+	if item != nil && item.ChartVarietyId > 0 {
 		br.Msg = "添加失败,品种名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -109,12 +109,12 @@ func (c *VarietyController) Edit() {
 	varietyName := utils.TrimStr(req.VarietyName)
 
 	item, err := cross_variety.GetVarietyByName(varietyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil && item.ChartVarietyId != req.ChartVarietyId {
+	if item != nil && item.ChartVarietyId != req.ChartVarietyId && item.ChartVarietyId > 0 {
 		br.Msg = "添加失败,品种名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -246,7 +246,7 @@ func (c *VarietyController) Delete() {
 
 	varietyInfo, err := cross_variety.GetVarietyById(req.ChartVarietyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "该品种不存在或已删除"
 			br.IsSendEmail = false
 		} else {

+ 2 - 2
controllers/data_manage/data_manage_permission/message.go

@@ -129,7 +129,7 @@ func (c *DataMangePermissionController) MessageRead() {
 	messageOb := new(data_manage_permission.DataPermissionMessage)
 	messageItem, e := messageOb.GetItemById(req.MessageId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "消息不存在, 请刷新页面"
 			return
 		}
@@ -221,7 +221,7 @@ func (c *DataMangePermissionController) MessageDetail() {
 	messageOb := new(data_manage_permission.DataPermissionMessage)
 	messageItem, e := messageOb.GetItemById(messageId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "消息不存在, 请刷新页面"
 			return
 		}

+ 183 - 17
controllers/data_manage/edb_classify.go

@@ -9,7 +9,10 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"sort"
+	"strconv"
+	"strings"
 )
 
 // EdbClassifyController 数据管理-分类模块
@@ -29,13 +32,13 @@ func (this *EdbClassifyController) ListV2() {
 		this.ServeJSON()
 	}()
 	rootList, err := data_manage.GetEdbClassifyByParentId(0, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 	classifyAll, err := data_manage.GetEdbClassifyAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -57,7 +60,7 @@ func (this *EdbClassifyController) ListV2() {
 	// 获取当前账号的不可见指标
 	obj := data_manage.EdbInfoNoPermissionAdmin{}
 	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 		return
@@ -67,7 +70,7 @@ func (this *EdbClassifyController) ListV2() {
 		noPermissionEdbInfoIdMap[v.EdbInfoId] = true
 	}
 	allEdbInfo, err := data_manage.GetEdbInfoAll(utils.EDB_INFO_TYPE)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -288,7 +291,7 @@ func (this *EdbClassifyController) EditEdbClassify() {
 		return
 	}
 
-	err, errMsg := data.EditEdbClassify(req.ClassifyId, req.ClassifyName, this.Lang, this.SysUser)
+	err, errMsg := data.EditEdbClassify(req.ClassifyId, req.ParentId, req.ClassifyName, this.Lang, this.SysUser, false)
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg
@@ -650,13 +653,13 @@ func (this *EdbClassifyController) ItemsV2() {
 		this.ServeJSON()
 	}()
 	rootList, err := data_manage.GetEdbClassifyByParentId(0, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 	classifyAll, err := data_manage.GetEdbClassifyAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -775,7 +778,7 @@ func (this *EdbClassifyController) ClassifyEdbInfoList() {
 	// 获取当前账号的不可见指标
 	obj := data_manage.EdbInfoNoPermissionAdmin{}
 	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 		return
@@ -786,7 +789,7 @@ func (this *EdbClassifyController) ClassifyEdbInfoList() {
 	}
 
 	allEdbInfo, err := data_manage.GetEdbInfoByClassifyId(classifyId, 0, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -836,19 +839,19 @@ func (this *EdbClassifyController) ItemsV3() {
 		this.ServeJSON()
 	}()
 	rootList, err := data_manage.GetEdbClassifyByParentId(0, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 	rootTwoList, err := data_manage.GetEdbClassifyByParentIdTwo(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 	classifyAll, err := data_manage.GetEdbClassifyAllV2(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -974,7 +977,7 @@ func (this *EdbClassifyController) SimpleList() {
 		sysUserId = this.SysUser.AdminId
 	}
 	rootList, err := data_manage.GetEdbClassifyByParentId(parentId, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -987,7 +990,7 @@ func (this *EdbClassifyController) SimpleList() {
 		// 获取当前账号的不可见指标
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1058,6 +1061,14 @@ func (this *EdbClassifyController) SimpleList() {
 		sortList = nodeAll
 		sort.Sort(sortList)
 	}
+	if isOnlyMe {
+		sortList, err = data.GetEdbClassifyByIsMe(sysUserId, parentId, 0, sortList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+	}
 
 	language := `CN`
 	// 指标显示的语言
@@ -1101,9 +1112,9 @@ func (this *EdbClassifyController) ClassifyTree() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-
+	level, _ := this.GetInt(`Level`)
 	allList, err := data_manage.GetNormalEdbClassifyAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -1127,7 +1138,7 @@ func (this *EdbClassifyController) ClassifyTree() {
 			button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			allList[k].Button = button
 		}
-		nodeAll = data.GetClassifyTreeRecursive(allList, 0)
+		nodeAll = data.GetClassifyTreeRecursive(allList, 0, level)
 		//根据sort值排序
 		sortList = nodeAll
 		sort.Sort(sortList)
@@ -1213,3 +1224,158 @@ func (this *EdbClassifyController) ClassifyTree() {
 //	br.Success = true
 //	br.Msg = "移动成功"
 //}
+
+// EdbInfoList
+// @Title 批量编辑指标列表接口
+// @Description 批量编辑指标列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   EdbInfoId   query   int  true       "指标id"
+// @Param   KeyWord   query   string  false       "搜索关键词:指标ID/指标名称"
+// @Success 200 {object} data_manage.EdbInfoListResp
+// @router /classify/edb/list [get]
+func (this *EdbInfoController) ClassifyEdbInfoList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	subClassify, _ := this.GetBool("SubClassify")
+	sources := this.GetString("Sources")
+	keyWord := this.GetString("KeyWord")
+	sysUserIds := this.GetString("SysUserIds")
+	classifyIdsStr := this.GetString("ClassifyIds")
+	classifyIds := strings.Split(classifyIdsStr, ",")
+
+	var condition string
+	var pars []interface{}
+
+	// 已授权分类id
+	//permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.SysUser.AdminId, 0)
+	//if err != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+	//	return
+	//}
+	classifyIdsArr := make([]int, 0)
+	for _, v := range classifyIds {
+		if v != `` {
+			id, _ := strconv.Atoi(v)
+			classifyIdsArr = append(classifyIdsArr, id)
+		}
+	}
+
+	//if len(permissionClassifyIdList) > 0 {
+	//	classifyIdsArr = utils.IntersectInt(permissionClassifyIdList, classifyIdsArr)
+	//}
+
+	condition += " AND edb_info_type = 0 "
+	if len(classifyIdsArr) > 0 {
+		if !subClassify {
+			condition += " AND classify_id IN(" + utils.GetOrmInReplace(len(classifyIdsArr)) + ") "
+			pars = append(pars, classifyIdsArr)
+		} else {
+			classifyAll, err := data_manage.GetNormalEdbClassifyAll()
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取数据失败,Err:" + err.Error()
+				return
+			}
+			finalClassifyIds := make([]int, 0)
+			parents := data.GetEdbClassifyChildrenRecursiveByParentIds(classifyAll, classifyIds)
+			sort.Slice(parents, func(i, j int) bool {
+				return parents[i].Level < parents[i].Level
+			})
+			for _, v := range parents {
+				finalClassifyIds = append(finalClassifyIds, v.ClassifyId)
+			}
+
+			condition += " AND classify_id IN(" + utils.GetOrmInReplace(len(finalClassifyIds)) + ") "
+			pars = append(pars, finalClassifyIds)
+		}
+	}
+
+	if keyWord != "" {
+		keyWordArr := strings.Split(keyWord, " ")
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				condition += ` AND edb_name LIKE '%` + v + `%' `
+			}
+		}
+	}
+	if sources != "" {
+		condition += " AND source IN(" + utils.GetOrmInReplace(len(strings.Split(sources, ","))) + ") "
+		pars = append(pars, strings.Split(sources, ","))
+	}
+	if sysUserIds != "" {
+		adminIds := strings.Split(sysUserIds, ",")
+		if len(adminIds) == 0 {
+			br.Msg = "请选择正确的创建人"
+			return
+		}
+		adminIdsSlice := make([]int, 0)
+		for _, adminId := range adminIds {
+			adminIdInt, e := strconv.Atoi(adminId)
+			if e != nil {
+				br.Msg = "请选择正确的创建人"
+				return
+			}
+			adminIdsSlice = append(adminIdsSlice, adminIdInt)
+		}
+		condition += "  AND sys_user_id in (" + utils.GetOrmInReplace(len(adminIds)) + ") "
+		pars = append(pars, adminIdsSlice)
+	}
+
+	// 获取当前账号的不可见指标
+	obj := data_manage.EdbInfoNoPermissionAdmin{}
+	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+		return
+	}
+	noPermissionEdbInfoIds := make([]int, 0)
+	for _, v := range confList {
+		noPermissionEdbInfoIds = append(noPermissionEdbInfoIds, v.EdbInfoId)
+	}
+	if len(noPermissionEdbInfoIds) > 0 {
+		condition += " AND edb_info_id NOT IN(" + utils.GetOrmInReplace(len(noPermissionEdbInfoIds)) + ") "
+		pars = append(pars, noPermissionEdbInfoIds)
+	}
+
+	count, err := data_manage.GetEdbInfoByConditionCount(condition, pars)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	page := paging.GetPaging(currentIndex, pageSize, count)
+
+	list, err := data_manage.GetEdbInfoListByCondition(condition, pars, startSize, pageSize, "")
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	resp := new(data_manage.EdbInfoFilterDataResp)
+	resp.List = list
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

File diff suppressed because it is too large
+ 188 - 105
controllers/data_manage/edb_info.go


+ 12 - 7
controllers/data_manage/edb_info_calculate.go

@@ -764,7 +764,7 @@ func (this *ChartInfoController) CalculateBatchEdit() {
 
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标已被删除,请刷新页面"
 			br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error()
 			return
@@ -933,7 +933,7 @@ func (this *ChartInfoController) CalculateBatchReset() {
 
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标已被删除,请刷新页面"
 			br.ErrMsg = "指标已删除,请刷新页面:Err:" + err.Error()
 			return
@@ -968,7 +968,7 @@ func (this *ChartInfoController) CalculateBatchReset() {
 	//	for _, v := range fromEdbInfoList {
 	//		edbInfo, err := data_manage.GetEdbInfoById(v.FromEdbInfoId)
 	//		if err != nil {
-	//			if err.Error() == utils.ErrNoRow() {
+	//			if utils.IsErrNoRow(err) {
 	//				br.Msg = "重新计算失败"
 	//				br.Msg = "指标 " + strconv.Itoa(v.FromEdbInfoId) + " 不存在"
 	//				return
@@ -1347,7 +1347,7 @@ func (this *ChartInfoController) EditPythonEdb() {
 	//获取指标信息
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标已被删除,请刷新页面"
 			br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error()
 			return
@@ -1476,7 +1476,12 @@ func (this *EdbInfoController) QueryEdbDataTable() {
 	if edbInfo.Source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
 		templateStr = fmt.Sprintf("# 查询条件\nquery = {\"edb_code\": \"%s\"}\n# 排序\nsort = [(\"data_time\", -1)]  # -1 表示降序排列,对应 SQL 的 DESC\nprojection = {\"data_time\": 1, \"value\": 1, \"_id\": 0}  # 只选择data_time和value字段,忽略_id字段\n# 使用 find() 方法获取数据,然后使用 aggregate() 转换为列表\nraw_data = list(collection.find(query, projection).sort(sort))\n# 将结果转换为 DataFrame\nraw = pd.DataFrame(raw_data)\n# 转换data_time字段为本地时区时间\nraw['data_time'] = raw['data_time'].apply(lambda x: x.replace(tzinfo=utc_tz)).dt.tz_convert(local_tz).dt.strftime('%s')", edbInfo.EdbCode, "%Y-%m-%d")
 	} else {
-		templateStr = fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,`value` FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
+		switch utils.DbDriverName {
+		case `dm`:
+			templateStr = fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,\"value\" FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
+		default:
+			templateStr = fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,`value` FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
+		}
 	}
 	info := data_manage.TableInfoResp{
 		ColumnList:  columnList,
@@ -2252,7 +2257,7 @@ func (this *ChartInfoController) CalculateMultiChoice() {
 	}
 
 	list, err := data_manage.GetEdbInfoByIdList(edbIdArr)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标列表失败"
 		br.ErrMsg = "获取指标列表失败,Err:" + err.Error()
 		return
@@ -2445,7 +2450,7 @@ func (this *ChartInfoController) CalculateMultiSearch() {
 		}
 
 		list, err := data_manage.GetEdbInfoByIdList(edbIdArr)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标列表失败"
 			br.ErrMsg = "获取指标列表失败,Err:" + err.Error()
 			return

+ 50 - 23
controllers/data_manage/edb_info_refresh.go

@@ -97,14 +97,14 @@ func (c *EdbInfoController) RefreshClassifyList() {
 	switch source {
 	case utils.DATA_SOURCE_MYSTEEL_CHEMICAL: // 钢联
 		rootList, err := data_manage.GetBaseFromMysteelChemicalClassifyByParentId(0)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
 		}
 
 		classifyAll, err := data_manage.GetAllBaseFromMysteelChemicalClassify()
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
@@ -161,14 +161,14 @@ func (c *EdbInfoController) RefreshClassifyList() {
 			Children:     nil,
 		})
 		rootList, err := data_manage.GetBaseFromSmmClassifyByParentId(0)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
 		}
 
 		classifyAll, err := data_manage.GetAllBaseFromSmmClassify()
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
@@ -204,7 +204,7 @@ func (c *EdbInfoController) RefreshClassifyList() {
 
 	default:
 		tmpList, err := data_manage.GetAllEdbClassify()
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
@@ -262,11 +262,20 @@ func buildTree(items []*edb_refresh.BaseClassifyItems, parentId int) []*edb_refr
 // @router /edb_info/refresh/edb_list [get]
 func (c *EdbInfoController) RefreshEdbList() {
 	br := new(models.BaseResponse).Init()
-
 	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
 		c.Data["json"] = br
 		c.ServeJSON()
 	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
 
 	source, _ := c.GetInt("Source")
 	subSource, _ := c.GetInt("SubSource")
@@ -304,7 +313,7 @@ func (c *EdbInfoController) RefreshEdbList() {
 	startSize = utils.StartIndex(currentIndex, pageSize)
 
 	total, list, err := data.GetList(source, subSource, classifyId, terminalCode, sysUserId, frequency, keyword, status, startSize, pageSize, sortParam, sortType)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -359,7 +368,7 @@ func (c *EdbInfoController) GetEdbRefreshDefaultConfig() {
 	}
 
 	// 非有色的来源,频度不能为空
-	if source != utils.DATA_SOURCE_YS && frequency == `` {
+	if source != utils.DATA_SOURCE_YS && source != utils.DATA_SOURCE_RADISH_RESEARCH && frequency == `` {
 		br.Msg = "频度不能为空"
 		br.IsSendEmail = false
 		return
@@ -481,7 +490,7 @@ func (c *EdbInfoController) SaveEdbRefreshStatus() {
 	if req.IsSelectAll {
 		// 如果是列表全选
 		_, edbList, err := data.GetList(req.Source, req.SubSource, req.ClassifyId, req.TerminalCode, req.SysUserId, req.Frequency, req.Keyword, req.Status, 0, 100000, "", "")
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
@@ -529,7 +538,7 @@ func (c *EdbInfoController) SaveEdbRefreshStatus() {
 	if isStop == 1 {
 		fromEdbIdList := make([]int, 0)
 		edbList, e := data_manage.GetEdbInfoByIdList(edbIdList)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + e.Error()
 			return
@@ -598,7 +607,7 @@ func (c *EdbInfoController) SaveEdbRefreshStatusSingle() {
 	// 查询指标
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标不存在"
 			return
 		}
@@ -670,7 +679,7 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 	}
 	edbType := 1 //基础指标
 	switch req.Source {
-	case utils.DATA_SOURCE_MYSTEEL_CHEMICAL, utils.DATA_SOURCE_WIND: // wind
+	case utils.DATA_SOURCE_MYSTEEL_CHEMICAL, utils.DATA_SOURCE_WIND, utils.DATA_SOURCE_THS, utils.DATA_SOURCE_PB_FINANCE, utils.DATA_SOURCE_PB: // wind
 	case -1:
 		req.Source = 0
 		edbType = 2
@@ -681,11 +690,15 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 	// todo 批量设置刷新状态修改
 	edbIdList := make([]int, 0)
 	edbCodeList := make([]string, 0)
+	isStop := 0
+	if req.ModifyStatus == `暂停` {
+		isStop = 1
+	}
 	// 指标id列表
 	if req.IsSelectAll {
 		// 如果是列表全选
 		_, edbList, err := data.GetEdbRelationList(req.Source, edbType, req.ClassifyId, req.SysUserId, req.Frequency, req.Keyword, req.Status, 0, 100000, "", "")
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
@@ -703,12 +716,32 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 			if ok {
 				continue
 			}
-
+			if v.RelationNum > 0 && v.IsSupplierStop == 0 && isStop == 1 {
+				br.Msg = "保存失败,停用指标已被引用,指标ID:" + v.EdbCode + "指标名称:" + v.EdbName
+				br.ErrMsg = "保存失败,停用指标已被引用,指标ID:" + v.EdbCode + "指标名称:" + v.EdbName
+				return
+			}
 			// 加入到待配置的指标列表id
 			edbIdList = append(edbIdList, v.EdbInfoId)
 		}
 	} else {
 		edbIdList = req.EdbSelectIdList
+		_, edbRelationList, err := data.GetEdbRelationListByIds(edbIdList, req.Source)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbRelationList {
+			if v.RelationNum > 0 && v.IsSupplierStop == 0 && isStop == 1 {
+				br.Msg = "保存失败,停用指标已被引用,指标ID:" + v.EdbCode + "指标名称:" + v.EdbName
+				br.ErrMsg = "保存失败,停用指标已被引用,指标ID:" + v.EdbCode + "指标名称:" + v.EdbName
+				return
+			}
+			// 加入到待配置的指标列表id
+			// 加入到待配置的指标列表id
+			edbIdList = append(edbIdList, v.EdbInfoId)
+		}
 	}
 
 	if len(edbIdList) <= 0 {
@@ -718,12 +751,12 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 	}
 	//查询指标信息
 	edbList, e := data_manage.GetEdbInfoByIdList(edbIdList)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + e.Error()
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
-
+	//var edbList []*data_manage.EdbInfo
 	// 如果是钢联化工,那么需要过滤供应商暂停的指标
 	if req.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
 		// 获取未被供应商暂停的指标
@@ -751,7 +784,6 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
 		}
-
 		if len(edbList) <= 0 {
 			br.Ret = 200
 			br.Success = true
@@ -770,11 +802,6 @@ func (c *EdbInfoController) SaveRelationEdbRefreshStatus() {
 		}
 	}
 
-	isStop := 0
-	if req.ModifyStatus == `暂停` {
-		isStop = 1
-	}
-
 	// 查询计算指标ID
 	// 查询相关的计算指标
 	calculateEdbIdList := make([]int, 0)

+ 42 - 14
controllers/data_manage/edb_info_relation.go

@@ -80,7 +80,7 @@ func (c *EdbInfoRelationController) RelationEdbList() {
 	startSize = utils.StartIndex(currentIndex, pageSize)
 
 	total, list, err := data.GetEdbRelationList(source, edbType, classifyId, sysUserId, frequency, keyword, status, startSize, pageSize, sortParam, sortType)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -127,7 +127,7 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 	startSize = utils.StartIndex(currentIndex, pageSize)
 
 	total, relationList, err := data_manage.GetEdbInfoRelationDetailList(edbInfoId, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -144,6 +144,9 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 	// 查询事件日历
 	eventInfoIds := make([]int, 0)
 
+	// 预测指标
+	predictEdbIds := make([]int, 0)
+
 	for _, v := range relationList {
 		switch v.ReferObjectType {
 		case utils.EDB_RELATION_SANDBOX:
@@ -154,18 +157,21 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 			chartInfoIds = append(chartInfoIds, v.ReferObjectId)
 		case utils.EDB_RELATION_TABLE:
 			tableInfoIds = append(tableInfoIds, v.ReferObjectId)
+		case utils.EDB_RELATION_PREDICT_EDB:
+			predictEdbIds = append(predictEdbIds, v.ReferObjectId)
 		}
 	}
-	objectNameMap := make(map[int]string)
+	objectNameMap := make(map[string]string)
 	if len(sandboxIds) > 0 {
 		sandboxList, err := sandbox.GetSandboxNameByIds(sandboxIds)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取数据失败,Err:" + err.Error()
 			return
 		}
 		for _, v := range sandboxList {
-			objectNameMap[v.SandboxId] = v.Name
+			name := fmt.Sprintf("%d_%d", utils.EDB_RELATION_SANDBOX, v.SandboxId)
+			objectNameMap[name] = v.Name
 		}
 	}
 
@@ -176,26 +182,28 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 		pars := make([]interface{}, 0)
 		pars = append(pars, eventInfoIds)
 		eventList, err := matterOb.GetItemsByCondition(cond, pars, []string{}, "")
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取事件日历数据失败,Err:" + err.Error()
 			return
 		}
 		for _, v := range eventList {
-			objectNameMap[v.FeCalendarMatterId] = fmt.Sprintf("%s, %s", v.MatterDate, v.ChartPermissionName)
+			name := fmt.Sprintf("%d_%d", utils.EDB_RELATION_CALENDAR, v.FeCalendarMatterId)
+			objectNameMap[name] = fmt.Sprintf("%s, %s", v.MatterDate, v.ChartPermissionName)
 		}
 	}
 
 	// 查询图表
 	if len(chartInfoIds) > 0 {
 		chartList, err := data_manage.GetChartInfoByIdList(chartInfoIds)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表数据失败,Err:" + err.Error()
 			return
 		}
 		for _, v := range chartList {
-			objectNameMap[v.ChartInfoId] = v.ChartName
+			name := fmt.Sprintf("%d_%d", utils.EDB_RELATION_CHART, v.ChartInfoId)
+			objectNameMap[name] = v.ChartName
 		}
 	}
 
@@ -205,7 +213,7 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 		pars := make([]interface{}, 0)
 		pars = append(pars, tableInfoIds)
 		tableList, err := excel.GetNoContentExcelInfoListByConditionNoPage(cond, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取表格数据失败,Err:" + err.Error()
 			return
@@ -223,7 +231,7 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 			pars = make([]interface{}, 0)
 			pars = append(pars, parentIds)
 			parentList, err := excel.GetNoContentExcelInfoListByConditionNoPage(cond, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取表格数据失败,Err:" + err.Error()
 				return
@@ -233,16 +241,32 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 			}
 		}
 		for _, v := range tableList {
+			name := fmt.Sprintf("%d_%d", utils.EDB_RELATION_TABLE, v.ExcelInfoId)
 			if v.ParentId > 0 {
 				parentName := excelParentName[v.ParentId]
-				objectNameMap[v.ExcelInfoId] = fmt.Sprintf("%s_%s", parentName, v.ExcelName)
+				objectNameMap[name] = fmt.Sprintf("%s_%s", parentName, v.ExcelName)
 			} else {
-				objectNameMap[v.ExcelInfoId] = v.ExcelName
+				objectNameMap[name] = v.ExcelName
 			}
 		}
 	}
+
+	// 查询预测指标名称
+	if len(predictEdbIds) > 0 {
+		predictList, err := data_manage.GetEdbInfoByIdList(predictEdbIds)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取预测指标信息失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range predictList {
+			name := fmt.Sprintf("%d_%d", utils.EDB_RELATION_PREDICT_EDB, v.EdbInfoId)
+			objectNameMap[name] = v.EdbName
+		}
+	}
 	for _, v := range relationList {
-		referObjectName, _ := objectNameMap[v.ReferObjectId]
+		name := fmt.Sprintf("%d_%d", v.ReferObjectType, v.ReferObjectId)
+		referObjectName, _ := objectNameMap[name]
 		tmp := &data_manage.EdbInfoRelationDetail{
 			EdbInfoRelationId:  v.EdbInfoRelationId,
 			EdbInfoId:          v.EdbInfoId,
@@ -271,6 +295,8 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 				tmp.ReferObjectTypeName = "跨品种分析"
 			case utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
 				tmp.ReferObjectTypeName = "商品价格曲线"
+			case utils.CHART_SOURCE_RANGE_ANALYSIS:
+				tmp.ReferObjectTypeName = "区间分析"
 			}
 		case utils.EDB_RELATION_TABLE:
 			switch v.ReferObjectSubType {
@@ -281,6 +307,8 @@ func (c *EdbInfoRelationController) RelationEdbListDetail() {
 			case utils.BALANCE_TABLE:
 				tmp.ReferObjectTypeName = "平衡表"
 			}
+		case utils.EDB_RELATION_PREDICT_EDB:
+			tmp.ReferObjectTypeName = "预测指标"
 		}
 		list = append(list, tmp)
 	}

+ 3 - 2
controllers/data_manage/eia_steo.go

@@ -47,6 +47,7 @@ func (this *EdbInfoController) EiaSteoClassify() {
 	childClassifyMap := make(map[int][]*data_manage.BaseFromEiaSteoClassifyView)
 	rootList := make([]*data_manage.BaseFromEiaSteoClassifyView, 0)
 	for _, v := range classifyList {
+		v.UniqueCode = strconv.Itoa(v.BaseFromEiaSteoClassifyId)
 		if v.Level == 1 {
 			rootList = append(rootList, v)
 		} else {
@@ -556,7 +557,7 @@ func (c *EdbInfoController) EiaSteoNameCheck() {
 			EdbName: v.EdbName,
 		})
 		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_EIA_STEO, 0, utils.EDB_DATA_LIMIT)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
 			return
@@ -814,7 +815,7 @@ func (this *EdbInfoController) EiaSteoAdd() {
 
 	tmpInfo, err := data_manage.GetBaseFromEiaSteoIndexByCode(req.EdbCode)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取失败,Err:" + err.Error()
 			return

+ 21 - 10
controllers/data_manage/excel/balance_table.go

@@ -17,13 +17,14 @@ import (
 	excel2 "eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/tealeg/xlsx"
 	"io/ioutil"
 	"os"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/tealeg/xlsx"
 )
 
 // GetChildTable
@@ -505,7 +506,7 @@ func (c *ExcelInfoController) BalanceChartInfoAdd() {
 	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
 	if e != nil {
 		br.Msg = "操作失败"
-		br.ErrMsg = "获取系统用户数据失败,Err:" + err.Error()
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
 		return
 	}
 	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
@@ -712,7 +713,7 @@ func (c *ExcelInfoController) GetBalanceChartList() {
 	// 查询所有子表
 	excelInfo, err := excel.GetExcelInfoById(excelInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "表格不存在"
 			return
 		}
@@ -810,7 +811,7 @@ func (c *ExcelInfoController) DeleteBalanceChart() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -1146,6 +1147,11 @@ func (c *ExcelInfoController) AddStaticExcel() {
 	resp.ExcelInfoId = excelInfo.ExcelInfoId
 	resp.UniqueCode = excelInfo.UniqueCode
 
+	// 写入ES
+	go func() {
+		excel2.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "保存成功"
@@ -1413,13 +1419,18 @@ func downloadBalanceTable(excelInfo *excel.ExcelInfo, lang string) (savePath, zi
 				errMsg = msg
 				return
 			}
-			tableData, er := excel2.GetTableDataByMixedTableData(newResult, false)
+			tableData, er := excel2.GetTableDataByMixedTableData(newResult, false, childExcelInfo.ExcelInfoId)
 			if er != nil {
 				errMsg = "获取失败"
 				err = fmt.Errorf("转换成table失败,Err:" + err.Error())
 				return
 			}
-
+			//tableData, err = excel2.HandleRuleToTableCell(childExcelInfo.ExcelInfoId, tableData)
+			//if err != nil {
+			//	errMsg = "获取失败"
+			//	err = fmt.Errorf("处理条件格式管理规则失败,Err:%w", err)
+			//	return
+			//}
 			// 将单个sheet的数据写入到excel
 			err = tableData.WriteExcelSheetData(xlsxFile, childExcelInfo.ExcelName)
 			if err != nil {
@@ -1590,7 +1601,7 @@ func (this *ExcelInfoController) BalanceChartInfoBaseEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -1613,7 +1624,7 @@ func (this *ExcelInfoController) BalanceChartInfoBaseEdit() {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := excel.GetExcelChartEdbById(edbInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表不存在!"
 				br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 				return
@@ -1648,7 +1659,7 @@ func (this *ExcelInfoController) BalanceChartInfoBaseEdit() {
 
 			edbExist, err := excel.GetBalanceChartEdbByCondition(edbCondition, edbPars)
 			if err != nil {
-				if err.Error() != utils.ErrNoRow() {
+				if !utils.IsErrNoRow(err) {
 					br.Msg = "判断英文指标名称是否存在失败"
 					br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + err.Error()
 					return
@@ -1680,7 +1691,7 @@ func (this *ExcelInfoController) BalanceChartInfoBaseEdit() {
 
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return

+ 20 - 9
controllers/data_manage/excel/custom_analysis.go

@@ -13,6 +13,7 @@ import (
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/data/excel"
 	excel2 "eta/eta_api/services/data/excel"
+	excel3 "eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -61,7 +62,7 @@ func (c *CustomAnalysisController) ExcelByName() {
 	// 获取数据详情
 	excelDetail, err := excelModel.GetNoContentExcelInfoByName(excelName, utils.CUSTOM_ANALYSIS_TABLE, sysUser.AdminId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "获取成功"
@@ -224,6 +225,11 @@ func (c *CustomAnalysisController) Add() {
 	// 生成excel文件
 	go excel.UpdateExcelInfoFileUrl(excelInfo)
 
+	// 写入ES
+	go func() {
+		excel3.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+	}()
+
 	//新增操作日志
 	//{
 	//	excelLog := &data_manage.ExcelInfoLog{
@@ -344,6 +350,11 @@ func (c *CustomAnalysisController) Save() {
 	// 生成excel文件
 	go excel.UpdateExcelInfoFileUrl(excelInfo)
 
+	// 写入ES
+	go func() {
+		excel3.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+	}()
+
 	//新增操作日志
 	//{
 	//	excelLog := &data_manage.ExcelInfoLog{
@@ -402,7 +413,7 @@ func (c *CustomAnalysisController) BaseExcelDetail() {
 	// 获取数据详情
 	excelDetail, err := excelModel.GetNoContentExcelInfoByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "获取成功"
@@ -560,7 +571,7 @@ func (c *CustomAnalysisController) ExcelDataList() {
 	// 获取数据详情
 	excelDetail, err := excelModel.GetNoContentExcelInfoByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "获取成功"
@@ -785,7 +796,7 @@ func (c *CustomAnalysisController) ClassifyList() {
 		classifyMap[v.ExcelClassifyId] = v
 	}
 	allExcelInfo, err := excelModel.GetNoContentExcelInfoAll(source, sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 		return
@@ -948,14 +959,14 @@ func (c *CustomAnalysisController) List() {
 	// 筛选分类
 	if !isShare && excelClassifyId > 0 {
 		_, err := excelModel.GetExcelClassifyById(excelClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取表格信息失败"
 			br.ErrMsg = "获取信息失败,GetExcelClassify,Err:" + err.Error()
 			return
 		}
 
 		childClassify, e, _ := excel2.GetChildClassifyByClassifyId(excelClassifyId, source)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 			return
@@ -989,7 +1000,7 @@ func (c *CustomAnalysisController) List() {
 	}
 	startSize = paging.StartIndex(currentIndex, pageSize)
 	list, err := excelModel.GetNoContentExcelListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取表格信息失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
@@ -1002,7 +1013,7 @@ func (c *CustomAnalysisController) List() {
 
 	// 总数据量
 	dataCount, err := excelModel.GetExcelListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取表格列表信息失败"
 		br.ErrMsg = "获取表格列表数据总数失败,Err:" + err.Error()
 		return
@@ -1055,7 +1066,7 @@ func (c *CustomAnalysisController) Share() {
 
 	excelInfo, e := excelModel.GetExcelInfoById(req.ExcelInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "表格不存在, 请刷新页面"
 			return
 		}

+ 1 - 1
controllers/data_manage/excel/custom_analysis_edb.go

@@ -312,7 +312,7 @@ func (c *CustomAnalysisController) EditEdb() {
 
 	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标已被删除,请刷新页面"
 			br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error()
 			return

+ 24 - 15
controllers/data_manage/excel/excel_classify.go

@@ -9,6 +9,7 @@ import (
 	response2 "eta/eta_api/models/data_manage/excel/response"
 	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
+	excelService "eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
 	"sort"
@@ -87,14 +88,14 @@ func (this *ExcelClassifyController) List() {
 		}
 
 		allExcelInfo, err = excel.GetBalanceNoContentExcelInfoAll(source, excelIds, showUserId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 			return
 		}
 	} else {
 		allExcelInfo, err = excel.GetNoContentExcelInfoAll(source, showUserId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 			return
@@ -153,6 +154,9 @@ func (this *ExcelClassifyController) List() {
 			nodeAll = append(nodeAll, v)
 		}
 	}
+	if isShowMe {
+		nodeAll = excel2.GetClassifyListRemoveNoExcel(nodeAll)
+	}
 
 	resp := response2.ExcelClassifyListResp{
 		AllNodes: nodeAll,
@@ -193,7 +197,7 @@ func AnalysisClassifyList(this *ExcelClassifyController) (br *models.BaseRespons
 	// 获取三级分类
 	// 根据来源获取所有excel表格(无内容)
 	allExcelInfo, err := excel.GetNoContentExcelInfoAll(source, showUserId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 		return
@@ -429,7 +433,7 @@ func (this *ExcelClassifyController) AddExcelClassify() {
 		var parent *excel.ExcelClassify
 		parent, err = excel.GetExcelClassifyById(req.ParentId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "父级分类不存在"
 				return
 			}
@@ -574,7 +578,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 	// 校验是否存在该分类
 	ExcelClassifyInfo, err := excel.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "该分类不存在"
 			br.ErrMsg = "该分类不存在"
 			return
@@ -604,7 +608,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 			tipsMsg = "该分类下关联表格不可删除"
 		} else {
 			childClassify, e := excel.GetChildClassifyById(req.ExcelClassifyId)
-			if e != nil && e.Error() != utils.ErrNoRow() {
+			if e != nil && !utils.IsErrNoRow(e) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 				return
@@ -618,7 +622,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 				var pars []interface{}
 				pars = append(pars, classifyIds)
 				childCount, err := excel.GetExcelInfoCountByCondition(condition, pars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "查询分类下表格数量失败,Err:" + err.Error()
 					return
@@ -698,7 +702,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 	if req.ExcelClassifyId > 0 && req.ExcelInfoId == 0 {
 		//判断是否含有指标
 		count, err := excel.GetExcelInfoCountByClassifyId(req.ExcelClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -710,7 +714,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			return
 		} else {
 			childClassify, e := excel.GetChildClassifyById(req.ExcelClassifyId)
-			if e != nil && e.Error() != utils.ErrNoRow() {
+			if e != nil && !utils.IsErrNoRow(e) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 				return
@@ -724,7 +728,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 				var pars []interface{}
 				pars = append(pars, classifyIds)
 				childCount, err := excel.GetExcelInfoCountByCondition(condition, pars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "查询分类下表格数量失败,Err:" + err.Error()
 					return
@@ -741,7 +745,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 		if err != nil {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取分类失败,Err:" + err.Error()
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "分类不存在"
 				br.ErrMsg = "分类不存在"
 			}
@@ -761,7 +765,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 	if req.ExcelInfoId > 0 {
 		excelInfo, err := excel.GetExcelInfoById(req.ExcelInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "表格已删除,请刷新页面"
 				br.ErrMsg = "表格已删除,请刷新页面"
 				return
@@ -789,6 +793,11 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			return
 		}
 
+		// 写入ES
+		go func() {
+			excelService.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+		}()
+
 		// 返回下一个表格的信息
 		{
 			var nextItem *excel.ExcelInfo
@@ -805,7 +814,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			pars = append(pars, excelInfo.Sort, excelInfo.Sort, excelInfo.ExcelInfoId)
 
 			nextItem, err = excel.GetNextExcelInfoByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
 				return
@@ -814,14 +823,14 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			// 如果没找到,那么查找下一个分类的第一个表格
 			if nextItem == nil {
 				currClassifyInfo, err := excel.GetExcelClassifyById(excelInfo.ExcelClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取当前表格分类信息失败,Err:" + err.Error()
 					return
 				}
 
 				nextItem, err = excel.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort, currClassifyInfo.Source)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
 					return

+ 524 - 39
controllers/data_manage/excel/excel_info.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	excelPermissionModel "eta/eta_api/models/data_manage/data_manage_permission"
 	excel3 "eta/eta_api/models/data_manage/excel"
 	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/models/data_manage/excel/response"
@@ -13,6 +14,7 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
+	"eta/eta_api/services/elastic"
 	"eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
@@ -89,7 +91,7 @@ func (c *ExcelInfoController) Add() {
 	if req.ExcelClassifyId > 0 {
 		excelClassify, e := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				br.ErrMsg = "分类不存在"
 				br.IsSendEmail = false
@@ -110,7 +112,7 @@ func (c *ExcelInfoController) Add() {
 	if req.ParentId > 0 {
 		parentExcelInfo, e := excel3.GetExcelInfoById(req.ParentId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "父级ETA表格被删除,请刷新页面"
 				return
 			}
@@ -121,6 +123,18 @@ func (c *ExcelInfoController) Add() {
 		req.ExcelClassifyId = parentExcelInfo.ExcelClassifyId
 	}
 
+	// 额外配置(表格冻结行列等)
+	var extraConfig string
+	if req.ExtraConfig != nil {
+		b, e := json.Marshal(req.ExtraConfig)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("操作失败, %v", e)
+			return
+		}
+		extraConfig = string(b)
+	}
+
 	var condition string
 	var pars []interface{}
 	condition += " AND excel_classify_id=? AND parent_id=?"
@@ -257,6 +271,7 @@ func (c *ExcelInfoController) Add() {
 		UpdateUserId:       sysUser.AdminId,
 		UpdateUserRealName: sysUser.RealName,
 		SourcesFrom:        req.SourcesFrom,
+		ExtraConfig:        extraConfig,
 	}
 
 	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
@@ -293,6 +308,7 @@ func (c *ExcelInfoController) Add() {
 			//ParentId:           req.ParentId,
 			UpdateUserId:       sysUser.AdminId,
 			UpdateUserRealName: sysUser.RealName,
+			ExtraConfig:        extraConfig,
 		}
 	}
 	err = excel3.AddExcelInfo(excelInfo, excelEdbMappingList, childExcel)
@@ -336,6 +352,15 @@ func (c *ExcelInfoController) Add() {
 	//	go data_manage.AddExcelInfoLog(excelLog)
 	//}
 
+	// 写入ES
+	go func() {
+		excel.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+
+		if childExcel != nil && childExcel.ExcelInfoId > 0 {
+			excel.EsAddOrEditExcel(childExcel.ExcelInfoId)
+		}
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "保存成功"
@@ -373,10 +398,14 @@ func (c *ExcelInfoController) List() {
 
 	pageSize, _ := c.GetInt("PageSize")
 	currentIndex, _ := c.GetInt("CurrentIndex")
-	keyword := c.GetString("Keyword")
+	keyword := c.GetString("KeyWord")
 	adminId, _ := c.GetInt("AdminId")
 	source, _ := c.GetInt("Source")
 
+	if keyword == `` { // 兼容前端
+		keyword = c.GetString("Keyword")
+	}
+
 	var total int
 	page := paging.GetPaging(currentIndex, pageSize, total)
 
@@ -407,14 +436,14 @@ func (c *ExcelInfoController) List() {
 	// 筛选分类
 	if excelClassifyId > 0 {
 		_, err := excel3.GetExcelClassifyById(excelClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取表格信息失败"
 			br.ErrMsg = "获取信息失败,GetExcelClassify,Err:" + err.Error()
 			return
 		}
 
 		childClassify, e, _ := excel2.GetChildClassifyByClassifyId(excelClassifyId, source)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 			return
@@ -431,10 +460,27 @@ func (c *ExcelInfoController) List() {
 			pars = append(pars, classifyIds)
 		}
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( excel_name LIKE ? )`
-		pars = utils.GetLikeKeywordPars(pars, keyword, 1)
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` excel_name LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` excel_name LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
+
 	if adminId > 0 {
 		condition += " AND sys_user_id = ? "
 		pars = append(pars, adminId)
@@ -475,7 +521,7 @@ func (c *ExcelInfoController) List() {
 
 			//获取表格信息
 			tmpList, e := excel3.GetNoContentExcelListByConditionNoPage(newCondition, newPars)
-			if e != nil && e.Error() != utils.ErrNoRow() {
+			if e != nil && !utils.IsErrNoRow(e) {
 				br.Success = true
 				br.Msg = "获取表格信息失败"
 				br.ErrMsg = "获取表格信息失败,Err:" + e.Error()
@@ -533,7 +579,7 @@ func (c *ExcelInfoController) List() {
 	}
 	//获取表格信息
 	list, err := excel3.GetNoContentExcelListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取表格信息失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
@@ -541,7 +587,7 @@ func (c *ExcelInfoController) List() {
 	}
 
 	lenList := len(list)
-	if list == nil || lenList <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || lenList <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		list = make([]*excel3.MyExcelInfoList, 0)
 	}
 
@@ -592,13 +638,17 @@ func (c *ExcelInfoController) List() {
 				// excel表格按钮权限
 				list[k].Button = excel2.GetBalanceExcelInfoOpButton(sysUser.AdminId, v.SysUserId, v.HaveOperaAuth, v.ExcelInfoId)
 			}
+			// 持仓分析表格
+			if v.Source == utils.TRADE_ANALYSIS_TABLE || v.Source == utils.TRADE_ANALYSIS_CORRELATION_TABLE {
+				list[k].Button = services.GetTradeAnalysisTableOpButton(v.SysUserId, sysUser.AdminId, sysUser.RoleTypeCode, v.HaveOperaAuth)
+			}
 		}
 
 	}
 
 	// 总数据量
 	dataCount, err := excel3.GetExcelListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取表格列表信息失败"
 		br.ErrMsg = "获取表格列表数据总数失败,Err:" + err.Error()
 		return
@@ -849,7 +899,7 @@ func (c *ExcelInfoController) Edit() {
 	if req.ExcelClassifyId > 0 {
 		excelClassify, e := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				br.ErrMsg = "分类不存在"
 				br.IsSendEmail = false
@@ -869,7 +919,7 @@ func (c *ExcelInfoController) Edit() {
 	if excelInfo.ParentId > 0 {
 		parentExcelInfo, e := excel3.GetExcelInfoById(excelInfo.ParentId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "父级ETA表格被删除,请刷新页面"
 				return
 			}
@@ -1021,6 +1071,18 @@ func (c *ExcelInfoController) Edit() {
 		updateExcelInfoParams = []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "Content", "SourcesFrom"}
 	}
 
+	// 额外配置(表格冻结行列等)
+	if req.ExtraConfig != nil {
+		b, e := json.Marshal(req.ExtraConfig)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("操作失败, %v", e)
+			return
+		}
+		excelInfo.ExtraConfig = string(b)
+		updateExcelInfoParams = append(updateExcelInfoParams, "ExtraConfig")
+	}
+
 	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
 	if len(edbInfoIdList) > 0 {
 		for _, edbInfoId := range edbInfoIdList {
@@ -1070,6 +1132,16 @@ func (c *ExcelInfoController) Edit() {
 		err = excel3.AddExcelDraft(excelDraftInfo)
 	}
 
+	// 判断是否清除该表引用
+	if req.IsColChange {
+		err = excel3.DeleteReferencedExcelConfig(excelInfo.UniqueCode)
+		if err != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = err.Error()
+			return
+		}
+	}
+
 	resp := response.AddExcelInfoResp{
 		ExcelInfoId: excelInfo.ExcelInfoId,
 		UniqueCode:  excelInfo.UniqueCode,
@@ -1079,6 +1151,11 @@ func (c *ExcelInfoController) Edit() {
 	//删除公共图库那边的缓存
 	_ = utils.Rc.Delete(utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode)
 
+	// 写入ES
+	go func() {
+		excel.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "修改成功"
@@ -1134,7 +1211,7 @@ func (c *ExcelInfoController) Move() {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取分类信息失败" + err.Error()
 
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "分类已被删除,不可移动,请刷新页面"
 				br.ErrMsg = "分类已被删除,不可移动,请刷新页面"
 				br.IsSendEmail = false
@@ -1343,7 +1420,7 @@ func (c *ExcelInfoController) Delete() {
 		condition += " AND sort>=? "
 		pars = append(pars, excelInfo.Sort)
 		nextItem, err = excel3.GetNextExcelInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
 			return
@@ -1352,7 +1429,7 @@ func (c *ExcelInfoController) Delete() {
 		// 如果没找到,那么查找下一个分类的第一个表格
 		if nextItem == nil {
 			currClassifyInfo, err := excel3.GetExcelClassifyById(excelInfo.ExcelClassifyId)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取当前表格分类信息失败,Err:" + err.Error()
 				return
@@ -1381,7 +1458,7 @@ func (c *ExcelInfoController) Delete() {
 			//}
 
 			nextItem, err = excel3.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort, currClassifyInfo.Source)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
 				return
@@ -1400,6 +1477,11 @@ func (c *ExcelInfoController) Delete() {
 	//删除公共图库那边的缓存
 	_ = utils.Rc.Delete(utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL)
 
+	// 写入ES
+	go func() {
+		excel.EsAddOrEditExcel(excelInfo.ExcelInfoId)
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.IsAddLog = true
@@ -1451,7 +1533,7 @@ func (c *ExcelInfoController) AddDraft() {
 
 	excelClassify, err := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			br.IsSendEmail = false
@@ -1535,6 +1617,8 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 	uniqueCode := c.GetString("UniqueCode")
 	fromScene, _ := c.GetInt("FromScene", 0)
+	referencedId, _ := c.GetInt("ReferencedId", 0)
+	uuid := c.GetString("Uuid")
 
 	var err error
 	if uniqueCode == `` {
@@ -1548,7 +1632,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取ETA表格信息失败,Err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "ETA表格被删除,请刷新页面"
 			br.ErrMsg = "ETA表格被删除,请刷新页面,Err:" + err.Error()
 			br.IsSendEmail = false
@@ -1600,7 +1684,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 		}
 		excelSource = strings.Join(sourceNameList, ",")
 		excelSourceEn = strings.Join(sourceNameEnList, ",")
-	case utils.MIXED_TABLE:
+	case utils.MIXED_TABLE, utils.BALANCE_TABLE:
 		var result request.MixedTableReq
 		err = json.Unmarshal([]byte(excelInfo.Content), &result)
 		if err != nil {
@@ -1617,7 +1701,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
-		tableData, err = excel.GetTableDataByMixedTableData(newResult, true)
+		tableData, err = excel.GetTableDataByMixedTableData(newResult, true, excelInfo.ExcelInfoId)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
@@ -1646,7 +1730,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 
 	tableData = excel.HandleTableCell(tableData)
-	tableData, err = excel.HandleRuleToTableCell(excelInfo.ExcelInfoId, tableData)
+	// tableData, err = excel.HandleRuleToTableCell(excelInfo.ExcelInfoId, tableData)
 	if err != nil {
 		utils.FileLog.Info("表格管理规则处理失败,HandleRuleToTableCell err:", err.Error())
 	}
@@ -1666,15 +1750,26 @@ func (c *ExcelInfoController) GetExcelTableData() {
 		}
 	}
 
+	// 获取表格引用
+	reference, err := excel3.GetReferencedExcelConfig(referencedId, fromScene, uniqueCode, uuid)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取表格引用失败,Err:" + err.Error()
+		return
+	}
+
 	resp := response.ExcelTableDetailResp{
-		UniqueCode:    excelInfo.UniqueCode,
-		ExcelImage:    excelInfo.ExcelImage,
-		ExcelName:     excelInfo.ExcelName,
-		TableInfo:     tableData,
-		Config:        config,
-		SourcesFrom:   excelInfo.SourcesFrom,
-		ExcelSource:   excelSource,
-		ExcelSourceEn: excelSourceEn,
+		UniqueCode:            excelInfo.UniqueCode,
+		ExcelImage:            excelInfo.ExcelImage,
+		ExcelName:             excelInfo.ExcelName,
+		TableInfo:             tableData,
+		Config:                config,
+		SourcesFrom:           excelInfo.SourcesFrom,
+		ExcelSource:           excelSource,
+		ExcelSourceEn:         excelSourceEn,
+		ExcelInfoId:           excelInfo.ExcelInfoId,
+		Source:                excelInfo.Source,
+		ReferencedExcelConfig: reference,
 	}
 	br.Ret = 200
 	br.Success = true
@@ -2569,7 +2664,7 @@ func (c *ExcelInfoController) Download() {
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取ETA表格信息失败,Err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "ETA表格被删除,请刷新页面"
 			br.ErrMsg = "ETA表格被删除,请刷新页面,Err:" + err.Error()
 			br.IsSendEmail = false
@@ -2624,12 +2719,18 @@ func (c *ExcelInfoController) Download() {
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
-		tableData, err = excel.GetTableDataByMixedTableData(newResult, false)
+		tableData, err = excel.GetTableDataByMixedTableData(newResult, false, excelInfo.ExcelInfoId)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
+		//tableData, err = excel.HandleRuleToTableCell(excelInfo.ExcelInfoId, tableData)
+		//if err != nil {
+		//	br.Msg = "获取失败"
+		//	br.ErrMsg = "处理条件格式管理规则失败,Err:" + err.Error()
+		//	return
+		//}
 	case utils.BALANCE_TABLE: // 混合表格
 		savePath, fileName, uploadDir, err, errMsg := downloadBalanceTable(excelInfo, c.Lang)
 		if err != nil {
@@ -3003,7 +3104,7 @@ func (c *ExcelInfoController) BatchRefresh() {
 	syncing, e := data.BatchRefreshEdbByEdbIds(edbIds, redisKey, refreshKeys)
 	if e != nil {
 		br.Msg = "刷新失败"
-		br.ErrMsg = "刷新表格关联指标信息失败,Err:" + err.Error()
+		br.ErrMsg = "刷新表格关联指标信息失败,Err:" + e.Error()
 		return
 	}
 
@@ -3206,12 +3307,10 @@ func (c *ExcelInfoController) EditExcelRule() {
 		br.Msg = "应用选区不能为空"
 		return
 	}
-	if req.FontColor == "" {
-		br.Msg = "字体颜色不能为空"
-		return
-	}
-	if req.BackgroundColor == "" {
-		br.Msg = "背景颜色不能为空"
+	req.BackgroundColor = strings.TrimSpace(req.BackgroundColor)
+	req.FontColor = strings.TrimSpace(req.FontColor)
+	if req.FontColor == "" && req.BackgroundColor == "" {
+		br.Msg = "字体颜色或背景颜色不能同时为空"
 		return
 	}
 	if req.RuleType == 3 && req.RightValue == "" {
@@ -3349,3 +3448,389 @@ func (c *ExcelInfoController) GetExcelRuleDetail() {
 	br.Ret = 200
 	br.Success = true
 }
+
+// SearchByEs
+// @Title ES搜索
+// @Description ES搜索
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   Keyword   query   string  true       "搜索关键词"
+// @Param   Source   query   int  true       "格来源,1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"
+// @Param   IsShowMe   query   bool  false       "是否只看我的,true、false"
+// @Param   IsShare   query   bool  false       "是否只看我的,true、false"
+// @Success 200 {object} response.ExcelListResp
+// @router /excel_info/search_by_es [get]
+func (c *ExcelInfoController) SearchByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	source, _ := c.GetInt("Source")
+	if source <= 0 {
+		source = utils.EXCEL_DEFAULT
+	}
+	isShowMe, _ := c.GetBool("IsShowMe")
+	isShare, _ := c.GetBool("IsShare")
+	keyword := c.GetString("KeyWord")
+	if keyword == `` {
+		keyword = c.GetString("Keyword")
+	}
+
+	var total, startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	// 平衡表的查询条件
+	//var condBalance string
+	//var parsBalance []interface{}
+	//if source == utils.BALANCE_TABLE {
+	//	condBalance += ` AND source = ? AND parent_id = 0 AND balance_type = 0` // 只显示动态表的一级表(不显示子表和静态表)
+	//	parsBalance = append(parsBalance, source)
+	//}
+
+	// 可见性过滤
+	var queryIds, exceptIds []int
+
+	// 自定义分析表
+	var queryAdminId int
+	if source == utils.CUSTOM_ANALYSIS_TABLE {
+		// 自定义分析共享表格
+		if isShare {
+			var kw string
+			if keyword != "" {
+				kw = fmt.Sprint("%", kw, "%")
+			}
+			// 查询我分享的/分享给我的表格
+			excels, e := excelPermissionModel.GetAdminAuthExcelInfoPermission(source, sysUser.AdminId, kw)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("获取我分享的/分享给我的表格失败, %v", e)
+				return
+			}
+			var excelIds []int
+			for _, v := range excels {
+				id := int(v.ExcelInfoId)
+				if !utils.InArrayByInt(excelIds, id) {
+					excelIds = append(excelIds, id)
+					continue
+				}
+			}
+			if len(excelIds) == 0 {
+				list := make([]*excel3.SearchExcelInfo, 0)
+				resp := response.SearchExcelListResp{
+					Paging: page,
+					List:   list,
+				}
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				br.Data = resp
+				return
+			}
+			queryIds = excelIds
+		} else {
+			// 非共享只看我的
+			isShowMe = true
+		}
+	}
+
+	// 获取所有有权限的指标和分类
+	permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserExcelAndClassifyPermissionList(c.SysUser.AdminId, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+		return
+	}
+	hasCheck := make(map[int]bool)
+	if isShowMe {
+		if source == utils.BALANCE_TABLE { //平衡表的,显示同时需要显示协作人相关的图表
+			//找到当前协作人相关的表格ID
+			obj := new(excel3.ExcelWorker)
+			existList, err := obj.GetBySysUserId(sysUser.AdminId)
+			if err != nil {
+				br.Msg = "获取表格协作人失败!"
+				br.ErrMsg = "获取表格协作人失败,Err:" + err.Error()
+				return
+			}
+			var excelIds []int
+			var newCondition string
+			var newPars []interface{}
+			if len(existList) > 0 {
+				for _, v := range existList {
+					excelIds = append(excelIds, v.ExcelInfoId)
+				}
+				newCondition += fmt.Sprintf(` AND source = ? AND (excel_info_id IN (%s) or sys_user_id = ?)`, utils.GetOrmInReplace(len(excelIds)))
+				newPars = append(newPars, source, excelIds, sysUser.AdminId)
+			} else {
+				newCondition += ` AND sys_user_id = ? `
+				newPars = append(newPars, sysUser.AdminId)
+			}
+
+			//获取表格信息
+			tmpList, e := excel3.GetNoContentExcelListByConditionNoPage(newCondition, newPars)
+			if e != nil && !utils.IsErrNoRow(e) {
+				br.Success = true
+				br.Msg = "获取表格信息失败"
+				br.ErrMsg = "获取表格信息失败,Err:" + e.Error()
+				return
+			}
+			classifyIdListTmp := make([]int, 0)
+			for _, v := range tmpList {
+				classifyIdListTmp = append(classifyIdListTmp, v.ExcelClassifyId)
+			}
+			classifyMap := make(map[int]*excel3.ExcelClassify)
+
+			// 分类信息
+			if len(classifyIdListTmp) > 0 {
+				classifyListTmp, e := excel3.GetClassifyByIdList(classifyIdListTmp)
+				if e != nil {
+					br.Msg = "获取表格分类信息失败"
+					br.ErrMsg = "获取表格分类列表数据失败,Err:" + e.Error()
+					return
+				}
+				for _, v := range classifyListTmp {
+					classifyMap[v.ExcelClassifyId] = v
+				}
+			}
+			excelIds = make([]int, 0)
+			for _, v := range tmpList {
+				// 数据权限
+				if classifyInfo, ok := classifyMap[v.ExcelClassifyId]; ok {
+					v.HaveOperaAuth = data_manage_permission.CheckExcelPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.ExcelInfoId, v.ExcelClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					if v.HaveOperaAuth {
+						excelIds = append(excelIds, v.ExcelInfoId)
+					}
+					hasCheck[v.ExcelInfoId] = v.HaveOperaAuth
+				}
+			}
+			if len(excelIds) > 0 {
+				queryIds = excelIds
+			} else {
+				list := make([]*excel3.MyExcelInfoList, 0)
+				resp := response.ExcelListResp{
+					Paging: page,
+					List:   list,
+				}
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				br.Data = resp
+				return
+			}
+
+		} else {
+			queryAdminId = sysUser.AdminId
+		}
+	}
+
+	// es搜索表格
+	t, list, e := elastic.SearchExcelInfoData(utils.EsExcelIndexName, keyword, source, queryAdminId, queryIds, exceptIds, startSize, pageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("搜索表格失败, %v", e)
+		return
+	}
+	total = int(t)
+
+	if len(list) > 0 {
+		classifyIdList := make([]int, 0)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ExcelClassifyId)
+
+		}
+		classifyMap := make(map[int]*excel3.ExcelClassify)
+
+		// 分类信息
+		{
+			classifyList, err := excel3.GetClassifyByIdList(classifyIdList)
+			if err != nil {
+				br.Msg = "获取表格列表信息失败"
+				br.ErrMsg = "获取表格分类列表数据失败,Err:" + err.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ExcelClassifyId] = v
+			}
+		}
+
+		for k, v := range list {
+			// 数据权限
+			if authCheck, ok1 := hasCheck[v.ExcelInfoId]; ok1 {
+				v.HaveOperaAuth = authCheck
+			} else {
+				if classifyInfo, ok := classifyMap[v.ExcelClassifyId]; ok {
+					v.HaveOperaAuth = data_manage_permission.CheckExcelPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.ExcelInfoId, v.ExcelClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				}
+			}
+			if v.Source == utils.BALANCE_TABLE {
+				// 处理按钮权限和编辑状态
+				markStatus, err := services.UpdateExcelEditMark(v.ExcelInfoId, sysUser.AdminId, 2, sysUser.RealName)
+				if err != nil {
+					br.Msg = "查询标记状态失败"
+					br.ErrMsg = "查询标记状态失败,Err:" + err.Error()
+					return
+				}
+				if markStatus.Status == 0 {
+					list[k].CanEdit = true
+				} else {
+					list[k].Editor = markStatus.Editor
+				}
+
+				// excel表格按钮权限
+				list[k].Button = excel2.GetBalanceExcelInfoOpButton(sysUser.AdminId, v.SysUserId, v.HaveOperaAuth, v.ExcelInfoId)
+			}
+		}
+	}
+
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp := response.SearchExcelListResp{
+		Paging: page,
+		List:   list,
+	}
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// GetExcelReferenceDetail
+// @Title 表格引用配置详情
+// @Description 表格引用配置详情
+// @Param   ExcelInfoRuleMappingId   query   int  true       "id"
+// @Success Ret=200 获取成功
+// @router /excel_info/reference/detail [get]
+//func (c *ExcelInfoController) GetExcelReferenceDetail() {
+//	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
+//	}
+//	excelReferenceCode := c.GetString("ExcelReferenceCode")
+//
+//	item, err := excel3.GetReferencedExcelConfigByUniqueCode(excelReferenceCode)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取规则"
+//		br.ErrMsg = "管理规则添加失败,Err:" + err.Error()
+//		return
+//	}
+//
+//	br.Data = item
+//	br.Msg = "获取成功"
+//	br.Ret = 200
+//	br.Success = true
+//}
+
+// GetExcelReferenceDetail
+// @Title 表格引用配置保存
+// @Description 表格引用配置保存
+// @Param   ExcelInfoRuleMappingId   query   int  true       "id"
+// @Success Ret=200 获取成功
+// @router /excel_info/reference/save [post]
+func (c *ExcelInfoController) SaveExcelReference() {
+	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
+	}
+	var req excel3.ExcelReferencesReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	addList := make([]*excel3.ReferencedExcelConfig, 0)
+
+	exist, e := excel3.GetReferencedExcelConfig(req.ReferencedId, req.FromScene, req.UniqueCode, req.Uuid)
+	if e != nil && !utils.IsErrNoRow(e) {
+		br.Msg = "查找引用失败"
+		br.ErrMsg = "查找引用失败,Err:" + e.Error()
+		return
+	}
+	if exist.ReferencedExcelConfigId == 0 {
+		item := excel3.ReferencedExcelConfig{
+			UniqueCode:   req.UniqueCode,
+			ReferencedId: req.ReferencedId,
+			FromScene:    req.FromScene,
+			Uuid:         req.Uuid,
+			WidthList:    req.WidthList,
+			HeightList:   req.HeightList,
+			OpUserId:     sysUser.AdminId,
+			OpUserName:   sysUser.RealName,
+			CreateTime:   time.Now(),
+			ModifyTime:   time.Now(),
+		}
+		addList = append(addList, &item)
+	} else {
+		exist.WidthList = req.WidthList
+		exist.HeightList = req.HeightList
+		exist.OpUserId = sysUser.AdminId
+		exist.OpUserName = sysUser.RealName
+		exist.ModifyTime = time.Now()
+		err = excel3.UpdateReferencedExcelConfig(&exist)
+		if err != nil {
+			br.Msg = "更新引用失败"
+			br.ErrMsg = "更新引用失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	if len(addList) > 0 {
+		err = excel3.AddReferencedExcelConfig(addList)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "添加引用失败"
+			br.ErrMsg = "添加引用失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	excelInfo, err := excel3.GetExcelInfoByUnicode(req.UniqueCode)
+	if err != nil {
+		br.Msg = "获取表格信息失败"
+		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
+		return
+	}
+	if excelInfo.ExcelInfoId > 0 {
+		//删除公共图库那边的缓存
+		_ = utils.Rc.Delete(utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode)
+	}
+
+	br.Msg = "添加成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 2 - 2
controllers/data_manage/factor_edb_series.go

@@ -328,7 +328,7 @@ func (this *FactorEdbSeriesController) Edit() {
 	seriesOb := new(data_manage.FactorEdbSeries)
 	seriesItem, e := seriesOb.GetItemById(req.SeriesId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "该因子指标系列不存在"
 			return
 		}
@@ -460,7 +460,7 @@ func (this *FactorEdbSeriesController) Detail() {
 	seriesOb := new(data_manage.FactorEdbSeries)
 	series, e := seriesOb.GetItemById(seriesId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "该因子指标系列不存在"
 			return
 		}

+ 52 - 29
controllers/data_manage/fenwei_data.go

@@ -173,36 +173,53 @@ func (this *EdbInfoController) FenweiIndexData() {
 	}
 
 	resultList := make([]*data_manage.BaseFromFenweiIndexList, 0)
-	for _, v := range indexes {
-		product := new(data_manage.BaseFromFenweiIndexList)
-		product.FenweiIndexId = v.FenweiIndexId
-		product.ClassifyId = v.ClassifyId
-		product.Unit = v.Unit
-		product.IndexCode = v.IndexCode
-		product.IndexName = v.IndexName
-		product.Frequency = v.Frequency
-		product.CreateTime = v.CreateTime
-		product.ModifyTime = v.ModifyTime
-
-		edbInfo := edbCodeMap[v.IndexCode]
-		if edbInfo != nil {
-			product.EdbInfoId = edbInfo.EdbInfoId
-		}
-
-		total := countMap[v.IndexCode]
-		page := paging.GetPaging(currentIndex, pageSize, total)
-		dataList, e := data_manage.GetFenweiIndexData(v.IndexCode, startSize, pageSize)
-		if e != nil {
-			br.Msg = "获取数据失败"
-			br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+	if indexes != nil {
+		// 获取指标数据最新更新时间
+		lastModifyTimeList, err := data_manage.GetFenWeiDataLastModifyTimeList(indexCodes)
+		if err != nil {
 			return
 		}
-		if dataList == nil {
-			dataList = make([]*data_manage.BaseFromFenweiData, 0)
+		lastModifyTimeMap := make(map[string]string)
+		for _, v := range lastModifyTimeList {
+			lastModifyTimeMap[v.IndexCode] = v.ModifyTime
+		}
+
+		for _, v := range indexes {
+			product := new(data_manage.BaseFromFenweiIndexList)
+			product.FenweiIndexId = v.FenweiIndexId
+			product.ClassifyId = v.ClassifyId
+			product.Unit = v.Unit
+			product.IndexCode = v.IndexCode
+			product.IndexName = v.IndexName
+			product.Frequency = v.Frequency
+			product.CreateTime = v.CreateTime
+
+			if lastModifyTimeMap[v.IndexCode] != "" {
+				product.ModifyTime = lastModifyTimeMap[v.IndexCode]
+			} else {
+				product.ModifyTime = ""
+			}
+
+			edbInfo := edbCodeMap[v.IndexCode]
+			if edbInfo != nil {
+				product.EdbInfoId = edbInfo.EdbInfoId
+			}
+
+			total := countMap[v.IndexCode]
+			page := paging.GetPaging(currentIndex, pageSize, total)
+			dataList, e := data_manage.GetFenweiIndexData(v.IndexCode, startSize, pageSize)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			if dataList == nil {
+				dataList = make([]*data_manage.BaseFromFenweiData, 0)
+			}
+			product.DataList = dataList
+			product.Paging = page
+			resultList = append(resultList, product)
 		}
-		product.DataList = dataList
-		product.Paging = page
-		resultList = append(resultList, product)
 	}
 
 	br.Ret = 200
@@ -318,8 +335,14 @@ func (this *EdbInfoController) FenweiSingleData() {
 	ret.IndexName = indexInfo.IndexName
 	ret.Frequency = indexInfo.Frequency
 	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
-	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
 	ret.Unit = indexInfo.Unit
+	// 获取数据最新更新时间
+	lastModifyTimeList, err := data_manage.GetFenWeiDataLastModifyTimeList([]string{indexInfo.IndexCode})
+	if err != nil {
+		return
+	}
+	ret.ModifyTime = lastModifyTimeList[0].ModifyTime
+
 	for _, v := range dataTmpList {
 		tmp := &data_manage.FenweiSingleData{
 			Value:    v.Value,
@@ -921,7 +944,7 @@ func (this *EdbInfoController) FenWeiIndexDataExport() {
 
 			var dataList []*data_manage.BaseFromFenweiData
 			dataList, err = data_manage.GetBaseFromFenWeiDataByIndexCode(v.IndexCode)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.ErrMsg = "GetBaseFromFenWeiDataByIndexCode,Err:" + err.Error()
 				br.Msg = "获取数据失败"
 				return

+ 15 - 0
controllers/data_manage/fix.go

@@ -0,0 +1,15 @@
+package data_manage
+
+func init() {
+
+	// 刷新指标
+	//data.AddOrEditAllEdbInfoToEs()
+
+	// 修复ETA图库
+	//data.AddAllChartInfo()
+
+	// 修复我的图库
+	//data.AddAllMyChartInfo()
+	//
+	//fmt.Println("修复完成")
+}

+ 19 - 16
controllers/data_manage/future_good/future_good_chart_classify.go

@@ -36,7 +36,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -67,14 +67,14 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 	}
 
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT})
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -108,13 +108,13 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -124,16 +124,19 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 		chartInfoMap[v.ChartClassifyId] = append(chartInfoMap[v.ChartClassifyId], v)
 	}
 	rootChildMap := make(map[int][]*data_manage.ChartClassifyItems)
+	res := make([]*data_manage.ChartClassifyItems, 0)
 	for _, v := range rootList {
 		rootChildMap[v.ParentId] = append(rootChildMap[v.ParentId], v)
 		if existItems, ok := chartInfoMap[v.ChartClassifyId]; ok {
 			v.Children = existItems
 		} else {
-			items := make([]*data_manage.ChartClassifyItems, 0)
-			v.Children = items
+			// items := make([]*data_manage.ChartClassifyItems, 0)
+			// v.Children = items
+			continue
 		}
+		res = append(res, v)
 	}
-	resp.AllNodes = rootList
+	resp.AllNodes = res
 
 	return
 }
@@ -200,7 +203,7 @@ func (this *FutureGoodChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, 0, req.Level, utils.CHART_SOURCE_FUTURE_GOOD, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, 0, req.Level, utils.CHART_SOURCE_FUTURE_GOOD, 0, this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -304,7 +307,7 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -366,7 +369,7 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -390,7 +393,7 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassify() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -452,7 +455,7 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -472,14 +475,14 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -614,7 +617,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartClassifyByParentId(chartClassifyInfo.ParentId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return

+ 152 - 100
controllers/data_manage/future_good/future_good_chart_info.go

@@ -16,13 +16,14 @@ import (
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"os"
 	"os/exec"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // FutureGoodChartInfoController 商品价格图表管理
@@ -81,7 +82,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
@@ -89,8 +90,25 @@ func (this *FutureGoodChartInfoController) ChartList() {
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 		//pars = append(pars, chartClassifyId)
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -105,7 +123,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -123,7 +141,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -131,7 +149,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -175,7 +193,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -186,7 +204,7 @@ func (this *FutureGoodChartInfoController) ChartList() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -236,7 +254,7 @@ func (this *FutureGoodChartInfoController) ChartInfoSave() {
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面!"
 			br.ErrMsg = "图表已被删除,请刷新页面,ChartInfoId:" + strconv.Itoa(req.ChartInfoId)
 			return
@@ -345,7 +363,7 @@ func (this *FutureGoodChartInfoController) ChartInfoAdd() {
 
 	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -387,7 +405,7 @@ func (this *FutureGoodChartInfoController) ChartInfoAdd() {
 		if v.Source == utils.CHART_SOURCE_DEFAULT { //ETA指标
 			edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "指标不存在!"
 					br.ErrMsg = "指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId)
 					return
@@ -415,7 +433,7 @@ func (this *FutureGoodChartInfoController) ChartInfoAdd() {
 		} else { // 商品指标
 			edbInfo, err := future_good.GetFutureGoodEdbInfo(edbInfoId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "指标不存在!"
 					br.ErrMsg = "指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId)
 					return
@@ -630,7 +648,7 @@ func (this *FutureGoodChartInfoController) ChartInfoEdit() {
 
 	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -646,7 +664,7 @@ func (this *FutureGoodChartInfoController) ChartInfoEdit() {
 	}
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -708,7 +726,7 @@ func (this *FutureGoodChartInfoController) ChartInfoEdit() {
 		if v.Source == utils.CHART_SOURCE_DEFAULT { //ETA指标
 			edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "图表不存在!"
 					br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId)
 					return
@@ -728,7 +746,7 @@ func (this *FutureGoodChartInfoController) ChartInfoEdit() {
 		} else { //商品指标
 			edbInfo, err := future_good.GetFutureGoodEdbInfo(edbInfoId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "指标不存在!"
 					br.ErrMsg = "指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId)
 					return
@@ -844,7 +862,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -878,7 +896,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 	//校验指标信息是否存在
 	edbInfo, err := data_manage.GetEdbInfoById(edbInfoMapping.EdbInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表不存在!"
 			br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoMapping.EdbInfoId)
 			return
@@ -908,7 +926,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -933,7 +951,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 			}
 			futureGoodEdbInfo, err := future_good.GetFutureGoodEdbInfo(futureGoodEdbInfoMapping.EdbInfoId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "图表不存在!"
 					br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoMapping.EdbInfoId)
 					return
@@ -949,7 +967,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 				return
 			}
 
-			list, _ := future_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfo.FutureGoodEdbInfoId)
+			/*list, _ := future_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfo.FutureGoodEdbInfoId)
 			for _, v := range list {
 				if v.FutureGoodEdbNameEn == `` {
 					v.FutureGoodEdbNameEn = strings.TrimPrefix(req.FutureGoodNameEn, " ")
@@ -959,7 +977,7 @@ func (this *FutureGoodChartInfoController) ChartEnInfoEdit() {
 					v.FutureGoodEdbNameEn = strings.TrimSuffix(req.FutureGoodNameEn, " ")
 				}
 				v.Update([]string{"FutureGoodEdbNameEn"})
-			}
+			}*/
 		}
 	case utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
 		err = data_manage.EditFutureGoodProfitChartEnInfoAndEdbEnInfo(req.ChartInfoId, req.ChartNameEn, edbInfo.EdbInfoId, req.EdbNameEn, req.UnitEn, req.ProfitNameEn)
@@ -1022,7 +1040,7 @@ func (this *FutureGoodChartInfoController) ChartInfoNewest() {
 		this.ServeJSON()
 	}()
 	item, err := data_manage.GetChartInfoByNewest(2)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取最新图表失败"
 		br.ErrMsg = "获取最新图表失败,Err:" + err.Error()
 		return
@@ -1095,12 +1113,12 @@ func (this *FutureGoodChartInfoController) ChartInfoMove() {
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
 		tmpChartInfo, tmpErr := data_manage.GetChartInfoByClassifyIdAndName(req.ChartClassifyId, chartInfo.ChartName)
-		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
 			return
 		}
-		if tmpChartInfo != nil {
+		if tmpChartInfo != nil && tmpChartInfo.ChartInfoId > 0 {
 			br.Msg = "移动失败,同一个分类下图表名称不允许重复"
 			br.ErrMsg = "移动失败,同一个分类下图表名称不允许重复"
 			return
@@ -1154,7 +1172,7 @@ func (this *FutureGoodChartInfoController) ChartInfoMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
@@ -1266,7 +1284,7 @@ func (this *FutureGoodChartInfoController) ChartInfoDetail() {
 	if chartInfoId > 0 {
 		chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图被删除,请刷新页面"
 				br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 				return
@@ -1310,7 +1328,7 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 	}
 	futureGoodEdbInfoMapping, err = data_manage.GetFutureGoodEdbChartEdbMapping(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "期货指标不存在"
 			return
 		}
@@ -1332,16 +1350,16 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 		return
 	}
 
-	maxYear := 0
+	var maxDate time.Time
 	for _, v := range edbInfoMappingList {
 		if v.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, v.LatestDate)
-			if maxYear < latestDateT.Year() {
-				maxYear = latestDateT.Year()
+			if latestDateT.After(maxDate) {
+				maxDate = latestDateT
 			}
 		}
 	}
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 
 	// 商品价格曲线图的一些配置
 	var barConfig data_manage.FutureGoodBarChartInfoReq
@@ -1364,6 +1382,7 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 		// 默认取第一个现货指标
 		baseEdbInfoId = edbInfoMappingList[0].EdbInfoId
 		baseEdbInfoMapping = edbInfoMappingList[0]
+		barConfig.BaseEdbInfoId = baseEdbInfoId
 	} else {
 		baseEdbInfoMapping, err = data_manage.GetChartEdbMappingByEdbInfoId(baseEdbInfoId)
 		if err != nil {
@@ -1401,6 +1420,33 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 				}
 			}
 		}
+		if v.Source == 0 {
+			name := strings.Split(v.EdbName, "(")
+			if barConfig.FutureGoodEdbName != "" {
+				name[0] = barConfig.FutureGoodEdbName
+			}
+			if len(name) > 1 {
+				if barConfig.FutureGoodEdbName == "" {
+					barConfig.FutureGoodEdbName = name[0]
+				}
+				v.EdbName = name[0] + "(" + name[1]
+			}
+			//英文
+			// 编译正则表达式,匹配一个或多个数字
+
+			if v.EdbNameEn != "" {
+				name = strings.Split(v.EdbNameEn, "(")
+				if barConfig.FutureGoodEdbNameEn != "" {
+					name[0] = barConfig.FutureGoodEdbNameEn
+				}
+				if len(name) > 1 {
+					if barConfig.FutureGoodEdbNameEn == "" {
+						barConfig.FutureGoodEdbNameEn = name[0]
+					}
+					v.EdbNameEn = name[0] + "(" + name[1]
+				}
+			}
+		}
 	}
 	if len(warnEdbList) > 0 {
 		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
@@ -1416,7 +1462,7 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1489,7 +1535,7 @@ func (this *FutureGoodChartInfoController) ChartInfoDetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -1543,7 +1589,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1743,6 +1789,33 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				}
 			}
 		}
+		if v.Source == 0 {
+			name := strings.Split(v.EdbName, "(")
+			if barConfig.FutureGoodEdbName != "" {
+				name[0] = barConfig.FutureGoodEdbName
+			}
+			if len(name) > 1 {
+				if barConfig.FutureGoodEdbName == "" {
+					barConfig.FutureGoodEdbName = name[0]
+				}
+				v.EdbName = name[0] + "(" + name[1]
+			}
+			//英文
+			// 编译正则表达式,匹配一个或多个数字
+
+			if v.EdbNameEn != "" {
+				name = strings.Split(v.EdbNameEn, "(")
+				if barConfig.FutureGoodEdbNameEn != "" {
+					name[0] = barConfig.FutureGoodEdbNameEn
+				}
+				if len(name) > 1 {
+					if barConfig.FutureGoodEdbNameEn == "" {
+						barConfig.FutureGoodEdbNameEn = name[0]
+					}
+					v.EdbNameEn = name[0] + "(" + name[1]
+				}
+			}
+		}
 	}
 	if len(warnEdbList) > 0 {
 		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
@@ -1758,7 +1831,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1931,13 +2004,13 @@ func (this *FutureGoodChartInfoController) ChartInfoEdbInfoDetail() {
 		br.Msg = "获取失败,Err:" + err.Error()
 		return
 	}
-	maxYear := 0
+	var maxDate time.Time
 	if edbInfo.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 	if startDate == "" {
 		br.Msg = "参数错误"
 		br.Msg = "参数错误,无效的查询日期"
@@ -2100,7 +2173,7 @@ func (this *FutureGoodChartInfoController) BaseChartInfoDetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -2231,7 +2304,7 @@ func (this *FutureGoodChartInfoController) BaseChartInfoDetailFromUniqueCode() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -2318,7 +2391,7 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 		showSysId = sysUser.AdminId
 	}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -2327,7 +2400,7 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -2341,7 +2414,7 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, []int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT}, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT}, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -2371,13 +2444,17 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -2436,7 +2513,7 @@ func (this *FutureGoodChartInfoController) ChartInfoRefresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -2816,7 +2893,7 @@ func copyChartInfo(oldChartInfo *data_manage.ChartInfo, chartClassifyId int, cha
 	}
 	chartClassify, err := data_manage.GetChartClassifyById(chartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -3141,7 +3218,7 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -3178,7 +3255,7 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 	//校验指标信息是否存在
 	edbInfoList, err := data_manage.GetEdbInfoByIdList(edbIds)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表不存在!"
 			br.ErrMsg = "图表指标不存在,ChartInfoId:" + strconv.Itoa(req.ChartInfoId)
 			return
@@ -3221,7 +3298,7 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 
 			edbExist, e := data_manage.GetEdbInfoByCondition(edbCondition, edbPars)
 			if e != nil {
-				if e.Error() != utils.ErrNoRow() {
+				if !utils.IsErrNoRow(e) {
 					br.Msg = "判断英文指标名称是否存在失败"
 					br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + e.Error()
 					return
@@ -3253,7 +3330,7 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -3285,6 +3362,22 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 			}
 			xDataList := barConfig.XDataList
 			length := len(xDataList)
+			oldFutureEdbName := barConfig.FutureGoodEdbName
+			oldFutureEdbNameEn := barConfig.FutureGoodEdbNameEn
+			if oldFutureEdbName == "" {
+				futureGoodEdbInfoMapping, err := data_manage.GetFutureGoodEdbChartEdbMapping(chartItem.ChartInfoId)
+				if err != nil {
+					br.Msg = "修改失败"
+					br.ErrMsg = "获取图表现货价格指标信息失败,指标信息失败,Err:" + err.Error()
+					return
+				}
+				list, _ := future_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
+				for _, v := range list {
+					oldFutureEdbName = v.FutureGoodEdbName
+					oldFutureEdbNameEn = v.FutureGoodEdbNameEn
+					break
+				}
+			}
 			switch this.Lang {
 			case utils.EnLangVersion:
 				for k, v := range req.XDataList {
@@ -3298,6 +3391,10 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 						}
 					}
 				}
+				if req.FutureGoodName != `` {
+					barConfig.FutureGoodEdbNameEn = req.FutureGoodName
+					barConfig.FutureGoodEdbName = oldFutureEdbName
+				}
 			default:
 				for k, v := range req.XDataList {
 					v = strings.TrimPrefix(v, " ")
@@ -3310,6 +3407,10 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 						}
 					}
 				}
+				if req.FutureGoodName != `` {
+					barConfig.FutureGoodEdbName = req.FutureGoodName
+					barConfig.FutureGoodEdbNameEn = oldFutureEdbNameEn
+				}
 			}
 			barConfig.XDataList = xDataList
 			barConfigByte, e := json.Marshal(barConfig)
@@ -3321,55 +3422,6 @@ func (this *FutureGoodChartInfoController) BaseInfoEdit() {
 			chartItem.BarConfig = string(barConfigByte)
 		}
 		err = data_manage.EditBaseFutureGoodChartInfoAndEdbEnInfo(chartItem, &req, this.Lang)
-		if req.FutureGoodName != `` {
-			futureGoodEdbInfoMapping, err := data_manage.GetFutureGoodEdbChartEdbMapping(chartItem.ChartInfoId)
-			if err != nil {
-				br.Msg = "修改失败"
-				br.ErrMsg = "获取图表现货价格指标信息失败,指标信息失败,Err:" + err.Error()
-				return
-			}
-			futureGoodEdbInfo, err := future_good.GetFutureGoodEdbInfo(futureGoodEdbInfoMapping.EdbInfoId)
-			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
-					br.Msg = "图表不存在!"
-					br.ErrMsg = "图表指标不存在,futureGoodEdbInfo:" + strconv.Itoa(futureGoodEdbInfo.FutureGoodEdbInfoId)
-					return
-				} else {
-					br.Msg = "获取图表信息失败!"
-					br.ErrMsg = "获取图表的指标信息失败,Err:" + err.Error()
-					return
-				}
-			}
-			if futureGoodEdbInfo == nil {
-				br.Msg = "期货商品指标不存在!"
-				br.ErrMsg = "期货商品指标不存在,futureGoodEdbInfo:" + strconv.Itoa(futureGoodEdbInfo.FutureGoodEdbInfoId)
-				return
-			}
-
-			list, _ := future_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfo.FutureGoodEdbInfoId)
-			for _, v := range list {
-				switch this.Lang {
-				case utils.EnLangVersion:
-					if v.FutureGoodEdbNameEn == `` {
-						v.FutureGoodEdbNameEn = strings.TrimPrefix(req.FutureGoodName, " ")
-						v.FutureGoodEdbNameEn = strings.TrimSuffix(req.FutureGoodName, " ")
-					} else {
-						v.FutureGoodEdbNameEn = strings.TrimPrefix(strings.Replace(v.FutureGoodEdbNameEn, v.FutureGoodEdbNameEn, req.FutureGoodName, -1), " ")
-						v.FutureGoodEdbNameEn = strings.TrimSuffix(req.FutureGoodName, " ")
-					}
-					v.Update([]string{"FutureGoodEdbNameEn"})
-				default:
-					if v.FutureGoodEdbName == `` {
-						v.FutureGoodEdbName = strings.TrimPrefix(req.FutureGoodName, " ")
-						v.FutureGoodEdbName = strings.TrimSuffix(req.FutureGoodName, " ")
-					} else {
-						v.FutureGoodEdbName = strings.TrimPrefix(strings.Replace(v.FutureGoodEdbName, v.FutureGoodEdbName, req.FutureGoodName, -1), " ")
-						v.FutureGoodEdbName = strings.TrimSuffix(req.FutureGoodName, " ")
-					}
-					v.Update([]string{"FutureGoodEdbName"})
-				}
-			}
-		}
 	case utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
 		if len(req.XDataList) > 0 {
 			// 处理横轴名称

+ 6 - 6
controllers/data_manage/future_good/future_good_edb_info.go

@@ -60,7 +60,7 @@ func (this *FutureGoodEdbInfoController) FutureGoodEdbInfoList() {
 	}
 
 	list, err := future_good2.GetFutureGoodEdbInfoList(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -141,14 +141,14 @@ func (this *FutureGoodEdbInfoController) FutureGoodEdbInfoDataList() {
 	}
 
 	total, err := future_good2.GetFutureGoodEdbDataListCount(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	list, err := future_good2.GetFutureGoodEdbDataList(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -156,7 +156,7 @@ func (this *FutureGoodEdbInfoController) FutureGoodEdbInfoDataList() {
 
 	// 获取用到的指标信息
 	futureGoodEdbInfoList, err := future_good2.GetAllFutureGoodEdbInfoList()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -219,7 +219,7 @@ func (this *FutureGoodEdbInfoController) FutureGoodEdbInfoGroupList() {
 	}
 
 	list, err := future_good2.GetFutureGoodEdbInfoGroupList(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -320,7 +320,7 @@ func (this *FutureGoodEdbInfoController) FutureGoodEdbExchangeList() {
 	}
 
 	list, err := future_good2.GetFutureGoodEdbExchangeList(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return

+ 9 - 9
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -73,7 +73,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoAdd() {
 
 	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -165,7 +165,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoAdd() {
 		edbInfoId := v.EdbInfoId
 		futureGoodEdbInfo, tmpErr := future_good.GetFutureGoodEdbInfo(edbInfoId)
 		if tmpErr != nil {
-			if tmpErr.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(tmpErr) {
 				br.Msg = "期货商品指标不存在!"
 				br.ErrMsg = "期货商品指标不存在,指标id:" + strconv.Itoa(edbInfoId)
 				return
@@ -397,7 +397,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoEdit() {
 
 	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -413,7 +413,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoEdit() {
 	}
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -520,7 +520,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoEdit() {
 		edbInfoId := v.EdbInfoId
 		futureGoodEdbInfo, tmpErr := future_good.GetFutureGoodEdbInfo(edbInfoId)
 		if tmpErr != nil {
-			if tmpErr.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(tmpErr) {
 				br.Msg = "期货商品指标不存在!"
 				br.ErrMsg = "期货商品指标不存在,指标id:" + strconv.Itoa(edbInfoId)
 				return
@@ -713,7 +713,7 @@ func copyProfitChartInfo(oldChartInfo *data_manage.ChartInfo, chartClassifyId in
 	}
 	chartClassify, err := data_manage.GetChartClassifyById(chartClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			br.ErrMsg = "分类不存在"
 			return
@@ -1124,7 +1124,7 @@ func getFutureGoodProfitChartInfo(chartInfo *data_manage.ChartInfoView, sysUser
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1188,7 +1188,7 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1387,7 +1387,7 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err: " + err.Error()
 				return

+ 59 - 10
controllers/data_manage/gl_data.go

@@ -1,12 +1,13 @@
 package data_manage
 
 import (
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
-	"github.com/tealeg/xlsx"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
 	"os"
 	"path/filepath"
 	"time"
@@ -174,30 +175,78 @@ func (this *EdbInfoController) GlData() {
 func (this *EdbInfoController) GlSearchList() {
 	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 = "请重新登录"
 		return
 	}
 
-	//关键字
-	keyword := this.GetString("Keyword")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyword := this.GetString("KeyWord")
+	if keyword == `` {
+		keyword = this.GetString("Keyword")
+	}
 
-	list, err := data_manage.GetGlItemList(keyword)
-	if err != nil {
-		br.ErrMsg = "获取失败,Err:" + err.Error()
+	var total, startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	// es搜索
+	t, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_GL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
+	if e != nil {
 		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("ES-搜索数据源列表失败, %v", e)
 		return
 	}
+	total = int(t)
+	resp := new(data_manage.GlDataPageListResp)
+	resp.Paging = paging.GetPaging(currentIndex, pageSize, total)
+	if len(list) == 0 {
+		resp.List = make([]*data_manage.GlSearchIndex, 0)
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
+		return
+	}
+	highlightMap := make(map[int]string)
+	for _, v := range list {
+		highlightMap[v.PrimaryId] = v.SearchText
+	}
+
+	var ids []int
+	for _, v := range list {
+		ids = append(ids, v.PrimaryId)
+	}
+	items, e := data_manage.GetGlItemListByIds(ids)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取指标列表失败, %v", e)
+		return
+	}
+	for _, v := range items {
+		v.Source = utils.DATA_SOURCE_GL
+		v.SourceName = "钢联原始指标库"
+		v.SearchText = highlightMap[v.Id]
+	}
+	resp.List = items
 
+	br.Data = resp
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
-	br.Data = list
 }
 
 // GlSingleData

+ 1045 - 0
controllers/data_manage/gpr_risk_data.go

@@ -0,0 +1,1045 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+)
+
+type BaseFromGprRiskController struct {
+	controllers.BaseAuthController
+}
+
+// GprRiskClassify
+// @Title GPR地缘风险指数数据分类
+// @Description GPR地缘风险指数数据分类接口
+// @Success 200 {object} data_manage.BaseFromGprRiskClassify
+// @router /gpr_risk/classify [get]
+func (this *BaseFromGprRiskController) GprRiskClassify() {
+	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
+	}
+
+	classifyAll, err := data_manage.GetAllBaseFromGprRiskClassify()
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//组装一级分类
+	rootMap := make(map[int][]*data_manage.BaseFromGprRiskClassifyItems)
+	list := make([]*data_manage.BaseFromGprRiskClassifyItems, 0)
+	for _, classify := range classifyAll {
+		classify.UniqueCode = strconv.Itoa(classify.ClassifyId)
+		if classify.ParentId == 0 {
+			if _, ok := rootMap[classify.ClassifyId]; !ok {
+				rootMap[classify.ClassifyId] = make([]*data_manage.BaseFromGprRiskClassifyItems, 0)
+				list = append(list, classify)
+
+			}
+		} else {
+			child, ok := rootMap[classify.ParentId]
+			if ok {
+				child = append(child, classify)
+				rootMap[classify.ParentId] = child
+			}
+		}
+	}
+
+	for k, v := range list {
+		child, ok := rootMap[v.ClassifyId]
+		if ok {
+			list[k].Children = child
+		}
+	}
+	//组装二级分类
+	var ret data_manage.BaseFromGprRiskClassifyResp
+	ret.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// GprRiskIndexData
+// @Title 获取GPR地缘风险指数数据
+// @Description 获取GPR地缘风险指数数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /gpr_risk/index/data [get]
+func (this *BaseFromGprRiskController) GprRiskIndexData() {
+	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")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	// 增加频度请求入参
+	frequency := this.GetString("Frequency")
+
+	//获取指标
+	var condition string
+	var pars []interface{}
+
+	if classifyId > 0 {
+		condition += ` AND classify_id=? `
+		pars = append(pars, classifyId)
+	}
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+
+	GprRiskList, err := data_manage.GetGprRiskIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	edbCodeList := make([]string, 0)
+	for _, v := range GprRiskList {
+		edbCodeList = append(edbCodeList, v.IndexCode)
+	}
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	dataMap := make(map[string][]*data_manage.BaseFromGprRiskData)
+	total := 0
+	if len(edbCodeList) > 0 {
+		edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_GPR_RISK, edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据源失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbCode] = v
+		}
+		// 首先对分类下的指标按照日期进行分页,再针对日期,进行排序
+		dataTimes, err := data_manage.GetGprRiskIndexDataTimePageByCodes(edbCodeList, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据日期信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataTimes) > 0 {
+			startDate := utils.GormDateStrToDateStr(dataTimes[len(dataTimes)-1])
+			endDate := utils.GormDateStrToDateStr(dataTimes[0])
+			// 把截止日往后加1天
+			endDateT, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+			endDate = endDateT.AddDate(0, 0, 1).Format(utils.FormatDate)
+			dataList, e := data_manage.GetGprRiskIndexDataByDataTime(edbCodeList, startDate, endDate)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			//将数据按照指标进行分类
+			for _, v := range dataList {
+				dataMap[v.IndexCode] = append(dataMap[v.IndexCode], v)
+			}
+		}
+
+		total, err = data_manage.GetGprRiskIndexDataTimePageCount(edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	resultList := make([]*data_manage.BaseFromGprRiskIndexList, 0)
+
+	for _, v := range GprRiskList {
+		product := new(data_manage.BaseFromGprRiskIndexList)
+		product.BaseFromGprRiskIndexId = v.BaseFromGprRiskIndexId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.ModifyTime = v.ModifyTime
+		product.ClassifyId = v.ClassifyId
+		if edb, ok := edbInfoMap[v.IndexCode]; ok {
+			product.EdbInfoId = edb.EdbInfoId
+			product.EdbExist = 1
+		}
+
+		dataListTmp, ok := dataMap[v.IndexCode]
+		if !ok {
+			dataListTmp = make([]*data_manage.BaseFromGprRiskData, 0)
+		}
+		product.DataList = dataListTmp
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// GprRiskSearchList
+// @Title GprRisk模糊搜索
+// @Description GprRisk模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} models.BaseResponse
+// @router /gpr_risk/search_list [get]
+func (this *BaseFromGprRiskController) GprRiskSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	list := make([]*data_manage.BaseFromGprRiskIndexSearchItem, 0)
+	var err error
+	//关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetGprRiskItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+
+	} else {
+		list, err = data_manage.GetGprRiskItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+	classifyIds := make([]int, 0)
+	for _, v := range list {
+		classifyIds = append(classifyIds, v.ClassifyId)
+	}
+	classifyList, err := data_manage.GetBaseFromGprRiskClassifyByIds(classifyIds)
+	if err != nil {
+		br.Msg = "搜索失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	classifyMap := make(map[int]int)
+	for _, v := range classifyList {
+		classifyMap[v.ClassifyId] = v.ParentId
+	}
+	for _, v := range list {
+		v.ParentClassifyId = classifyMap[v.ClassifyId]
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// GprRiskSingleData
+// @Title 获取GprRisk数据
+// @Description 获取GprRisk单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /gpr_risk/single_data [get]
+func (this *BaseFromGprRiskController) GprRiskSingleData() {
+	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
+	}
+	indexCode := this.GetString("IndexCode")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	var total int64
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	indexInfo, err := data_manage.GetBaseFromGprRiskIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	total, err = data_manage.GetGprRiskIndexDataTotalByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, int(total))
+	dataTmpList, err := data_manage.GetGprRiskIndexDataByCode(indexCode, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_GPR_RISK, indexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据源失败"
+		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.GprRiskSingleDataResp
+	var dataList []*data_manage.GprRiskSingleData
+
+	if edbInfo != nil {
+		ret.EdbInfoId = edbInfo.EdbInfoId
+		ret.EdbExist = 1
+	}
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromGprRiskIndexId = indexInfo.BaseFromGprRiskIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.GprRiskSingleData{
+			Value:    v.Value,
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+	ret.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// GprRiskIndexList
+// @Title GPR地缘风险指数指标列表
+// @Description GPR地缘风险指数指标列表
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Success 200 {object} data_manage.BaseFromGprRiskClassifyResp
+// @router /gpr_risk/classify/index/list [get]
+func (this *BaseFromGprRiskController) GprRiskIndexList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	indexList, err := data_manage.GetGprRiskIndexByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.BaseFromGprRiskClassifyResp
+	list := make([]*data_manage.BaseFromGprRiskClassifyItems, 0)
+	for _, v := range indexList {
+		classify := new(data_manage.BaseFromGprRiskClassifyItems)
+		classify.ClassifyId = classifyId
+		classify.BaseFromGprRiskIndexId = v.BaseFromGprRiskIndexId
+		classify.IndexCode = v.IndexCode
+		classify.ClassifyName = v.IndexName
+		classify.UniqueCode = fmt.Sprintf("%d_%d", classifyId, v.BaseFromGprRiskIndexId)
+		list = append(list, classify)
+	}
+	ret.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// GprRiskNameCheck
+// @Title 加入指标库的重名检测
+// @Description 加入指标库的重名检测
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} NameCheckResult
+// @router /gpr_risk/edb_info/name_check [post]
+func (this *BaseFromGprRiskController) GprRiskNameCheck() {
+	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 []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_GPR_RISK, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_GPR_RISK, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GprRiskAddCheck
+// @Title 加入指标库指标Id检测
+// @Description 加入指标库指标Id检测
+// @Param	request	body request.BatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /gpr_risk/edb_info/add_check [post]
+func (c *BaseFromGprRiskController) GprRiskAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req.IndexCodes)
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_GPR_RISK)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetGprRiskIndex(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromGprRiskIndexList, 0)
+	for _, v := range list {
+		if edb, ok := existMap[v.IndexCode]; ok {
+			v.EdbInfoId = edb.EdbInfoId
+			v.EdbClassifyId = edb.ClassifyId
+			v.EdbUniqueCode = edb.UniqueCode
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GprRiskEdbInfoAdd
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /gpr_risk/edb_info/add [post]
+func (this *BaseFromGprRiskController) GprRiskEdbInfoAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req data_manage.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	req.EdbCode = strings.Trim(req.EdbCode, " ")
+
+	if req.EdbCode == "" {
+		br.Msg = "指标ID不能为空"
+		return
+	}
+
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	count, err := data_manage.GetGprRiskIndexDataCount(req.EdbCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if count == 0 {
+		br.Msg = "指标不存在"
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_GPR_RISK, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 试用平台更新用户累计新增指标数
+	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+		return
+	}
+	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+		go func() {
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	//新增操作日志
+	{
+		edbLog := new(data_manage.EdbInfoLog)
+		edbLog.EdbInfoId = edbInfo.EdbInfoId
+		edbLog.SourceName = edbInfo.SourceName
+		edbLog.Source = edbInfo.Source
+		edbLog.EdbCode = edbInfo.EdbCode
+		edbLog.EdbName = edbInfo.EdbName
+		edbLog.ClassifyId = edbInfo.ClassifyId
+		edbLog.SysUserId = sysUser.AdminId
+		edbLog.SysUserRealName = sysUser.RealName
+		edbLog.CreateTime = time.Now()
+		edbLog.Content = string(this.Ctx.Input.RequestBody)
+		edbLog.Status = "新增指标"
+		edbLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddEdbInfoLog(edbLog)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// ExportGprRiskList
+// @Title 导出GPR地缘风险指数数据
+// @Description 导出GPR地缘风险指数数据
+// @Param   ClassifyId   query   int  true       "关键字搜索"
+// @Param   IndexCode   query   string  true       "指标编码"
+// @Success 200  导出成功
+// @router /gpr_risk/export [get]
+func (this *BaseFromGprRiskController) ExportGprRiskList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	indexCode := this.GetString("IndexCode")
+
+	if classifyId <= 0 && indexCode == "" {
+		br.Msg = "请选择分类或者指标"
+		return
+	}
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var condition string
+	var pars []interface{}
+	var classifyName string
+	if classifyId > 0 {
+		classifyInfo, err := data_manage.GetBaseFromGprRiskClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		classifyName = classifyInfo.ClassifyName
+		childClassify, err := data_manage.GetBaseFromGprRiskClassifyByParentId(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+
+		if len(childClassify) > 0 {
+			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			for _, child := range childClassify {
+				pars = append(pars, child.ClassifyId)
+			}
+		} else {
+			condition += ` AND classify_id=?`
+			pars = append(pars, classifyId)
+		}
+	}
+	if indexCode != "" {
+		condition += ` AND index_code=? `
+		pars = append(pars, indexCode)
+	}
+
+	indexList, err := data_manage.GetGprRiskIndex(condition, pars)
+	if err != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "获取指标失败,Err:" + err.Error()
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+
+	codeList := make([]string, 0)
+	frequenciesMap := make(map[string][]*data_manage.BaseFromGprRiskIndexList)
+	for _, v := range indexList {
+		codeList = append(codeList, v.IndexCode)
+		frequenciesMap[v.Frequency] = append(frequenciesMap[v.Frequency], v)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromGprRiskData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetGprRiskIndexDataByCodes(codeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+	}
+	// 按照频率分组排序
+	frequencies := []string{
+		"日度", "周度", "旬度", "月度", "季度", "半年度", "年度",
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		indexCodeList, ok := frequenciesMap[frequency]
+		if !ok {
+			continue
+		}
+		if len(indexCodeList) <= 0 {
+			fmt.Printf("sheet:%s, 不存在指标", frequency)
+			return
+		}
+		var sheetName string
+		switch frequency {
+		case "日度":
+			sheetName = "日度(Daily)"
+		case "周度":
+			sheetName = "周度(Weekly)"
+		case "旬度":
+			sheetName = "旬度(ten-day)"
+		case "月度":
+			sheetName = "月度(Monthly)"
+		case "季度":
+			sheetName = "季度(Quarterly)"
+		case "半年度":
+			sheetName = "半年度(Semi-annual)"
+		case "年度":
+			sheetName = "年度(Annual)"
+		default:
+			sheetName = "其他数据"
+		}
+		sheetNew, err := xlsxFile.AddSheet(sheetName)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, idx := range frequenciesMap[frequency] {
+			indexIdList = append(indexIdList, idx.BaseFromGprRiskIndexId)
+		}
+		dataTimeList, err := data_manage.GetGprRiskDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取数据时间失败,Err:" + err.Error()
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, icl := range indexCodeList {
+			// 获取数据
+			dataList, ok := dataListMap[icl.IndexCode]
+			if !ok {
+				continue
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称/Metric Name")
+				frequencyRow.AddCell().SetValue("频度/Frequency")
+				unitRow.AddCell().SetValue("单位/Unit")
+				lastModifyDateRow.AddCell().SetValue("更新时间/Update Time")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(icl.IndexName)
+			frequencyRow.AddCell().SetValue(icl.Frequency)
+			unitRow.AddCell().SetValue(icl.Unit)
+
+			timeDate, err := time.Parse(utils.FormatDateTime, dataList[0].ModifyTime)
+			if err != nil {
+				continue
+			}
+			lastModifyDateRow.AddCell().SetValue(timeDate.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromGprRiskData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		e := xlsxFile.Save(downLoadnFilePath)
+		if e != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName := classifyName
+	if indexCode != "" && len(indexList) == 1 {
+		fileName = indexList[0].IndexName
+	}
+	fileName = strings.Replace(fileName, ": ", "_", -1)
+	fileName = strings.Replace(fileName, ", ", "_", -1)
+	fileName = strings.Replace(fileName, " ", "_", -1)
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	fmt.Println(fileName)
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}
+
+// GetFrequency
+// @Title GPR地缘风险指数数据频度
+// @Description GPR地缘风险指数数据频度接口
+// @Param   ClassifyId   query   string  true       "分类Id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /gpr_risk/frequency [get]
+func (this *BaseFromGprRiskController) GetFrequency() {
+	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
+	}
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	frequencyList, err := data_manage.GetGprRiskFrequencyByClassifyId(classifyId)
+	if err != nil {
+		br.Msg = "获取频度失败"
+		br.ErrMsg = "获取频度失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+}

+ 22 - 0
controllers/data_manage/jiayue_edb_source.go

@@ -71,6 +71,15 @@ func (this *JiaYueEdbSourceController) FrequencyList() {
 		return
 	}
 
+	// 测试环境老在报错=_=!
+	if utils.RunMode == "debug" {
+		br.Data = make([]string, 0)
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
 	frequencies, e := data.GetJiaYueFrequencyListFromBridge()
 	if e != nil {
 		br.Msg = "获取失败"
@@ -141,6 +150,19 @@ func (this *JiaYueEdbSourceController) IndexPageList() {
 		currentIndex = 1
 	}
 
+	// 测试环境老在报错=_=!
+	if utils.RunMode == "debug" {
+		page := paging.GetPaging(currentIndex, pageSize, 0)
+		resp := new(data_manage.JiaYueIndexPageListResp)
+		resp.Paging = page
+		resp.List = make([]*data_manage.DictIndexItem, 0)
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
 	var params data_manage.BridgeJiaYuePageIndexReq
 	params.PageIndex = currentIndex
 	params.PageSize = pageSize

+ 21 - 18
controllers/data_manage/line_equation/line_chart_classify.go

@@ -36,7 +36,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -64,14 +64,14 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 	source := utils.CHART_SOURCE_LINE_EQUATION
 
 	rootList, err := data_manage.GetChartClassifyByParentId(0, source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAll([]int{source})
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -113,14 +113,14 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	// 获取所有的分类
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_EQUATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	// /获取所有的图表
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_LINE_EQUATION}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -129,16 +129,19 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 	for _, v := range allChartInfo {
 		chartInfoMap[v.ChartClassifyId] = append(chartInfoMap[v.ChartClassifyId], v)
 	}
-	for k, v := range rootList {
+	res := make([]*data_manage.ChartClassifyItems, 0)
+	for _, v := range rootList {
 		if existItems, ok := chartInfoMap[v.ChartClassifyId]; ok {
 			v.Children = existItems
 		} else {
-			items := make([]*data_manage.ChartClassifyItems, 0)
-			v.Children = items
+			// items := make([]*data_manage.ChartClassifyItems, 0)
+			// v.Children = items
+			continue
 		}
-		rootList[k] = v
+		res = append(res, v)
+		// rootList[k] = v
 	}
-	resp.AllNodes = rootList
+	resp.AllNodes = res
 
 	return
 }
@@ -205,7 +208,7 @@ func (this *LineEquationChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_LINE_EQUATION, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_LINE_EQUATION, 0, this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -309,7 +312,7 @@ func (this *LineEquationChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -371,7 +374,7 @@ func (this *LineEquationChartClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -395,7 +398,7 @@ func (this *LineEquationChartClassifyController) DeleteChartClassify() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -458,7 +461,7 @@ func (this *LineEquationChartClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -478,14 +481,14 @@ func (this *LineEquationChartClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -620,7 +623,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartClassifyByParentId(chartClassifyInfo.ParentId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return

+ 45 - 24
controllers/data_manage/line_equation/line_chart_info.go

@@ -413,7 +413,7 @@ func (this *LineEquationChartInfoController) Move() {
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
 		tmpChartInfo, tmpErr := data_manage.GetChartInfoByClassifyIdAndName(req.ChartClassifyId, chartInfo.ChartName)
-		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
 			return
@@ -472,7 +472,7 @@ func (this *LineEquationChartInfoController) Move() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
@@ -588,15 +588,32 @@ func (this *LineEquationChartInfoController) List() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
 		}
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -611,7 +628,7 @@ func (this *LineEquationChartInfoController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -629,7 +646,7 @@ func (this *LineEquationChartInfoController) List() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -637,7 +654,7 @@ func (this *LineEquationChartInfoController) List() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -681,7 +698,7 @@ func (this *LineEquationChartInfoController) List() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -692,7 +709,7 @@ func (this *LineEquationChartInfoController) List() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -743,7 +760,7 @@ func (this *LineEquationChartInfoController) Detail() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -817,7 +834,7 @@ func (this *LineEquationChartInfoController) Detail() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -945,7 +962,7 @@ func (this *LineEquationChartInfoController) DetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -983,7 +1000,7 @@ func (this *LineEquationChartInfoController) DetailFromUniqueCode() {
 					myCond += ` AND a.chart_info_id=? `
 					myPars = append(myPars, chartInfo.ChartInfoId)
 					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
-					if err != nil && err.Error() != utils.ErrNoRow() {
+					if err != nil && !utils.IsErrNoRow(err) {
 						br.Msg = "获取失败"
 						br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 						return
@@ -1059,7 +1076,7 @@ func (this *LineEquationChartInfoController) Refresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -1219,7 +1236,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -1383,7 +1400,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -1479,7 +1496,7 @@ func (this *LineEquationChartInfoController) EnInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -1497,7 +1514,7 @@ func (this *LineEquationChartInfoController) EnInfoEdit() {
 		pars = append(pars, req.ChartInfoId, req.ChartNameEn, utils.CHART_SOURCE_LINE_EQUATION)
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -1597,7 +1614,7 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 
 	sourceList := []int{utils.CHART_SOURCE_LINE_EQUATION}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -1606,7 +1623,7 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1620,7 +1637,7 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -1650,13 +1667,17 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -1718,7 +1739,7 @@ func (this *LineEquationChartInfoController) BaseInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -1743,7 +1764,7 @@ func (this *LineEquationChartInfoController) BaseInfoEdit() {
 		pars = append(pars, req.ChartName)
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return

+ 100 - 64
controllers/data_manage/line_feature/chart_info.go

@@ -15,10 +15,11 @@ import (
 	lineFeatureServ "eta/eta_api/services/data/line_feature"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // LineFeaturesChartInfoController 统计特征图表管理
@@ -64,7 +65,7 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSave() {
 	if err != nil {
 		br.Msg = "指标A异常"
 		br.ErrMsg = "指标A异常,err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = `指标A不存在`
 			br.IsSendEmail = false
 		}
@@ -170,12 +171,12 @@ func (this *LineFeaturesChartInfoController) MultipleGraphPreview() {
 
 	// 曲线图表信息
 	curveConf := req.Curve
-	maxYear := 0
+	var maxDate time.Time
 	if edbInfoMapping.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfoMapping.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
 	}
-	startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxYear)
+	startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxDate)
 	{
 		tmpChartInfo := *chartInfo
 		// 获取图表中的指标数据
@@ -225,7 +226,7 @@ func (this *LineFeaturesChartInfoController) MultipleGraphPreview() {
 	// 标准差图表信息
 	{
 		// 配置了数据才有返回
-		if req.StandardDeviation.CalculateValue > 0 {
+		if req.StandardDeviation.CalculateValue > 1 {
 			tmpChartInfo := *chartInfo
 			tmpChartInfo.ChartName = fmt.Sprintf("%s%d期滚动标准差", edbInfoMapping.EdbName, req.StandardDeviation.CalculateValue)
 
@@ -434,12 +435,12 @@ func (this *LineFeaturesChartInfoController) MultipleGraphPreviewCurve() {
 		tmpChartInfo := *chartInfo
 
 		curveConf := req.Curve
-		maxYear := 0
+		var maxDate time.Time
 		if edbInfoMapping.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, edbInfoMapping.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
 		}
-		startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxYear)
+		startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxDate)
 
 		// 获取图表中的指标数据
 		edbList, _, _, _, err, errMsg := data.GetChartEdbData(tmpChartInfo.ChartInfoId, tmpChartInfo.ChartType, tmpChartInfo.Calendar, startDate, endDate, []*data_manage.ChartEdbInfoMapping{edbInfoMapping}, tmpChartInfo.ExtraConfig, tmpChartInfo.SeasonExtraConfig)
@@ -553,11 +554,15 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveChart() {
 	}
 
 	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
 	}
+	// 兼容gorm
+	if multipleGraphConfigChartMapping != nil && multipleGraphConfigChartMapping.Id <= 0 {
+		multipleGraphConfigChartMapping = nil
+	}
 
 	err = nil
 	var isAdd bool
@@ -566,13 +571,13 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveChart() {
 		isAdd = true
 	} else {
 		chartInfo, err := data_manage.GetChartInfoById(multipleGraphConfigChartMapping.ChartInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = `保存失败`
 			br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 			return
 		}
 		// 说明图还在,没有被删除
-		if chartInfo != nil {
+		if chartInfo != nil && chartInfo.ChartInfoId > 0 {
 			chartInfoId = multipleGraphConfigChartMapping.ChartInfoId
 			req.ChartName = chartInfo.ChartName
 			req.ClassifyId = chartInfo.ChartClassifyId
@@ -584,12 +589,12 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveChart() {
 	isSendEmail := true
 
 	curveConf := req.Curve
-	maxYear := 0
+	var maxDate time.Time
 	if edbInfoMapping.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfoMapping.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
 	}
-	startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxYear)
+	startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxDate)
 	switch req.Source {
 	case utils.CHART_MULTIPLE_GRAPH_CURVE: // 曲线图
 		curveConf := req.Curve
@@ -811,7 +816,7 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveChart() {
 			br.ErrMsg = "保存配置与图表的关联关系失败,ERR:" + err.Error()
 			return
 		}
-	} else if multipleGraphConfigChartMapping != nil {
+	} else if multipleGraphConfigChartMapping != nil && multipleGraphConfigChartMapping.MultipleGraphConfigId > 0 {
 		multipleGraphConfigChartMapping.ChartInfoId = chartInfo.ChartInfoId
 		multipleGraphConfigChartMapping.ModifyTime = time.Now()
 		err = multipleGraphConfigChartMapping.Update([]string{"ChartInfoId", "ModifyTime"})
@@ -865,7 +870,7 @@ func CopyMultipleGraphConfigSaveChart(req request.SaveMultipleGraphChartReq, thi
 	}
 
 	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
@@ -873,7 +878,7 @@ func CopyMultipleGraphConfigSaveChart(req request.SaveMultipleGraphChartReq, thi
 
 	// 原图
 	oldChartInfo, err := data_manage.GetChartInfoById(multipleGraphConfigChartMapping.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 		return
@@ -1063,7 +1068,7 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveEdb() {
 	}
 
 	multipleGraphConfigEdbMapping, err := data_manage.GetMultipleGraphConfigEdbMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
@@ -1071,17 +1076,17 @@ func (this *LineFeaturesChartInfoController) MultipleGraphConfigSaveEdb() {
 	err = nil
 	var isAdd bool
 	var edbInfoId int
-	if multipleGraphConfigEdbMapping == nil {
+	if multipleGraphConfigEdbMapping == nil || multipleGraphConfigEdbMapping.MultipleGraphConfigId <= 0 {
 		isAdd = true
 	} else {
 		edbInfo, err := data_manage.GetEdbInfoById(multipleGraphConfigEdbMapping.EdbInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = `保存失败`
 			br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 			return
 		}
 		// 说明指标还在,没有被删除
-		if edbInfo != nil && !req.IsSaveAs {
+		if edbInfo != nil && edbInfo.EdbInfoId > 0 && !req.IsSaveAs {
 			edbInfoId = multipleGraphConfigEdbMapping.EdbInfoId
 			req.EdbName = edbInfo.EdbName
 			req.ClassifyId = edbInfo.ClassifyId
@@ -1462,12 +1467,12 @@ func (this *LineFeaturesChartInfoController) Move() {
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
 		tmpChartInfo, tmpErr := data_manage.GetChartInfoByClassifyIdAndName(req.ChartClassifyId, chartInfo.ChartName)
-		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
 			return
 		}
-		if tmpChartInfo != nil {
+		if tmpChartInfo != nil && tmpChartInfo.ChartInfoId > 0 {
 			br.Msg = "移动失败,同一个分类下图表名称不允许重复"
 			br.ErrMsg = "移动失败,同一个分类下图表名称不允许重复"
 			return
@@ -1521,14 +1526,14 @@ func (this *LineFeaturesChartInfoController) Move() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
 		}
 
 		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
-		if firstClassify != nil && firstClassify.Sort == 0 {
+		if firstClassify != nil && firstClassify.ChartClassifyId > 0 && firstClassify.Sort == 0 {
 			updateSortStr := ` sort + 1 `
 			_ = data_manage.UpdateChartInfoSortByClassifyId(firstClassify.ChartClassifyId, 0, firstClassify.ChartInfoId-1, []int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY}, updateSortStr)
 		}
@@ -1632,15 +1637,30 @@ func (this *LineFeaturesChartInfoController) List() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
 		}
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 	}
+
+	var keyWordArr []string
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		newKeyWord := strings.Split(keyword, " ")
+		keywordStr := strings.Replace(keyword, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -1655,7 +1675,7 @@ func (this *LineFeaturesChartInfoController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1673,7 +1693,7 @@ func (this *LineFeaturesChartInfoController) List() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -1681,7 +1701,7 @@ func (this *LineFeaturesChartInfoController) List() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -1725,7 +1745,7 @@ func (this *LineFeaturesChartInfoController) List() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -1736,7 +1756,7 @@ func (this *LineFeaturesChartInfoController) List() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -1779,7 +1799,7 @@ func (this *LineFeaturesChartInfoController) Detail() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -1830,12 +1850,15 @@ func (this *LineFeaturesChartInfoController) Detail() {
 			br.ErrMsg = "格式化配置项失败,Err:" + err.Error()
 			return
 		}
-		maxYear := 0
+		var maxDate time.Time
 		if edbMapping.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, edbMapping.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
 		}
-		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxYear)
+		if chartInfo.ChartType == utils.CHART_TYPE_SEASON && chartInfo.DateType == utils.DateTypeNYears {
+			maxDate = time.Date(maxDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+		}
+		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxDate)
 		edbList, resultResp, err, errMsg = lineFeatureServ.GetStandardDeviationData(0, startDate, endDate, edbMapping, calculateValue)
 	case utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE:
 		var percentileConfig request.Percentile
@@ -1845,12 +1868,15 @@ func (this *LineFeaturesChartInfoController) Detail() {
 			br.ErrMsg = "格式化配置项失败,Err:" + err.Error()
 			return
 		}
-		maxYear := 0
+		var maxDate time.Time
 		if edbMapping.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, edbMapping.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
+		}
+		if chartInfo.ChartType == utils.CHART_TYPE_SEASON && chartInfo.DateType == utils.DateTypeNYears {
+			maxDate = time.Date(maxDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
 		}
-		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxYear)
+		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxDate)
 		edbList, resultResp, err, errMsg = lineFeatureServ.GetPercentileData(0, startDate, endDate, edbMapping, percentileConfig.CalculateValue, percentileConfig.CalculateUnit, percentileConfig.PercentType)
 	case utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY:
 		var frequencyDistributionConfig request.FrequencyDistribution
@@ -1898,7 +1924,7 @@ func (this *LineFeaturesChartInfoController) Detail() {
 	}
 
 	// 判断是否加入我的图库
-	if chartInfoId > 0 && chartInfo != nil {
+	if chartInfoId > 0 && chartInfo != nil && chartInfo.ChartInfoId > 0 {
 		{
 			var myChartCondition string
 			var myChartPars []interface{}
@@ -1908,7 +1934,7 @@ func (this *LineFeaturesChartInfoController) Detail() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -2036,7 +2062,7 @@ func (this *LineFeaturesChartInfoController) DetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -2074,7 +2100,7 @@ func (this *LineFeaturesChartInfoController) DetailFromUniqueCode() {
 					myCond += ` AND a.chart_info_id=? `
 					myPars = append(myPars, chartInfo.ChartInfoId)
 					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
-					if err != nil && err.Error() != utils.ErrNoRow() {
+					if err != nil && !utils.IsErrNoRow(err) {
 						br.Msg = "获取失败"
 						br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 						return
@@ -2150,7 +2176,7 @@ func (this *LineFeaturesChartInfoController) Refresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -2232,7 +2258,7 @@ func (this *LineFeaturesChartInfoController) Copy() {
 	}
 
 	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByChartId(oldChartInfo.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
@@ -2316,7 +2342,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -2392,7 +2418,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		if !isOk {
 			if errMsg != "" {
 				uniqueCode := ""
-				if chartInfo != nil {
+				if chartInfo != nil && chartInfo.ChartInfoId > 0 {
 					uniqueCode = chartInfo.UniqueCode
 				}
 				tmpTip := fmt.Sprintf("查询图表详情失败,line_feature.GetChartInfoDetailFromUniqueCode UniqueCode:%s,err:%s", uniqueCode, errMsg)
@@ -2459,12 +2485,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			errMsg = "格式化配置项失败,Err:" + tmpErr.Error()
 			return
 		}
-		maxYear := 0
+		var maxDate time.Time
 		if edbMapping.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, edbMapping.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
 		}
-		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxYear)
+		if chartInfo.ChartType == utils.CHART_TYPE_SEASON && chartInfo.DateType == utils.DateTypeNYears {
+			maxDate = time.Date(maxDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+		}
+		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxDate)
 		edbList, resultResp, err, msg = lineFeatureServ.GetStandardDeviationData(0, startDate, endDate, edbMapping, calculateValue)
 	case utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE:
 		var percentileConfig request.Percentile
@@ -2474,12 +2503,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			errMsg = "格式化配置项失败,Err:" + err.Error()
 			return
 		}
-		maxYear := 0
+		var maxDate time.Time
 		if edbMapping.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, edbMapping.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
+		}
+		if chartInfo.ChartType == utils.CHART_TYPE_SEASON && chartInfo.DateType == utils.DateTypeNYears {
+			maxDate = time.Date(maxDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
 		}
-		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxYear)
+		startDate, endDate := utils.GetDateByDateTypeV2(chartInfo.DateType, chartInfo.StartDate, chartInfo.EndDate, chartInfo.StartYear, maxDate)
 		edbList, resultResp, err, msg = lineFeatureServ.GetPercentileData(0, startDate, endDate, edbMapping, percentileConfig.CalculateValue, percentileConfig.CalculateUnit, percentileConfig.PercentType)
 	case utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY:
 		var frequencyDistributionConfig request.FrequencyDistribution
@@ -2504,7 +2536,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		return
 	}
 
-	if chartInfo.ChartInfoId > 0 && chartInfo != nil {
+	if chartInfo != nil && chartInfo.ChartInfoId > 0 {
 		//判断是否加入我的图库
 		{
 			var myChartCondition string
@@ -2515,7 +2547,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -2611,7 +2643,7 @@ func (this *LineFeaturesChartInfoController) EnInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -2629,7 +2661,7 @@ func (this *LineFeaturesChartInfoController) EnInfoEdit() {
 		pars = append(pars, req.ChartInfoId, req.ChartNameEn, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY)
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return
@@ -2729,7 +2761,7 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 
 	sourceList := []int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY}
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -2738,7 +2770,7 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -2752,7 +2784,7 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -2782,13 +2814,17 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -2850,7 +2886,7 @@ func (this *LineFeaturesChartInfoController) BaseInfoEdit() {
 	//判断指标名称是否存在
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面"
 			br.ErrMsg = "图表已被删除,请刷新页面"
 			return
@@ -2876,7 +2912,7 @@ func (this *LineFeaturesChartInfoController) BaseInfoEdit() {
 		pars = append(pars, req.ChartName)
 		existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 		if err != nil {
-			if err.Error() != utils.ErrNoRow() {
+			if !utils.IsErrNoRow(err) {
 				br.Msg = "判断英文图表名称是否存在失败"
 				br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 				return

+ 21 - 18
controllers/data_manage/line_feature/classify.go

@@ -36,7 +36,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -64,14 +64,14 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 	source := utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION
 
 	rootList, err := data_manage.GetChartClassifyByParentId(0, source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY})
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -113,14 +113,14 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	// 获取所有的分类
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	// /获取所有的图表
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -129,16 +129,19 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 	for _, v := range allChartInfo {
 		chartInfoMap[v.ChartClassifyId] = append(chartInfoMap[v.ChartClassifyId], v)
 	}
-	for k, v := range rootList {
+	res := make([]*data_manage.ChartClassifyItems, 0)
+	for _, v := range rootList {
 		if existItems, ok := chartInfoMap[v.ChartClassifyId]; ok {
 			v.Children = existItems
 		} else {
-			items := make([]*data_manage.ChartClassifyItems, 0)
-			v.Children = items
+			// items := make([]*data_manage.ChartClassifyItems, 0)
+			// v.Children = items
+			continue
 		}
-		rootList[k] = v
+		res = append(res, v)
+		// rootList[k] = v
 	}
-	resp.AllNodes = rootList
+	resp.AllNodes = res
 
 	return
 }
@@ -205,7 +208,7 @@ func (this *LineFeaturesChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, 0, this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -309,7 +312,7 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -371,7 +374,7 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -395,7 +398,7 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassify() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -458,7 +461,7 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -478,14 +481,14 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return
@@ -620,7 +623,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyMove() {
 
 	} else {
 		firstClassify, err := data_manage.GetFirstChartClassifyByParentId(chartClassifyInfo.ParentId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
 			return

+ 11 - 13
controllers/data_manage/manual.go

@@ -2,13 +2,13 @@ package data_manage
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
+	"fmt"
 	"strconv"
 	"strings"
 	"time"
@@ -224,12 +224,12 @@ func (this *ChartClassifyController) AddManualClassify() {
 	}
 
 	classifyItem, err := data_manage.GetManualClassifyByClassifyName(req.ClassifyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "判断名称是否已存在失败"
 		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 		return
 	}
-	if classifyItem != nil {
+	if classifyItem != nil && classifyItem.ClassifyId > 0 {
 		if classifyItem.IsShow == 1 {
 			br.Msg = "分类名称已存在,请重新输入"
 			br.IsSendEmail = false
@@ -243,7 +243,7 @@ func (this *ChartClassifyController) AddManualClassify() {
 				return
 			}
 			parentItem, _ := data_manage.GetManualClassifyById(req.ParentId)
-			if parentItem != nil && parentItem.IsShow == 0 {
+			if parentItem != nil && parentItem.ClassifyId > 0 && parentItem.IsShow == 0 {
 				err = data_manage.ModifyManualClassifyIsShow(1, parentItem.ClassifyId, req.ParentId)
 				if err != nil {
 					br.Msg = "保存失败"
@@ -315,17 +315,15 @@ func (this *ChartClassifyController) ManualClassifyEdit() {
 		return
 	}
 	classifyItem, err := data_manage.GetManualClassifyByClassifyName(req.ClassifyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "修改失败"
 		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 		return
 	}
 
-	if classifyItem != nil {
-		if item.ClassifyId != classifyItem.ClassifyId {
-			br.Msg = "名称已存在,请重新输入"
-			return
-		}
+	if classifyItem != nil && classifyItem.ClassifyId > 0 && item.ClassifyId != classifyItem.ClassifyId {
+		br.Msg = "名称已存在,请重新输入"
+		return
 	}
 
 	err = data_manage.ModifyManualClassifyName(req.ClassifyName, req.ClassifyId, req.ParentId)
@@ -364,7 +362,7 @@ func (this *ChartClassifyController) ManualClassifyDel() {
 		return
 	}
 	classifyItem, err := data_manage.GetManualClassifyById(req.ClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "查找分类失败"
 		br.ErrMsg = "查找分类失败,Err:" + err.Error()
 		return
@@ -377,7 +375,7 @@ func (this *ChartClassifyController) ManualClassifyDel() {
 
 	// 获取当前分类下是否存在子分类
 	count, err := data_manage.GetChildManualClassifyCount(req.ClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "删除失败"
 		br.ErrMsg = "根据分类id获取下面存在的子分类数量失败,Err:" + err.Error()
 		return
@@ -391,7 +389,7 @@ func (this *ChartClassifyController) ManualClassifyDel() {
 	if classifyItem.ParentId > 0 {
 		// 获取当前分类下的指标数
 		count, err = data_manage.GetManualEdbInfoCountByClassifyId(req.ClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "根据分类id获取下面存在的指标数量失败,Err:" + err.Error()
 			return

+ 55 - 11
controllers/data_manage/manual_edb.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/elastic"
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
@@ -274,19 +275,47 @@ func (c *ManualEdbController) EdbSearch() {
 
 	var startSize int
 	if pageSize <= 0 {
-		pageSize = utils.PageSize20
+		pageSize = utils.PageSize15
 	}
 	if currentIndex <= 0 {
 		currentIndex = 1
 	}
 	startSize = utils.StartIndex(currentIndex, pageSize)
+	resp := new(models.EdbListResp)
 
 	//关键字
 	keyword := c.GetString("Keyword")
+	keyword = strings.TrimSpace(keyword)
 
 	var condition string
 	var pars []interface{}
 
+	// es搜索
+	highlightMap := make(map[string]string)
+	if keyword != "" {
+		_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_MANUAL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("ES-搜索手工指标列表失败, %v", e)
+			return
+		}
+		if len(list) == 0 {
+			resp.List = make([]*models.EdbInfoListItem, 0)
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
+		var codes []string
+		for _, v := range list {
+			codes = append(codes, v.IndexCode)
+			highlightMap[v.IndexCode] = v.SearchText
+		}
+		condition += fmt.Sprintf(` AND a.TRADE_CODE IN (%s)`, utils.GetOrmInReplace(len(list)))
+		pars = append(pars, codes)
+	}
+
 	//userId := sysUser.AdminId
 	//超管账号可以查看分类下的所有频度数据
 	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
@@ -304,10 +333,10 @@ func (c *ManualEdbController) EdbSearch() {
 
 	}
 
-	if keyword != "" {
-		condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
-		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
-	}
+	//if keyword != "" {
+	//	condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+	//	pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	//}
 
 	total, err := models.GetCountEdbInfoList(condition, pars)
 	if err != nil {
@@ -315,22 +344,27 @@ func (c *ManualEdbController) EdbSearch() {
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-
 	list, err := models.GetEdbInfoList(condition, pars, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-
 	for _, v := range list {
 		v.UniqueCode = utils.MD5(v.TradeCode)
+		// ES搜索信息
+		v.Source = utils.DATA_SOURCE_MANUAL
+		v.SourceName = "手工指标录入"
+		s := highlightMap[v.TradeCode]
+		if s == "" {
+			s = v.SecName
+		}
+		v.ClassifyUniqueCode = utils.MD5(strconv.Itoa(v.ClassifyId))
+		v.SearchText = s
 	}
 
-	resp := models.EdbListResp{
-		List:   list,
-		Paging: paging.GetPaging(currentIndex, pageSize, total),
-	}
+	resp.List = list
+	resp.Paging = paging.GetPaging(currentIndex, pageSize, total)
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -401,6 +435,16 @@ func (c *ManualEdbController) EdbList() {
 		if num > 0 {
 			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
 			pars = append(pars, classifyIdList)
+		} else {
+			resp := models.EdbListResp{
+				List:   []*models.EdbInfoListItem{},
+				Paging: paging.GetPaging(currentIndex, pageSize, 0),
+			}
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
 		}
 
 	} else {

+ 25 - 14
controllers/data_manage/multiple_graph_config.go

@@ -61,7 +61,7 @@ func (this *ChartInfoController) MultipleGraphConfigSave() {
 	if err != nil {
 		br.Msg = "指标A异常"
 		br.ErrMsg = "指标A异常,err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = `指标A不存在`
 			br.IsSendEmail = false
 		}
@@ -81,7 +81,7 @@ func (this *ChartInfoController) MultipleGraphConfigSave() {
 	if err != nil {
 		br.Msg = "指标B异常"
 		br.ErrMsg = "指标B异常,err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = `指标B不存在`
 			br.IsSendEmail = false
 		}
@@ -191,7 +191,7 @@ func (this *ChartInfoController) MultipleGraphPreview() {
 		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
 		return
 	}
-	maxYear := 0
+	var maxDate time.Time
 	var edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping
 	for _, v := range mappingList {
 		if v.EdbInfoId == req.EdbInfoIdA {
@@ -202,7 +202,7 @@ func (this *ChartInfoController) MultipleGraphPreview() {
 		}
 		if v.LatestDate != "" {
 			latestDateT, _ := time.Parse(utils.FormatDate, v.LatestDate)
-			maxYear = latestDateT.Year()
+			maxDate = latestDateT
 		}
 	}
 	if edbInfoMappingA == nil {
@@ -242,7 +242,7 @@ func (this *ChartInfoController) MultipleGraphPreview() {
 			}
 		}
 
-		startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxYear)
+		startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxDate)
 		// 获取图表中的指标数据
 		edbList, _, _, _, err, errMsg := data.GetChartEdbData(tmpChartInfo.ChartInfoId, tmpChartInfo.ChartType, tmpChartInfo.Calendar, startDate, endDate, mappingList, tmpChartInfo.ExtraConfig, tmpChartInfo.SeasonExtraConfig)
 		if err != nil {
@@ -362,7 +362,7 @@ func (this *ChartInfoController) MultipleGraphPreview() {
 
 			// 数据的开始/结束日期
 			curveConf := req.Curve
-			startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxYear)
+			startDate, endDate := utils.GetDateByDateTypeV2(curveConf.DateType, curveConf.StartDate, curveConf.EndDate, curveConf.StartYear, maxDate)
 
 			rollingCorrelationData := make([]interface{}, 0)
 			for _, rollingCorrelationConf := range rollingCorrelationConfList {
@@ -513,6 +513,10 @@ func (this *ChartInfoController) MultipleGraphPreviewCurve() {
 			startDate = "2020-01-01"
 		case 11:
 			startDate = "2022-01-01"
+		case 12:
+			startDate = "2023-01-01"
+		case 13:
+			startDate = "2024-01-01"
 		}
 
 		edbInfoType := 0
@@ -672,11 +676,14 @@ func (this *ChartInfoController) MultipleGraphConfigSaveChart() {
 	}
 
 	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
 	}
+	if multipleGraphConfigChartMapping != nil && multipleGraphConfigChartMapping.Id <= 0 {
+		multipleGraphConfigChartMapping = nil
+	}
 
 	err = nil
 	var isAdd bool
@@ -685,13 +692,13 @@ func (this *ChartInfoController) MultipleGraphConfigSaveChart() {
 		isAdd = true
 	} else {
 		chartInfo, err := data_manage.GetChartInfoById(multipleGraphConfigChartMapping.ChartInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = `保存失败`
 			br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 			return
 		}
 		// 说明图还在,没有被删除
-		if chartInfo != nil {
+		if chartInfo != nil && chartInfo.ChartInfoId > 0 {
 			chartInfoId = multipleGraphConfigChartMapping.ChartInfoId
 			req.ChartName = chartInfo.ChartName
 			req.ClassifyId = chartInfo.ChartClassifyId
@@ -1014,7 +1021,7 @@ func CopyMultipleGraphConfigSaveChart(req request.SaveMultipleGraphChartReq, thi
 	}
 
 	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
@@ -1022,7 +1029,7 @@ func CopyMultipleGraphConfigSaveChart(req request.SaveMultipleGraphChartReq, thi
 
 	// 原图
 	oldChartInfo, err := data_manage.GetChartInfoById(multipleGraphConfigChartMapping.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 		return
@@ -1271,11 +1278,15 @@ func (this *ChartInfoController) MultipleGraphConfigSaveEdb() {
 	}
 
 	multipleGraphConfigEdbMapping, err := data_manage.GetMultipleGraphConfigEdbMappingByIdAndSource(req.MultipleGraphConfigId, req.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = `保存失败`
 		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
 		return
 	}
+	if multipleGraphConfigEdbMapping != nil && multipleGraphConfigEdbMapping.Id <= 0 {
+		multipleGraphConfigEdbMapping = nil
+	}
+
 	err = nil
 	var isAdd bool
 	var edbInfoId int
@@ -1283,13 +1294,13 @@ func (this *ChartInfoController) MultipleGraphConfigSaveEdb() {
 		isAdd = true
 	} else {
 		edbInfo, err := data_manage.GetEdbInfoById(multipleGraphConfigEdbMapping.EdbInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = `保存失败`
 			br.ErrMsg = "获取图表信息失败,ERR:" + err.Error()
 			return
 		}
 		// 说明指标还在,没有被删除
-		if edbInfo != nil && !req.IsSaveAs {
+		if edbInfo != nil && edbInfo.EdbInfoId > 0 && !req.IsSaveAs {
 			edbInfoId = multipleGraphConfigEdbMapping.EdbInfoId
 			req.EdbName = edbInfo.EdbName
 			req.ClassifyId = edbInfo.ClassifyId

+ 94 - 60
controllers/data_manage/my_chart.go

@@ -70,34 +70,63 @@ func (this *MyChartController) ChartList() {
 	condition += ` AND source = ? `
 	pars = append(pars, utils.CHART_SOURCE_DEFAULT)
 
-	chartClassifyIds := make([]int, 0)
-	if chartClassifyId > 0 {
+	// 是否显示精选资源
+	isSelected, _ := this.GetInt("IsSelected", -1)
 
-		list, e := data_manage.GetChartClassifyAllBySource(utils.CHART_SOURCE_DEFAULT)
-		if e != nil {
+	chartClassifyIds := make([]int, 0)
+	var classifyList []*data_manage.ChartClassifyItems
+	var err error
+	if isSelected >= 0 {
+		classifyList, err = data_manage.GetChartClassifyAllBySourceIsSelected(utils.CHART_SOURCE_DEFAULT, isSelected)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取图表分类失败, Err: %v", err)
+			return
+		}
+	} else {
+		classifyList, err = data_manage.GetChartClassifyAllBySource(utils.CHART_SOURCE_DEFAULT)
+		if err != nil {
 			br.Msg = "获取失败"
-			br.ErrMsg = fmt.Sprintf("获取图表分类失败, Err: %v", e)
+			br.ErrMsg = fmt.Sprintf("获取图表分类失败, Err: %v", err)
 			return
 		}
-		parents := data.GetChartClassifyChildrenRecursive(list, chartClassifyId)
+	}
+	if chartClassifyId > 0 {
+		parents := data.GetChartClassifyChildrenRecursive(classifyList, chartClassifyId)
 		sort.Slice(parents, func(i, j int) bool {
 			return parents[i].Level < parents[i].Level
 		})
 		for _, v := range parents {
 			chartClassifyIds = append(chartClassifyIds, v.ChartClassifyId)
 		}
-
-		//chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		//if err != nil && err.Error() != utils.ErrNoRow() {
-		//	br.Msg = "获取图表信息失败"
-		//	br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
-		//	return
-		//}
-		condition += " AND chart_classify_id IN(" + utils.GetOrmInReplace(len(chartClassifyIds)) + ") "
+		condition += " AND chart_classify_id IN (" + utils.GetOrmInReplace(len(chartClassifyIds)) + ") "
+		pars = append(pars, chartClassifyIds)
+	} else if isSelected >= 0 {
+		for _, v := range classifyList {
+			chartClassifyIds = append(chartClassifyIds, v.ChartClassifyId)
+		}
+		condition += " AND chart_classify_id IN (" + utils.GetOrmInReplace(len(chartClassifyIds)) + ") "
 		pars = append(pars, chartClassifyIds)
 	}
+
+	var keyWordArr []string
 	if keyWord != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyWord + `%' OR chart_name_en LIKE '%` + keyWord + `%' )`
+		newKeyWord := strings.Split(keyWord, " ")
+		keywordStr := strings.Replace(keyWord, " ", "", -1)
+
+		condition += " AND ( "
+		condition += ` chart_name LIKE '%` + keywordStr + `%' OR chart_name_en LIKE '%` + keywordStr + `%' OR`
+
+		keyWordArr = append(keyWordArr, newKeyWord...)
+		if len(keyWordArr) > 0 {
+			for _, v := range keyWordArr {
+				if v != "" {
+					condition += ` chart_name LIKE '%` + v + `%' OR chart_name_en LIKE '%` + v + `%' OR`
+				}
+			}
+		}
+		condition = strings.TrimRight(condition, "OR")
+		condition += " ) "
 	}
 
 	//只看我的
@@ -112,7 +141,7 @@ func (this *MyChartController) ChartList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -130,7 +159,7 @@ func (this *MyChartController) ChartList() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -138,7 +167,7 @@ func (this *MyChartController) ChartList() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -215,7 +244,7 @@ func (this *MyChartController) ChartList() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -226,7 +255,7 @@ func (this *MyChartController) ChartList() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -261,7 +290,7 @@ func (this *MyChartController) ClassifyList() {
 	}
 	//获取图表信息
 	list, err := data_manage.GetMyChartClassifyAll(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取分类信息失败"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
@@ -269,7 +298,7 @@ func (this *MyChartController) ClassifyList() {
 	}
 
 	resp := new(data_manage.MyChartClassifyResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.MyChartClassifyItem, 0)
 		resp.List = items
 		br.Ret = 200
@@ -441,7 +470,7 @@ func (this *MyChartController) ClassifyEdit() {
 		return
 	}
 	item, err := data_manage.GetMyChartClassifyById(sysUser.AdminId, req.MyChartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 		return
@@ -529,7 +558,7 @@ func (this *MyChartController) ClassifyMove() {
 	}
 	//查询该分类存不存在
 	item, err := data_manage.GetMyChartClassifyById(sysUser.AdminId, req.MyChartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "移动失败,找不到该分类"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 		return
@@ -579,14 +608,14 @@ func (this *MyChartController) ClassifyMove() {
 		updateCol = append(updateCol, "Sort", "ModifyTime")
 	} else {
 		firstClassify, err := data_manage.GetFirstMyChartClassifyByAdminId(sysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前账号下的排序第一条的分类信息失败,Err:" + err.Error()
 			return
 		}
 
 		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
-		if firstClassify != nil && firstClassify.Sort == 0 {
+		if firstClassify != nil && firstClassify.MyChartClassifyId > 0 && firstClassify.Sort == 0 {
 			updateSortStr := ` sort + 1 `
 			_ = data_manage.UpdateMyChartClassifySortByClassifyId(sysUser.AdminId, firstClassify.MyChartClassifyId-1, 0, updateSortStr)
 		}
@@ -653,7 +682,7 @@ func (this *MyChartController) ClassifyDelete() {
 	}
 
 	item, err := data_manage.GetMyChartClassifyById(sysUser.AdminId, req.MyChartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 		return
@@ -752,7 +781,7 @@ func (this *MyChartController) MyChartAdd() {
 	}
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败!"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -773,14 +802,14 @@ func (this *MyChartController) MyChartAdd() {
 	pars = append(pars, req.ChartInfoId)
 
 	existItem, err := data_manage.GetMyChartDetailByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,校验名称是否存在失败,Err:" + err.Error()
 		return
 	}
 	resp := new(data_manage.MyChartAddResp)
 	var myChartClassifyId string
-	if existItem != nil { //修改
+	if existItem != nil && existItem.MyChartId > 0 { //修改
 		fmt.Println("modify")
 		for _, v := range req.MyChartClassifyId {
 			myChartClassifyId += strconv.Itoa(v) + ","
@@ -813,7 +842,7 @@ func (this *MyChartController) MyChartAdd() {
 			var sort float64
 			// 查找最小排序值
 			firstMapItem, _ := data_manage.GetMyChartSort(sysUser.AdminId, v, 0)
-			if firstMapItem != nil {
+			if firstMapItem != nil && firstMapItem.MyChartClassifyMappingId > 0 {
 				sort = firstMapItem.Sort
 			}
 			//获取最大的排序字段
@@ -893,7 +922,7 @@ func (this *MyChartController) MyChartAddToClassify() {
 	}
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败!"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
@@ -914,14 +943,14 @@ func (this *MyChartController) MyChartAddToClassify() {
 	pars = append(pars, req.ChartInfoId)
 
 	existItem, err := data_manage.GetMyChartDetailByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,校验名称是否存在失败,Err:" + err.Error()
 		return
 	}
 	resp := new(data_manage.MyChartAddResp)
 	var myChartClassifyId string
-	if existItem != nil { //修改
+	if existItem != nil && existItem.MyChartId > 0 { //修改
 		fmt.Println("modify")
 		for _, v := range req.MyChartClassifyId {
 			myChartClassifyId += strconv.Itoa(v) + ","
@@ -1034,9 +1063,9 @@ func (this *MyChartController) GetMyChartClassifyIdList() {
 	pars = append(pars, sysUser.AdminId, chartInfoId)
 
 	existItem, _ := data_manage.GetMyChartDetailByCondition(condition, pars)
-	if existItem != nil {
+	if existItem != nil && existItem.MyChartId > 0 {
 		myChartClassifyList, err := data_manage.GetMyChartClassifyList(existItem.MyChartId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败!"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -1232,6 +1261,7 @@ func (this *MyChartController) MyChartList() {
 
 	myChartId, _ := this.GetInt("MyChartId")
 	isShared, _ := this.GetBool("IsShared")
+	keyword := this.GetString("Keyword")
 
 	var total int
 	page := paging.GetPaging(currentIndex, pageSize, total)
@@ -1257,7 +1287,7 @@ func (this *MyChartController) MyChartList() {
 		if isShared {
 			myClassify, e := data_manage.GetMyChartClassifyByClassifyId(myChartClassifyId)
 			if e != nil {
-				if e.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(e) {
 					br.Msg = "分类已被删除, 请刷新页面"
 					return
 				}
@@ -1268,6 +1298,14 @@ func (this *MyChartController) MyChartList() {
 			chartAdminId = myClassify.AdminId
 		}
 	}
+	if keyword != "" {
+		if this.Lang == utils.LANG_EN {
+			condition += " AND (b.chart_name_en like ?) "
+		} else {
+			condition += " AND (b.chart_name like ?) "
+		}
+		pars = append(pars, "%"+keyword+"%")
+	}
 
 	condition += " AND (a.admin_id = ? OR d.is_public = 1)"
 	pars = append(pars, chartAdminId)
@@ -1282,7 +1320,7 @@ func (this *MyChartController) MyChartList() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1300,14 +1338,14 @@ func (this *MyChartController) MyChartList() {
 
 	//获取图表信息
 	list, err := data_manage.GetMyChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
 	}
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -1382,7 +1420,7 @@ func (this *MyChartController) MyChartList() {
 	}
 
 	resp := new(data_manage.MyChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.MyChartList, 0)
 		resp.Paging = page
 		resp.List = items
@@ -1392,7 +1430,7 @@ func (this *MyChartController) MyChartList() {
 		return
 	}
 	total, err = data_manage.GetMyChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取我的图表数据总数失败,Err:" + err.Error()
 		return
@@ -1573,7 +1611,7 @@ func (this *MyChartController) ChartRecommendList() {
 
 	//获取图表信息
 	list, err := data_manage.GetRecommendChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -1581,7 +1619,7 @@ func (this *MyChartController) ChartRecommendList() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -1632,7 +1670,7 @@ func (this *MyChartController) ChartRecommendList() {
 	}
 
 	resp := new(data_manage.ChartRecommendListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.List = items
 		br.Ret = 200
@@ -1681,7 +1719,7 @@ func (this *MyChartController) MyChartSearch() {
 
 	//获取图表信息
 	list, err := data_manage.GetMyChartSearchByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -1776,7 +1814,7 @@ func (this *MyChartController) MyChartSearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1893,7 +1931,7 @@ func (this *MyChartController) PublicClassifyList() {
 	}
 	//获取图表信息
 	list, err := data_manage.GetPublicChartClassifyAllExceptMy(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取公共分类信息失败"
 		br.ErrMsg = "获取公共分类信息失败,Err:" + err.Error()
@@ -1901,7 +1939,7 @@ func (this *MyChartController) PublicClassifyList() {
 	}
 
 	resp := new(data_manage.PublicChartClassifyResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		resp.List = make([]data_manage.PublicChartClassifyList, 0)
 		br.Ret = 200
 		br.Success = true
@@ -1963,11 +2001,11 @@ func (this *MyChartController) PublicClassifyList() {
 	// 指标显示的语言
 	{
 		configDetail, _ := system.GetConfigDetailByCode(this.SysUser.AdminId, system.ChartLanguageVar)
-		if configDetail != nil {
+		if configDetail != nil && configDetail.ConfigId > 0 {
 			language = configDetail.ConfigValue
 		} else {
 			configDetail, _ = system.GetDefaultConfigDetailByCode(system.ChartLanguageVar)
-			if configDetail != nil {
+			if configDetail != nil && configDetail.ConfigId > 0 {
 				language = configDetail.ConfigValue
 			}
 		}
@@ -2010,7 +2048,7 @@ func (this *MyChartController) ModifyClassifyPublicStatus() {
 	}
 	//查询该分类存不存在
 	item, err := data_manage.GetMyChartClassifyById(sysUser.AdminId, req.MyChartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "修改失败,找不到该分类"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 		return
@@ -2082,7 +2120,7 @@ func (this *MyChartController) CopyClassifyAndChart() {
 	}
 	//查询该公共分类存不存在
 	item, err := data_manage.GetPublicMyChartClassifyById(req.MyChartClassifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "复制失败,找不到该分类"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 		return
@@ -2237,7 +2275,7 @@ func (this *MyChartController) CompanyPublicClassifyList() {
 		pars = append(pars, keyword)
 	}
 	list, err := data_manage.GetCompanyPublicClassifyList(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取用户可见分类列表失败"
 		br.ErrMsg = "获取用户可见分类列表失败, Err:" + err.Error()
@@ -2245,7 +2283,7 @@ func (this *MyChartController) CompanyPublicClassifyList() {
 	}
 
 	resp := new(data_manage.MyChartClassifyResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.MyChartClassifyItem, 0)
 		resp.List = items
 		br.Ret = 200
@@ -2267,10 +2305,6 @@ func (this *MyChartController) CompanyPublicClassifyList() {
 	br.Data = resp
 }
 
-//func init() {
-//	data.AddAllMyChartInfo()
-//}
-
 // ClassifyFrameworkNodeList
 // @Title 我的图表分类-关联的框架节点列表
 // @Description 我的图表分类-关联的框架节点列表
@@ -2302,7 +2336,7 @@ func (this *MyChartController) ClassifyFrameworkNodeList() {
 
 	_, e := data_manage.GetMyChartClassifyById(sysUser.AdminId, classifyId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "分类不存在, 请刷新页面"
 			return
 		}

+ 61 - 18
controllers/data_manage/mysteel_chemical_data.go

@@ -44,14 +44,14 @@ func (this *EdbInfoController) MysteelChemicalClassify() {
 	}
 
 	rootList, err := data_manage.GetBaseFromMysteelChemicalClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromMysteelChemicalClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -113,7 +113,7 @@ func (this *EdbInfoController) MysteelChemicalIndexList() {
 		return
 	}
 	allBaseFromMysteelChemicalIndex, err := data_manage.GetMysteelChemicalIndexByClassifyId(classifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
@@ -594,7 +594,7 @@ func (this *EdbInfoController) MysteelChemicalData() {
 			dataList = make([]*data_manage.MysteelChemicalData, 0)
 		}
 		edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_MYSTEEL_CHEMICAL, v.IndexCode)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取数据失败"
 			br.ErrMsg = "获取指标库统计数据失败,Err:" + err.Error()
 			return
@@ -1327,7 +1327,7 @@ func (c *EdbInfoController) NameCheck() {
 			EdbName: v.EdbName,
 		})
 		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, 0, utils.EDB_DATA_LIMIT)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
 			return
@@ -1585,7 +1585,7 @@ func (this *EdbInfoController) Add() {
 
 	tmpInfo, err := data_manage.GetBaseFromMysteelChemicalIndexByCode(req.EdbCode)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取失败,Err:" + err.Error()
 			return
@@ -1745,7 +1745,7 @@ func (c *EdbInfoController) AddCheck() {
 	br.Success = true
 }
 
-// MysteelChemicalSearch
+// MysteelChemicalBatchSearch
 // @Title 钢联化工指标查询
 // @Description 钢联化工指标查询
 // @Param   BaseFromMysteelChemicalClassifyIds   query   string  true       "分类id"
@@ -1779,17 +1779,58 @@ func (this *EdbInfoController) MysteelChemicalBatchSearch() {
 		condition += " AND (index_name like ? OR index_code like ?) "
 		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
 	}
+	// 频度(多选)
+	frequencies := this.GetString("Frequencies")
+	frequencies = strings.TrimSpace(frequencies)
+	if frequencies != "" {
+		freArr := strings.Split(frequencies, ",")
+		if len(freArr) > 0 {
+			condition += " AND frequency IN ?"
+			pars = append(pars, freArr)
+		}
+	}
+	resp := new(data_manage.MysteelChemicalPageListResp)
+	resp.List = make([]*data_manage.MysteelChemicalList, 0)
+
+	//if classifyIdStr == `` && keyword == `` {
+	//	var list = make([]*data_manage.MysteelChemicalList, 0)
+	//	br.Ret = 200
+	//	br.Success = true
+	//	br.Msg = "获取成功"
+	//	br.Data = list
+	//	return
+	//}
+
+	// 分页查询
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize10
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
 
-	if classifyIdStr == `` && keyword == `` {
-		var list = make([]*data_manage.MysteelChemicalList, 0)
+	// 获取未加入指标库的原始指标
+	total, e := data_manage.GetNoEdbMysteelChemicalIndexCount(condition, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取未加入指标库的钢联指标数失败, %v", e)
+		return
+	}
+	if total <= 0 {
+		page := paging.GetPaging(currentIndex, pageSize, 0)
+		resp.Paging = page
+		br.Data = resp
 		br.Ret = 200
 		br.Success = true
 		br.Msg = "获取成功"
-		br.Data = list
 		return
 	}
 
-	list, err := data_manage.GetMysteelChemicalIndex(condition, pars)
+	list, err := data_manage.GetNoEdbMysteelChemicalIndexPageList(condition, pars, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -1802,6 +1843,7 @@ func (this *EdbInfoController) MysteelChemicalBatchSearch() {
 			classifyIdInts = append(classifyIdInts, v.BaseFromMysteelChemicalClassifyId)
 		}
 	}
+	classifyListMap := make(map[int]int, 0)
 	if len(classifyIdInts) > 0 {
 		// 查询父级分类信息
 		classifyList, e := data_manage.GetBaseFromMysteelChemicalClassifyByIds(classifyIdInts)
@@ -1810,20 +1852,21 @@ func (this *EdbInfoController) MysteelChemicalBatchSearch() {
 			br.ErrMsg = "获取失获取目录信息失败,Err:" + e.Error()
 			return
 		}
-		classifyListMap := make(map[int]int, 0)
 		for _, v := range classifyList {
 			classifyListMap[v.BaseFromMysteelChemicalClassifyId] = v.ParentId
 		}
-		for _, v := range list {
-			v.UniqueCode = fmt.Sprint(v.BaseFromMysteelChemicalClassifyId, "_", v.Id)
-			if p, ok := classifyListMap[v.BaseFromMysteelChemicalClassifyId]; ok {
-				v.ParentClassifyId = p
-			}
+	}
+	for _, v := range list {
+		if p, ok := classifyListMap[v.BaseFromMysteelChemicalClassifyId]; ok {
+			v.ParentClassifyId = p
 		}
+		resp.List = append(resp.List, v)
 	}
 
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
-	br.Data = list
+	br.Data = resp
 }

+ 14 - 5
controllers/data_manage/predict_edb_classify.go

@@ -259,7 +259,7 @@ func (this *PredictEdbClassifyController) Edit() {
 		return
 	}
 
-	err, errMsg := data.EditEdbClassify(req.ClassifyId, req.ClassifyName, this.Lang, this.SysUser)
+	err, errMsg := data.EditEdbClassify(req.ClassifyId, req.ParentId, req.ClassifyName, this.Lang, this.SysUser, true)
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg
@@ -702,7 +702,7 @@ func (this *PredictEdbClassifyController) SimpleList() {
 	}
 
 	rootList, err := data_manage.GetEdbClassifyByParentId(parentId, 1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -715,7 +715,7 @@ func (this *PredictEdbClassifyController) SimpleList() {
 		// 获取当前账号的不可见指标
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -792,6 +792,15 @@ func (this *PredictEdbClassifyController) SimpleList() {
 		sort.Sort(sortList)
 	}
 
+	if isOnlyMe {
+		sortList, err = data.GetEdbClassifyByIsMe(sysUserId, parentId, 1, sortList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取只看我的分类列表失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 是否允许添加一级分类
 	canOpClassify := true
 	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0, true)
@@ -836,7 +845,7 @@ func (this *PredictEdbClassifyController) ClassifyTree() {
 	}()
 
 	allList, err := data_manage.GetPredictEdbClassifyAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -860,7 +869,7 @@ func (this *PredictEdbClassifyController) ClassifyTree() {
 			button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			allList[k].Button = button
 		}
-		nodeAll = data.GetClassifyTreeRecursive(allList, 0)
+		nodeAll = data.GetClassifyTreeRecursive(allList, 0, 0)
 		//根据sort值排序
 		sortList = nodeAll
 		sort.Sort(sortList)

+ 211 - 95
controllers/data_manage/predict_edb_info.go

@@ -80,7 +80,7 @@ func (this *PredictEdbInfoController) EdbChartList() {
 	// 筛选分类
 	if classifyId > 0 {
 		childClassify, e, _ := data.GetChildClassifyByClassifyId(classifyId)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 			return
@@ -104,7 +104,7 @@ func (this *PredictEdbInfoController) EdbChartList() {
 	// 获取当前账号的不可见指标
 	obj := data_manage.EdbInfoNoPermissionAdmin{}
 	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 		return
@@ -120,14 +120,14 @@ func (this *PredictEdbInfoController) EdbChartList() {
 	}
 	//获取指标信息
 	dataCount, list, err := data_manage.GetEdbInfoFilterList(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取预测指标列表失败"
 		br.ErrMsg = "获取预测指标列表失败,Err:" + err.Error()
 		return
 	}
 
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		list = make([]*data_manage.EdbInfoList, 0)
 	} else {
 		classifyIdList := make([]int, 0)
@@ -245,14 +245,14 @@ func (this *PredictEdbInfoController) List() {
 	}
 	//获取指标信息
 	edbInfoItem, err := data_manage.GetEdbInfoByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
 	}
 
-	if edbInfoItem == nil || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if edbInfoItem == nil || (err != nil && utils.IsErrNoRow(err)) {
 		item := new(data_manage.EdbInfoList)
 		resp.Paging = page
 		resp.Item = item
@@ -289,7 +289,7 @@ func (this *PredictEdbInfoController) List() {
 	//获取指标数据(实际已生成)
 	{
 		dataCount, dataList, err := data.GetPageData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, edbInfoItem.LatestDate, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标信息失败"
 			br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 			return
@@ -427,31 +427,56 @@ func (this *PredictEdbInfoController) Add() {
 	ruleList := make([]request.RuleConfig, 0)
 	{
 		ruleMap := make(map[string]request.RuleConfig)
+		ruleEndNumSortMap := make(map[int]request.RuleConfig)
 		dateIntList := make([]int64, 0)
+		endNumList := make([]int, 0)
 		for _, v := range req.RuleList {
-			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
-			if err != nil {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
-				br.IsSendEmail = false
-				return
+			if req.EndDateType == 0 {
+				confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
+				if err != nil {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
+					br.IsSendEmail = false
+					return
+				}
+				dateIntList = append(dateIntList, confEndDate.Unix())
+				ruleMap[v.EndDate] = v
+			} else {
+				if _, ok := ruleEndNumSortMap[v.EndNum]; ok {
+					br.Msg = "所选期数不能和其他时间段相同"
+					return
+				}
+				endNumList = append(endNumList, v.EndNum)
+				ruleEndNumSortMap[v.EndNum] = v
 			}
-			dateIntList = append(dateIntList, confEndDate.Unix())
-			ruleMap[v.EndDate] = v
-		}
-		sort.Slice(dateIntList, func(i, j int) bool {
-			return dateIntList[i] < dateIntList[j]
-		})
-		for _, dateInt := range dateIntList {
-			currDateTime := time.Unix(dateInt, 0)
-			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
-			if !ok {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择"
-				br.IsSendEmail = false
-				return
+		}
+		if req.EndDateType == 0 {
+			sort.Slice(dateIntList, func(i, j int) bool {
+				return dateIntList[i] < dateIntList[j]
+			})
+			for _, dateInt := range dateIntList {
+				currDateTime := time.Unix(dateInt, 0)
+				item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
+			}
+		} else {
+			sort.Ints(endNumList)
+			for _, endNum := range endNumList {
+				item, ok := ruleEndNumSortMap[endNum]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
 			}
-			ruleList = append(ruleList, item)
 		}
 	}
 	req.RuleList = ruleList
@@ -479,6 +504,19 @@ func (this *PredictEdbInfoController) Add() {
 	}
 	resp := respItem.Data
 
+	edbInfoIdArr := make([]int, 0)
+	//查询相关的指标
+	edbMappingList, err := data_manage.GetAllCalculateByEdbInfoIdV2(resp.EdbInfoId)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取引用的指标信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range edbMappingList {
+		edbInfoIdArr = append(edbInfoIdArr, v.FromEdbInfoId)
+	}
+	// 添加指标引用记录
+	_ = data.SavePredictEdbInfoRelation(edbInfoIdArr, resp.EdbInfoId)
 	//添加es
 	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)
 
@@ -523,7 +561,7 @@ func (this *PredictEdbInfoController) ChartImageSet() {
 		if err != nil {
 			br.Msg = "保存失败"
 			br.ErrMsg = "保存失败,Err:" + err.Error()
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "找不到该指标"
 				br.ErrMsg = "找不到该指标"
 				br.IsSendEmail = false
@@ -603,31 +641,56 @@ func (this *PredictEdbInfoController) Edit() {
 	ruleList := make([]request.RuleConfig, 0)
 	{
 		ruleMap := make(map[string]request.RuleConfig)
+		ruleEndNumSortMap := make(map[int]request.RuleConfig)
 		dateIntList := make([]int64, 0)
+		endNumList := make([]int, 0)
 		for _, v := range req.RuleList {
-			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
-			if err != nil {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
-				br.IsSendEmail = false
-				return
+			if req.EndDateType == 0 {
+				confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
+				if err != nil {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
+					br.IsSendEmail = false
+					return
+				}
+				dateIntList = append(dateIntList, confEndDate.Unix())
+				ruleMap[v.EndDate] = v
+			} else {
+				if _, ok := ruleEndNumSortMap[v.EndNum]; ok {
+					br.Msg = "所选期数不能和其他时间段相同"
+					return
+				}
+				endNumList = append(endNumList, v.EndNum)
+				ruleEndNumSortMap[v.EndNum] = v
 			}
-			dateIntList = append(dateIntList, confEndDate.Unix())
-			ruleMap[v.EndDate] = v
-		}
-		sort.Slice(dateIntList, func(i, j int) bool {
-			return dateIntList[i] < dateIntList[j]
-		})
-		for _, dateInt := range dateIntList {
-			currDateTime := time.Unix(dateInt, 0)
-			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
-			if !ok {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择"
-				br.IsSendEmail = false
-				return
+		}
+		if req.EndDateType == 0 {
+			sort.Slice(dateIntList, func(i, j int) bool {
+				return dateIntList[i] < dateIntList[j]
+			})
+			for _, dateInt := range dateIntList {
+				currDateTime := time.Unix(dateInt, 0)
+				item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
+			}
+		} else {
+			sort.Ints(endNumList)
+			for _, endNum := range endNumList {
+				item, ok := ruleEndNumSortMap[endNum]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
 			}
-			ruleList = append(ruleList, item)
 		}
 	}
 	req.RuleList = ruleList
@@ -681,6 +744,19 @@ func (this *PredictEdbInfoController) Edit() {
 	}
 	resp := respItem.Data
 
+	edbInfoIdArr := make([]int, 0)
+	//查询相关的指标
+	edbMappingList, err := data_manage.GetAllCalculateByEdbInfoIdV2(resp.EdbInfoId)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取引用的指标信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range edbMappingList {
+		edbInfoIdArr = append(edbInfoIdArr, v.FromEdbInfoId)
+	}
+	// 添加指标引用记录
+	_ = data.SavePredictEdbInfoRelation(edbInfoIdArr, resp.EdbInfoId)
 	//修改es
 	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)
 
@@ -850,7 +926,7 @@ func (this *PredictEdbInfoController) Detail() {
 	if edbInfo.EdbType == 1 {
 		// 获取所有的指标预测规则配置
 		tmpPredictEdbConfList, err := data_manage.GetPredictEdbConfListById(edbInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取预测指标配置信息失败,Err:" + err.Error()
 			return
@@ -859,7 +935,7 @@ func (this *PredictEdbInfoController) Detail() {
 			var tmpPredictEdbConfCalculateMappingDetail []*data_manage.PredictEdbConfCalculateMappingDetail
 			if v.RuleType == 9 || v.RuleType == 14 {
 				tmpPredictEdbConfCalculateMappingDetail, err = data_manage.GetPredictEdbConfCalculateMappingDetailListByConfigId(v.PredictEdbInfoId, v.ConfigId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取预测指标配置与关联指标信息失败,Err:" + err.Error()
 					return
@@ -901,6 +977,7 @@ func (this *PredictEdbInfoController) Detail() {
 				ModifyTime:       v.ModifyTime,
 				CreateTime:       v.CreateTime,
 				CalculateList:    tmpPredictEdbConfCalculateMappingDetail,
+				EndNum:           v.EndNum,
 			}
 			predictEdbConfList = append(predictEdbConfList, tmp)
 		}
@@ -1100,7 +1177,7 @@ func (this *PredictEdbInfoController) FilterByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1176,6 +1253,15 @@ func (this *PredictEdbInfoController) FilterByEs() {
 	for i := 0; i < edbInfoListLen; i++ {
 		edbInfoList[i].EdbNameAlias = edbInfoList[i].EdbName
 		classifyIdList = append(classifyIdList, edbInfoList[i].ClassifyId)
+		// 如果没有关键词,那么搜索结果字段取指标名,前端已统一用该字段显示搜索的列表内容
+		if keyWord == "" {
+			if this.Lang == utils.ZhLangVersion {
+				edbInfoList[i].SearchText = edbInfoList[i].EdbName
+			}
+			if this.Lang == utils.EnLangVersion {
+				edbInfoList[i].SearchText = edbInfoList[i].EdbNameEn
+			}
+		}
 	}
 
 	// 当前列表中的分类map
@@ -1407,13 +1493,17 @@ func (this *PredictEdbInfoController) DataList() {
 		}
 	}
 
-	maxYear := 0
+	var maxDate time.Time
 	if edbInfo.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
+	}
+	if chartType == utils.CHART_TYPE_SEASON && dateType == utils.DateTypeNYears {
+		// 季节性图需要特殊处理最近N年数据
+		maxDate = time.Date(maxDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 	if endDate == "" {
 		endDate = time.Now().Format(utils.FormatDate)
 	}
@@ -1519,31 +1609,56 @@ func (this *PredictEdbInfoController) ChartDataList() {
 	ruleList := make([]request.RuleConfig, 0)
 	{
 		ruleMap := make(map[string]request.RuleConfig)
+		ruleEndNumSortMap := make(map[int]request.RuleConfig)
 		dateIntList := make([]int64, 0)
+		endNumList := make([]int, 0)
 		for _, v := range req.RuleList {
-			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
-			if err != nil {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
-				br.IsSendEmail = false
-				return
+			if req.EndDateType == 0 {
+				confEndDate, err := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
+				if err != nil {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
+					br.IsSendEmail = false
+					return
+				}
+				dateIntList = append(dateIntList, confEndDate.Unix())
+				ruleMap[v.EndDate] = v
+			} else {
+				if _, ok := ruleEndNumSortMap[v.EndNum]; ok {
+					br.Msg = "所选期数不能和其他时间段相同"
+					return
+				}
+				endNumList = append(endNumList, v.EndNum)
+				ruleEndNumSortMap[v.EndNum] = v
 			}
-			dateIntList = append(dateIntList, confEndDate.Unix())
-			ruleMap[v.EndDate] = v
-		}
-		sort.Slice(dateIntList, func(i, j int) bool {
-			return dateIntList[i] < dateIntList[j]
-		})
-		for _, dateInt := range dateIntList {
-			currDateTime := time.Unix(dateInt, 0)
-			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
-			if !ok {
-				br.Msg = "配置项中时间异常,请重新选择"
-				br.ErrMsg = "配置项中时间异常,请重新选择"
-				br.IsSendEmail = false
-				return
+		}
+		if req.EndDateType == 0 {
+			sort.Slice(dateIntList, func(i, j int) bool {
+				return dateIntList[i] < dateIntList[j]
+			})
+			for _, dateInt := range dateIntList {
+				currDateTime := time.Unix(dateInt, 0)
+				item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
+			}
+		} else {
+			sort.Ints(endNumList)
+			for _, endNum := range endNumList {
+				item, ok := ruleEndNumSortMap[endNum]
+				if !ok {
+					br.Msg = "配置项中时间异常,请重新选择"
+					br.ErrMsg = "配置项中时间异常,请重新选择"
+					br.IsSendEmail = false
+					return
+				}
+				ruleList = append(ruleList, item)
 			}
-			ruleList = append(ruleList, item)
 		}
 	}
 
@@ -1552,13 +1667,17 @@ func (this *PredictEdbInfoController) ChartDataList() {
 
 	endDateStr := `` //数据的结束日期
 	for _, v := range ruleList {
-		endDateStr = v.EndDate //预测指标的结束日期
-		confEndDate, err := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
-		if err != nil {
-			br.Msg = "配置项中时间异常,请重新选择"
-			br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
-			return
+		var confEndDate time.Time
+		if v.EndDate != "" {
+			endDateStr = v.EndDate //预测指标的结束日期
+			confEndDate, err = time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
+			if err != nil {
+				br.Msg = "配置项中时间异常,请重新选择"
+				br.ErrMsg = "配置项中时间异常,请重新选择,err:" + err.Error()
+				return
+			}
 		}
+
 		// 没有数据,自己瞎测试
 		//switch v.RuleType {
 		//case 3: //3:同比
@@ -1619,6 +1738,7 @@ func (this *PredictEdbInfoController) ChartDataList() {
 			FixedValue:       0,
 			Value:            v.Value,
 			EndDate:          confEndDate,
+			EndNum:           v.EndNum,
 			ModifyTime:       time.Now(),
 			CreateTime:       time.Now(),
 			DataList:         tmpDataList,
@@ -1631,20 +1751,20 @@ func (this *PredictEdbInfoController) ChartDataList() {
 	if err != nil {
 		br.Msg = "获取来源指标信息失败"
 		br.ErrMsg = "获取来源指标信息失败"
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.ErrMsg = "获取来源指标信息失败,Err:" + err.Error()
 		}
 		br.Success = true
 		return
 	}
 	// todo 确认预测指标是否用的是来源指标的最新日期
-	maxYear := 0
+	var maxDate time.Time
 	if sourceEdbInfoItem.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, sourceEdbInfoItem.LatestDate)
-		maxYear = latestDateT.Year()
+		maxDate = latestDateT
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 	if endDate == "" {
 		endDate = time.Now().Format(utils.FormatDate)
 	}
@@ -1692,7 +1812,7 @@ func (this *PredictEdbInfoController) ChartDataList() {
 		// 获取预测数据
 		var predictMinValue, predictMaxValue float64
 
-		predictDataList, predictMinValue, predictMaxValue, err, errMsg := data.GetChartPredictEdbInfoDataListByConfList(predictEdbConfAndDataList, startDate, sourceEdbInfoItem.LatestDate, endDateStr, sourceEdbInfoItem.Frequency, req.DataDateType, allDataList)
+		predictDataList, predictMinValue, predictMaxValue, err, errMsg := data.GetChartPredictEdbInfoDataListByConfList(predictEdbConfAndDataList, startDate, sourceEdbInfoItem.LatestDate, endDateStr, req.EndDateType, sourceEdbInfoItem.Frequency, req.DataDateType, allDataList)
 		if err != nil {
 			br.Msg = "获取预测指标数据失败"
 			if errMsg != `` {
@@ -1930,10 +2050,6 @@ func (this *PredictEdbInfoController) Modify() {
 //
 //}
 
-//func init() {
-//	data.AddOrEditAllEdbInfoToEs()
-//}
-
 // ClassifyEdbInfoItems
 // @Title 获取分类下指标接口
 // @Description 获取分类下指标接口
@@ -1960,7 +2076,7 @@ func (this *PredictEdbInfoController) ClassifyEdbInfoItems() {
 	// 获取当前账号的不可见指标
 	obj := data_manage.EdbInfoNoPermissionAdmin{}
 	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 		return
@@ -1977,7 +2093,7 @@ func (this *PredictEdbInfoController) ClassifyEdbInfoItems() {
 	}
 
 	allEdbInfo, err := data_manage.GetEdbInfoByClassifyId(classifyId, 1, sysUserId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -2093,7 +2209,7 @@ func (this *PredictEdbInfoController) ChartImageSetBySvg() {
 	if err != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,Err:" + err.Error()
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "找不到该指标"
 			br.ErrMsg = "找不到该指标"
 			br.IsSendEmail = false

+ 1045 - 0
controllers/data_manage/purang_data.go

@@ -0,0 +1,1045 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+)
+
+type BaseFromPurangController struct {
+	controllers.BaseAuthController
+}
+
+// PurangClassify
+// @Title Purang数据分类
+// @Description Purang数据分类接口
+// @Success 200 {object} data_manage.BaseFromPurangClassify
+// @router /purang/classify [get]
+func (this *BaseFromPurangController) PurangClassify() {
+	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
+	}
+
+	classifyAll, err := data_manage.GetAllBaseFromPurangClassify()
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//组装一级分类
+	rootMap := make(map[int][]*data_manage.BaseFromPurangClassifyItems)
+	list := make([]*data_manage.BaseFromPurangClassifyItems, 0)
+	for _, classify := range classifyAll {
+		classify.UniqueCode = strconv.Itoa(classify.ClassifyId)
+		if classify.ParentId == 0 {
+			if _, ok := rootMap[classify.ClassifyId]; !ok {
+				rootMap[classify.ClassifyId] = make([]*data_manage.BaseFromPurangClassifyItems, 0)
+				list = append(list, classify)
+
+			}
+		} else {
+			child, ok := rootMap[classify.ParentId]
+			if ok {
+				child = append(child, classify)
+				rootMap[classify.ParentId] = child
+			}
+		}
+	}
+
+	for k, v := range list {
+		child, ok := rootMap[v.ClassifyId]
+		if ok {
+			list[k].Children = child
+		}
+	}
+	//组装二级分类
+	var ret data_manage.BaseFromPurangClassifyResp
+	ret.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// PurangIndexData
+// @Title 获取Purang数据
+// @Description 获取Purang数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /purang/index/data [get]
+func (this *BaseFromPurangController) PurangIndexData() {
+	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")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	// 增加频度请求入参
+	frequency := this.GetString("Frequency")
+
+	//获取指标
+	var condition string
+	var pars []interface{}
+
+	if classifyId > 0 {
+		condition += ` AND classify_id=? `
+		pars = append(pars, classifyId)
+	}
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+
+	purangList, err := data_manage.GetPurangIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	edbCodeList := make([]string, 0)
+	for _, v := range purangList {
+		edbCodeList = append(edbCodeList, v.IndexCode)
+	}
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	dataMap := make(map[string][]*data_manage.BaseFromPurangData)
+	total := 0
+	if len(edbCodeList) > 0 {
+		edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_PURANG, edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据源失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbCode] = v
+		}
+		// 首先对分类下的指标按照日期进行分页,再针对日期,进行排序
+		dataTimes, err := data_manage.GetPurangIndexDataTimePageByCodes(edbCodeList, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据日期信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataTimes) > 0 {
+			startDate := utils.GormDateStrToDateStr(dataTimes[len(dataTimes)-1])
+			endDate := utils.GormDateStrToDateStr(dataTimes[0])
+			// 把截止日往后加1天
+			endDateT, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+			endDate = endDateT.AddDate(0, 0, 1).Format(utils.FormatDate)
+			dataList, e := data_manage.GetPurangIndexDataByDataTime(edbCodeList, startDate, endDate)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			//将数据按照指标进行分类
+			for _, v := range dataList {
+				dataMap[v.IndexCode] = append(dataMap[v.IndexCode], v)
+			}
+		}
+
+		total, err = data_manage.GetPurangIndexDataTimePageCount(edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	resultList := make([]*data_manage.BaseFromPurangIndexList, 0)
+
+	for _, v := range purangList {
+		product := new(data_manage.BaseFromPurangIndexList)
+		product.BaseFromPurangIndexId = v.BaseFromPurangIndexId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.ModifyTime = v.ModifyTime
+		product.ClassifyId = v.ClassifyId
+		if edb, ok := edbInfoMap[v.IndexCode]; ok {
+			product.EdbInfoId = edb.EdbInfoId
+			product.EdbExist = 1
+		}
+
+		dataListTmp, ok := dataMap[v.IndexCode]
+		if !ok {
+			dataListTmp = make([]*data_manage.BaseFromPurangData, 0)
+		}
+		product.DataList = dataListTmp
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// PurangSearchList
+// @Title Purang模糊搜索
+// @Description Purang模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} models.BaseResponse
+// @router /purang/search_list [get]
+func (this *BaseFromPurangController) PurangSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	list := make([]*data_manage.BaseFromPurangIndexSearchItem, 0)
+	var err error
+	//关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetPurangItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+
+	} else {
+		list, err = data_manage.GetPurangItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+	classifyIds := make([]int, 0)
+	for _, v := range list {
+		classifyIds = append(classifyIds, v.ClassifyId)
+	}
+	classifyList, err := data_manage.GetBaseFromPurangClassifyByIds(classifyIds)
+	if err != nil {
+		br.Msg = "搜索失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	classifyMap := make(map[int]int)
+	for _, v := range classifyList {
+		classifyMap[v.ClassifyId] = v.ParentId
+	}
+	for _, v := range list {
+		v.ParentClassifyId = classifyMap[v.ClassifyId]
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// PurangSingleData
+// @Title 获取Purang数据
+// @Description 获取Purang单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /purang/single_data [get]
+func (this *BaseFromPurangController) PurangSingleData() {
+	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
+	}
+	indexCode := this.GetString("IndexCode")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	var total int64
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	indexInfo, err := data_manage.GetBaseFromPurangIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	total, err = data_manage.GetPurangIndexDataTotalByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, int(total))
+	dataTmpList, err := data_manage.GetPurangIndexDataByCode(indexCode, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_PURANG, indexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据源失败"
+		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.PurangSingleDataResp
+	var dataList []*data_manage.PurangSingleData
+
+	if edbInfo != nil {
+		ret.EdbInfoId = edbInfo.EdbInfoId
+		ret.EdbExist = 1
+	}
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromPurangIndexId = indexInfo.BaseFromPurangIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.PurangSingleData{
+			Value:    v.Value,
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+	ret.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// PurangIndexList
+// @Title Purang指标列表
+// @Description Purang指标列表
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Success 200 {object} data_manage.BaseFromPurangClassifyResp
+// @router /purang/classify/index/list [get]
+func (this *BaseFromPurangController) PurangIndexList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	indexList, err := data_manage.GetPurangIndexByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.BaseFromPurangClassifyResp
+	list := make([]*data_manage.BaseFromPurangClassifyItems, 0)
+	for _, v := range indexList {
+		classify := new(data_manage.BaseFromPurangClassifyItems)
+		classify.ClassifyId = classifyId
+		classify.BaseFromPurangIndexId = v.BaseFromPurangIndexId
+		classify.IndexCode = v.IndexCode
+		classify.ClassifyName = v.IndexName
+		classify.UniqueCode = fmt.Sprintf("%d_%d", classifyId, v.BaseFromPurangIndexId)
+		list = append(list, classify)
+	}
+	ret.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// PurangNameCheck
+// @Title 加入指标库的重名检测
+// @Description 加入指标库的重名检测
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} NameCheckResult
+// @router /purang/edb_info/name_check [post]
+func (this *BaseFromPurangController) PurangNameCheck() {
+	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 []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_PURANG, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_PURANG, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// PurangAddCheck
+// @Title 加入指标库指标Id检测
+// @Description 加入指标库指标Id检测
+// @Param	request	body request.BatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /purang/edb_info/add_check [post]
+func (c *BaseFromPurangController) PurangAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req.IndexCodes)
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_PURANG)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetPurangIndex(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromPurangIndexList, 0)
+	for _, v := range list {
+		if edb, ok := existMap[v.IndexCode]; ok {
+			v.EdbInfoId = edb.EdbInfoId
+			v.EdbClassifyId = edb.ClassifyId
+			v.EdbUniqueCode = edb.UniqueCode
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// PurangEdbInfoAdd
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /purang/edb_info/add [post]
+func (this *BaseFromPurangController) PurangEdbInfoAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req data_manage.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	req.EdbCode = strings.Trim(req.EdbCode, " ")
+
+	if req.EdbCode == "" {
+		br.Msg = "指标ID不能为空"
+		return
+	}
+
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	count, err := data_manage.GetPurangIndexDataCount(req.EdbCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if count == 0 {
+		br.Msg = "指标不存在"
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_PURANG, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 试用平台更新用户累计新增指标数
+	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+		return
+	}
+	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+		go func() {
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	//新增操作日志
+	{
+		edbLog := new(data_manage.EdbInfoLog)
+		edbLog.EdbInfoId = edbInfo.EdbInfoId
+		edbLog.SourceName = edbInfo.SourceName
+		edbLog.Source = edbInfo.Source
+		edbLog.EdbCode = edbInfo.EdbCode
+		edbLog.EdbName = edbInfo.EdbName
+		edbLog.ClassifyId = edbInfo.ClassifyId
+		edbLog.SysUserId = sysUser.AdminId
+		edbLog.SysUserRealName = sysUser.RealName
+		edbLog.CreateTime = time.Now()
+		edbLog.Content = string(this.Ctx.Input.RequestBody)
+		edbLog.Status = "新增指标"
+		edbLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddEdbInfoLog(edbLog)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// ExportPurangList
+// @Title 导出Purang数据
+// @Description 导出Purang数据
+// @Param   ClassifyId   query   int  true       "关键字搜索"
+// @Param   IndexCode   query   string  true       "指标编码"
+// @Success 200  导出成功
+// @router /purang/export [get]
+func (this *BaseFromPurangController) ExportPurangList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	indexCode := this.GetString("IndexCode")
+
+	if classifyId <= 0 && indexCode == "" {
+		br.Msg = "请选择分类或者指标"
+		return
+	}
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var condition string
+	var pars []interface{}
+	var classifyName string
+	if classifyId > 0 {
+		classifyInfo, err := data_manage.GetBaseFromPurangClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		classifyName = classifyInfo.ClassifyName
+		childClassify, err := data_manage.GetBaseFromPurangClassifyByParentId(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+
+		if len(childClassify) > 0 {
+			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			for _, child := range childClassify {
+				pars = append(pars, child.ClassifyId)
+			}
+		} else {
+			condition += ` AND classify_id=?`
+			pars = append(pars, classifyId)
+		}
+	}
+	if indexCode != "" {
+		condition += ` AND index_code=? `
+		pars = append(pars, indexCode)
+	}
+
+	indexList, err := data_manage.GetPurangIndex(condition, pars)
+	if err != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "获取指标失败,Err:" + err.Error()
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+
+	codeList := make([]string, 0)
+	frequenciesMap := make(map[string][]*data_manage.BaseFromPurangIndexList)
+	for _, v := range indexList {
+		codeList = append(codeList, v.IndexCode)
+		frequenciesMap[v.Frequency] = append(frequenciesMap[v.Frequency], v)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromPurangData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetPurangIndexDataByCodes(codeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+	}
+	// 按照频率分组排序
+	frequencies := []string{
+		"日度", "周度", "旬度", "月度", "季度", "半年度", "年度",
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		indexCodeList, ok := frequenciesMap[frequency]
+		if !ok {
+			continue
+		}
+		if len(indexCodeList) <= 0 {
+			fmt.Printf("sheet:%s, 不存在指标", frequency)
+			return
+		}
+		var sheetName string
+		switch frequency {
+		case "日度":
+			sheetName = "日度(Daily)"
+		case "周度":
+			sheetName = "周度(Weekly)"
+		case "旬度":
+			sheetName = "旬度(ten-day)"
+		case "月度":
+			sheetName = "月度(Monthly)"
+		case "季度":
+			sheetName = "季度(Quarterly)"
+		case "半年度":
+			sheetName = "半年度(Semi-annual)"
+		case "年度":
+			sheetName = "年度(Annual)"
+		default:
+			sheetName = "其他数据"
+		}
+		sheetNew, err := xlsxFile.AddSheet(sheetName)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, idx := range frequenciesMap[frequency] {
+			indexIdList = append(indexIdList, idx.BaseFromPurangIndexId)
+		}
+		dataTimeList, err := data_manage.GetPurangDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取数据时间失败,Err:" + err.Error()
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, icl := range indexCodeList {
+			// 获取数据
+			dataList, ok := dataListMap[icl.IndexCode]
+			if !ok {
+				continue
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称/Metric Name")
+				frequencyRow.AddCell().SetValue("频度/Frequency")
+				unitRow.AddCell().SetValue("单位/Unit")
+				lastModifyDateRow.AddCell().SetValue("更新时间/Update Time")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(icl.IndexName)
+			frequencyRow.AddCell().SetValue(icl.Frequency)
+			unitRow.AddCell().SetValue(icl.Unit)
+
+			timeDate, err := time.Parse(utils.FormatDateTime, dataList[0].ModifyTime)
+			if err != nil {
+				continue
+			}
+			lastModifyDateRow.AddCell().SetValue(timeDate.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromPurangData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		e := xlsxFile.Save(downLoadnFilePath)
+		if e != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName := classifyName
+	if indexCode != "" && len(indexList) == 1 {
+		fileName = indexList[0].IndexName
+	}
+	fileName = strings.Replace(fileName, ": ", "_", -1)
+	fileName = strings.Replace(fileName, ", ", "_", -1)
+	fileName = strings.Replace(fileName, " ", "_", -1)
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	fmt.Println(fileName)
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}
+
+// GetFrequency
+// @Title Purang数据频度
+// @Description Purang数据频度接口
+// @Param   ClassifyId   query   string  true       "分类Id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /purang/frequency [get]
+func (this *BaseFromPurangController) GetFrequency() {
+	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
+	}
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	frequencyList, err := data_manage.GetPurangFrequencyByClassifyId(classifyId)
+	if err != nil {
+		br.Msg = "获取频度失败"
+		br.ErrMsg = "获取频度失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+} 

+ 22 - 13
controllers/data_manage/range_analysis/chart_classify.go

@@ -8,6 +8,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/data_manage_permission"
+	"eta/eta_api/services/data/range_analysis"
 	"eta/eta_api/utils"
 	"fmt"
 	"sort"
@@ -60,7 +61,7 @@ func (this *RangeChartClassifyController) ChartClassifyList() {
 	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
 	// 查询分类节点
 	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_RANGE_ANALYSIS)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -127,6 +128,14 @@ func (this *RangeChartClassifyController) ChartClassifyList() {
 			nodeAll = append(nodeAll, v)
 		}
 	}
+	if isShowMe {
+		nodeAll, err = range_analysis.GetClassifyListByIsShowMe(this.SysUser.AdminId, parentId, source, nodeAll)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+	}
 
 	// 整体排序
 	if len(nodeAll) > 0 {
@@ -145,19 +154,19 @@ func (this *RangeChartClassifyController) ChartClassifyList() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_RANGE_ANALYSIS)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_RANGE_ANALYSIS)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
 	allChartInfo, err := data_manage.GetChartInfoByAdminId([]int{utils.CHART_SOURCE_RANGE_ANALYSIS, utils.CHART_SOURCE_RANGE_ANALYSIS}, adminInfo.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
@@ -253,7 +262,7 @@ func (this *RangeChartClassifyController) AddChartClassify() {
 	}
 
 	// 新增图表分类
-	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_RANGE_ANALYSIS, this.Lang, this.SysUser)
+	_, err, errMsg, isSendEmail := data.AddChartClassify(req.ChartClassifyName, req.ParentId, req.Level, utils.CHART_SOURCE_RANGE_ANALYSIS, 0, this.Lang, this.SysUser)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = "添加分类失败,Err:" + err.Error()
@@ -357,7 +366,7 @@ func (this *RangeChartClassifyController) DeleteChartClassifyCheck() {
 
 	if deleteStatus != 1 && req.ChartInfoId == 0 {
 		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
 			return
@@ -419,7 +428,7 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
 		//判断是否含有指标
 		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
 			return
@@ -443,7 +452,7 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 	if req.ChartInfoId > 0 {
 		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "图表已删除,请刷新页面"
 				br.ErrMsg = "指标不存在,Err:" + err.Error()
 				return
@@ -494,7 +503,7 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 		chartSeriesOb := new(data_manage.FactorEdbSeriesChartMapping)
 		seriesMappingItem, e := chartSeriesOb.GetItemByChartInfoId(chartInfo.ChartInfoId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 			} else {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取图表关联失败, Err: " + e.Error()
@@ -518,7 +527,7 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 		}
 		// 删除配置关联指标数据
 		multiConfig, e := data_manage.GetMultipleGraphConfigChartMappingByChartId(chartInfo.ChartInfoId)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取图表关联配置失败, Err: " + e.Error()
 			return
@@ -541,7 +550,7 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 		pars = append(pars, req.ChartInfoId)
 
 		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 			return
@@ -561,14 +570,14 @@ func (this *RangeChartClassifyController) DeleteChartClassify() {
 			pars = append(pars, chartInfo.ChartClassifyId)
 
 			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
 				return
 			}
 			if classifyItem != nil {
 				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
 					return

+ 30 - 23
controllers/data_manage/range_analysis/chart_info.go

@@ -73,7 +73,7 @@ func (this *RangeChartChartInfoController) Preview() {
 	for _, v := range req.ChartEdbInfoList {
 		edbInfoMapping, e := data_manage.GetChartEdbMappingByEdbInfoId(v.EdbInfoId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = v.EdbAliasName + "指标不存在"
 				br.ErrMsg = v.EdbAliasName + "指标不存在"
 				return
@@ -336,7 +336,7 @@ func (this *RangeChartChartInfoController) Detail() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图被删除,请刷新页面"
 			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
 			return
@@ -415,7 +415,7 @@ func (this *RangeChartChartInfoController) Detail() {
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -564,7 +564,7 @@ func (this *RangeChartChartInfoController) DetailFromUniqueCode() {
 	status := true
 	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			status = false
 		} else {
 			br.Msg = "获取失败"
@@ -602,7 +602,7 @@ func (this *RangeChartChartInfoController) DetailFromUniqueCode() {
 					myCond += ` AND a.chart_info_id=? `
 					myPars = append(myPars, chartInfo.ChartInfoId)
 					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
-					if err != nil && err.Error() != utils.ErrNoRow() {
+					if err != nil && !utils.IsErrNoRow(err) {
 						br.Msg = "获取失败"
 						br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 						return
@@ -659,7 +659,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-				if err != nil && err.Error() != utils.ErrNoRow() {
+				if err != nil && !utils.IsErrNoRow(err) {
 					msg = "获取失败"
 					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 					return
@@ -826,7 +826,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
 
 			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				msg = "获取失败"
 				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 				return
@@ -937,7 +937,7 @@ func (this *RangeChartChartInfoController) List() {
 
 	if chartClassifyId > 0 {
 		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取图表信息失败"
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
@@ -969,7 +969,7 @@ func (this *RangeChartChartInfoController) List() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -987,7 +987,7 @@ func (this *RangeChartChartInfoController) List() {
 
 	//获取图表信息
 	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Success = true
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -995,7 +995,7 @@ func (this *RangeChartChartInfoController) List() {
 	}
 
 	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取图表信息失败"
 		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
 		return
@@ -1039,7 +1039,7 @@ func (this *RangeChartChartInfoController) List() {
 	}
 
 	resp := new(data_manage.ChartListResp)
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	if list == nil || len(list) <= 0 || (err != nil && utils.IsErrNoRow(err)) {
 		items := make([]*data_manage.ChartInfoView, 0)
 		resp.Paging = page
 		resp.List = items
@@ -1050,7 +1050,7 @@ func (this *RangeChartChartInfoController) List() {
 	}
 
 	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标信息失败"
 		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 		return
@@ -1147,7 +1147,7 @@ func (this *RangeChartChartInfoController) Copy() {
 
 		_, e = data_manage.GetChartClassifyById(req.ChartClassifyId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -1160,7 +1160,7 @@ func (this *RangeChartChartInfoController) Copy() {
 	// 图表信息
 	originChart, e := data_manage.GetChartInfoById(req.ChartInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "原图表不存在"
 			return
 		}
@@ -1253,7 +1253,7 @@ func (this *RangeChartChartInfoController) Refresh() {
 		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,无需刷新"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -1804,6 +1804,9 @@ func (this *RangeChartChartInfoController) SearchByEs() {
 	startSize = paging.StartIndex(currentIndex, pageSize)
 
 	keyword := this.GetString("Keyword")
+	if keyword == `` { // 兼容jp前端
+		keyword = this.GetString("KeyWord")
+	}
 
 	//只看我的
 	isShowMe, _ := this.GetBool("IsShowMe")
@@ -1815,7 +1818,7 @@ func (this *RangeChartChartInfoController) SearchByEs() {
 	sourceList := make([]int, 0)
 	sourceList = append(sourceList, utils.CHART_SOURCE_RANGE_ANALYSIS)
 
-	var searchList []*data_manage.ChartInfo
+	var searchList []*data_manage.ChartInfoMore
 	var total int64
 	var err error
 
@@ -1824,7 +1827,7 @@ func (this *RangeChartChartInfoController) SearchByEs() {
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -1838,7 +1841,7 @@ func (this *RangeChartChartInfoController) SearchByEs() {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 			return
@@ -1868,13 +1871,17 @@ func (this *RangeChartChartInfoController) SearchByEs() {
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
-			tmp.ChartInfo = *v
+			tmp.ChartInfo = v.ChartInfo
 			// 图表数据权限
 			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
 			}
+			tmp.SearchText = v.SearchText
+			if tmp.SearchText == "" {
+				tmp.SearchText = v.ChartName
+			}
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -1935,7 +1942,7 @@ func (this *RangeChartChartInfoController) BaseInfoEdit() {
 
 	chartItem, e := data_manage.GetChartInfoById(req.ChartInfoId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "图表已被删除, 请刷新页面"
 			return
 		}
@@ -1963,7 +1970,7 @@ func (this *RangeChartChartInfoController) BaseInfoEdit() {
 	pars = append(pars, req.ChartName)
 	existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "判断英文图表名称是否存在失败"
 			br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
 			return
@@ -2056,7 +2063,7 @@ func (this *RangeChartChartInfoController) ChartInfoSave() {
 
 	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "图表已被删除,请刷新页面!"
 			br.ErrMsg = "图表已被删除,请刷新页面,ChartInfoId:" + strconv.Itoa(req.ChartInfoId)
 			return

+ 5 - 5
controllers/data_manage/sci_data.go

@@ -36,14 +36,14 @@ func (this *EdbInfoController) SciClassify() {
 	}
 
 	rootList, err := data_manage.GetBaseFromSciClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromSciClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -52,7 +52,7 @@ func (this *EdbInfoController) SciClassify() {
 	baseFromSciIndexMap := make(map[int][]*data_manage.BaseFromSciClassifyItems)
 
 	allBaseFromSciIndex, err := data_manage.GetSciIndexAll()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
@@ -144,14 +144,14 @@ func (this *EdbInfoController) SciClassifyName() {
 	}
 
 	rootList, err := data_manage.GetBaseFromSciClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromSciClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return

+ 56 - 20
controllers/data_manage/sci_hq_data.go

@@ -180,7 +180,7 @@ func (this *SciHqDataController) EditClassify() {
 	}
 	classify, err := data_manage.GetSciHqClassifyById(req.ClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			return
 		}
@@ -264,7 +264,7 @@ func (this *SciHqDataController) MoveClassify() {
 		return
 	}
 
-	err, errMsg := data.MoveSciHqClassify(req.ClassifyId, req.ParentId, req.PrevClassifyId, req.NextClassifyId)
+	err, errMsg := data.MoveSciHqClassify(req.ClassifyId, req.ParentClassifyId, req.PrevClassifyId, req.NextClassifyId)
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg
@@ -295,7 +295,7 @@ func (this *SciHqDataController) IndexList() {
 	}()
 	classifyId, _ := this.GetInt("ClassifyId", 0)
 	indexList, err := data_manage.GetSciHqIndexBaseInfoByClassifyId(classifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
@@ -333,12 +333,12 @@ func (this *SciHqDataController) BatchIndexList() {
 	}
 	if req.IsSelectAll {
 		if len(req.SelectedId) > 0 {
-			condition += ` AND base_from_sci_hq_index_id NOT IN (` + utils.GetOrmInReplace(len(req.SelectedId)) + `)`
+			condition += ` AND base_from_sci_hq_index_id NOT IN (?)`
 			pars = append(pars, req.SelectedId)
 		}
 	} else {
 		if len(req.SelectedId) > 0 {
-			condition += ` AND base_from_sci_hq_index_id IN (` + utils.GetOrmInReplace(len(req.SelectedId)) + `)`
+			condition += ` AND base_from_sci_hq_index_id IN (?)`
 			pars = append(pars, req.SelectedId)
 		}
 	}
@@ -353,11 +353,14 @@ func (this *SciHqDataController) BatchIndexList() {
 			br.ErrMsg = "获取分类失败,Err:" + err.Error()
 			return
 		}
-		if len(childClassify) > 0 {
-			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
-			for _, child := range childClassify {
-				pars = append(pars, child.ClassifyId)
-			}
+		var childIds []int
+		for _, v := range childClassify {
+			childIds = append(childIds, v.ClassifyId)
+		}
+		if len(childIds) > 0 {
+			childIds = append(childIds, req.ClassifyId)
+			condition += `AND classify_id IN (?)`
+			pars = append(pars, childIds)
 		} else {
 			condition += ` AND classify_id=?`
 			pars = append(pars, req.ClassifyId)
@@ -429,7 +432,7 @@ func (this *SciHqDataController) IndexPageList() {
 		}
 		total = tmpTotal
 		tmpIndexList, err := data_manage.GetSciHqIndexByPage(startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -457,7 +460,7 @@ func (this *SciHqDataController) IndexPageList() {
 		}
 		total = tmpTotal
 		tmpIndexList, err := data_manage.GetSciHqIndexByClassifyId(classifyIds, startSize, pageSize)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 			return
@@ -465,6 +468,11 @@ func (this *SciHqDataController) IndexPageList() {
 		indexList = tmpIndexList
 	}
 
+	// 唯一编码前端定位用
+	for _, v := range indexList {
+		v.UniqueCode = fmt.Sprintf("%d_%d", v.ClassifyId, v.BaseFromSciHqIndexId)
+	}
+
 	page := paging.GetPaging(currrentIndex, pageSize, total)
 	resp := new(response.SciHqIndexPageListResp)
 	resp.List = indexList
@@ -534,7 +542,7 @@ func (this *SciHqDataController) SingleData() {
 		return
 	}
 	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_SCI_HQ, indexInfo.IndexCode)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取指标数据失败"
 		br.ErrMsg = "获取指标库数据失败,Err:" + err.Error()
 		return
@@ -736,7 +744,7 @@ func (this *SciHqDataController) AddEdbInfo() {
 
 	_, err = data_manage.GetSciHqIndexByIndexCode(req.EdbCode)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "指标不存在"
 			return
 		}
@@ -757,6 +765,19 @@ func (this *SciHqDataController) AddEdbInfo() {
 		return
 	}
 
+	// 刷新指标数据
+	refreshRes, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, "")
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("刷新指标数据失败, %v", e)
+		return
+	}
+	if refreshRes != nil && refreshRes.Ret != 200 {
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("刷新指标数据失败, Ret: %d, Msg: %s, ErrMsg: %s", refreshRes.Ret, refreshRes.Msg, refreshRes.ErrMsg)
+		return
+	}
+
 	// 试用平台更新用户累计新增指标数
 	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
 	if e != nil {
@@ -947,7 +968,7 @@ func (c *SciHqDataController) NameCheck() {
 			EdbName: v.EdbName,
 		})
 		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_SCI_HQ, 0, utils.EDB_DATA_LIMIT)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取卓创红期已存在信息失败,Err:" + err.Error()
 			return
@@ -1091,6 +1112,19 @@ func (this *SciHqDataController) BatchAdd() {
 			continue
 		}
 
+		// 刷新指标数据
+		refreshRes, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, "")
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("刷新指标数据失败, %v", e)
+			return
+		}
+		if refreshRes != nil && refreshRes.Ret != 200 {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("刷新指标数据失败, Ret: %d, Msg: %s, ErrMsg: %s", refreshRes.Ret, refreshRes.Msg, refreshRes.ErrMsg)
+			return
+		}
+
 		// 试用平台更新用户累计新增指标数
 		if utils.BusinessCode == utils.BusinessCodeSandbox {
 			go func() {
@@ -1417,11 +1451,13 @@ func (this *SciHqDataController) ExportSciHqList() {
 			br.ErrMsg = "获取分类失败,Err:" + err.Error()
 			return
 		}
-		if len(childClassify) > 0 {
-			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
-			for _, child := range childClassify {
-				pars = append(pars, child.ClassifyId)
-			}
+		var childIds []int
+		for _, v := range childClassify {
+			childIds = append(childIds, v.ClassifyId)
+		}
+		if len(childIds) > 0 {
+			condition += `AND classify_id IN (?)`
+			pars = append(pars, childIds)
 		} else {
 			condition += ` AND classify_id=?`
 			pars = append(pars, classifyId)

+ 50 - 25
controllers/data_manage/smm_api.go

@@ -4,10 +4,10 @@ import (
 	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"strconv"
 	"strings"
 )
 
@@ -66,16 +66,16 @@ func (this *EdbInfoController) SmmApiList() {
 	if len(types) > 0 {
 		condition += " AND ( "
 		for _, v := range types {
-			typeArr := strings.Split(v,",")
+			typeArr := strings.Split(v, ",")
 			for i, v := range typeArr {
 				if i == 0 {
 					condition += " ( "
 				}
 				typeStr := "type_"
 				typeStr += fmt.Sprintf("%d", i+1)
-				condition += typeStr+" =? "
+				condition += typeStr + " =? "
 				pars = append(pars, v)
-				if i == len(typeArr) - 1 {
+				if i == len(typeArr)-1 {
 					condition += " ) "
 				} else {
 					condition += " AND "
@@ -88,13 +88,13 @@ func (this *EdbInfoController) SmmApiList() {
 	}
 
 	if frequency != "" {
-		frequencyArr := strings.Split(frequency,",")
+		frequencyArr := strings.Split(frequency, ",")
 		condition += ` AND frequency IN (` + utils.GetOrmInReplace(len(frequencyArr)) + `) `
 		pars = append(pars, frequencyArr)
 	}
 
 	if dataState != "" {
-		stateArr := strings.Split(dataState,",")
+		stateArr := strings.Split(dataState, ",")
 		if strings.Contains(dataState, "normal") {
 			stateArr = append(stateArr, "")
 			condition += ` AND data_state IN (` + utils.GetOrmInReplace(len(stateArr)) + `) `
@@ -107,25 +107,50 @@ func (this *EdbInfoController) SmmApiList() {
 
 	sortStr := ``
 
+	keyword = strings.TrimSpace(keyword)
 	if keyword != "" {
-		keyWordArr := strings.Split(keyword, " ")
-		if len(keyWordArr) > 0 {
-			condition += " AND ( "
-			keywordStr := strings.Replace(keyword, " ", "", -1)
-			condition += ` CONCAT(index_name,index_code) LIKE '%` + keywordStr + `%' OR `
-			sortStr += ` CASE WHEN CONCAT(index_name,index_code) LIKE '%` + keywordStr + `%' THEN 1 `
-			for i, v := range keyWordArr {
-				condition += ` CONCAT(index_name,index_code) LIKE '%` + v + `%' OR`
-				sortStr += ` WHEN CONCAT(index_name,index_code) LIKE '%` + v + `%' THEN  ` + strconv.Itoa(i+2) + ` `
+		//keyWordArr := strings.Split(keyword, " ")
+		//if len(keyWordArr) > 0 {
+		//	condition += " AND ( "
+		//	keywordStr := strings.Replace(keyword, " ", "", -1)
+		//	condition += ` CONCAT(index_name,index_code) LIKE '%` + keywordStr + `%' OR `
+		//	sortStr += ` CASE WHEN CONCAT(index_name,index_code) LIKE '%` + keywordStr + `%' THEN 1 `
+		//	for i, v := range keyWordArr {
+		//		condition += ` CONCAT(index_name,index_code) LIKE '%` + v + `%' OR`
+		//		sortStr += ` WHEN CONCAT(index_name,index_code) LIKE '%` + v + `%' THEN  ` + strconv.Itoa(i+2) + ` `
+		//	}
+		//	sortStr += ` END, `
+		//	condition = strings.TrimRight(condition, "OR")
+		//	condition += " ) "
+		//}
+
+		// ES搜
+		_, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_YS, 0, []int{}, []int{}, []string{}, startSize, req.PageSize)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("ES-搜索SMM指标失败, %v", e)
+			return
+		}
+		if len(list) == 0 {
+			br.Data = data_manage.BaseFromSmmIndexListResp{
+				Paging: paging.GetPaging(req.CurrentIndex, req.PageSize, 0),
+				List:   make([]*data_manage.BaseFromSmmIndexItem, 0),
 			}
-			sortStr += ` END, `
-			condition = strings.TrimRight(condition, "OR")
-			condition += " ) "
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			return
 		}
+		var indexIds []int
+		for _, v := range list {
+			indexIds = append(indexIds, v.PrimaryId)
+		}
+		condition += fmt.Sprintf(" AND base_from_smm_index_id IN (%s)", utils.GetOrmInReplace(len(indexIds)))
+		pars = append(pars, indexIds)
 	}
 
 	if indexCodes != "" {
-		indexCodeArr := strings.Split(indexCodes,",")
+		indexCodeArr := strings.Split(indexCodes, ",")
 		indexCodeStr := ""
 		for _, v := range indexCodeArr {
 			indexCodeStr += "'" + v + "',"
@@ -141,7 +166,7 @@ func (this *EdbInfoController) SmmApiList() {
 	}
 
 	total, err := data_manage.GetSmmIndexDataListCount(condition, pars)
-	if err!= nil {
+	if err != nil {
 		br.Msg = "获取指标总数失败"
 		br.ErrMsg = "获取指标总数失败,Err:" + err.Error()
 		return
@@ -203,11 +228,11 @@ func (this *EdbInfoController) SmmApiTypeList() {
 
 	// 初始化
 	for _, v := range typeList {
-		if v.Type1 != ""{
-			if _, ok := typeMap[v.Type1];!ok {
+		if v.Type1 != "" {
+			if _, ok := typeMap[v.Type1]; !ok {
 				typeMap[v.Type1] = make(map[string][]string)
 			} else {
-				if _, ok := typeMap[v.Type1][v.Type2];!ok {
+				if _, ok := typeMap[v.Type1][v.Type2]; !ok {
 					typeMap[v.Type1][v.Type2] = make([]string, 0)
 				}
 			}
@@ -215,7 +240,7 @@ func (this *EdbInfoController) SmmApiTypeList() {
 	}
 
 	for _, v := range typeList {
-		if v.Type1 != ""{
+		if v.Type1 != "" {
 			typeMap[v.Type1][v.Type2] = append(typeMap[v.Type1][v.Type2], v.Type3)
 		}
 	}
@@ -227,7 +252,7 @@ func (this *EdbInfoController) SmmApiTypeList() {
 			var child data_manage.TypeListRespItem
 			child.Type = type2
 			for _, type3 := range type3List {
-				child.Child = append(child.Child, data_manage.TypeListRespItem{type3,nil})
+				child.Child = append(child.Child, data_manage.TypeListRespItem{type3, nil})
 			}
 			item.Child = append(item.Child, child)
 		}

+ 8 - 4
controllers/data_manage/smm_data.go

@@ -13,6 +13,7 @@ import (
 	"github.com/tealeg/xlsx"
 	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -36,14 +37,14 @@ func (this *EdbInfoController) SmmClassify() {
 	}
 
 	rootList, err := data_manage.GetBaseFromSmmClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromSmmClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -63,6 +64,7 @@ func (this *EdbInfoController) SmmClassify() {
 
 	rootChildMap := make(map[int][]*data_manage.BaseFromSmmClassifyItems)
 	for _, v := range classifyAll {
+		v.UniqueCode = strconv.Itoa(v.ClassifyId)
 		rootChildMap[v.ParentId] = append(rootChildMap[v.ParentId], v)
 		/*if existItems, ok := baseFromSmmIndexMap[v.ClassifyId]; ok {
 			v.Children = existItems
@@ -93,6 +95,7 @@ func (this *EdbInfoController) SmmClassify() {
 		Level:              1,
 		Sort:               0,
 		Children:           nil,
+		UniqueCode:         "0",
 	}
 	/*initIndexList, err := data_manage.GetBaseFromSmmIndexByClassifyId(initClassify.ClassifyId)
 	if err != nil {
@@ -162,6 +165,7 @@ func (this *EdbInfoController) SmmIndexList() {
 			Level:                0,
 			Sort:                 0,
 			Children:             nil,
+			UniqueCode:           fmt.Sprintf("%d_%d", v.ClassifyId, v.BaseFromSmmIndexId),
 		}
 		list = append(list, tmp)
 	}
@@ -193,14 +197,14 @@ func (this *EdbInfoController) SmmClassifyName() {
 	}
 
 	rootList, err := data_manage.GetBaseFromSmmClassifyByParentId(0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromSmmClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return

+ 225 - 0
controllers/data_manage/stl/stl.go

@@ -0,0 +1,225 @@
+package stl
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/services/data/stl"
+	"eta/eta_api/utils"
+	"strings"
+
+	"eta/eta_api/models/data_manage/stl/request"
+	"eta/eta_api/models/data_manage/stl/response"
+)
+
+type STLController struct {
+	controllers.BaseAuthController
+}
+
+// Preview
+// @Title STL分解预览
+// @Description STL分解预览
+// @Success 200 {object} request.STLReq
+// @router /chart_info/preview [post]
+func (c *STLController) Preview() {
+	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
+	}
+	var req *request.StlConfigReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "请求参数错误"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	resp, msg, err := stl.GenerateStlEdbData(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "预览异常"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "预览成功"
+	br.Ret = 200
+	br.Success = true
+	return
+}
+
+// SaveConf
+// @Title STL分解配置保存
+// @Description STL分解配置保存
+// @Success 200 {object} request.STLReq
+// @router /config/save [post]
+func (c *STLController) SaveConf() {
+	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
+	}
+	var req *request.StlConfigReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "请求参数错误"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	configId, msg, err := stl.SaveStlConfig(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "保存异常"
+		}
+		br.Msg = msg
+		br.ErrMsg = "保存失败,err:" + err.Error()
+		return
+	}
+	resp := new(response.SaveStlConfigResp)
+	resp.CalculateStlConfigId = configId
+
+	br.Data = resp
+	br.Msg = "保存成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// ConfigDetail
+// @Title STL分解配置保存
+// @Description STL分解配置保存
+// @Success 200 {object} request.STLReq
+// @router /config/detail [get]
+func (c *STLController) ConfigDetail() {
+	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
+	}
+	edbInfoId, err := c.GetInt("EdbInfoId")
+	if err != nil {
+		br.Msg = "请求参数错误"
+		br.ErrMsg = err.Error()
+		return
+	}
+	resp, msg, err := stl.GetStlConfig(edbInfoId)
+	if err != nil {
+		if msg == "" {
+			msg = "获取异常"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// SaveStlEdbInfo
+// @Title STL分解指标保存到指标库
+// @Description STL分解指标保存到指标库
+// @Success 200 {object} request.STLReq
+// @router /edb_info/save [post]
+func (c *STLController) SaveStlEdbInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req *request.SaveStlEdbInfoReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "请求参数错误"
+		br.ErrMsg = err.Error()
+		return
+	}
+	sysUser := c.SysUser
+
+	edbInfoId, IsSendEmail, msg, err := stl.SaveStlEdbInfo(req, sysUser.AdminId, sysUser.RealName, c.Lang)
+	if err != nil {
+		if msg == "" {
+			msg = "保存异常"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+	resp := new(response.SaveStlEdbInfoResp)
+	resp.EdbInfoId = edbInfoId
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.IsSendEmail = IsSendEmail
+}
+
+// EdbInfoFilterByEs
+// @Title 指标筛选接口
+// @Description 指标筛选接口
+// @Param   KeyWord   query   string  false       "搜索关键词:指标ID/指标名称"
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Success 200 {object} data_manage.EdbInfoList
+// @router /edb_info/search [get]
+func (this *STLController) EdbInfoFilterByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+	if keyWord == "" {
+		keyWord = this.GetString("Keyword")
+	}
+	keyWord = strings.TrimSpace(keyWord)
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	resp, msg, err := stl.SearchEdbInfoWithStl(this.SysUser.AdminId, keyWord, currentIndex, pageSize, this.Lang)
+	if err != nil {
+		if msg == "" {
+			msg = "获取异常"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 8 - 8
controllers/data_manage/supply_analysis/variety.go

@@ -76,7 +76,7 @@ func (this *VarietyController) List() {
 		}
 		total, list, err = varietyObj.GetListByPage(condition, pars, startSize, pageSize)
 	}
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -146,12 +146,12 @@ func (this *VarietyController) Add() {
 	}
 	varietyName := utils.TrimStr(req.VarietyName)
 	item, err := supply_analysis.GetVarietyByName(varietyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil {
+	if item != nil && item.VarietyId > 0 {
 		br.Msg = "添加失败,品种名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -219,12 +219,12 @@ func (this *VarietyController) Edit() {
 	varietyName := utils.TrimStr(req.VarietyName)
 
 	item, err := supply_analysis.GetVarietyByName(varietyName)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
-	if item != nil && item.VarietyId != req.VarietyId {
+	if item != nil && item.VarietyId != req.VarietyId && item.VarietyId > 0 {
 		br.Msg = "添加失败,品种名称不能重复"
 		br.IsSendEmail = false
 		return
@@ -364,7 +364,7 @@ func (this *VarietyController) Delete() {
 
 	varietyInfo, err := supply_analysis.GetVarietyById(req.VarietyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "该品种不存在或已删除"
 			br.IsSendEmail = false
 		} else {
@@ -411,7 +411,7 @@ func (this *VarietyController) Detail() {
 	if err != nil {
 		br.Msg = "查询品种失败"
 		br.ErrMsg = "查询品种失败;ERR:" + err.Error()
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "不存在该品种或该品种已被删除"
 			br.ErrMsg = "不存在该品种或该品种已被删除"
 			br.IsSendEmail = false
@@ -626,7 +626,7 @@ func (this *VarietyController) ModifyProductionDay() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, req.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return

+ 15 - 11
controllers/data_manage/supply_analysis/variety_edb.go

@@ -11,12 +11,13 @@ import (
 	supply_analysisServ "eta/eta_api/services/data/supply_analysis"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/tealeg/xlsx"
 	"os"
 	"path/filepath"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/tealeg/xlsx"
 )
 
 // EdbList
@@ -56,7 +57,7 @@ func (this *VarietyController) EdbList() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, varietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -64,7 +65,7 @@ func (this *VarietyController) EdbList() {
 
 	var list []*supply_analysis.VarietyEdbInfoItem
 	list, err = supply_analysis.GetAllVarietyEdbInfoByVarietyId(varietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -96,7 +97,7 @@ func (this *VarietyController) EdbList() {
 
 		if tmpItem, ok := edbInfoAndClassifyMap[v.EdbInfoId]; ok {
 			classifyNameList := make([]string, 0)
- 
+
 			// 所属分类
 			{
 				classifyList, tmpErr, errMsg := data.GetFullClassifyByClassifyId(tmpItem.ClassifyId)
@@ -205,7 +206,7 @@ func (this *VarietyController) AddToEdb() {
 
 	varietyEdbInfo, err := supply_analysis.GetVarietyEdbInfoByVarietyEdbId(req.VarietyEdbId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "找不到该指标"
 			br.IsSendEmail = false
 		} else {
@@ -218,7 +219,7 @@ func (this *VarietyController) AddToEdb() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, varietyEdbInfo.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -231,7 +232,7 @@ func (this *VarietyController) AddToEdb() {
 
 	if varietyEdbInfo.EdbInfoId > 0 {
 		tmpEdbInfo, err := data_manage.GetEdbInfoById(varietyEdbInfo.EdbInfoId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "添加失败"
 			br.ErrMsg = "查询ETA指标失败,ERR:" + err.Error()
 			return
@@ -346,7 +347,7 @@ func (this *VarietyController) EdbDataExport() {
 
 	var list []*supply_analysis.VarietyEdbInfoItem
 	list, err = supply_analysis.GetAllVarietyEdbInfoByVarietyId(varietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -620,7 +621,7 @@ func (this *VarietyController) EdbInfoDataTb() {
 		Calendar:         "",
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, varietyEdbInfo.EndDate.Year())
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, varietyEdbInfo.EndDate)
 
 	var startDateTime time.Time
 	if startDate != `` {
@@ -749,7 +750,10 @@ func (this *VarietyController) EdbInfoDataSeasonal() {
 		Calendar:         "",
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, varietyEdbInfo.EndDate.Year())
+	// 特殊处理季节性图的日期
+	maxDate := time.Date(varietyEdbInfo.EndDate.Year()+1, 1, 1, 0, 0, 0, 0, time.Local)
+
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxDate)
 
 	dataList, minVal, maxVal, err := supply_analysisServ.GetChartEdbSeasonalData(varietyEdbId, calendar, startDate, endDate, edbInfo.LatestDate)
 	if err != nil {
@@ -848,7 +852,7 @@ func (this *VarietyController) EdbDataListV2() {
 		Calendar:         "",
 	}
 
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, varietyEdbInfo.EndDate.Year())
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, varietyEdbInfo.EndDate)
 
 	var startDateTime time.Time
 	if startDate != `` {

+ 8 - 8
controllers/data_manage/supply_analysis/variety_plant.go

@@ -50,7 +50,7 @@ func (this *VarietyController) PlantList() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, varietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -58,7 +58,7 @@ func (this *VarietyController) PlantList() {
 
 	var list []*supply_analysis.VarietyPlantItem
 	list, err = supply_analysis.GetAllVarietyPlantByVarietyId(varietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -141,7 +141,7 @@ func (this *VarietyController) AddPlant() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, req.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -320,7 +320,7 @@ func (this *VarietyController) EditPlant() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, varietyPlantInfo.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -443,7 +443,7 @@ func (this *VarietyController) DeletePlant() {
 	}
 
 	varietyPlantInfo, err := supply_analysis.GetVarietyPlantById(req.VarietyPlantId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "删除失败"
 		br.ErrMsg = "查找品种装置失败,Err:" + err.Error()
 		return
@@ -471,7 +471,7 @@ func (this *VarietyController) DeletePlant() {
 	// 是否有装置的操作权限
 	var hasPermission bool
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, varietyPlantInfo.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return
@@ -485,7 +485,7 @@ func (this *VarietyController) DeletePlant() {
 	// 保留一条装置校验
 	{
 		total, err := supply_analysis.GetCountVarietyPlantByVarietyId(varietyInfo.VarietyId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "删除失败"
 			br.ErrMsg = "查找品种装置总数量失败,Err:" + err.Error()
 			return
@@ -542,7 +542,7 @@ func (this *VarietyController) CopyPlant() {
 	var hasPermission bool //是否有操作权限
 	// 是否有装置的操作权限
 	hasPermission, err = supply_analysisServ.HasVarietyPlantPermission(this.SysUser, req.VarietyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "查询是否有装置的操作权限失败;ERR:" + err.Error()
 		return

+ 1394 - 0
controllers/data_manage/usda_fas_data.go

@@ -0,0 +1,1394 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+)
+
+type BaseFromUsdaFasController struct {
+	controllers.BaseAuthController
+}
+
+// UsdaFasClassify
+// @Title 美国农业部数据分类
+// @Description 美国农业部数据分类接口
+// @Success 200 {object} data_manage.BaseFromUsdaFasClassify
+// @router /usda_fas/classify [get]
+func (this *BaseFromUsdaFasController) UsdaFasClassify() {
+	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
+	}
+
+	classifyAll, err := data_manage.GetAllBaseFromUsdaFasClassify()
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//组装一级分类
+	rootMap := make(map[int][]*data_manage.BaseFromUsdaFasClassifyItems)
+	list := make([]*data_manage.BaseFromUsdaFasClassifyItems, 0)
+	for _, classify := range classifyAll {
+		classify.UniqueCode = strconv.Itoa(classify.ClassifyId)
+		if classify.ParentId == 0 {
+			if _, ok := rootMap[classify.ClassifyId]; !ok {
+				rootMap[classify.ClassifyId] = make([]*data_manage.BaseFromUsdaFasClassifyItems, 0)
+				list = append(list, classify)
+
+			}
+		} else {
+			child, ok := rootMap[classify.ParentId]
+			if ok {
+				child = append(child, classify)
+				rootMap[classify.ParentId] = child
+			}
+		}
+	}
+
+	for k, v := range list {
+		child, ok := rootMap[v.ClassifyId]
+		if ok {
+			list[k].Children = child
+		}
+	}
+	//组装二级分类
+	var ret data_manage.BaseFromUsdaFasClassifyResp
+	ret.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// UsdaFasIndexData
+// @Title 获取美国农业部数据
+// @Description 获取美国农业部数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /usda_fas/index/data [get]
+func (this *BaseFromUsdaFasController) UsdaFasIndexData() {
+	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")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	// 增加频度请求入参
+	frequency := this.GetString("Frequency")
+
+	//获取指标
+	var condition string
+	var pars []interface{}
+
+	if classifyId >= 0 {
+		classifyInfo, err := data_manage.GetBaseFromUsdaFasClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "获取分类信息失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}
+		if classifyInfo.Level == 2 || classifyInfo.ParentId > 0 {
+			condition += ` AND classify_id=? `
+			pars = append(pars, classifyId)
+		} else if classifyInfo.Level == 1 {
+			childClassify, err := data_manage.GetBaseFromUsdaFasClassifyByParentId(classifyId)
+			if err != nil {
+				br.Msg = "获取分类信息失败"
+				br.ErrMsg = "获取子分类信息失败,Err:" + err.Error()
+				return
+			}
+			var classifyList []int
+			for _, v := range childClassify {
+				classifyList = append(classifyList, v.ClassifyId)
+			}
+			condition += ` AND classify_id IN (` + utils.GetOrmInReplace(len(classifyList)) + `) `
+			pars = append(pars, classifyList)
+		}
+	}
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+
+	UsdaFasList, err := data_manage.GetUsdaFasIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	edbCodeList := make([]string, 0)
+	for _, v := range UsdaFasList {
+		edbCodeList = append(edbCodeList, v.IndexCode)
+	}
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	dataMap := make(map[string][]*data_manage.BaseFromUsdaFasData)
+	total := 0
+	if len(edbCodeList) > 0 {
+		edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_USDA_FAS, edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据源失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbCode] = v
+		}
+		// 首先对分类下的指标按照日期进行分页,再针对日期,进行排序
+		dataTimes, err := data_manage.GetUsdaFasIndexDataTimePageByCodes(edbCodeList, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据日期信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataTimes) > 0 {
+			startDate := dataTimes[len(dataTimes)-1]
+			endDate := dataTimes[0]
+			// 把截止日往后加1天
+			endDateT, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+			endDate = endDateT.AddDate(0, 0, 1).Format(utils.FormatDate)
+			dataList, e := data_manage.GetUsdaFasIndexDataByDataTime(edbCodeList, startDate, endDate)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			//将数据按照指标进行分类
+			for _, v := range dataList {
+				dataMap[v.IndexCode] = append(dataMap[v.IndexCode], v)
+			}
+		}
+
+		total, err = data_manage.GetUsdaFasIndexDataTimePageCount(edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	resultList := make([]*data_manage.BaseFromUsdaFasIndexList, 0)
+
+	for _, v := range UsdaFasList {
+		product := new(data_manage.BaseFromUsdaFasIndexList)
+		product.BaseFromUsdaFasIndexId = v.BaseFromUsdaFasIndexId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.ModifyTime = v.ModifyTime
+		if edb, ok := edbInfoMap[v.IndexCode]; ok {
+			product.EdbInfoId = edb.EdbInfoId
+			product.EdbExist = 1
+		}
+
+		/*total, err := data_manage.GetUsdaFasIndexDataCount(v.IndexCode)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		page := paging.GetPaging(currentIndex, pageSize, total)
+		dataList, err := data_manage.GetUsdaFasIndexData(v.IndexCode, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}*/
+		dataListTmp, ok := dataMap[v.IndexCode]
+		if !ok {
+			dataListTmp = make([]*data_manage.BaseFromUsdaFasData, 0)
+		}
+		product.DataList = dataListTmp
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// UsdaFasSearchList
+// @Title UsdaFas模糊搜索
+// @Description UsdaFas模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} models.BaseResponse
+// @router /usda_fas/search_list [get]
+func (this *BaseFromUsdaFasController) UsdaFasSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	list := make([]*data_manage.BaseFromUsdaFasIndexSearchItem, 0)
+	var err error
+	//关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetUsdaFasItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+
+	} else {
+		// todo es 模糊搜索
+		list, err = data_manage.GetUsdaFasItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+	classifyIds := make([]int, 0)
+	for _, v := range list {
+		classifyIds = append(classifyIds, v.ClassifyId)
+	}
+	classifyList, err := data_manage.GetBaseFromUsdaFasClassifyByIds(classifyIds)
+	if err != nil {
+		br.Msg = "搜索失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	classifyMap := make(map[int]int)
+	for _, v := range classifyList {
+		classifyMap[v.ClassifyId] = v.ParentId
+	}
+	for _, v := range list {
+		v.ParentClassifyId = classifyMap[v.ClassifyId]
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// UsdaFasSingleData
+// @Title 获取UsdaFas数据
+// @Description 获取UsdaFas单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /usda_fas/single_data [get]
+func (this *BaseFromUsdaFasController) UsdaFasSingleData() {
+	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
+	}
+	indexCode := this.GetString("IndexCode")
+	indexInfo, err := data_manage.GetBaseFromUsdaFasIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	dataTmpList, err := data_manage.GetUsdaFasIndexDataByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_USDA_FAS, indexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据源失败"
+		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.UsdaFasSingleDataResp
+	var dataList []*data_manage.UsdaFasSingleData
+
+	if edbInfo != nil {
+		ret.EdbInfoId = edbInfo.EdbInfoId
+		ret.EdbExist = 1
+	}
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromUsdaFasIndexId = indexInfo.BaseFromUsdaFasIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.UsdaFasSingleData{
+			Value:    v.Value,
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// UsdaFasIndexList
+// @Title 美国农业部指标列表
+// @Description 美国农业部指标列表
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Success 200 {object} data_manage.BaseFromUsdaFasClassifyResp
+// @router /usda_fas/classify/index/list [get]
+func (this *BaseFromUsdaFasController) UsdaFasIndexList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	indexList, err := data_manage.GetUsdaFasIndexByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.BaseFromUsdaFasClassifyResp
+	list := make([]*data_manage.BaseFromUsdaFasClassifyItems, 0)
+	for _, v := range indexList {
+		classify := new(data_manage.BaseFromUsdaFasClassifyItems)
+		classify.ClassifyId = classifyId
+		classify.BaseFromUsdaFasIndexId = v.BaseFromUsdaFasIndexId
+		classify.IndexCode = v.IndexCode
+		classify.ClassifyName = v.IndexName
+		classify.UniqueCode = fmt.Sprintf("%d_%d", classifyId, v.BaseFromUsdaFasIndexId)
+		list = append(list, classify)
+	}
+	ret.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// UsdaFasBatchSearch
+// @Title 美国农业部指标查询
+// @Description 美国农业部指标查询
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /usda_fas/batch_search [get]
+func (this *BaseFromUsdaFasController) UsdaFasBatchSearch() {
+	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
+	}
+	classifyIdStr := this.GetString("ClassifyIds")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	resp := data_manage.BaseFromUsdaFasIndexSearchList{}
+	total := 0
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	var list = make([]*data_manage.BaseFromUsdaFasIndexList, 0)
+	var condition string
+	var pars []interface{}
+	classifyIds := strings.Split(classifyIdStr, ",")
+	if len(classifyIds) > 0 && classifyIds[0] != `` {
+		condition += " AND classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+		pars = append(pars, classifyIds)
+	}
+	keyword := this.GetString("Keyword")
+	if keyword != `` {
+		condition += " AND (index_name like ? OR index_code like ?) "
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+	frequencies := this.GetString("Frequencies")
+	if frequencies != "" {
+		frequencyList := strings.Split(frequencies, ",")
+		condition += " AND frequency IN (" + utils.GetOrmInReplace(len(frequencyList)) + " ) "
+		pars = append(pars, frequencyList)
+	}
+	/*if classifyIdStr == `` && keyword == `` && frequencies == `` {
+		resp.Paging = page
+		resp.List = list
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
+		return
+	}*/
+	condition += ` AND index_code not in (SELECT edb_code FROM edb_info WHERE source=?) `
+	pars = append(pars, utils.DATA_SOURCE_USDA_FAS)
+
+	list, err := data_manage.GetUsdaFasIndexPage(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	total, err = data_manage.GetUsdaFasIndexPageCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// UsdaFasBatchAdd
+// @Title 美国农业部批量新增
+// @Description 美国农业部批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /usda_fas/batch_add [post]
+func (this *BaseFromUsdaFasController) UsdaFasBatchAdd() {
+	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
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_UsdaFas_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data_manage.UsdaFasIndexSource2EdbReq
+		r.EdbCode = v.EdbCode
+		r.EdbName = v.EdbName
+		r.Frequency = v.Frequency
+		r.Unit = v.Unit
+		r.ClassifyId = v.ClassifyId
+		r.AdminId = sysUser.AdminId
+		r.AdminRealName = sysUser.RealName
+
+		edbInfo, e, errMsg, skip := data.UsdaFasIndexSource2Edb(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// UsdaFasNameCheck
+// @Title 加入指标库的重名检测
+// @Description 加入指标库的重名检测
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} NameCheckResult
+// @router /usda_fas/edb_info/name_check [post]
+func (this *BaseFromUsdaFasController) UsdaFasNameCheck() {
+	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 []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_USDA_FAS, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_USDA_FAS, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// UsdaFasAddCheck
+// @Title 加入指标库指标Id检测
+// @Description 加入指标库指标Id检测
+// @Param	request	body request.BatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /usda_fas/edb_info/add_check [post]
+func (c *BaseFromUsdaFasController) UsdaFasAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req.IndexCodes)
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_USDA_FAS)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetUsdaFasIndex(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromUsdaFasIndexList, 0)
+	for _, v := range list {
+		if edb, ok := existMap[v.IndexCode]; ok {
+			v.EdbInfoId = edb.EdbInfoId
+			v.EdbClassifyId = edb.ClassifyId
+			v.EdbUniqueCode = edb.UniqueCode
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// UsdaFasEdbInfoAdd
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /usda_fas/edb_info/add [post]
+func (this *BaseFromUsdaFasController) UsdaFasEdbInfoAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req data_manage.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	req.EdbCode = strings.Trim(req.EdbCode, " ")
+
+	if req.EdbCode == "" {
+		br.Msg = "指标ID不能为空"
+		return
+	}
+
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	count, err := data_manage.GetUsdaFasIndexDataCount(req.EdbCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if count == 0 {
+		br.Msg = "指标不存在"
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(utils.DATA_SOURCE_USDA_FAS, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 试用平台更新用户累计新增指标数
+	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+		return
+	}
+	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+		go func() {
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	//新增操作日志
+	{
+		edbLog := new(data_manage.EdbInfoLog)
+		edbLog.EdbInfoId = edbInfo.EdbInfoId
+		edbLog.SourceName = edbInfo.SourceName
+		edbLog.Source = edbInfo.Source
+		edbLog.EdbCode = edbInfo.EdbCode
+		edbLog.EdbName = edbInfo.EdbName
+		edbLog.ClassifyId = edbInfo.ClassifyId
+		edbLog.SysUserId = sysUser.AdminId
+		edbLog.SysUserRealName = sysUser.RealName
+		edbLog.CreateTime = time.Now()
+		edbLog.Content = string(this.Ctx.Input.RequestBody)
+		edbLog.Status = "新增指标"
+		edbLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddEdbInfoLog(edbLog)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// ExportUsdaFasList
+// @Title 导出美国农业部数据
+// @Description 导出美国农业部数据
+// @Param   ClassifyId   query   int  true       "关键字搜索"
+// @Param   IndexCode   query   string  true       "指标编码"
+// @Success 200  导出成功
+// @router /usda_fas/export [get]
+func (this *BaseFromUsdaFasController) ExportUsdaFasList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	indexCode := this.GetString("IndexCode")
+
+	if classifyId <= 0 && indexCode == "" {
+		br.Msg = "请选择分类或者指标"
+		return
+	}
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var condition string
+	var pars []interface{}
+	var classifyName string
+	if classifyId > 0 {
+		classifyInfo, err := data_manage.GetBaseFromUsdaFasClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		classifyName = classifyInfo.ClassifyName
+		childClassify, err := data_manage.GetBaseFromUsdaFasClassifyByParentId(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+
+		if len(childClassify) > 0 {
+			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			for _, child := range childClassify {
+				pars = append(pars, child.ClassifyId)
+			}
+		} else {
+			condition += ` AND classify_id=?`
+			pars = append(pars, classifyId)
+		}
+	}
+	if indexCode != "" {
+		condition += ` AND index_code=? `
+		pars = append(pars, indexCode)
+	}
+
+	indexList, err := data_manage.GetUsdaFasIndex(condition, pars)
+	if err != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "获取指标失败,Err:" + err.Error()
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+
+	codeList := make([]string, 0)
+	frequenciesMap := make(map[string][]*data_manage.BaseFromUsdaFasIndexList)
+	for _, v := range indexList {
+		codeList = append(codeList, v.IndexCode)
+		frequenciesMap[v.Frequency] = append(frequenciesMap[v.Frequency], v)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromUsdaFasData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetUsdaFasIndexDataByCodes(codeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+	}
+	// 按照频率分组排序
+	frequencies := []string{
+		"日度", "周度", "旬度", "月度", "季度", "半年度", "年度",
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		indexCodeList, ok := frequenciesMap[frequency]
+		if !ok {
+			continue
+		}
+		if len(indexCodeList) <= 0 {
+			fmt.Printf("sheet:%s, 不存在指标", frequency)
+			return
+		}
+		var sheetName string
+		switch frequency {
+		case "日度":
+			sheetName = "日度(Daily)"
+		case "周度":
+			sheetName = "周度(Weekly)"
+		case "旬度":
+			sheetName = "旬度(ten-day)"
+		case "月度":
+			sheetName = "月度(Monthly)"
+		case "季度":
+			sheetName = "季度(Quarterly)"
+		case "半年度":
+			sheetName = "半年度(Semi-annual)"
+		case "年度":
+			sheetName = "年度(Annual)"
+		default:
+			sheetName = "其他数据"
+		}
+		sheetNew, err := xlsxFile.AddSheet(sheetName)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, idx := range frequenciesMap[frequency] {
+			indexIdList = append(indexIdList, idx.BaseFromUsdaFasIndexId)
+		}
+		dataTimeList, err := data_manage.GetUsdaFasDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取数据时间失败,Err:" + err.Error()
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, icl := range indexCodeList {
+			// 获取数据
+			dataList, ok := dataListMap[icl.IndexCode]
+			if !ok {
+				continue
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称/Metric Name")
+				frequencyRow.AddCell().SetValue("频度/Frequency")
+				unitRow.AddCell().SetValue("单位/Unit")
+				lastModifyDateRow.AddCell().SetValue("更新时间/Update Time")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(icl.IndexName)
+			frequencyRow.AddCell().SetValue(icl.Frequency)
+			unitRow.AddCell().SetValue(icl.Unit)
+
+			timeDate, err := time.Parse(utils.FormatDateTime, dataList[0].ModifyTime)
+			if err != nil {
+				continue
+			}
+			lastModifyDateRow.AddCell().SetValue(timeDate.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromUsdaFasData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		e := xlsxFile.Save(downLoadnFilePath)
+		if e != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName := classifyName
+	if indexCode != "" && len(indexList) == 1 {
+		fileName = indexList[0].IndexName
+	}
+	fileName = strings.Replace(fileName, ": ", "_", -1)
+	fileName = strings.Replace(fileName, ", ", "_", -1)
+	fileName = strings.Replace(fileName, " ", "_", -1)
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	fmt.Println(fileName)
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}
+
+// GetFrequency
+// @Title 美国农业部数据频度
+// @Description 美国农业部数据频度接口
+// @Param   ClassifyId   query   string  true       "分类Id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /usda_fas/frequency [get]
+func (this *BaseFromUsdaFasController) GetFrequency() {
+	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
+	}
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	frequencyList, err := data_manage.GetUsdaFasFrequencyByClassifyId(classifyId)
+	if err != nil {
+		br.Msg = "获取频度失败"
+		br.ErrMsg = "获取频度失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+}
+
+// BatchAddEdbCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body data_manage.BatchManualEdbReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /usda_fas/batch/add/check [post]
+func (c *BaseFromUsdaFasController) BatchAddEdbCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 最大批量添加的数量
+	codeMaxT := 31
+
+	var req data_manage.BatchCheckUsdaFasEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,Err:" + err.Error()
+		return
+	}
+	req.Keyword = strings.TrimSpace(req.Keyword)
+	classifyIdStr := req.ClassifyIds
+
+	var list = make([]*data_manage.BaseFromUsdaFasIndexList, 0)
+	var condition string
+	var pars []interface{}
+
+	if req.ListAll {
+		classifyIds := strings.Split(classifyIdStr, ",")
+		if len(classifyIds) > 0 && classifyIds[0] != `` {
+			condition += " AND classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+			pars = append(pars, classifyIds)
+		}
+		keyword := req.Keyword
+		if keyword != `` {
+			condition += " AND (index_name like ? OR index_code like ?) "
+			pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+		}
+		frequencies := req.Frequencies
+		if frequencies != "" {
+			frequencyList := strings.Split(frequencies, ",")
+			condition += " AND frequency IN (" + utils.GetOrmInReplace(len(frequencyList)) + " ) "
+			pars = append(pars, frequencyList)
+		}
+		codes := req.TradeCodeList
+		codeList := make([]string, 0)
+		if codes != "" {
+			codeList = strings.Split(codes, ",")
+		}
+		if len(codeList) > 0 {
+			condition += ` AND index_code not in (` + utils.GetOrmInReplace(len(codeList)) + `) `
+			pars = append(pars, codeList)
+		}
+	} else {
+		codes := req.TradeCodeList
+		codeList := make([]string, 0)
+		if codes != "" {
+			codeList = strings.Split(codes, ",")
+		}
+		if len(codeList) <= 0 {
+			br.Msg = "请选择指标"
+			br.ErrMsg = "请选择指标"
+			return
+		}
+		// 指标
+		condition += ` AND index_code in (` + utils.GetOrmInReplace(len(codeList)) + `) `
+		pars = append(pars, codeList)
+
+	}
+	condition += ` AND index_code not in (SELECT edb_code FROM edb_info WHERE source=?) `
+	pars = append(pars, utils.DATA_SOURCE_USDA_FAS)
+
+	list, err = data_manage.GetUsdaFasIndexPage(condition, pars, 0, codeMaxT)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if len(list) >= codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	br.Data = list
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 7 - 7
controllers/data_manage/wind_data.go

@@ -29,7 +29,7 @@ func (this *EdbInfoController) WindClassify() {
 	parentId, _ := this.GetInt("ParentId")
 	// 特殊处理顶级分类
 	rootList, err := data_manage.GetEdbClassifyByParentId(parentId, 0)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -38,7 +38,7 @@ func (this *EdbInfoController) WindClassify() {
 	if parentId == 0 {
 		// 查询wind指标的所有一级分类
 		classifyIdList, e := data_manage.GetEdbClassifyIdListBySource(utils.DATA_SOURCE_WIND)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类列表失败,Err:" + e.Error()
 			return
@@ -53,7 +53,7 @@ func (this *EdbInfoController) WindClassify() {
 		}
 		// 查询wind指标的所有一级分类下的指标信息
 		rootIds, e := data_manage.GetEdbClassifyRootIdsByClassifyIds(classifyIdList)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类列表失败,Err:" + e.Error()
 			return
@@ -70,7 +70,7 @@ func (this *EdbInfoController) WindClassify() {
 		// 获取当前账号的不可见指标
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
 			return
@@ -218,7 +218,7 @@ func (this *EdbInfoController) WindEdbInfoList() {
 	edbInfoId, _ := this.GetInt("EdbInfoId")
 	if classifyId > 0 {
 		childClassify, e, _ := data.GetChildClassifyByClassifyId(classifyId)
-		if e != nil && e.Error() != utils.ErrNoRow() {
+		if e != nil && !utils.IsErrNoRow(e) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
 			return
@@ -270,7 +270,7 @@ func (this *EdbInfoController) WindEdbInfoList() {
 		if classifyId > 0 { // todo 当没有传入分类ID时,如何处理 同一个分类ID,顶级分类是一样的
 			targetClassify, err := data_manage.GetEdbClassifyById(classifyId)
 			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
+				if utils.IsErrNoRow(err) {
 					br.Msg = "当前分类不存在"
 					return
 				}
@@ -279,7 +279,7 @@ func (this *EdbInfoController) WindEdbInfoList() {
 				return
 			}
 			targetClassifyList, err = data_manage.GetEdbClassifyByRootIdLevel(targetClassify.RootId, targetClassify.ClassifyType, "")
-			if err != nil && err.Error() != utils.ErrNoRow() {
+			if err != nil && !utils.IsErrNoRow(err) {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
 				return

+ 10 - 8
controllers/data_manage/yongyi_data.go

@@ -40,7 +40,7 @@ func (this *EdbInfoController) YongyiClassify() {
 	}
 
 	classifyAll, err := data_manage.GetAllBaseFromYongyiClassify()
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
@@ -128,7 +128,7 @@ func (this *EdbInfoController) YongyiIndexData() {
 	if classifyId >= 0 {
 		classifyInfo, err := data_manage.GetBaseFromYongyiClassifyById(classifyId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -320,7 +320,7 @@ func (this *EdbInfoController) YongyiSingleData() {
 		return
 	}
 	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_YONYI, indexCode)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取数据源失败"
 		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
 		return
@@ -343,7 +343,7 @@ func (this *EdbInfoController) YongyiSingleData() {
 	ret.Unit = indexInfo.Unit
 	for _, v := range dataTmpList {
 		tmp := &data_manage.YongyiSingleData{
-			Value:    v.Value,
+			Value:    v.Value.String(),
 			DataTime: v.DataTime,
 		}
 		dataList = append(dataList, tmp)
@@ -370,7 +370,7 @@ func (this *EdbInfoController) YongyiIndexList() {
 	}()
 	classifyId, _ := this.GetInt("ClassifyId", 0)
 	indexList, err := data_manage.GetYongyiIndexByClassifyId(classifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
+	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
@@ -660,7 +660,7 @@ func (this *EdbInfoController) YongyiNameCheck() {
 			EdbName: v.EdbName,
 		})
 		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_YONYI, 0, utils.EDB_DATA_LIMIT)
-		if err != nil && err.Error() != utils.ErrNoRow() {
+		if err != nil && !utils.IsErrNoRow(err) {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
 			return
@@ -962,7 +962,7 @@ func (this *EdbInfoController) ExportYongyiList() {
 	if classifyId > 0 {
 		classifyInfo, err := data_manage.GetBaseFromYongyiClassifyById(classifyId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "分类不存在"
 				return
 			}
@@ -980,9 +980,11 @@ func (this *EdbInfoController) ExportYongyiList() {
 
 		if len(childClassify) > 0 {
 			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			var classifyIdList []int
 			for _, child := range childClassify {
-				pars = append(pars, child.ClassifyId)
+				classifyIdList = append(classifyIdList, child.ClassifyId)
 			}
+			pars = append(pars, classifyIdList)
 		} else {
 			condition += ` AND classify_id=?`
 			pars = append(pars, classifyId)

+ 316 - 0
controllers/data_source/data_source.go

@@ -0,0 +1,316 @@
+package data_source
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	dataSourceModel "eta/eta_api/models/data_source"
+	"eta/eta_api/services/elastic"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strconv"
+)
+
+// SearchByEs
+// @Title ES搜索
+// @Description ES搜索
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   Keyword   query   string  true       "搜索关键词"
+// @Param   Source   query   int  true       "数据源"
+// @Success 200 {object} response.ExcelListResp
+// @router /common/search_by_es [get]
+func (c *DataSourceController) SearchByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	keyword := c.GetString("KeyWord")
+	if keyword == `` {
+		keyword = c.GetString("Keyword")
+	}
+	source, _ := c.GetInt("Source")
+	if source <= 0 {
+		br.Msg = "来源有误"
+		br.ErrMsg = fmt.Sprintf("数据来源有误, Source: %d", source)
+		return
+	}
+	subSource, _ := c.GetInt("SubSource")
+
+	// 以下为兼容各旧接口的额外传参,不为空时修改Resp对应的Key
+	primaryIdKey := c.GetString("PrimaryIdKey")
+	indexNameKey := c.GetString("IndexNameKey")
+	classifyIdKey := c.GetString("ClassifyIdKey")
+
+	var total, startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	// es搜索
+	t, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, source, subSource, []int{}, []int{}, []string{}, startSize, pageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("ES-搜索数据源列表失败, %v", e)
+		return
+	}
+	total = int(t)
+
+	// (短期方案)中国煤炭市场网/煤炭江湖额外补充基础字段
+	indexModifyTime := make(map[string]string)
+	indexBaseInfo := make(map[string]*dataSourceModel.BaseFromCoalmineIndexBase)
+	{
+		if source == utils.DATA_SOURCE_MTJH {
+			var updateCodes []string
+			for _, v := range list {
+				if v.ModifyTime == "" {
+					updateCodes = append(updateCodes, v.IndexCode)
+				}
+			}
+			if len(updateCodes) > 0 {
+				baseIndexes, e := dataSourceModel.GetMtjhBaseInfoFromDataTable(updateCodes)
+				if e != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = fmt.Sprintf("获取煤炭江湖指标基础信息失败, %v", e)
+					return
+				}
+				for _, v := range baseIndexes {
+					indexModifyTime[v.IndexCode] = utils.TimeTransferString(utils.FormatDateTime, v.ModifyTime)
+				}
+			}
+		}
+		if source == utils.DATA_SOURCE_COAL {
+			var updateCodes []string
+			for _, v := range list {
+				if v.Unit == "" || v.Frequency == "" || v.ModifyTime == "" {
+					updateCodes = append(updateCodes, v.IndexCode)
+				}
+			}
+			if len(updateCodes) > 0 {
+				baseIndexes, e := dataSourceModel.GetCoalmineBaseInfoFromDataTable(updateCodes)
+				if e != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = fmt.Sprintf("获取中国煤炭市场网指标基础信息失败, %v", e)
+					return
+				}
+				for _, v := range baseIndexes {
+					indexBaseInfo[v.IndexCode] = v
+				}
+			}
+		}
+	}
+
+	listMap := make([]map[string]interface{}, 0)
+	for _, v := range list {
+		// (短期方案)由于start_date、end_date和latest_value字段不全的历史遗留问题,这里查出来并补充进ES里面去
+		var updateEs bool
+		if v.StartDate == "" || v.EndDate == "" || v.LatestValue == "" || v.LatestValue == "0" {
+			minMax, e := dataSourceModel.GetBaseIndexDataMinMax(v.Source, v.SubSource, v.IndexCode)
+			if e != nil && !utils.IsErrNoRow(e) {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("获取指标开始结束时间失败, %v", e)
+				return
+			}
+			if minMax != nil {
+				v.StartDate = minMax.MinDate
+				v.EndDate = minMax.MaxDate
+				v.LatestValue = minMax.LatestValue
+				updateEs = true
+			}
+		}
+
+		// 煤炭江湖缺ModifyTime
+		if source == utils.DATA_SOURCE_MTJH && v.ModifyTime == "" && indexModifyTime[v.IndexCode] != "" {
+			v.ModifyTime = indexModifyTime[v.IndexCode]
+			updateEs = true
+		}
+
+		// 中国煤炭市场网缺Unit, Frequency, ModifyTime
+		if source == utils.DATA_SOURCE_COAL && (v.Unit == "" || v.Frequency == "" || v.ModifyTime == "") {
+			if indexBaseInfo[v.IndexCode] != nil {
+				v.Unit = indexBaseInfo[v.IndexCode].Unit
+				v.Frequency = indexBaseInfo[v.IndexCode].Frequency
+				v.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, indexBaseInfo[v.IndexCode].ModifyTime)
+				updateEs = true
+			}
+		}
+
+		// 写入ES更新队列
+		if updateEs {
+			if e := utils.Rc.LPush(utils.CACHE_DATA_SOURCE_ES_HANDLE, v); e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprintf("写入ES更新队列失败, Source: %d, IndexCode: %s, err: %v", v.Source, v.IndexCode, e)
+				return
+			}
+		}
+
+		// 转换成map返回
+		listMap = append(listMap, v.ToMap(primaryIdKey, indexNameKey, classifyIdKey))
+	}
+
+	// 美国农业部(多一个ParentClassifyId字段)
+	if source == utils.DATA_SOURCE_USDA_FAS {
+		// 父级分类ID
+		classifyIds := make([]int, 0)
+		for _, v := range list {
+			classifyIds = append(classifyIds, v.ClassifyId)
+		}
+		classifyList, e := data_manage.GetBaseFromUsdaFasClassifyByIds(classifyIds)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取美国农业部分类失败, %v", e)
+			return
+		}
+		classifyMap := make(map[int]int)
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v.ParentId
+		}
+		for _, v := range listMap {
+			id, ok := v["ClassifyId"].(int)
+			if !ok {
+				v["ParentClassifyId"] = 0
+				continue
+			}
+			v["ParentClassifyId"] = classifyMap[id]
+		}
+	}
+
+	// 煤炭江湖(多一个Area字段)
+	if source == utils.DATA_SOURCE_MTJH {
+		cond := ``
+		pars := make([]interface{}, 0)
+		indexes, e := data_manage.GetMtjhItemsByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取煤炭江湖指标失败, %v", e)
+			return
+		}
+		indexArea := make(map[string]string)
+		for _, v := range indexes {
+			indexArea[v.IndexCode] = v.Area
+		}
+		for _, v := range listMap {
+			code, ok := v["IndexCode"].(string)
+			if !ok {
+				v["Area"] = ""
+				continue
+			}
+			v["Area"] = indexArea[code]
+		}
+	}
+
+	// 个别数据源需要统一唯一编码前端定位用
+	if primaryIdKey == "" {
+		primaryIdKey = "Id"
+	}
+	if classifyIdKey == "" {
+		classifyIdKey = "ClassifyId"
+	}
+	idUniqueCodeArr := []int{
+		utils.DATA_SOURCE_SCI_HQ, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, utils.DATA_SOURCE_YS, utils.DATA_SOURCE_EIA_STEO,
+	}
+	if utils.InArrayByInt(idUniqueCodeArr, source) {
+		for _, v := range listMap {
+			classifyId, ok := v[classifyIdKey].(int)
+			if !ok {
+				continue
+			}
+			id, ok := v[primaryIdKey].(int)
+			if !ok {
+				continue
+			}
+			v["ClassifyUniqueCode"] = strconv.Itoa(classifyId)
+			v["UniqueCode"] = fmt.Sprintf("%d_%d", classifyId, id)
+		}
+	}
+	//if source == utils.DATA_SOURCE_MANUAL {
+	//	// 手工指标
+	//	var wxUserId int64
+	//	wxUserId = int64(sysUser.AdminId)
+	//	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
+	//		wxUserId = 0
+	//	}
+	//	classifies, err := models.GetEdbdataClassify(wxUserId)
+	//	if err != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = fmt.Sprintf("获取手工指标分类失败, %v", e)
+	//		return
+	//	}
+	//	unicodeMap := make(map[int]string)
+	//	for _, v := range classifies {
+	//		unicodeMap[v.ClassifyId] = v.UniqueCode
+	//	}
+	//	for _, v := range listMap {
+	//		classifyId, ok := v["ClassifyId"].(int)
+	//		if !ok {
+	//			continue
+	//		}
+	//		v["ClassifyUniqueCode"] = unicodeMap[classifyId]
+	//	}
+	//}
+
+	// 萝卜投研-LevelPath用作前端定位
+	levelPathMap := make(map[int]string)
+	if source == utils.DATA_SOURCE_RADISH_RESEARCH {
+		classifyOb := new(data_manage.BaseFromRadishResearchClassify)
+		classifies, e := classifyOb.GetItemsByCondition("", make([]interface{}, 0), []string{classifyOb.Cols().PrimaryId, classifyOb.Cols().LevelPath}, "")
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprintf("获取萝卜投研分类失败, %v", e)
+			return
+		}
+		for _, v := range classifies {
+			levelPathMap[v.BaseFromRadishResearchClassifyId] = v.LevelPath
+		}
+	}
+
+	for _, v := range listMap {
+		classifyId, ok := v[classifyIdKey].(int)
+		if !ok {
+			v["ClassifyUniqueCode"] = ""
+			continue
+		}
+		v["ClassifyUniqueCode"] = strconv.Itoa(classifyId)
+		startDate := v["StartDate"].(string)
+		v["StartDate"] = utils.GormDateStrToDateStr(startDate)
+		endDate := v["EndDate"].(string)
+		v["EndDate"] = utils.GormDateStrToDateStr(endDate)
+
+		if source == utils.DATA_SOURCE_RADISH_RESEARCH {
+			// 未分类
+			if classifyId == 0 {
+				v["ClassifyLevelPath"] = "0"
+				continue
+			}
+			v["ClassifyLevelPath"] = levelPathMap[classifyId]
+		}
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := dataSourceModel.SearchDataSourceResp{
+		Paging: page,
+		List:   listMap,
+	}
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 7 - 8
controllers/data_source/sci99.go

@@ -103,7 +103,6 @@ func (this *DataSourceController) Sci99Data() {
 		pars = append(pars, "%"+keyword+"%")
 	}
 
-
 	sci99List, err := data_source.GetSci99Index(condition, pars)
 	if err != nil {
 		br.Msg = "获取数据失败"
@@ -121,13 +120,13 @@ func (this *DataSourceController) Sci99Data() {
 		product.Unit = v.Unit
 		product.ModifyTime = v.ModifyTime
 
-		modifyTime, err := data_source.GetSci99IndexLatestDate(v.IndexCode)
-		if err != nil && err.Error() != utils.ErrNoRow() {
-			br.Msg = "获取更新时间失败"
-			br.ErrMsg = "获取更新时间失败,Err:" + err.Error()
-			return
-		}
-		product.ModifyTime = modifyTime
+		// modifyTime, err := data_source.GetSci99IndexLatestDate(v.IndexCode)
+		// if err != nil && !utils.IsErrNoRow(err) {
+		// 	br.Msg = "获取更新时间失败"
+		// 	br.ErrMsg = "获取更新时间失败,Err:" + err.Error()
+		// 	return
+		// }
+		// product.ModifyTime = modifyTime
 
 		total, err := data_source.GetSci99IndexDataCount(v.IndexCode)
 		page := paging.GetPaging(currentIndex, pageSize, total)

+ 25 - 26
controllers/data_stat/edb_source_stat.go

@@ -225,7 +225,7 @@ func (this *EdbSourceStatController) EdbDeleteLog() {
 	}
 	total, err := data_stat.GetEdbDeleteLogCount(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标删除列表总数失败"
 			br.ErrMsg = "获取指标删除列表总数失败,Err:" + err.Error()
 			return
@@ -378,7 +378,7 @@ func (this *EdbSourceStatController) EdbUpdateLog() {
 	}
 	total, err := data_stat.GetEdbUpdateLogCount(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标删除列表总数失败"
 			br.ErrMsg = "获取指标删除列表总数失败,Err:" + err.Error()
 			return
@@ -555,7 +555,7 @@ func (this *EdbSourceStatController) EdbUpdateStat() {
 	}
 	total, err := data_stat.GetEdbUpdateStatCount(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标列表总数失败"
 			br.ErrMsg = "获取指标列表总数失败,Err:" + err.Error()
 			return
@@ -727,7 +727,7 @@ func (this *EdbSourceStatController) EdbSourceStat() {
 	}
 	total, err := data_stat.GetEdbSourceStatCount(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取数据源统计列表总数失败"
 			br.ErrMsg = "获取数据源统计列表总数失败,Err:" + err.Error()
 			return
@@ -805,24 +805,27 @@ func (this *EdbSourceStatController) EdbUpdateFailedList() {
 	terminalCode := this.GetString("TerminalCode", "")
 	createTime := this.GetString("CreateTime", "")
 
-	if terminalCode == "" {
-		br.Msg = "请选择对应的终端信息"
-		return
-	}
-	terminalInfo, err := data_manage.GetEdbTerminalByTerminalCode(terminalCode)
-	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
-			br.Msg = "终端不存在"
-			return
-		}
-		br.Msg = "查询终端信息出错"
-		br.ErrMsg = "查询终端信息出错 Err:" + err.Error()
-		return
-	}
 	condition := " and source = ? and terminal_code = ?"
 	var pars []interface{}
 	pars = append(pars, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, terminalCode)
 
+	terminalName := ""
+	terminalDir := ""
+	if terminalCode != "" {
+		terminalInfo, err := data_manage.GetEdbTerminalByTerminalCode(terminalCode)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "终端不存在"
+				return
+			}
+			br.Msg = "查询终端信息出错"
+			br.ErrMsg = "查询终端信息出错 Err:" + err.Error()
+			return
+		}
+		terminalName = terminalInfo.Name
+		terminalDir = terminalInfo.DirPath
+	}
+
 	if createTime != "" {
 		startT, err := time.ParseInLocation(utils.FormatDate, createTime, time.Local)
 		if err != nil {
@@ -856,9 +859,9 @@ func (this *EdbSourceStatController) EdbUpdateFailedList() {
 	}
 	resp := data_stat.GetEdbUpdateFailedResp{
 		List:             list,
-		Name:             terminalInfo.Name,
+		Name:             terminalName,
 		TerminalCode:     terminalCode,
-		DirPath:          terminalInfo.DirPath,
+		DirPath:          terminalDir,
 		UpdateSuccessNum: successNum,
 		UpdateFailedNum:  failedNum,
 	}
@@ -909,16 +912,12 @@ func (this *EdbSourceStatController) EdbUpdateFailedDetailList() {
 		return
 	}
 
-	if terminalCode == "" {
-		br.Msg = "请选择对应的终端信息"
-		return
-	}
 	if frequency == "" {
 		br.Msg = "请选择对应的频度"
 		return
 	}
 
-	condition := " and source = ? and terminal_code = ? and frequency=? and data_update_failed_reason=? and data_update_result = 2"
+	condition := " and source = ? AND terminal_code = ? and frequency=? and data_update_failed_reason=? and data_update_result = 2"
 	var pars []interface{}
 	pars = append(pars, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, terminalCode, frequency, sourceUpdateFailedReason)
 
@@ -935,7 +934,7 @@ func (this *EdbSourceStatController) EdbUpdateFailedDetailList() {
 
 	total, err := data_stat.GetEdbUpdateStatCount(condition, pars)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(err) {
 			br.Msg = "获取指标列表总数失败"
 			br.ErrMsg = "获取指标列表总数失败,Err:" + err.Error()
 			return

+ 42 - 0
controllers/data_stat/edb_terminal.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/services/data_stat"
 	"eta/eta_api/utils"
+	"fmt"
 )
 
 // EdbTerminalController 数据源终端管理
@@ -198,3 +199,44 @@ func (this *EdbTerminalController) TerminalCodeList() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
+
+// TerminalIndexDirInfo
+// @Title 获取指标终端文件夹信息
+// @Description 获取指标终端文件夹信息
+// @Success 200 {object} data_manage.EdbTerminalDirInfo
+// @router /terminal/index_dir [get]
+func (this *EdbTerminalController) TerminalIndexDirInfo() {
+	br := new(models.BaseResponse).Init()
+	br.IsSendEmail = false
+	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
+	}
+	source, _ := this.GetInt("Source")
+	indexId, _ := this.GetInt("IndexId")
+	if source <= 0 || indexId <= 0 {
+		br.Msg = "请选择数据源和指标ID"
+		return
+	}
+	info := new(data_manage.EdbTerminalDirInfo)
+	var err error
+	info, err = data_stat.GetEdbTerminalDirInfo(indexId, source)
+	if err != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取终端文件夹信息失败indexId:%d,source:%d,Err:%s", indexId, source, err.Error()))
+		//br.Msg = "获取终端文件夹信息失败"
+		//br.ErrMsg = "获取终端文件夹信息失败 ErrMsg:" + err.Error()
+		//return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = info
+}

+ 5 - 3
controllers/document_manage/document_manage_controller.go

@@ -156,7 +156,8 @@ func (this *DocumentManageController) DocumentReportList() {
 	if currentIndex <= 0 {
 		currentIndex = 1
 	}
-	documentReportPage, err := document_manage_service.DocumentReportList(documentType, chartPermissionIdList, classifyIdList, keyword, orderField, orderType, currentIndex, pageSize)
+	startSize := utils.StartIndex(currentIndex, pageSize)
+	documentReportPage, err := document_manage_service.DocumentReportList(documentType, chartPermissionIdList, classifyIdList, keyword, orderField, orderType, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取报告列表失败"
 		br.ErrMsg = "获取报告列表失败,Err:" + err.Error()
@@ -211,7 +212,8 @@ func (this *DocumentManageController) RuiSiReportList() {
 	if currentIndex <= 0 {
 		currentIndex = 1
 	}
-	RuiSiReportPage, err := document_manage_service.RuiSiReportList(classifyIdFirst, classifyIdSecond, classifyIdThird, chartPermissionIdList, keyword, orderField, orderType, currentIndex, pageSize)
+	startSize := utils.StartIndex(currentIndex, pageSize)
+	RuiSiReportPage, err := document_manage_service.RuiSiReportList(classifyIdFirst, classifyIdSecond, classifyIdThird, chartPermissionIdList, keyword, orderField, orderType, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取报告列表失败"
 		br.ErrMsg = "获取报告列表失败,Err:" + err.Error()
@@ -257,7 +259,7 @@ func (this *DocumentManageController) DocumentRuiSiDetail() {
 
 	reportDetail, err := document_manage_service.DocumentRuiSiDetail(reportId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "报告已被删除"
 			return
 		}

+ 398 - 0
controllers/edb_monitor/edb_monitor.go

@@ -0,0 +1,398 @@
+package edb_monitor
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/edb_monitor/request"
+	edbmonitor "eta/eta_api/services/edb_monitor"
+	"strings"
+)
+
+type EdbMonitorController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 预警管理列表
+// @Description 预警管理列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类ID,多选用逗号分隔"
+// @Param   Level   query   string  true       "预警等级,多选用逗号分隔"
+// @Param   State   query   string  true       "预警状态,多选用逗号分隔"
+// @Param   UserId   query   string  true       "创建人ID,多选用逗号分隔"
+// @Success 200 {object} response.EdbMonitorInfoListResp
+// @router /list [get]
+func (m *EdbMonitorController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := m.GetInt("PageSize")
+	currentIndex, _ := m.GetInt("CurrentIndex")
+	classifyId := m.GetString("ClassifyId")
+	level := m.GetString("Level")
+	state := m.GetString("State")
+	userId := m.GetString("UserId")
+
+	resp, msg, err := edbmonitor.GetMonitorList(classifyId, level, state, userId, pageSize, currentIndex)
+	if err != nil {
+		if msg == "" {
+			msg = "获取列表失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "获取列表成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Add
+// @Title 预警管理添加
+// @Description 预警管理添加
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /add [post]
+func (m *EdbMonitorController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorInfoSaveReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	switch req.MonitorType {
+	case edbmonitor.EDB_MONITOR_TYPE_DOWN, edbmonitor.EDB_MONITOR_TYPE_UP:
+	default:
+		br.Msg = "请选择预警等级"
+		return
+	}
+	req.MonitorData = strings.TrimSpace(req.MonitorData)
+	if req.MonitorData == "" {
+		br.Msg = "请输入预警值"
+		return
+	}
+	req.EdbMonitorName = strings.TrimSpace(req.EdbMonitorName)
+	if req.EdbMonitorName == "" {
+		br.Msg = "请输入预警名称"
+		return
+	}
+
+	msg, err := edbmonitor.SaveEdbMonitorInfo(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "添加失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "添加成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// edit
+// @Title 预警管理编辑
+// @Description 预警管理编辑
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /edit [post]
+func (m *EdbMonitorController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorInfoSaveReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+	if req.EdbInfoId <= 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if req.EdbMonitorId <= 0 {
+		br.Msg = "请选择预警"
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	switch req.MonitorType {
+	case edbmonitor.EDB_MONITOR_TYPE_DOWN, edbmonitor.EDB_MONITOR_TYPE_UP:
+	default:
+		br.Msg = "请选择预警等级"
+		return
+	}
+	req.MonitorData = strings.TrimSpace(req.MonitorData)
+	if req.MonitorData == "" {
+		br.Msg = "请输入预警值"
+		return
+	}
+	req.EdbMonitorName = strings.TrimSpace(req.EdbMonitorName)
+	if req.EdbMonitorName == "" {
+		br.Msg = "请输入预警名称"
+		return
+	}
+
+	msg, err := edbmonitor.SaveEdbMonitorInfo(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "编辑失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "编辑成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// delete
+// @Title 预警管理编辑
+// @Description 预警管理编辑
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /delete [post]
+func (m *EdbMonitorController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorInfoDeleteReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+	if req.EdbMonitorId <= 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	msg, err := edbmonitor.DeleteEdbMonitorInfo(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "删除失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "删除成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Close
+// @Title 预警管理关闭
+// @Description 预警管理关闭
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /close [post]
+func (m *EdbMonitorController) Close() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorInfoCloseReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+	if req.EdbMonitorId <= 0 {
+		br.Msg = "请选择预警"
+		return
+	}
+
+	msg, err := edbmonitor.CloseEdbMonitorInfo(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "关闭失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "关闭成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Restart
+// @Title 预警管理重启
+// @Description 预警管理重启
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /restart [post]
+func (m *EdbMonitorController) Restart() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorInfoRestartReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+	if req.EdbMonitorId <= 0 {
+		br.Msg = "请选择预警"
+		return
+	}
+
+	msg, err := edbmonitor.RestartEdbMonitorInfo(req, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "重启失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "重启成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GetMonitorLevel
+// @Title 预警管理等级列表
+// @Description 预警管理等级列表
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /monitor_level/list [get]
+func (m *EdbMonitorController) GetMonitorLevel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	list, msg, err := edbmonitor.GetEdbMonitorLevelList()
+	if err != nil {
+		if msg == "" {
+			msg = "获取预警等级失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = list
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GetMonitorUser
+// @Title 预警管理用户列表
+// @Description 预警管理用户列表
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /monitor_user/list [get]
+func (m *EdbMonitorController) GetMonitorUser() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	resp, msg, err := edbmonitor.GetEdbMonitorInfoUserList()
+	if err != nil {
+		if msg == "" {
+			msg = "获取用户列表失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 240 - 0
controllers/edb_monitor/edb_monitor_classify.go

@@ -0,0 +1,240 @@
+package edb_monitor
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/edb_monitor/request"
+	edbmonitor "eta/eta_api/services/edb_monitor"
+	"strings"
+)
+
+type EdbMonitorClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 预警管理分类列表
+// @Description 预警管理分类列表
+// @Success 200 {object} response.EdbMonitorClassifyTree
+// @router /classify/list [get]
+func (c *EdbMonitorClassifyController) List() {
+	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
+	}
+	resp, msg, err := edbmonitor.GetEdbMonitorClassifyTree()
+	if err != nil {
+		if msg == "" {
+			msg = "获取分类列表失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Add
+// @Title 预警管理分类添加
+// @Description 预警管理分类添加
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /classify/add [post]
+func (c *EdbMonitorClassifyController) Add() {
+	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
+	}
+
+	var req request.EdbMonitorClassifySaveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "分类名称不能为空"
+		return
+	}
+	if req.Level <= 0 || req.ClassifyId > 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	msg, err := edbmonitor.SaveEdbMonitorClassify(req)
+	if err != nil {
+		if msg == "" {
+			msg = "分类添加失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "分类添加成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Edit
+// @Title 预警管理分类编辑
+// @Description 预警管理分类编辑
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @router /classify/edit [post]
+func (c *EdbMonitorClassifyController) Edit() {
+	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
+	}
+
+	var req request.EdbMonitorClassifySaveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "分类不存在,请刷新页面"
+		return
+	}
+	req.ClassifyName = strings.TrimSpace(req.ClassifyName)
+	if req.ClassifyName == "" {
+		br.Msg = "分类名称不能为空"
+		return
+	}
+	if req.Level <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	msg, err := edbmonitor.SaveEdbMonitorClassify(req)
+	if err != nil {
+		if msg == "" {
+			msg = "分类添加失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "分类编辑成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Delete
+// @Title 预警管理分类删除
+// @Description 预警管理分类删除
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @router /classify/delete [post]
+func (c *EdbMonitorClassifyController) Delete() {
+	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
+	}
+
+	var req request.EdbMonitorClassifyDeleteReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "分类不存在,请刷新页面"
+		return
+	}
+
+	msg, err := edbmonitor.DeleteEdbMonitorClassify(req)
+	if err != nil {
+		if msg == "" {
+			msg = "分类删除失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "分类删除成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Move
+// @Title 预警分类移动接口
+// @Description 预警分类移动接口
+// @Param   request body request.MoveEdbMonitorClassifyReq  true  "每页数据条数"
+// @router /classify/move [post]
+func (c *EdbMonitorClassifyController) Move() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	var req request.MoveEdbMonitorClassifyReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "分类id小于等于0"
+		return
+	}
+	msg, err := edbmonitor.MoveEdbMonitorClassify(req)
+	if err != nil {
+		if msg == "" {
+			msg = "分类移动失败"
+		}
+		br.Msg = msg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Msg = "分类移动成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 251 - 0
controllers/edb_monitor/edb_monitor_message.go

@@ -0,0 +1,251 @@
+package edb_monitor
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/edb_monitor/request"
+	edbmonitor "eta/eta_api/services/edb_monitor"
+	"eta/eta_api/utils"
+	"net/http"
+	"strconv"
+	"time"
+
+	"github.com/gorilla/websocket"
+)
+
+type EdbMonitorMessageController struct {
+	controllers.BaseAuthController
+}
+
+var upgrader = websocket.Upgrader{
+	ReadBufferSize:  1024,
+	WriteBufferSize: 1024,
+	CheckOrigin: func(r *http.Request) bool {
+		return true
+	},
+}
+
+// GetMonitorLevel
+// @Title 预警管理消息
+// @Description 预警管理消息
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /message/connect [get]
+func (m *EdbMonitorMessageController) Connect() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var conn *websocket.Conn
+	connKey := edbmonitor.EDB_MONITOR_MESSAGE_CONNECT_CACHE + strconv.Itoa(sysUser.AdminId)
+	ok := utils.Rc.IsExist(connKey)
+	if !ok {
+		conn = edbmonitor.MonitorMessageConn[sysUser.AdminId]
+		if conn != nil {
+			conn.Close()
+		}
+	}
+	err := utils.Rc.Put(connKey, "1", time.Minute*1)
+	if err != nil {
+		br.Msg = "系统错误"
+		br.ErrMsg = "连接失败,err:" + err.Error()
+		return
+	}
+	conn, err = upgrader.Upgrade(m.Ctx.ResponseWriter, m.Ctx.Request, nil)
+	if err != nil {
+		br.Msg = "连接失败"
+		br.ErrMsg = "连接失败,err:" + err.Error()
+		return
+	}
+	defer conn.Close()
+
+	edbmonitor.MonitorMessageConn[sysUser.AdminId] = conn
+	conn.SetCloseHandler(func(code int, text string) error {
+		delete(edbmonitor.MonitorMessageConn, sysUser.AdminId)
+		utils.Rc.Delete(connKey)
+		return nil
+	})
+
+	go func() {
+		// 心跳检测
+		for {
+			isClose, err := edbmonitor.EdbMonitorMessageHealth(sysUser.AdminId)
+			if err != nil {
+				utils.FileLog.Error("指标预警信息健康检查失败,err:%s, adminId:%d", err.Error(), sysUser.AdminId)
+				return
+			}
+			if isClose {
+				return
+			}
+		}
+	}()
+
+	messageList, err := edbmonitor.GetHistoryMessages(sysUser.AdminId)
+	if err != nil {
+		utils.FileLog.Error("获取指标预警信息历史失败,err:%s, adminId:%d", err.Error(), sysUser.AdminId)
+	}
+	success := make(chan int, 10)
+	go func() {
+		defer close(success)
+		for i, msg := range messageList {
+			if i == 0 {
+				// 多条消息仅发送最新一条
+				err = edbmonitor.SendMessages(sysUser.AdminId, msg.EdbInfoId, msg.EdbInfoType, msg.EdbClassifyId, msg.EdbUniqueCode, msg.Message, msg.TriggerTime)
+				if err != nil {
+					utils.FileLog.Error("指标预警信息发送失败,err:%s, adminId:%d", err.Error(), sysUser.AdminId)
+				} else {
+					success <- msg.EdbMonitorMessageId
+				}
+			} else {
+				success <- msg.EdbMonitorMessageId
+			}
+		}
+	}()
+	go func() {
+		readList := make([]int, 0)
+		for {
+			msgId, ok := <-success
+			if !ok {
+				break
+			}
+			readList = append(readList, msgId)
+		}
+		_, err = edbmonitor.ReadEdbMonitorMessageList(readList, sysUser.AdminId)
+		if err != nil {
+			utils.FileLog.Error("指标预警信息已读失败,err:%s, adminId:%d", err.Error(), sysUser.AdminId)
+		}
+	}()
+
+	for {
+		ok = utils.Rc.IsExist(connKey)
+		if !ok {
+			br.Msg = "连接已断开"
+			br.Ret = 200
+			br.Success = true
+			return
+		}
+		time.Sleep(10 * time.Second)
+	}
+}
+
+// Close
+// @Title 预警管理消息
+// @Description 预警管理消息
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /message/close [post]
+func (m *EdbMonitorMessageController) Close() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	conn := edbmonitor.MonitorMessageConn[sysUser.AdminId]
+	if conn != nil {
+		conn.Close()
+	}
+
+	br.Msg = "关闭成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// List
+// @Title 预警管理消息列表
+// @Description 预警管理消息列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Success 200 {object} response.EdbMonitorClassifyTree
+// @router /message/list [get]
+func (c *EdbMonitorMessageController) List() {
+	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
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	resp, err := edbmonitor.GetMessageList(sysUser.AdminId, currentIndex, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Read
+// @Title 预警管理消息已读
+// @Description 预警管理消息已读
+// @Param   request body request.EdbMonitorSaveRequest  true  "每页数据条数"
+// @Success 200 {object} models.EnglishReportEmailPageListResp
+// @router /message/read [post]
+func (m *EdbMonitorMessageController) Read() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		m.Data["json"] = br
+		m.ServeJSON()
+	}()
+
+	sysUser := m.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EdbMonitorMessageReadReq
+	if err := json.Unmarshal(m.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,err:" + err.Error()
+		return
+	}
+	if req.EdbMonitorMessageId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	msg, err := edbmonitor.ReadEdbMonitorMessage(req.EdbMonitorMessageId, sysUser.AdminId)
+	if err != nil {
+		if msg == "" {
+			msg = "系统错误"
+		}
+		br.Msg = msg
+		br.ErrMsg = "读取消息失败,err:" + err.Error()
+		return
+	}
+
+	br.Msg = "已读成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 14 - 2
controllers/english_report/email.go

@@ -187,7 +187,7 @@ func (this *EnglishReportEmailController) Save() {
 
 	// 英文客户以邮箱为主, 邮箱去重, 手机号非必填, 此处不做手机号去重
 	exist, e := models.GetEnglishReportEmailByEmail(req.Email)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取同名邮箱失败, Err:" + e.Error()
 		return
@@ -595,6 +595,18 @@ func (this *EnglishReportEmailController) Send() {
 			noCompanyIdsMap[v] = struct{}{}
 		}
 	}
+
+	// 加个缓存吧,避免重复点击
+	cacheKey := "CACHE_ENGLISH_REPORT_SEND_" + strconv.Itoa(req.ReportId)
+	if !utils.Rc.SetNX(cacheKey, 1, 300*time.Second) {
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
 	// 指定品种的客户
 	sendCompanyIds := make([]int, 0)
 	if len(req.EnPermissions) > 0 {
@@ -933,7 +945,7 @@ func (this *EnglishReportEmailController) ImportListMatch() {
 	}
 	companyItem, e := models.GetEnglishCompanyById(companyId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "客户已被删除, 请刷新页面"
 			return
 		}

+ 5 - 5
controllers/english_report/en_permission.go

@@ -62,7 +62,7 @@ func (this *EnPermissionController) Add() {
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, req.PermissionName, req.ParentId)
 	exist, e := existOB.GetItemByCondition(existCond, existPars)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名品种权限失败, Err: " + e.Error()
 		return
@@ -143,7 +143,7 @@ func (this *EnPermissionController) Edit() {
 	existPars := make([]interface{}, 0)
 	existPars = append(existPars, req.PermissionName, req.ParentId, req.PermissionId)
 	exist, e := ob.GetItemByCondition(existCond, existPars)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "操作失败"
 		br.ErrMsg = "获取重名品种权限失败, Err: " + e.Error()
 		return
@@ -155,7 +155,7 @@ func (this *EnPermissionController) Edit() {
 
 	item, e := ob.GetItemById(req.PermissionId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "品种不存在, 请刷新页面"
 			return
 		}
@@ -384,7 +384,7 @@ func (this *EnPermissionController) Remove() {
 	ob := new(models.EnPermission)
 	item, e := ob.GetItemById(req.PermissionId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "品种不存在, 请刷新页面"
 			return
 		}
@@ -522,7 +522,7 @@ func (this *EnPermissionController) SetEnabled() {
 
 	item, e := ob.GetItemById(req.PermissionId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "品种不存在, 请刷新页面"
 			return
 		}

+ 30 - 21
controllers/english_report/english_classify.go

@@ -79,6 +79,7 @@ func (this *EnglishReportController) ListClassify() {
 	// 三级分类-品种权限
 	permissionMap := make(map[int][]int)
 
+	var secondClassify []*models.EnglishClassifyList
 	if len(idList) > 0 {
 		childIdMap := make(map[int]struct{}, 0)
 		for _, v := range idList {
@@ -97,6 +98,7 @@ func (this *EnglishReportController) ListClassify() {
 			br.ErrMsg = "获取二级分类失败,Err:" + err.Error()
 			return
 		}
+		secondClassify = tmpList
 		for _, v := range tmpList {
 			if _, ok := rootMap[v.ParentId]; !ok {
 				thirdIds = append(thirdIds, v.Id)
@@ -145,6 +147,13 @@ func (this *EnglishReportController) ListClassify() {
 			}
 		}
 	}
+	// 标记可删除的英文分类
+	err = services.MarkEnableDeleteEnlishClassify(rootList, secondClassify)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "标记可删除分类失败,Err:" + err.Error()
+		return
+	}
 
 	//处理一级分类
 	var sortList models.RSClassifyList
@@ -197,7 +206,7 @@ func (this *EnglishReportController) AddClassify() {
 	if parentId > 0 {
 		parentClassify, err := models.GetEnglishReportClassifyById(parentId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "上级分类不存在"
 				return
 			}
@@ -322,7 +331,7 @@ func (this *EnglishReportController) EditClassify() {
 
 	oldItem, err := models.GetEnglishReportClassifyById(classifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "当前分类不存在"
 			return
 		}
@@ -341,7 +350,7 @@ func (this *EnglishReportController) EditClassify() {
 	if parentId > 0 {
 		parent, err = models.GetEnglishReportClassifyById(parentId)
 		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(err) {
 				br.Msg = "上级分类不存在"
 				return
 			}
@@ -368,7 +377,7 @@ func (this *EnglishReportController) EditClassify() {
 	//判断是否已存在同个名称的分类
 	existItem, e := models.GetEnglishClassifyByClassifyNameParentId(classifyName, parentId)
 	if e != nil {
-		if e.Error() != utils.ErrNoRow() {
+		if !utils.IsErrNoRow(e) {
 			br.Msg = "查询已存在的分类出错"
 			br.ErrMsg = "查询已存在的分类出错, Err:" + e.Error()
 			return
@@ -473,7 +482,7 @@ func (this *EnglishReportController) DelClassify() {
 
 	classifyInfo, err := models.GetEnglishReportClassifyById(classifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "当前分类不存在"
 			br.ErrMsg = "当前分类不存在"
 			return
@@ -483,20 +492,20 @@ func (this *EnglishReportController) DelClassify() {
 		return
 	}
 
-	count, err := models.GetEnglishClassifyChildCounts(classifyId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
+	// count, err := models.GetEnglishClassifyChildCounts(classifyId)
+	// if err != nil && err.Error() != utils.ErrNoRow() {
+	// 	br.Msg = "获取信息失败"
+	// 	br.ErrMsg = "获取失败,Err:" + err.Error()
+	// 	return
+	// }
 
-	if count > 0 {
-		br.Msg = "请先删除该分类下关联分类"
-		br.Ret = 403
-		return
-	}
+	// if count > 0 {
+	// 	br.Msg = "请先删除该分类下关联分类"
+	// 	br.Ret = 403
+	// 	return
+	// }
 	reportCount, e := models.GetEnglishReportCounts(classifyId, classifyInfo.ParentId)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取失败,Err:" + e.Error()
 		return
@@ -508,7 +517,7 @@ func (this *EnglishReportController) DelClassify() {
 		return
 	}
 	videoCount, e := models.GetEnglishVideoCounts(classifyId, classifyInfo.ParentId)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取失败,Err:" + e.Error()
 		return
@@ -536,8 +545,8 @@ func (this *EnglishReportController) DelClassify() {
 		br.Ret = 403
 		return
 	}
-
-	if err = models.DeleteEnglishClassify(classifyId); err != nil {
+	err = classifyInfo.Delete()
+	if err != nil {
 		br.Msg = "删除失败"
 		br.ErrMsg = "删除报告失败, Err: " + err.Error()
 		return
@@ -745,7 +754,7 @@ func (this *EnglishReportController) SetEnabled() {
 	}
 	item, err := models.GetEnglishReportClassifyById(req.ClassifyId)
 	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(err) {
 			br.Msg = "分类不存在"
 			return
 		}

+ 3 - 3
controllers/english_report/english_company.go

@@ -266,7 +266,7 @@ func (this *EnglishCompanyController) Save() {
 
 	// 重名校验
 	exist, e := models.GetEnglishCompanyByName(req.CompanyName)
-	if e != nil && e.Error() != utils.ErrNoRow() {
+	if e != nil && !utils.IsErrNoRow(e) {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取客户信息失败, Err:" + e.Error()
 		return
@@ -298,7 +298,7 @@ func (this *EnglishCompanyController) Save() {
 			return
 		}
 	} else {
-		if exist != nil && exist.CompanyId != req.CompanyId {
+		if exist != nil && exist.CompanyId != req.CompanyId && exist.CompanyId > 0 {
 			br.Msg = "客户名称已存在"
 			return
 		}
@@ -721,7 +721,7 @@ func (this *EnglishCompanyController) SavePermission() {
 	nowTime := time.Now().Local()
 	item, e := models.GetEnglishCompanyById(req.CompanyId)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
+		if utils.IsErrNoRow(e) {
 			br.Msg = "客户已被删除, 请刷新页面"
 			return
 		}

Some files were not shown because too many files changed in this diff