index.go 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456
  1. package ai_predict_model
  2. import (
  3. "encoding/json"
  4. "eta/eta_api/controllers"
  5. "eta/eta_api/models"
  6. aiPredictModel "eta/eta_api/models/ai_predict_model"
  7. "eta/eta_api/models/ai_predict_model/request"
  8. "eta/eta_api/models/ai_predict_model/response"
  9. "eta/eta_api/models/data_manage"
  10. dataSourceModel "eta/eta_api/models/data_source"
  11. "eta/eta_api/models/system"
  12. "eta/eta_api/services"
  13. "eta/eta_api/services/data"
  14. "eta/eta_api/services/elastic"
  15. "eta/eta_api/utils"
  16. "fmt"
  17. "os"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "github.com/rdlucklib/rdluck_tools/paging"
  22. "github.com/tealeg/xlsx"
  23. )
  24. // AiPredictModelIndexController AI预测模型标的
  25. type AiPredictModelIndexController struct {
  26. controllers.BaseAuthController
  27. }
  28. // List
  29. // @Title 标的列表
  30. // @Description 标的列表
  31. // @Param PageSize query int true "每页数据条数"
  32. // @Param CurrentIndex query int true "当前页页码,从1开始"
  33. // @Param ClassifyId query int false "分类id"
  34. // @Param IndexId query int false "模型标的ID"
  35. // @Param Keyword query string false "搜索关键词"
  36. // @Success 200 {object} data_manage.ChartListResp
  37. // @router /index/list [get]
  38. func (this *AiPredictModelIndexController) List() {
  39. br := new(models.BaseResponse).Init()
  40. defer func() {
  41. this.Data["json"] = br
  42. this.ServeJSON()
  43. }()
  44. sysUser := this.SysUser
  45. if sysUser == nil {
  46. br.Msg = "请登录"
  47. br.ErrMsg = "请登录,SysUser Is Empty"
  48. br.Ret = 408
  49. return
  50. }
  51. pageSize, _ := this.GetInt("PageSize")
  52. currentIndex, _ := this.GetInt("CurrentIndex")
  53. classifyId, _ := this.GetInt("ClassifyId")
  54. indexId, _ := this.GetInt("IndexId")
  55. keyword := this.GetString("KeyWord")
  56. if keyword == "" {
  57. keyword = this.GetString("Keyword")
  58. }
  59. keyword = strings.TrimSpace(keyword)
  60. resp := new(aiPredictModel.AiPredictModelIndexPageListResp)
  61. // 分页
  62. var startSize int
  63. if pageSize <= 0 {
  64. pageSize = utils.PageSize20
  65. }
  66. if currentIndex <= 0 {
  67. currentIndex = 1
  68. }
  69. startSize = paging.StartIndex(currentIndex, pageSize)
  70. // 分类
  71. classifyIdName := make(map[int]string)
  72. {
  73. classifyOb := new(aiPredictModel.AiPredictModelClassify)
  74. list, e := classifyOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
  75. if e != nil {
  76. br.Msg = "获取失败"
  77. br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
  78. return
  79. }
  80. for _, v := range list {
  81. classifyIdName[v.AiPredictModelClassifyId] = v.ClassifyName
  82. }
  83. }
  84. // 筛选条件
  85. highlightMap := make(map[int]string)
  86. indexOb := new(aiPredictModel.AiPredictModelIndex)
  87. var cond string
  88. var pars []interface{}
  89. {
  90. if indexId > 0 {
  91. cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().PrimaryId)
  92. pars = append(pars, indexId)
  93. }
  94. if classifyId > 0 {
  95. cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
  96. pars = append(pars, classifyId)
  97. }
  98. //if keyword != "" {
  99. // cond += fmt.Sprintf(" AND %s LIKE ?", indexOb.Cols().IndexName)
  100. // pars = append(pars, fmt.Sprint("%", keyword, "%"))
  101. //}
  102. // 有关键词从es中搜索
  103. if keyword != "" {
  104. _, list, e := elastic.SearchDataSourceIndex(utils.EsDataSourceIndexName, keyword, utils.DATA_SOURCE_AI_PREDICT_MODEL, 0, []int{}, []int{}, []string{}, startSize, pageSize)
  105. if e != nil {
  106. br.Msg = "获取失败"
  107. br.ErrMsg = fmt.Sprintf("ES-搜索AI预测模型列表失败, %v", e)
  108. return
  109. }
  110. if len(list) == 0 {
  111. resp.List = make([]*aiPredictModel.AiPredictModelIndexItem, 0)
  112. br.Ret = 200
  113. br.Success = true
  114. br.Msg = "获取成功"
  115. br.Data = resp
  116. return
  117. }
  118. var ids []int
  119. for _, v := range list {
  120. ids = append(ids, v.PrimaryId)
  121. highlightMap[v.PrimaryId] = v.SearchText
  122. }
  123. cond += fmt.Sprintf(` AND %s IN (%s)`, indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
  124. pars = append(pars, ids)
  125. }
  126. }
  127. // 获取列表
  128. total, e := indexOb.GetCountByCondition(cond, pars)
  129. if e != nil {
  130. br.Msg = "获取失败"
  131. br.ErrMsg = fmt.Sprintf("获取标的总数失败, %v", e)
  132. return
  133. }
  134. list, e := indexOb.GetPageItemsByCondition(cond, pars, []string{}, "", startSize, pageSize)
  135. if e != nil {
  136. br.Msg = "获取失败"
  137. br.ErrMsg = fmt.Sprintf("获取分页列表失败, %v", e)
  138. return
  139. }
  140. pageList := make([]*aiPredictModel.AiPredictModelIndexItem, 0)
  141. for _, v := range list {
  142. t := v.Format2Item()
  143. t.ClassifyName = classifyIdName[v.ClassifyId]
  144. // 搜索高亮
  145. t.SearchText = v.IndexName
  146. s := highlightMap[v.AiPredictModelIndexId]
  147. if s != "" {
  148. t.SearchText = s
  149. }
  150. pageList = append(pageList, t)
  151. }
  152. page := paging.GetPaging(currentIndex, pageSize, total)
  153. resp.Paging = page
  154. resp.List = pageList
  155. br.Data = resp
  156. br.Ret = 200
  157. br.Success = true
  158. br.Msg = "获取成功"
  159. }
  160. // Import
  161. // @Title 导入标的和数据
  162. // @Description 导入标的和数据
  163. // @Param IndexFile query file true "标的文件"
  164. // @Success 200 Ret=200 录入成功
  165. // @router /index/import [post]
  166. func (this *AiPredictModelIndexController) Import() {
  167. br := new(models.BaseResponse).Init()
  168. defer func() {
  169. if br.ErrMsg == "" {
  170. br.IsSendEmail = false
  171. }
  172. this.Data["json"] = br
  173. this.ServeJSON()
  174. }()
  175. sysUser := this.SysUser
  176. if sysUser == nil {
  177. br.Msg = "请登录"
  178. br.ErrMsg = "请登录,SysUser Is Empty"
  179. br.Ret = 408
  180. return
  181. }
  182. file, _, e := this.GetFile("IndexFile")
  183. if e != nil {
  184. br.Msg = "导入失败"
  185. br.ErrMsg = fmt.Sprintf("获取文件失败, %v", e)
  186. return
  187. }
  188. path := "./static/ai_predict_model_temp_" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
  189. defer func() {
  190. _ = file.Close()
  191. _ = os.Remove(path)
  192. }()
  193. if e = this.SaveToFile("IndexFile", path); e != nil {
  194. br.Msg = "导入失败"
  195. br.ErrMsg = fmt.Sprintf("保存文件失败, %v", e)
  196. return
  197. }
  198. xlFile, e := xlsx.OpenFile(path)
  199. if e != nil {
  200. br.Msg = "导入失败"
  201. br.ErrMsg = fmt.Sprintf("打开excel文件失败, %v", e)
  202. return
  203. }
  204. // 获取分类和用户,遍历时校验
  205. classifyNameId := make(map[string]int)
  206. adminNameId := make(map[string]int)
  207. {
  208. classifyOb := new(aiPredictModel.AiPredictModelClassify)
  209. classifyCond := fmt.Sprintf(` AND %s = ?`, classifyOb.Cols().ParentId)
  210. classifyPars := make([]interface{}, 0)
  211. classifyPars = append(classifyPars, 0) // 只取一级分类(临时过渡方案,业务端只会加一级)
  212. classifies, e := classifyOb.GetItemsByCondition(classifyCond, classifyPars, []string{}, "")
  213. if e != nil {
  214. br.Msg = "导入失败"
  215. br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
  216. return
  217. }
  218. for _, v := range classifies {
  219. classifyNameId[v.ClassifyName] = v.AiPredictModelClassifyId
  220. }
  221. admins, e := system.GetSysAdminList(``, make([]interface{}, 0), []string{}, "")
  222. if e != nil {
  223. br.Msg = "导入失败"
  224. br.ErrMsg = fmt.Sprintf("获取用户失败, %v", e)
  225. return
  226. }
  227. for _, v := range admins {
  228. adminNameId[v.RealName] = v.AdminId
  229. }
  230. }
  231. // 遍历sheet页
  232. // 列表页:预测标的|分类|模型框架|创建人|预测日期|预测值|预测频度|方向准确率|绝对偏差
  233. type ImportDataColKey struct {
  234. IndexName string
  235. ColKey int
  236. DataDate time.Time
  237. }
  238. imports := make(map[string]*aiPredictModel.AiPredictModelImportData)
  239. importsData := make(map[string]map[time.Time]*aiPredictModel.AiPredictModelData)
  240. importsDailyData := make(map[string]map[time.Time]*aiPredictModel.AiPredictModelData)
  241. for sheetKey, sheet := range xlFile.Sheets {
  242. maxRow := sheet.MaxRow
  243. // 列表页
  244. if sheetKey == 0 {
  245. for i := 0; i < maxRow; i++ {
  246. // 忽略首行标题
  247. if i < 1 {
  248. continue
  249. }
  250. row := sheet.Row(i)
  251. cells := row.Cells
  252. if len(cells) < 9 {
  253. continue
  254. }
  255. // 标的名称
  256. indexName := strings.TrimSpace(cells[0].String())
  257. if indexName == "" {
  258. continue
  259. }
  260. if imports[indexName] == nil {
  261. imports[indexName] = new(aiPredictModel.AiPredictModelImportData)
  262. imports[indexName].Index = new(aiPredictModel.AiPredictModelIndex)
  263. imports[indexName].Data = make([]*aiPredictModel.AiPredictModelData, 0)
  264. }
  265. imports[indexName].Index.IndexName = indexName
  266. imports[indexName].Index.CreateTime = time.Now()
  267. imports[indexName].Index.ModifyTime = time.Now()
  268. imports[indexName].Index.TrainStatus = `训练成功`
  269. imports[indexName].Index.RunStatus = `运行成功`
  270. // 分类
  271. classifyName := strings.TrimSpace(cells[1].String())
  272. if classifyNameId[classifyName] <= 0 {
  273. br.Msg = fmt.Sprintf("分类:%s不存在", classifyName)
  274. return
  275. }
  276. imports[indexName].Index.ClassifyId = classifyNameId[classifyName]
  277. // 创建人
  278. adminName := strings.TrimSpace(cells[3].String())
  279. if adminNameId[adminName] <= 0 {
  280. br.Msg = fmt.Sprintf("创建人:%s不存在", adminName)
  281. return
  282. }
  283. imports[indexName].Index.SysUserId = adminNameId[adminName]
  284. imports[indexName].Index.SysUserRealName = adminName
  285. // 其余信息
  286. imports[indexName].Index.ModelFramework = strings.TrimSpace(cells[2].String())
  287. strDate := strings.TrimSpace(cells[4].String())
  288. predictDate, _ := utils.GetExcelDate(strDate)
  289. imports[indexName].Index.PredictDate = predictDate
  290. strVal := strings.TrimSpace(cells[5].String())
  291. if strVal == "" {
  292. continue
  293. }
  294. predictVal, _ := strconv.ParseFloat(strVal, 64)
  295. imports[indexName].Index.PredictValue = predictVal
  296. imports[indexName].Index.PredictFrequency = strings.TrimSpace(cells[6].String())
  297. imports[indexName].Index.DirectionAccuracy = strings.TrimSpace(cells[7].String())
  298. imports[indexName].Index.AbsoluteDeviation = strings.TrimSpace(cells[8].String())
  299. }
  300. }
  301. // 月度数据页
  302. if sheetKey == 1 {
  303. // 每五列为一个指标的数据
  304. colKeys := make(map[int]*ImportDataColKey) // 每一列对应的指标名称以及对应的字段序号
  305. for i := 0; i < maxRow; i++ {
  306. // 首行为指标名称
  307. if i == 0 {
  308. nameCol := 0
  309. row := sheet.Row(i)
  310. for ck, cell := range row.Cells {
  311. nameCol += 1
  312. if nameCol > 5 {
  313. nameCol = 1
  314. }
  315. if nameCol == 1 {
  316. // nameCol=1时为指标/数据行则为日期
  317. indexName := strings.TrimSpace(cell.String())
  318. if indexName == "" {
  319. continue
  320. }
  321. importsData[indexName] = make(map[time.Time]*aiPredictModel.AiPredictModelData)
  322. colKeys[ck] = &ImportDataColKey{
  323. ColKey: 1,
  324. IndexName: indexName,
  325. }
  326. // 后面四列分别对应: 实际值|预测值|方向|偏差率, 这里直接加无须考虑是否会越界
  327. colKeys[ck+1] = &ImportDataColKey{
  328. ColKey: 2,
  329. IndexName: indexName,
  330. }
  331. colKeys[ck+2] = &ImportDataColKey{
  332. ColKey: 3,
  333. IndexName: indexName,
  334. }
  335. colKeys[ck+3] = &ImportDataColKey{
  336. ColKey: 4,
  337. IndexName: indexName,
  338. }
  339. colKeys[ck+4] = &ImportDataColKey{
  340. ColKey: 5,
  341. IndexName: indexName,
  342. }
  343. continue
  344. }
  345. }
  346. continue
  347. }
  348. // 第二行为标题,跳过
  349. if i == 1 {
  350. continue
  351. }
  352. // 剩余为数据行
  353. row := sheet.Row(i)
  354. for ck, cell := range row.Cells {
  355. if colKeys[ck] == nil {
  356. continue
  357. }
  358. if colKeys[ck].IndexName == "" {
  359. continue
  360. }
  361. switch colKeys[ck].ColKey {
  362. case 1:
  363. // 日期列
  364. strDate := strings.TrimSpace(cell.String())
  365. dataDate, _ := utils.GetExcelDate(strDate)
  366. if dataDate.IsZero() {
  367. continue
  368. }
  369. colKeys[ck].DataDate = dataDate
  370. colKeys[ck+1].DataDate = dataDate
  371. colKeys[ck+2].DataDate = dataDate
  372. colKeys[ck+3].DataDate = dataDate
  373. colKeys[ck+4].DataDate = dataDate
  374. importRow := imports[colKeys[ck].IndexName]
  375. if importRow == nil {
  376. continue
  377. }
  378. // 新增当前日期数据
  379. importsData[colKeys[ck].IndexName][dataDate] = new(aiPredictModel.AiPredictModelData)
  380. importsData[colKeys[ck].IndexName][dataDate].DataTime = dataDate
  381. importsData[colKeys[ck].IndexName][dataDate].CreateTime = time.Now()
  382. importsData[colKeys[ck].IndexName][dataDate].ModifyTime = time.Now()
  383. importsData[colKeys[ck].IndexName][dataDate].Source = aiPredictModel.ModelDataSourceMonthly
  384. case 2, 3:
  385. // 实际值和预测值, 可能为空
  386. dataDate := colKeys[ck].DataDate
  387. if importsData[colKeys[ck].IndexName][dataDate] == nil {
  388. continue
  389. }
  390. strVal := strings.TrimSpace(cell.String())
  391. if strVal == "" {
  392. continue
  393. }
  394. val, _ := strconv.ParseFloat(strVal, 64)
  395. if colKeys[ck].ColKey == 2 {
  396. importsData[colKeys[ck].IndexName][dataDate].Value.Valid = true
  397. importsData[colKeys[ck].IndexName][dataDate].Value.Float64 = val
  398. } else {
  399. importsData[colKeys[ck].IndexName][dataDate].PredictValue.Valid = true
  400. importsData[colKeys[ck].IndexName][dataDate].PredictValue.Float64 = val
  401. }
  402. case 4, 5:
  403. // 方向/偏差率
  404. dataDate := colKeys[ck].DataDate
  405. if importsData[colKeys[ck].IndexName][dataDate] == nil {
  406. continue
  407. }
  408. str := strings.TrimSpace(cell.String())
  409. if str == "" {
  410. continue
  411. }
  412. if colKeys[ck].ColKey == 4 {
  413. importsData[colKeys[ck].IndexName][dataDate].Direction = str
  414. } else {
  415. importsData[colKeys[ck].IndexName][dataDate].DeviationRate = str
  416. }
  417. default:
  418. continue
  419. }
  420. }
  421. }
  422. }
  423. // 日度数据页
  424. if sheetKey == 2 {
  425. // 每3列为一个指标的数据
  426. colKeys := make(map[int]*ImportDataColKey) // 每一列对应的指标名称以及对应的字段序号
  427. for i := 0; i < maxRow; i++ {
  428. // 首行为指标名称
  429. if i == 0 {
  430. nameCol := 0
  431. row := sheet.Row(i)
  432. for ck, cell := range row.Cells {
  433. nameCol += 1
  434. if nameCol > 3 {
  435. nameCol = 1
  436. }
  437. if nameCol == 1 {
  438. // nameCol=1时为指标/数据行则为日期
  439. indexName := strings.TrimSpace(cell.String())
  440. if indexName == "" {
  441. continue
  442. }
  443. importsDailyData[indexName] = make(map[time.Time]*aiPredictModel.AiPredictModelData)
  444. colKeys[ck] = &ImportDataColKey{
  445. ColKey: 1,
  446. IndexName: indexName,
  447. }
  448. // 后面两列分别对应: 实际值|预测值, 这里直接加无须考虑是否会越界
  449. colKeys[ck+1] = &ImportDataColKey{
  450. ColKey: 2,
  451. IndexName: indexName,
  452. }
  453. colKeys[ck+2] = &ImportDataColKey{
  454. ColKey: 3,
  455. IndexName: indexName,
  456. }
  457. continue
  458. }
  459. }
  460. continue
  461. }
  462. // 第二行为标题,遇到"预测值"单元格,需要取出其中的值作为预测图例名称
  463. if i == 1 {
  464. row := sheet.Row(i)
  465. for ck, cell := range row.Cells {
  466. if colKeys[ck] == nil {
  467. continue
  468. }
  469. if colKeys[ck].IndexName == "" {
  470. continue
  471. }
  472. if colKeys[ck].ColKey != 3 {
  473. continue
  474. }
  475. if imports[colKeys[ck].IndexName] != nil && imports[colKeys[ck].IndexName].Index != nil {
  476. var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig
  477. extraConfig.DailyChart.PredictLegendName = strings.TrimSpace(cell.String())
  478. b, _ := json.Marshal(extraConfig)
  479. imports[colKeys[ck].IndexName].Index.ExtraConfig = string(b)
  480. }
  481. }
  482. continue
  483. }
  484. // 剩余为数据行
  485. row := sheet.Row(i)
  486. for ck, cell := range row.Cells {
  487. if colKeys[ck] == nil {
  488. continue
  489. }
  490. if colKeys[ck].IndexName == "" {
  491. continue
  492. }
  493. switch colKeys[ck].ColKey {
  494. case 1:
  495. // 日期列
  496. strDate := strings.TrimSpace(cell.String())
  497. dataDate, _ := utils.GetExcelDate(strDate)
  498. if dataDate.IsZero() {
  499. continue
  500. }
  501. colKeys[ck].DataDate = dataDate
  502. colKeys[ck+1].DataDate = dataDate
  503. colKeys[ck+2].DataDate = dataDate
  504. importRow := imports[colKeys[ck].IndexName]
  505. if importRow == nil {
  506. continue
  507. }
  508. // 新增当前日期数据
  509. importsDailyData[colKeys[ck].IndexName][dataDate] = new(aiPredictModel.AiPredictModelData)
  510. importsDailyData[colKeys[ck].IndexName][dataDate].DataTime = dataDate
  511. importsDailyData[colKeys[ck].IndexName][dataDate].CreateTime = time.Now()
  512. importsDailyData[colKeys[ck].IndexName][dataDate].ModifyTime = time.Now()
  513. importsDailyData[colKeys[ck].IndexName][dataDate].Source = aiPredictModel.ModelDataSourceDaily
  514. case 2, 3:
  515. // 实际值和预测值, 可能为空
  516. dataDate := colKeys[ck].DataDate
  517. if importsDailyData[colKeys[ck].IndexName][dataDate] == nil {
  518. continue
  519. }
  520. strVal := strings.TrimSpace(cell.String())
  521. if strVal == "" {
  522. continue
  523. }
  524. val, _ := strconv.ParseFloat(strVal, 64)
  525. if colKeys[ck].ColKey == 2 {
  526. importsDailyData[colKeys[ck].IndexName][dataDate].Value.Valid = true
  527. importsDailyData[colKeys[ck].IndexName][dataDate].Value.Float64 = val
  528. } else {
  529. importsDailyData[colKeys[ck].IndexName][dataDate].PredictValue.Valid = true
  530. importsDailyData[colKeys[ck].IndexName][dataDate].PredictValue.Float64 = val
  531. }
  532. default:
  533. continue
  534. }
  535. }
  536. }
  537. }
  538. }
  539. for indexName, v := range importsData {
  540. if imports[indexName] == nil {
  541. continue
  542. }
  543. for _, dateData := range v {
  544. imports[indexName].Data = append(imports[indexName].Data, dateData)
  545. }
  546. }
  547. for indexName, v := range importsDailyData {
  548. if imports[indexName] == nil {
  549. continue
  550. }
  551. for _, dateData := range v {
  552. imports[indexName].Data = append(imports[indexName].Data, dateData)
  553. }
  554. }
  555. importIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0)
  556. for _, v := range imports {
  557. importIndexes = append(importIndexes, v)
  558. }
  559. // 导入指标
  560. if e = services.ImportAiPredictModelIndexAndData(importIndexes, sysUser.AdminId, sysUser.RealName); e != nil {
  561. br.Msg = "操作失败"
  562. br.ErrMsg = fmt.Sprintf("导入指标数据失败, %v", e)
  563. return
  564. }
  565. // 写入es
  566. go func() {
  567. for _, v := range importIndexes {
  568. indexItem := new(dataSourceModel.SearchDataSource)
  569. indexItem.PrimaryId = v.Index.AiPredictModelIndexId
  570. indexItem.IndexName = v.Index.IndexName
  571. indexItem.IndexCode = v.Index.IndexCode
  572. indexItem.ClassifyId = v.Index.ClassifyId
  573. indexItem.Source = utils.DATA_SOURCE_AI_PREDICT_MODEL
  574. indexItem.SourceName = "AI预测模型"
  575. indexItem.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.Index.CreateTime)
  576. indexItem.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, v.Index.ModifyTime)
  577. docId := fmt.Sprintf("%d-%d", indexItem.Source, indexItem.PrimaryId)
  578. if e := elastic.EsAddOrEditDataSourceIndex(utils.EsDataSourceIndexName, docId, indexItem); e != nil {
  579. utils.FileLog.Info("AI预测模型-写入es失败, %v", e)
  580. continue
  581. }
  582. }
  583. }()
  584. br.Ret = 200
  585. br.Success = true
  586. br.Msg = "操作成功"
  587. }
  588. // Detail
  589. // @Title 标的详情
  590. // @Description 标的详情
  591. // @Param IndexId query int true "标的ID"
  592. // @Success 200 {object} data_manage.ChartListResp
  593. // @router /index/detail [get]
  594. func (this *AiPredictModelIndexController) Detail() {
  595. br := new(models.BaseResponse).Init()
  596. defer func() {
  597. if br.ErrMsg == "" {
  598. br.IsSendEmail = false
  599. }
  600. this.Data["json"] = br
  601. this.ServeJSON()
  602. }()
  603. sysUser := this.SysUser
  604. if sysUser == nil {
  605. br.Msg = "请登录"
  606. br.ErrMsg = "请登录,SysUser Is Empty"
  607. br.Ret = 408
  608. return
  609. }
  610. indexId, _ := this.GetInt("IndexId")
  611. if indexId <= 0 {
  612. br.Msg = "参数有误"
  613. br.ErrMsg = fmt.Sprintf("参数有误, IndexId: %d", indexId)
  614. return
  615. }
  616. resp := new(aiPredictModel.AiPredictModelDetailResp)
  617. indexOb := new(aiPredictModel.AiPredictModelIndex)
  618. indexItem, e := indexOb.GetItemById(indexId)
  619. if e != nil {
  620. if utils.IsErrNoRow(e) {
  621. br.Msg = "标的已被删除,请刷新页面"
  622. return
  623. }
  624. br.Msg = "获取失败"
  625. br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
  626. return
  627. }
  628. // 获取标的数据
  629. monthData, dailyData := make([]*aiPredictModel.AiPredictModelData, 0), make([]*aiPredictModel.AiPredictModelData, 0)
  630. {
  631. tableData := make([]*aiPredictModel.AiPredictModelDataItem, 0)
  632. dataOb := new(aiPredictModel.AiPredictModelData)
  633. dataCond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode)
  634. dataPars := make([]interface{}, 0)
  635. dataPars = append(dataPars, indexItem.IndexCode)
  636. list, e := dataOb.GetItemsByCondition(dataCond, dataPars, []string{}, fmt.Sprintf("%s DESC", dataOb.Cols().DataTime))
  637. if e != nil {
  638. br.Msg = "获取失败"
  639. br.ErrMsg = fmt.Sprintf("获取标的数据失败, %v", e)
  640. return
  641. }
  642. // tableData取月度数据,最多显示10条
  643. count, limit := 0, 10
  644. for _, v := range list {
  645. // 日度数据
  646. if v.Source == aiPredictModel.ModelDataSourceDaily {
  647. dailyData = append(dailyData, v)
  648. continue
  649. }
  650. // 月度数据
  651. if count < limit {
  652. tableData = append(tableData, v.Format2Item())
  653. count += 1
  654. }
  655. monthData = append(monthData, v)
  656. }
  657. resp.TableData = tableData
  658. }
  659. // 月度图表
  660. if len(monthData) > 0 {
  661. chartDetail, e := services.GetAiPredictChartDetailByData(indexItem, monthData, aiPredictModel.ModelDataSourceMonthly)
  662. if e != nil {
  663. br.Msg = "获取失败"
  664. br.ErrMsg = fmt.Sprintf("获取月度图表失败, %v", e)
  665. return
  666. }
  667. resp.ChartView = chartDetail
  668. }
  669. // 日度图表
  670. if len(dailyData) > 0 {
  671. dailyChartDetail, e := services.GetAiPredictChartDetailByData(indexItem, dailyData, aiPredictModel.ModelDataSourceDaily)
  672. if e != nil {
  673. br.Msg = "获取失败"
  674. br.ErrMsg = fmt.Sprintf("获取日度图表失败, %v", e)
  675. return
  676. }
  677. resp.DailyChartView = dailyChartDetail
  678. }
  679. br.Data = resp
  680. br.Ret = 200
  681. br.Success = true
  682. br.Msg = "获取成功"
  683. }
  684. // Save
  685. // @Title 保存标的
  686. // @Description 保存标的
  687. // @Param request body aiPredictModel.AiPredictModelIndexSaveReq true "type json string"
  688. // @Success 200 Ret=200 保存成功
  689. // @router /index/save [post]
  690. func (this *AiPredictModelIndexController) Save() {
  691. br := new(models.BaseResponse).Init()
  692. defer func() {
  693. if br.ErrMsg == "" {
  694. br.IsSendEmail = false
  695. }
  696. this.Data["json"] = br
  697. this.ServeJSON()
  698. }()
  699. sysUser := this.SysUser
  700. if sysUser == nil {
  701. br.Msg = "请登录"
  702. br.ErrMsg = "请登录,SysUser Is Empty"
  703. br.Ret = 408
  704. return
  705. }
  706. var req aiPredictModel.AiPredictModelIndexSaveReq
  707. if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
  708. br.Msg = "参数解析异常"
  709. br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
  710. return
  711. }
  712. if req.IndexId < 0 {
  713. br.Msg = "参数有误"
  714. br.ErrMsg = fmt.Sprintf("标的ID有误, IndexId: %d", req.IndexId)
  715. return
  716. }
  717. indexOb := new(aiPredictModel.AiPredictModelIndex)
  718. indexItem, e := indexOb.GetItemById(req.IndexId)
  719. if e != nil {
  720. if utils.IsErrNoRow(e) {
  721. br.Msg = "标的已被删除,请刷新页面"
  722. return
  723. }
  724. br.Msg = "操作失败"
  725. br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
  726. return
  727. }
  728. var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig
  729. if indexItem.ExtraConfig != "" {
  730. if e = json.Unmarshal([]byte(indexItem.ExtraConfig), &extraConfig); e != nil {
  731. br.Msg = "操作失败"
  732. br.ErrMsg = fmt.Sprintf("标的配置解析失败, %v", e)
  733. return
  734. }
  735. }
  736. if req.MonthlyChart != nil {
  737. extraConfig.MonthlyChart.LeftMin = req.MonthlyChart.LeftMin
  738. extraConfig.MonthlyChart.LeftMax = req.MonthlyChart.LeftMax
  739. extraConfig.MonthlyChart.Unit = req.MonthlyChart.Unit
  740. }
  741. if req.DailyChart != nil {
  742. extraConfig.DailyChart.LeftMin = req.DailyChart.LeftMin
  743. extraConfig.DailyChart.LeftMax = req.DailyChart.LeftMax
  744. extraConfig.DailyChart.Unit = req.DailyChart.Unit
  745. }
  746. configByte, _ := json.Marshal(extraConfig)
  747. indexItem.ExtraConfig = string(configByte)
  748. indexItem.ModifyTime = time.Now()
  749. updateCols := []string{indexOb.Cols().ExtraConfig, indexOb.Cols().ModifyTime}
  750. if e = indexItem.Update(updateCols); e != nil {
  751. br.Msg = "操作失败"
  752. br.ErrMsg = fmt.Sprintf("保存标的失败, %v", e)
  753. return
  754. }
  755. br.Ret = 200
  756. br.Msg = "操作成功"
  757. br.Success = true
  758. }
  759. // DashboardSave
  760. // @Title 保存看板
  761. // @Description 保存看板
  762. // @Param request body aiPredictModel.AiPredictModelDashboardSaveReq true "type json string"
  763. // @Success 200 Ret=200 新增成功
  764. // @router /index/dashboard/save [post]
  765. func (this *AiPredictModelIndexController) DashboardSave() {
  766. br := new(models.BaseResponse).Init()
  767. defer func() {
  768. if br.ErrMsg == "" {
  769. br.IsSendEmail = false
  770. }
  771. this.Data["json"] = br
  772. this.ServeJSON()
  773. }()
  774. sysUser := this.SysUser
  775. if sysUser == nil {
  776. br.Msg = "请登录"
  777. br.ErrMsg = "请登录,SysUser Is Empty"
  778. br.Ret = 408
  779. return
  780. }
  781. var req aiPredictModel.AiPredictModelDashboardSaveReq
  782. if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
  783. br.Msg = "参数解析异常"
  784. br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
  785. return
  786. }
  787. if req.IndexId <= 0 {
  788. br.Msg = "参数有误"
  789. br.ErrMsg = fmt.Sprintf("参数有误, %d", req.IndexId)
  790. return
  791. }
  792. req.DashboardName = strings.TrimSpace(req.DashboardName)
  793. indexOb := new(aiPredictModel.AiPredictModelIndex)
  794. _, e := indexOb.GetItemById(req.IndexId)
  795. if e != nil {
  796. if utils.IsErrNoRow(e) {
  797. br.Msg = "标的已被删除,请刷新页面"
  798. return
  799. }
  800. br.Msg = "操作失败"
  801. br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
  802. return
  803. }
  804. // 获取看板
  805. var isUpdate bool
  806. var updateCols []string
  807. dashboardItem := new(aiPredictModel.AiPredictModelDashboard)
  808. if req.IndexId > 0 {
  809. cond := fmt.Sprintf(" AND %s = ?", dashboardItem.Cols().AiPredictModelIndexId)
  810. pars := make([]interface{}, 0)
  811. pars = append(pars, req.IndexId)
  812. item, e := dashboardItem.GetItemByCondition(cond, pars, "")
  813. if e != nil && !utils.IsErrNoRow(e) {
  814. br.Msg = "操作失败"
  815. br.ErrMsg = fmt.Sprintf("获取标的看板失败, %v", e)
  816. return
  817. }
  818. if item != nil && item.AiPredictModelIndexId > 0 {
  819. isUpdate = true
  820. dashboardItem = item
  821. dashboardItem.DashboardName = req.DashboardName
  822. dashboardItem.ModifyTime = time.Now()
  823. updateCols = append(updateCols, dashboardItem.Cols().DashboardName, dashboardItem.Cols().ModifyTime)
  824. }
  825. }
  826. if !isUpdate {
  827. dashboardItem.AiPredictModelIndexId = req.IndexId
  828. dashboardItem.DashboardName = req.DashboardName
  829. dashboardItem.SysUserId = sysUser.AdminId
  830. dashboardItem.SysUserRealName = sysUser.RealName
  831. dashboardItem.CreateTime = time.Now()
  832. dashboardItem.ModifyTime = time.Now()
  833. }
  834. // 详情
  835. dashboardDetails := make([]*aiPredictModel.AiPredictModelDashboardDetail, 0)
  836. for i, v := range req.List {
  837. t := &aiPredictModel.AiPredictModelDashboardDetail{
  838. Type: v.Type,
  839. UniqueCode: v.UniqueCode,
  840. Sort: i + 1,
  841. CreateTime: time.Now(),
  842. ModifyTime: time.Now(),
  843. }
  844. dashboardDetails = append(dashboardDetails, t)
  845. }
  846. // 保存
  847. if e := dashboardItem.SaveIndexDashboard(dashboardItem, dashboardDetails, isUpdate, updateCols); e != nil {
  848. br.Msg = "操作失败"
  849. br.ErrMsg = fmt.Sprintf("保存标的看板失败, %v", e)
  850. return
  851. }
  852. br.Ret = 200
  853. br.Success = true
  854. br.Msg = "操作成功"
  855. }
  856. // DashboardDetail
  857. // @Title 看板详情
  858. // @Description 看板详情
  859. // @Param IndexId query int true "标的ID"
  860. // @Success 200 {object} aiPredictModel.AiPredictModelDashboardDetailResp
  861. // @router /index/dashboard/detail [get]
  862. func (this *AiPredictModelIndexController) DashboardDetail() {
  863. br := new(models.BaseResponse).Init()
  864. defer func() {
  865. if br.ErrMsg == "" {
  866. br.IsSendEmail = false
  867. }
  868. this.Data["json"] = br
  869. this.ServeJSON()
  870. }()
  871. sysUser := this.SysUser
  872. if sysUser == nil {
  873. br.Msg = "请登录"
  874. br.ErrMsg = "请登录,SysUser Is Empty"
  875. br.Ret = 408
  876. return
  877. }
  878. indexId, _ := this.GetInt("IndexId")
  879. resp := new(aiPredictModel.AiPredictModelDashboardDetailResp)
  880. indexOb := new(aiPredictModel.AiPredictModelIndex)
  881. indexItem, e := indexOb.GetItemById(indexId)
  882. if e != nil {
  883. if utils.IsErrNoRow(e) {
  884. br.Msg = "标的已被删除,请刷新页面"
  885. return
  886. }
  887. br.Msg = "获取失败"
  888. br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
  889. return
  890. }
  891. resp.CreateUserId = indexItem.SysUserId
  892. resp.CreateUserRealName = indexItem.SysUserRealName
  893. // 获取标的看板
  894. dashboardOb := new(aiPredictModel.AiPredictModelDashboard)
  895. dashboardItem := new(aiPredictModel.AiPredictModelDashboardItem)
  896. {
  897. cond := fmt.Sprintf(" AND %s = ?", dashboardOb.Cols().AiPredictModelIndexId)
  898. pars := make([]interface{}, 0)
  899. pars = append(pars, indexId)
  900. item, e := dashboardOb.GetItemByCondition(cond, pars, "")
  901. if e != nil && !utils.IsErrNoRow(e) {
  902. br.Msg = "操作失败"
  903. br.ErrMsg = fmt.Sprintf("获取标的看板失败, %v", e)
  904. return
  905. }
  906. if item != nil {
  907. dashboardItem = item.Format2Item()
  908. }
  909. }
  910. // 获取看板详情
  911. dashboardDetails := make([]*aiPredictModel.AiPredictModelDashboardDetailItem, 0)
  912. if dashboardItem.DashboardId > 0 {
  913. detailOb := new(aiPredictModel.AiPredictModelDashboardDetail)
  914. cond := fmt.Sprintf(" AND %s = ?", detailOb.Cols().AiPredictModelDashboardId)
  915. pars := make([]interface{}, 0)
  916. pars = append(pars, dashboardItem.DashboardId)
  917. list, e := detailOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", detailOb.Cols().Sort))
  918. if e != nil {
  919. br.Msg = "获取失败"
  920. br.ErrMsg = fmt.Sprintf("获取看板详情失败, %v", e)
  921. return
  922. }
  923. for _, v := range list {
  924. dashboardDetails = append(dashboardDetails, v.Format2Item())
  925. }
  926. }
  927. resp.AiPredictModelDashboardItem = dashboardItem
  928. resp.List = dashboardDetails
  929. br.Data = resp
  930. br.Ret = 200
  931. br.Success = true
  932. br.Msg = "获取成功"
  933. }
  934. // SearchByEs
  935. // @Title 图表模糊搜索(从es获取)
  936. // @Description 图表模糊搜索(从es获取)
  937. // @Param Keyword query string true "图表名称"
  938. // @Param IsShowMe query bool true "是否只看我的,true、false"
  939. // @Param Source query int true "来源,14:日度预测,15:月度预测,默认0:全部14+15"
  940. // @Success 200 {object} data_manage.ChartInfo
  941. // @router /chart/search_by_es [get]
  942. func (this *AiPredictModelIndexController) SearchByEs() {
  943. br := new(models.BaseResponse).Init()
  944. defer func() {
  945. if br.ErrMsg == "" {
  946. br.IsSendEmail = false
  947. }
  948. this.Data["json"] = br
  949. this.ServeJSON()
  950. }()
  951. sysUser := this.SysUser
  952. if sysUser == nil {
  953. br.Msg = "请登录"
  954. br.ErrMsg = "请登录,SysUser Is Empty"
  955. br.Ret = 408
  956. return
  957. }
  958. pageSize, _ := this.GetInt("PageSize")
  959. currentIndex, _ := this.GetInt("CurrentIndex")
  960. var startSize int
  961. if pageSize <= 0 {
  962. pageSize = utils.PageSize20
  963. }
  964. if currentIndex <= 0 {
  965. currentIndex = 1
  966. }
  967. startSize = paging.StartIndex(currentIndex, pageSize)
  968. keyword := this.GetString("Keyword")
  969. keyword = strings.TrimSpace(keyword)
  970. if keyword == "" {
  971. keyword = this.GetString("KeyWord")
  972. keyword = strings.TrimSpace(keyword)
  973. }
  974. //只看我的
  975. isShowMe, _ := this.GetBool("IsShowMe")
  976. showSysId := 0
  977. if isShowMe {
  978. showSysId = sysUser.AdminId
  979. }
  980. source, _ := this.GetInt("Source")
  981. sourceList := make([]int, 0)
  982. if source <= 0 {
  983. sourceList = append(sourceList, utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY, utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY)
  984. } else {
  985. sourceList = append(sourceList, source)
  986. }
  987. var searchList []*data_manage.ChartInfoMore
  988. var total int64
  989. var err error
  990. // 获取当前账号的不可见指标(AI预测的指标为标的均可见)
  991. noPermissionChartIdList := make([]int, 0)
  992. //{
  993. // obj := data_manage.EdbInfoNoPermissionAdmin{}
  994. // confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
  995. // if err != nil && !utils.IsErrNoRow(err) {
  996. // br.Msg = "获取失败"
  997. // br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
  998. // return
  999. // }
  1000. // for _, v := range confList {
  1001. // noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
  1002. // }
  1003. //}
  1004. if keyword != "" {
  1005. searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
  1006. } else {
  1007. total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
  1008. if err != nil && !utils.IsErrNoRow(err) {
  1009. br.Msg = "获取失败"
  1010. br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
  1011. return
  1012. }
  1013. }
  1014. finalList := make([]*data_manage.ChartInfoMore, 0)
  1015. if len(searchList) > 0 {
  1016. chartInfoIds := ""
  1017. chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
  1018. for _, v := range searchList {
  1019. chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
  1020. }
  1021. if chartInfoIds != "" {
  1022. chartInfoIds = strings.Trim(chartInfoIds, ",")
  1023. //判断是否需要展示英文标识
  1024. edbList, e := data_manage.GetChartEdbMappingListByChartInfoIds(chartInfoIds)
  1025. if e != nil {
  1026. br.Msg = "获取失败"
  1027. br.ErrMsg = "获取图表,指标信息失败,Err:" + e.Error()
  1028. return
  1029. }
  1030. for _, v := range edbList {
  1031. chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
  1032. }
  1033. }
  1034. for _, v := range searchList {
  1035. tmp := new(data_manage.ChartInfoMore)
  1036. tmp.ChartInfo = v.ChartInfo
  1037. // 图表数据权限
  1038. tmp.HaveOperaAuth = true
  1039. //判断是否需要展示英文标识
  1040. if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
  1041. tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
  1042. }
  1043. tmp.SearchText = v.SearchText
  1044. if tmp.SearchText == "" {
  1045. tmp.SearchText = v.ChartName
  1046. }
  1047. finalList = append(finalList, tmp)
  1048. }
  1049. }
  1050. //新增搜索词记录
  1051. {
  1052. searchKeyword := new(data_manage.SearchKeyword)
  1053. searchKeyword.KeyWord = keyword
  1054. searchKeyword.CreateTime = time.Now()
  1055. go data_manage.AddSearchKeyword(searchKeyword)
  1056. }
  1057. page := paging.GetPaging(currentIndex, pageSize, int(total))
  1058. resp := data_manage.ChartInfoListByEsResp{
  1059. Paging: page,
  1060. List: finalList,
  1061. }
  1062. br.Ret = 200
  1063. br.Success = true
  1064. br.Msg = "获取成功"
  1065. br.Data = resp
  1066. }
  1067. // ScriptPathSave
  1068. // @Title 保存标的关联脚本路径
  1069. // @Description 保存标的关联脚本路径
  1070. // @Param request body request.AiPredictModelIndexSaveScriptPathReq true "type json string"
  1071. // @Success 200 Ret=200 保存成功
  1072. // @router /index/script_path/save [post]
  1073. func (this *AiPredictModelIndexController) ScriptPathSave() {
  1074. br := new(models.BaseResponse).Init()
  1075. defer func() {
  1076. if br.ErrMsg == "" {
  1077. br.IsSendEmail = false
  1078. }
  1079. this.Data["json"] = br
  1080. this.ServeJSON()
  1081. }()
  1082. sysUser := this.SysUser
  1083. if sysUser == nil {
  1084. br.Msg = "请登录"
  1085. br.ErrMsg = "请登录,SysUser Is Empty"
  1086. br.Ret = 408
  1087. return
  1088. }
  1089. var req request.AiPredictModelIndexSaveScriptPathReq
  1090. if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
  1091. br.Msg = "参数解析异常"
  1092. br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
  1093. return
  1094. }
  1095. if req.IndexId < 0 {
  1096. br.Msg = "参数有误"
  1097. br.ErrMsg = fmt.Sprintf("标的ID有误, IndexId: %d", req.IndexId)
  1098. return
  1099. }
  1100. req.ScriptPath = strings.TrimSpace(req.ScriptPath)
  1101. if req.ScriptPath == "" {
  1102. br.Msg = "标的路径不能为空"
  1103. br.ErrMsg = fmt.Sprintf("标的路径有误, ScriptPath: %s", req.ScriptPath)
  1104. return
  1105. }
  1106. indexOb := new(aiPredictModel.AiPredictModelIndex)
  1107. indexItem, e := indexOb.GetItemById(req.IndexId)
  1108. if e != nil {
  1109. if utils.IsErrNoRow(e) {
  1110. br.Msg = "标的已被删除,请刷新页面"
  1111. return
  1112. }
  1113. br.Msg = "操作失败"
  1114. br.ErrMsg = fmt.Sprintf("获取标的失败, %v", e)
  1115. return
  1116. }
  1117. indexItem.ScriptPath = req.ScriptPath
  1118. indexItem.ModifyTime = time.Now()
  1119. updateCols := []string{indexOb.Cols().ScriptPath, indexOb.Cols().ModifyTime}
  1120. if e = indexItem.Update(updateCols); e != nil {
  1121. br.Msg = "操作失败"
  1122. br.ErrMsg = fmt.Sprintf("保存标的失败, %v", e)
  1123. return
  1124. }
  1125. br.Ret = 200
  1126. br.Msg = "操作成功"
  1127. br.Success = true
  1128. }
  1129. // GetCurrentRunningAiPredictModelIndexCount
  1130. // @Title 获取当前正在运行中的模型数量
  1131. // @Description 获取当前正在运行中的模型数量
  1132. // @Success 200 Ret=200 保存成功
  1133. // @Success 200 {object} response.CurrentRunningCountResp
  1134. // @router /index/running/count [get]
  1135. func (this *AiPredictModelIndexController) GetCurrentRunningAiPredictModelIndexCount() {
  1136. br := new(models.BaseResponse).Init()
  1137. defer func() {
  1138. if br.ErrMsg == "" {
  1139. br.IsSendEmail = false
  1140. }
  1141. this.Data["json"] = br
  1142. this.ServeJSON()
  1143. }()
  1144. sysUser := this.SysUser
  1145. if sysUser == nil {
  1146. br.Msg = "请登录"
  1147. br.ErrMsg = "请登录,SysUser Is Empty"
  1148. br.Ret = 408
  1149. return
  1150. }
  1151. // 查找当前标的是否存在待训练/训练中的模型
  1152. count, err := services.GetCurrentRunningAiPredictModelIndexCount()
  1153. if err != nil {
  1154. br.Msg = "训练失败"
  1155. br.ErrMsg = "训练失败,查找待训练的模型失败,Err:" + err.Error()
  1156. return
  1157. }
  1158. resp := response.CurrentRunningCountResp{
  1159. Total: count,
  1160. }
  1161. br.Data = resp
  1162. br.Ret = 200
  1163. br.Success = true
  1164. br.Msg = "获取成功"
  1165. }
  1166. // Run
  1167. // @Title 获取当前正在运行中的模型数量
  1168. // @Description 获取当前正在运行中的模型数量
  1169. // @Success 200 Ret=200 保存成功
  1170. // @Success 200 {object} response.CurrentRunningCountResp
  1171. // @router /index/run [post]
  1172. func (this *AiPredictModelIndexController) Run() {
  1173. br := new(models.BaseResponse).Init()
  1174. defer func() {
  1175. this.Data["json"] = br
  1176. this.ServeJSON()
  1177. }()
  1178. sysUser := this.SysUser
  1179. if sysUser == nil {
  1180. br.Msg = "请登录"
  1181. br.ErrMsg = "请登录,SysUser Is Empty"
  1182. br.Ret = 408
  1183. return
  1184. }
  1185. var req request.AiPredictModelIndexRunReq
  1186. if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
  1187. br.Msg = "参数解析异常"
  1188. br.ErrMsg = fmt.Sprintf("参数解析异常, %v", e)
  1189. return
  1190. }
  1191. classifyId := req.ClassifyId
  1192. //indexId, _ := this.GetInt("IndexId")
  1193. keyword := strings.TrimSpace(req.Keyword)
  1194. // 查找当前标的是否存在待训练/训练中的模型
  1195. count, err := services.GetCurrentRunningAiPredictModelIndexCount()
  1196. if err != nil {
  1197. br.Msg = "训练失败"
  1198. br.ErrMsg = "训练失败,查找待训练的模型失败,Err:" + err.Error()
  1199. return
  1200. }
  1201. if count > 0 {
  1202. br.Msg = "当前有模型正在训练/运行中,请勿重复训练"
  1203. br.ErrMsg = "当前有模型正在训练/运行中,请勿重复训练"
  1204. br.IsSendEmail = false
  1205. return
  1206. }
  1207. // 分类
  1208. classifyIdName := make(map[int]string)
  1209. {
  1210. classifyOb := new(aiPredictModel.AiPredictModelClassify)
  1211. list, e := classifyOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
  1212. if e != nil {
  1213. br.Msg = "获取失败"
  1214. br.ErrMsg = fmt.Sprintf("获取分类失败, %v", e)
  1215. return
  1216. }
  1217. for _, v := range list {
  1218. classifyIdName[v.AiPredictModelClassifyId] = v.ClassifyName
  1219. }
  1220. }
  1221. // 筛选条件
  1222. highlightMap := make(map[int]string)
  1223. indexOb := new(aiPredictModel.AiPredictModelIndex)
  1224. var cond string
  1225. var pars []interface{}
  1226. cond += fmt.Sprintf(` AND %s NOT IN (?) AND %s NOT IN (?) `, indexOb.Cols().TrainStatus, indexOb.Cols().RunStatus)
  1227. pars = append(pars, []string{aiPredictModel.TrainStatusWaiting, aiPredictModel.TrainStatusTraining}, []string{aiPredictModel.RunStatusWaiting, aiPredictModel.RunStatusRunning})
  1228. if req.SelectAll {
  1229. // 如果列表全选
  1230. if classifyId > 0 {
  1231. cond += fmt.Sprintf(" AND %s = ?", indexOb.Cols().ClassifyId)
  1232. pars = append(pars, classifyId)
  1233. }
  1234. // 有关键词从es中搜索
  1235. if keyword != "" {
  1236. // 使用scroll API获取所有匹配的数据
  1237. list, e := getAllSearchDataSource(keyword, utils.DATA_SOURCE_AI_PREDICT_MODEL, 0)
  1238. if e != nil {
  1239. br.Msg = "获取失败"
  1240. br.ErrMsg = fmt.Sprintf("获取失败,Err:%v", e)
  1241. return
  1242. }
  1243. if len(list) == 0 {
  1244. br.Msg = "没有找到可以运行的标的"
  1245. br.IsSendEmail = false
  1246. return
  1247. }
  1248. var ids []int
  1249. for _, v := range list {
  1250. ids = append(ids, v.PrimaryId)
  1251. highlightMap[v.PrimaryId] = v.SearchText
  1252. }
  1253. cond += fmt.Sprintf(` AND %s IN (%s)`, indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
  1254. pars = append(pars, ids)
  1255. }
  1256. // 不勾选的标的
  1257. if len(req.NotIndexIdList) > 0 {
  1258. var ids []int
  1259. for _, v := range req.NotIndexIdList {
  1260. ids = append(ids, v)
  1261. }
  1262. cond += fmt.Sprintf(` AND %s NOT IN (%s)`, indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
  1263. pars = append(pars, ids)
  1264. }
  1265. } else {
  1266. // 如果不是列表全选
  1267. if len(req.IndexIdList) <= 0 {
  1268. br.Msg = `请选择标的`
  1269. br.IsSendEmail = false
  1270. return
  1271. }
  1272. var ids []int
  1273. for _, v := range req.IndexIdList {
  1274. ids = append(ids, v)
  1275. }
  1276. cond += fmt.Sprintf(` AND %s IN (%s)`, indexOb.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
  1277. pars = append(pars, ids)
  1278. }
  1279. // 获取列表
  1280. list, e := indexOb.GetItemsByCondition(cond, pars, []string{`ai_predict_model_index_id`}, "")
  1281. if e != nil {
  1282. br.Msg = "获取失败"
  1283. br.ErrMsg = fmt.Sprintf("获取列表失败, %v", e)
  1284. return
  1285. }
  1286. indexIdList := make([]int, 0)
  1287. for _, v := range list {
  1288. indexIdList = append(indexIdList, v.AiPredictModelIndexId)
  1289. }
  1290. if len(indexIdList) <= 0 {
  1291. br.Msg = "没有找到可以运行的标的"
  1292. br.IsSendEmail = false
  1293. return
  1294. }
  1295. err = indexOb.UpdateRunStatusByIdList(indexIdList)
  1296. if err != nil {
  1297. br.Msg = "运行失败"
  1298. br.ErrMsg = fmt.Sprintf("运行失败, %v", e)
  1299. return
  1300. }
  1301. // 加入模型运行任务中
  1302. go services.AddAiModelRunTask(indexIdList, this.SysUser)
  1303. br.Data = indexIdList
  1304. br.Ret = 200
  1305. br.Success = true
  1306. br.Msg = "获取成功"
  1307. }
  1308. // getAllSearchDataSource
  1309. // @Description: 根据条件获取ES中的所有数据
  1310. // @author: Roc
  1311. // @datetime 2025-05-08 11:15:27
  1312. // @param keyword string
  1313. // @param source int
  1314. // @param subSource int
  1315. // @return list []*dataSourceModel.SearchDataSourceItem
  1316. // @return err error
  1317. func getAllSearchDataSource(keyword string, source, subSource int) (list []*dataSourceModel.SearchDataSourceItem, err error) {
  1318. dataLimit := 1000 // 每页获取的数据量
  1319. var scrollId string
  1320. // 使用scroll API获取所有匹配的数据
  1321. scrollId, list, e := elastic.SearchDataSourceIndexWithScroll(utils.EsDataSourceIndexName, keyword, source, subSource, []int{}, []int{}, []string{}, dataLimit)
  1322. if e != nil {
  1323. err = fmt.Errorf("ES-搜索列表失败, %v", e)
  1324. return
  1325. }
  1326. // 最终清理用的 scrollId 放到一个指针里,保证 defer 拿到最新值
  1327. finalScrollId := &scrollId
  1328. defer func() {
  1329. // 清除滚动查询的缓存
  1330. if *finalScrollId != "" {
  1331. elastic.ClearScrollDataSourceIndex(*finalScrollId)
  1332. }
  1333. }()
  1334. // 如果scrollId不为空,说明还有更多数据,继续获取
  1335. for scrollId != "" {
  1336. nextScrollId, nextList, e := elastic.ScrollDataSourceIndex(scrollId)
  1337. if e != nil {
  1338. err = fmt.Errorf("ES-获取更多数据失败, %v", e)
  1339. return
  1340. }
  1341. // 如果没有更多数据,则退出循环
  1342. if len(nextList) <= 0 {
  1343. break
  1344. }
  1345. list = append(list, nextList...)
  1346. if nextScrollId != `` {
  1347. scrollId = nextScrollId
  1348. *finalScrollId = scrollId // 更新 finalScrollId 的指向内容
  1349. }
  1350. }
  1351. return
  1352. }