chart_info.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. package data
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "hongze/hongze_chart_lib/models"
  8. "hongze/hongze_chart_lib/models/data_manage"
  9. "hongze/hongze_chart_lib/services/alarm_msg"
  10. "hongze/hongze_chart_lib/utils"
  11. "math"
  12. "sort"
  13. "time"
  14. )
  15. // ChartInfoRefreshV1 图表刷新
  16. func ChartInfoRefreshV1(chartInfoId int) (err error) {
  17. var errmsg string
  18. defer func() {
  19. if err != nil {
  20. go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "ChartInfoRefresh:"+errmsg, utils.EmailSendToUsers)
  21. fmt.Println("ChartInfoRefresh Err:" + errmsg)
  22. }
  23. }()
  24. baseEdbInfoArr, calculateInfoArr, err := data_manage.GetChartInfoRefreshData(chartInfoId)
  25. if err != nil {
  26. errmsg = "获取需要刷新的指标失败:Err:" + err.Error()
  27. return
  28. }
  29. var startDate string
  30. newBaseEdbInfoArr := make([]*data_manage.EdbInfo, 0)
  31. baseMap := make(map[int]*data_manage.EdbInfo)
  32. for _, bv := range baseEdbInfoArr {
  33. // 如果不是普通指标,那么过滤
  34. if bv.EdbInfoType != 0 {
  35. continue
  36. }
  37. if _, ok := baseMap[bv.EdbInfoId]; !ok {
  38. newBaseEdbInfoArr = append(newBaseEdbInfoArr, bv)
  39. }
  40. baseMap[bv.EdbInfoId] = bv
  41. }
  42. fmt.Println("calculateInfoArr:", len(calculateInfoArr))
  43. newCalculateInfoArr := make([]*data_manage.EdbInfo, 0)
  44. calculateMap := make(map[int]*data_manage.EdbInfo)
  45. var calculateArr []int
  46. for _, bv := range calculateInfoArr {
  47. if _, ok := calculateMap[bv.EdbInfoId]; !ok {
  48. newCalculateInfoArr = append(newCalculateInfoArr, bv)
  49. calculateArr = append(calculateArr, bv.EdbInfoId)
  50. }
  51. calculateMap[bv.EdbInfoId] = bv
  52. }
  53. sort.Ints(calculateArr)
  54. for _, bv := range newBaseEdbInfoArr {
  55. source := bv.Source
  56. edbInfoId := bv.EdbInfoId
  57. edbCode := bv.EdbCode
  58. startDate = bv.StartDate
  59. frequency := bv.Frequency
  60. if bv.StartDate == "0000-00-00" {
  61. continue
  62. }
  63. sTime, err := time.Parse(utils.FormatDate, bv.EndDate)
  64. if err != nil {
  65. return err
  66. }
  67. var limitDay int
  68. startDate := ""
  69. switch frequency {
  70. case "日度":
  71. limitDay = utils.DATA_REFRESH
  72. case "周度":
  73. limitDay = utils.DATA_REFRESH * 7
  74. case "月度":
  75. limitDay = utils.DATA_REFRESH * 30
  76. case "季度":
  77. limitDay = utils.DATA_REFRESH * 90
  78. case "年度":
  79. limitDay = utils.DATA_REFRESH * 365
  80. default:
  81. limitDay = utils.DATA_REFRESH
  82. }
  83. startDate = sTime.AddDate(0, 0, -limitDay).Format(utils.FormatDate)
  84. fmt.Println("source:", source)
  85. respItem, err := RefreshEdbData(edbInfoId, source, edbCode, startDate)
  86. if err != nil {
  87. errmsg = errors.New("RefreshEdbData Err:" + err.Error()).Error()
  88. return err
  89. }
  90. if respItem.Ret != 200 {
  91. errmsg = errors.New(respItem.ErrMsg + ";EdbCode:" + edbCode).Error()
  92. return err
  93. }
  94. //maxAndMinItem, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
  95. //if err != nil {
  96. // return err
  97. //}
  98. //if maxAndMinItem != nil {
  99. // err = data_manage.ModifyEdbInfoMaxAndMinInfo(edbInfoId, maxAndMinItem)
  100. // if err != nil {
  101. // return err
  102. // }
  103. //}
  104. }
  105. //刷新相关计算指标
  106. for _, v := range calculateArr {
  107. edbInfo := calculateMap[v]
  108. if edbInfo == nil {
  109. return err
  110. }
  111. startDate = edbInfo.StartDate
  112. source := edbInfo.Source
  113. if source == utils.DATA_SOURCE_CALCULATE {
  114. startDate = edbInfo.StartDate
  115. sTime, err := time.Parse(utils.FormatDate, edbInfo.EndDate)
  116. if err != nil {
  117. return err
  118. }
  119. startDate = sTime.Format(utils.FormatDate)
  120. }
  121. result, err := RefreshEdbCalculateData(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
  122. if err != nil {
  123. fmt.Println(v, "RefreshEdbCalculateData err", time.Now())
  124. errmsg = "RefreshEdbCalculateData Err:" + err.Error()
  125. return err
  126. }
  127. if result.Ret != 200 {
  128. fmt.Println(v, "RefreshEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
  129. errmsg = fmt.Sprint(v, "RefreshEdbCalculateData err;msg:", result.Msg, ";errMsg:", result.ErrMsg)
  130. return fmt.Errorf("刷新失败" + errmsg)
  131. }
  132. fmt.Println("end calculateArr:", v, time.Now())
  133. }
  134. return err
  135. }
  136. // GetFrequencyEn 获取频度的英文版
  137. func GetFrequencyEn(frequency string) (frequencyEn string) {
  138. switch frequency {
  139. case "日度":
  140. frequencyEn = "day"
  141. return
  142. case "周度":
  143. frequencyEn = "week"
  144. return
  145. case "旬度":
  146. frequencyEn = "ten days"
  147. return
  148. case "月度":
  149. frequencyEn = "month"
  150. return
  151. case "季度":
  152. frequencyEn = "quarter"
  153. return
  154. case "年度":
  155. frequencyEn = "year"
  156. return
  157. }
  158. return
  159. }
  160. func GetLeadUnitEn(unit string) (unitEn string) {
  161. switch unit {
  162. case "天":
  163. unitEn = "day"
  164. return
  165. case "周":
  166. unitEn = "week"
  167. return
  168. case "月":
  169. unitEn = "month"
  170. return
  171. case "季":
  172. unitEn = "quarter"
  173. return
  174. case "年":
  175. unitEn = "year"
  176. return
  177. }
  178. return
  179. }
  180. // GetChartEdbData 获取图表的指标数据
  181. func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, extraConfigStr string) (edbList []*models.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []models.YData, dataResp interface{}, err error, errMsg string) {
  182. edbList = make([]*models.ChartEdbInfoMapping, 0)
  183. // 指标对应的所有数据
  184. xEdbIdValue = make([]int, 0)
  185. yDataList = make([]models.YData, 0)
  186. var extraConfig interface{}
  187. switch chartType {
  188. case 7: // 柱形图
  189. var barConfig data_manage.BarChartInfoReq
  190. if extraConfigStr == `` {
  191. errMsg = "柱方图未配置"
  192. err = errors.New(errMsg)
  193. return
  194. }
  195. err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
  196. if err != nil {
  197. errMsg = "柱方图配置异常"
  198. err = errors.New(errMsg)
  199. return
  200. }
  201. extraConfig = barConfig
  202. case 10: // 截面散点图
  203. var tmpExtraConfig data_manage.SectionScatterReq
  204. if extraConfigStr == `` {
  205. errMsg = "截面散点图未配置"
  206. err = errors.New(errMsg)
  207. return
  208. }
  209. err = json.Unmarshal([]byte(extraConfigStr), &tmpExtraConfig)
  210. if err != nil {
  211. errMsg = "截面散点配置异常"
  212. err = errors.New(errMsg)
  213. return
  214. }
  215. extraConfig = tmpExtraConfig
  216. default:
  217. xEdbIdValue = make([]int, 0)
  218. yDataList = make([]models.YData, 0)
  219. }
  220. // 指标对应的所有数据
  221. edbDataListMap, edbList, err := getEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
  222. if err != nil {
  223. return
  224. }
  225. // 特殊图形数据处理
  226. switch chartType {
  227. case 7: // 柱形图
  228. barChartConf := extraConfig.(data_manage.BarChartInfoReq)
  229. xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
  230. for _, v := range edbList {
  231. // 指标别名
  232. if barChartConf.EdbInfoIdList != nil && len(barChartConf.EdbInfoIdList) > 0 {
  233. for _, reqEdb := range barChartConf.EdbInfoIdList {
  234. if v.EdbInfoId == reqEdb.EdbInfoId {
  235. v.EdbAliasName = reqEdb.Name
  236. }
  237. }
  238. }
  239. }
  240. case 10: // 截面散点图
  241. sectionScatterConf := extraConfig.(data_manage.SectionScatterReq)
  242. xEdbIdValue, dataResp, err = GetSectionScatterChartData(mappingList, edbDataListMap, sectionScatterConf)
  243. // 这个数据没有必要返回给前端
  244. for _, v := range edbList {
  245. v.DataList = nil
  246. }
  247. }
  248. return
  249. }
  250. // getEdbDataMapList 获取指标最后的基础数据
  251. func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping) (edbDataListMap map[int][]*models.EdbDataList, edbList []*models.ChartEdbInfoMapping, err error) {
  252. // 指标对应的所有数据
  253. edbDataListMap = make(map[int][]*models.EdbDataList)
  254. for _, v := range mappingList {
  255. //fmt.Println("v:", v.EdbInfoId)
  256. item := new(models.ChartEdbInfoMapping)
  257. item.EdbInfoId = v.EdbInfoId
  258. item.SourceName = v.SourceName
  259. item.Source = v.Source
  260. item.EdbCode = v.EdbCode
  261. item.EdbName = v.EdbName
  262. item.EdbType = v.EdbType
  263. item.EdbNameEn = v.EdbNameEn
  264. item.Frequency = v.Frequency
  265. item.FrequencyEn = GetFrequencyEn(v.Frequency)
  266. if v.Unit != `无` {
  267. item.Unit = v.Unit
  268. }
  269. item.UnitEn = v.UnitEn
  270. item.StartDate = v.StartDate
  271. item.EndDate = v.EndDate
  272. item.ModifyTime = v.ModifyTime
  273. item.EdbInfoCategoryType = v.EdbInfoCategoryType
  274. item.PredictChartColor = v.PredictChartColor
  275. if chartInfoId <= 0 {
  276. item.IsAxis = 1
  277. item.LeadValue = 0
  278. item.LeadUnit = ""
  279. //item.ChartEdbMappingId = 0
  280. item.ChartInfoId = 0
  281. item.IsOrder = false
  282. item.EdbInfoType = 1
  283. item.ChartStyle = ""
  284. item.ChartColor = ""
  285. item.ChartWidth = 0
  286. item.MaxData = v.MaxValue
  287. item.MinData = v.MinValue
  288. } else {
  289. item.IsAxis = v.IsAxis
  290. item.EdbInfoType = v.EdbInfoType
  291. item.LeadValue = v.LeadValue
  292. item.LeadUnit = v.LeadUnit
  293. item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
  294. //item.ChartEdbMappingId = v.ChartEdbMappingId
  295. item.ChartInfoId = v.ChartInfoId
  296. item.ChartStyle = v.ChartStyle
  297. item.ChartColor = v.ChartColor
  298. item.ChartWidth = v.ChartWidth
  299. item.IsOrder = v.IsOrder
  300. item.MaxData = v.MaxData
  301. item.MinData = v.MinData
  302. }
  303. item.LatestValue = v.LatestValue
  304. item.LatestDate = v.LatestDate
  305. item.UniqueCode = v.UniqueCode
  306. var startDateReal string
  307. var diffSeconds int64
  308. if chartType == 2 { //季节性图
  309. startDateReal = startDate
  310. } else {
  311. if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
  312. var startTimeRealTemp time.Time
  313. startDateParse, _ := time.Parse(utils.FormatDate, startDate)
  314. switch v.LeadUnit {
  315. case "天":
  316. startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
  317. case "月":
  318. startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
  319. case "季":
  320. startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
  321. case "周":
  322. startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
  323. case "年":
  324. startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
  325. }
  326. if startTimeRealTemp.Before(startDateParse) {
  327. startDateReal = startTimeRealTemp.Format(utils.FormatDate)
  328. diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
  329. } else {
  330. startDateReal = startDate
  331. diffSeconds = 0
  332. }
  333. // 预测指标的开始日期也要偏移
  334. {
  335. day, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, startDate, startDateReal)
  336. if tmpErr != nil {
  337. err = tmpErr
  338. return
  339. }
  340. latestDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, v.LatestDate, time.Local)
  341. if tmpErr != nil {
  342. err = tmpErr
  343. return
  344. }
  345. item.LatestDate = latestDateTime.AddDate(0, 0, day).Format(utils.FormatDate)
  346. }
  347. } else {
  348. startDateReal = startDate
  349. }
  350. }
  351. //fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
  352. calendarPreYear := 0
  353. if calendar == "农历" {
  354. newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
  355. if err != nil {
  356. fmt.Println("time.Parse:" + err.Error())
  357. }
  358. calendarPreYear = newStartDateReal.Year() - 1
  359. newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
  360. startDateReal = newStartDateReal.Format(utils.FormatDate)
  361. }
  362. dataList := make([]*models.EdbDataList, 0)
  363. //fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
  364. switch v.EdbInfoCategoryType {
  365. case 0:
  366. dataList, err = models.GetEdbDataList(v.Source, v.EdbInfoId, startDateReal, endDate)
  367. case 1:
  368. _, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, startDateReal, endDate, false)
  369. default:
  370. err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoCategoryType))
  371. }
  372. if err != nil {
  373. return
  374. }
  375. edbDataListMap[v.EdbInfoId] = dataList
  376. if diffSeconds != 0 && v.EdbInfoType == 0 {
  377. dataListLen := len(dataList)
  378. for i := 0; i < dataListLen; i++ {
  379. dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
  380. }
  381. }
  382. if chartType == 2 {
  383. latestDateStr := v.LatestDate //实际数据的截止日期
  384. latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
  385. if tmpErr != nil {
  386. err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
  387. return
  388. }
  389. latestDateYear := latestDate.Year() //实际数据截止年份
  390. if calendar == "农历" {
  391. if len(dataList) <= 0 {
  392. result := new(models.EdbDataResult)
  393. item.DataList = result
  394. } else {
  395. result, tmpErr := models.AddCalculateQuarterV5(dataList)
  396. if tmpErr != nil {
  397. err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
  398. return
  399. }
  400. // 处理季节图的截止日期
  401. for k, edbDataItems := range result.List {
  402. var cuttingDataTimestamp int64
  403. // 切割的日期时间字符串
  404. cuttingDataTimeStr := latestDate.AddDate(0, 0, edbDataItems.BetweenDay).Format(utils.FormatDate)
  405. //如果等于最后的实际日期,那么遍历找到该日期对应的时间戳,并将其赋值为 切割时间戳
  406. if edbDataItems.Year >= latestDateYear {
  407. for _, tmpData := range edbDataItems.Items {
  408. if tmpData.DataTime == cuttingDataTimeStr {
  409. cuttingDataTimestamp = tmpData.DataTimestamp
  410. break
  411. }
  412. }
  413. }
  414. edbDataItems.CuttingDataTimestamp = cuttingDataTimestamp
  415. result.List[k] = edbDataItems
  416. }
  417. if result.List[0].Year != calendarPreYear {
  418. itemList := make([]*models.EdbDataList, 0)
  419. items := new(models.EdbDataItems)
  420. //items.Year = calendarPreYear
  421. items.Items = itemList
  422. newResult := new(models.EdbDataResult)
  423. newResult.List = append(newResult.List, items)
  424. newResult.List = append(newResult.List, result.List...)
  425. item.DataList = newResult
  426. } else {
  427. item.DataList = result
  428. }
  429. }
  430. } else {
  431. currentYear := time.Now().Year()
  432. quarterDataList := make([]*models.QuarterData, 0)
  433. quarterMap := make(map[int][]*models.EdbDataList)
  434. var quarterArr []int
  435. for _, v := range dataList {
  436. itemDate, tmpErr := time.Parse(utils.FormatDate, v.DataTime)
  437. if tmpErr != nil {
  438. err = errors.New("季度指标日期转换,Err:" + tmpErr.Error() + ";DataTime:" + v.DataTime)
  439. return
  440. }
  441. year := itemDate.Year()
  442. newItemDate := itemDate.AddDate(currentYear-year, 0, 0)
  443. timestamp := newItemDate.UnixNano() / 1e6
  444. v.DataTimestamp = timestamp
  445. if findVal, ok := quarterMap[year]; !ok {
  446. quarterArr = append(quarterArr, year)
  447. findVal = append(findVal, v)
  448. quarterMap[year] = findVal
  449. } else {
  450. findVal = append(findVal, v)
  451. quarterMap[year] = findVal
  452. }
  453. }
  454. for _, v := range quarterArr {
  455. itemList := quarterMap[v]
  456. quarterItem := new(models.QuarterData)
  457. quarterItem.Year = v
  458. quarterItem.DataList = itemList
  459. //如果等于最后的实际日期,那么将切割时间戳记录
  460. if v == latestDateYear {
  461. var cuttingDataTimestamp int64
  462. for _, tmpData := range itemList {
  463. if tmpData.DataTime == latestDateStr {
  464. cuttingDataTimestamp = tmpData.DataTimestamp
  465. break
  466. }
  467. }
  468. quarterItem.CuttingDataTimestamp = cuttingDataTimestamp
  469. } else if v > latestDateYear {
  470. //如果大于最后的实际日期,那么第一个点就是切割的时间戳
  471. if len(itemList) > 0 {
  472. quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
  473. }
  474. }
  475. quarterDataList = append(quarterDataList, quarterItem)
  476. }
  477. item.DataList = quarterDataList
  478. }
  479. } else if chartType == 7 { //柱方图
  480. //item.DataList = dataList
  481. } else {
  482. item.DataList = dataList
  483. }
  484. edbList = append(edbList, item)
  485. }
  486. return
  487. }
  488. // BarChartData 柱方图的数据处理
  489. func BarChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (edbIdList []int, yDataList []models.YData, err error) {
  490. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  491. edbDataMap := make(map[int]map[string]float64)
  492. for edbInfoId, edbDataList := range edbDataListMap {
  493. edbDateData := make(map[string]float64)
  494. for _, edbData := range edbDataList {
  495. edbDateData[edbData.DataTime] = edbData.Value
  496. }
  497. edbDataMap[edbInfoId] = edbDateData
  498. }
  499. // edbIdList 指标展示顺序;x轴的指标顺序
  500. edbIdList = make([]int, 0)
  501. //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
  502. dateData := make(map[int]float64)
  503. if barChartInfoSort.Sort == 0 {
  504. for _, v := range mappingList {
  505. edbIdList = append(edbIdList, v.EdbInfoId)
  506. }
  507. } else {
  508. lenBarChartInfoDateList := len(barChartInfoDateList)
  509. if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
  510. err = errors.New("排序日期异常")
  511. return
  512. }
  513. notDataEdbIdList := make([]int, 0) //没有数据的指标id
  514. // 日期配置
  515. barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
  516. for edbInfoId, dataList := range edbDataListMap {
  517. if len(dataList) <= 0 {
  518. // 没有数据的指标id
  519. notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
  520. continue
  521. }
  522. findDate := barChartInfoDate.Date
  523. switch barChartInfoDate.Type {
  524. case 1: //最新值
  525. findDate = dataList[len(dataList)-1].DataTime
  526. case 2: //近期几天
  527. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  528. if tmpErr != nil {
  529. err = tmpErr
  530. return
  531. }
  532. findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  533. lenData := len(dataList) - 1
  534. for i := lenData; i >= 0; i-- {
  535. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  536. if tmpErr != nil {
  537. err = tmpErr
  538. return
  539. }
  540. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  541. findDate = dataList[i].DataTime
  542. break
  543. }
  544. }
  545. case 3: // 固定日期
  546. //最早的日期
  547. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  548. if tmpErr != nil {
  549. err = tmpErr
  550. return
  551. }
  552. //寻找固定日期的数据
  553. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  554. if tmpErr != nil {
  555. err = tmpErr
  556. return
  557. }
  558. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  559. tmpDate := tmpDateTime.Format(utils.FormatDate)
  560. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  561. findDate = tmpDate
  562. break
  563. }
  564. }
  565. default:
  566. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  567. return
  568. }
  569. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  570. dateData[edbInfoId] = tmpValue
  571. } else {
  572. // 没有数据的指标id
  573. notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
  574. }
  575. }
  576. //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
  577. // 排序
  578. dateDataSort := utils.NewMapSorter(dateData)
  579. sort.Sort(dateDataSort)
  580. if barChartInfoSort.Sort == 1 {
  581. // 先将没有数据的指标id放在最前面
  582. if len(notDataEdbIdList) > 0 {
  583. edbIdList = append(edbIdList, notDataEdbIdList...)
  584. }
  585. for _, v := range dateDataSort {
  586. edbIdList = append(edbIdList, v.Key)
  587. }
  588. } else {
  589. for i := len(dateDataSort) - 1; i >= 0; i-- {
  590. edbIdList = append(edbIdList, dateDataSort[i].Key)
  591. }
  592. // 再将没有数据的指标id放在最后面
  593. if len(notDataEdbIdList) > 0 {
  594. edbIdList = append(edbIdList, notDataEdbIdList...)
  595. }
  596. }
  597. }
  598. yDataList = make([]models.YData, 0) //y轴的数据列表
  599. for _, barChartInfoDate := range barChartInfoDateList {
  600. var maxDate time.Time
  601. findDataList := make([]float64, 0) // 当前日期的数据值
  602. for _, edbInfoId := range edbIdList {
  603. findDate := barChartInfoDate.Date //需要的日期值
  604. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  605. if len(dataList) <= 0 {
  606. // 没有数据的指标id
  607. findDataList = append(findDataList, 0)
  608. continue
  609. }
  610. switch barChartInfoDate.Type {
  611. case 1: //最新值
  612. dataList := edbDataListMap[edbInfoId]
  613. findDate = dataList[len(dataList)-1].DataTime
  614. case 2: //近期几天
  615. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  616. if tmpErr != nil {
  617. err = tmpErr
  618. return
  619. }
  620. findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  621. lenData := len(dataList) - 1
  622. for i := lenData; i >= 0; i-- {
  623. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  624. if tmpErr != nil {
  625. err = tmpErr
  626. return
  627. }
  628. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  629. findDate = dataList[i].DataTime
  630. break
  631. }
  632. }
  633. case 3: // 固定日期
  634. //最早的日期
  635. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  636. if tmpErr != nil {
  637. err = tmpErr
  638. return
  639. }
  640. //寻找固定日期的数据
  641. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  642. if tmpErr != nil {
  643. err = tmpErr
  644. return
  645. }
  646. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  647. tmpDate := tmpDateTime.Format(utils.FormatDate)
  648. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  649. findDate = tmpDate
  650. break
  651. }
  652. }
  653. default:
  654. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  655. return
  656. }
  657. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  658. if maxDate.IsZero() {
  659. maxDate = findDateTime
  660. } else {
  661. if findDateTime.After(maxDate) {
  662. maxDate = findDateTime
  663. }
  664. }
  665. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  666. findDataList = append(findDataList, tmpValue)
  667. } else {
  668. findDataList = append(findDataList, 0)
  669. }
  670. }
  671. yDate := "0000-00-00"
  672. if !maxDate.IsZero() {
  673. yDate = maxDate.Format(utils.FormatDate)
  674. }
  675. yDataList = append(yDataList, models.YData{
  676. Date: yDate,
  677. Value: findDataList,
  678. Color: barChartInfoDate.Color,
  679. Name: barChartInfoDate.Name,
  680. })
  681. }
  682. return
  683. }
  684. // ChartInfoRefreshV2 图表刷新
  685. // @author Roc
  686. // @datetime 2022-09-16 10:15:38
  687. // @description 将原来自己写的一套获取所有关联指标,然后刷新指标逻辑 改成 只获取使用的指标id,然后遍历去调用“指标刷新服务”
  688. func ChartInfoRefreshV2(chartInfoId int) (err error) {
  689. var errmsg string
  690. defer func() {
  691. if err != nil {
  692. go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errmsg, 3)
  693. //go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "ChartInfoRefresh:"+errmsg, utils.EmailSendToUsers)
  694. fmt.Println("ChartInfoRefresh Err:" + errmsg)
  695. }
  696. }()
  697. edbMappingList, err := data_manage.GetChartEdbMappingList(chartInfoId)
  698. if err != nil {
  699. errmsg = "获取需要刷新的指标失败:Err:" + err.Error()
  700. return
  701. }
  702. edbIdList := make([]int, 0)
  703. for _, v := range edbMappingList {
  704. edbIdList = append(edbIdList, v.EdbInfoId)
  705. }
  706. // 批量刷新
  707. err, errmsg = EdbInfoRefreshAllFromBase(edbIdList, false)
  708. if err != nil {
  709. return
  710. }
  711. return
  712. }
  713. // GetSectionScatterChartData 柱方图的数据处理
  714. func GetSectionScatterChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, extraConfig data_manage.SectionScatterReq) (edbIdList []int, chartDataResp data_manage.SectionScatterInfoResp, err error) {
  715. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  716. edbDataMap := make(map[int]map[string]float64)
  717. for edbInfoId, edbDataList := range edbDataListMap {
  718. edbDateData := make(map[string]float64)
  719. for _, edbData := range edbDataList {
  720. edbDateData[edbData.DataTime] = edbData.Value
  721. }
  722. edbDataMap[edbInfoId] = edbDateData
  723. }
  724. // edbIdList 指标展示顺序;x轴的指标顺序
  725. edbIdList = make([]int, 0)
  726. edbMappingMap := make(map[int]*models.ChartEdbInfoMapping)
  727. for _, v := range mappingList {
  728. edbIdList = append(edbIdList, v.EdbInfoId)
  729. edbMappingMap[v.EdbInfoId] = v
  730. }
  731. //SectionScatterSeriesInfoResp
  732. dataListResp := make([]data_manage.SectionScatterSeriesItemResp, 0) //y轴的数据列表
  733. for _, seriesItem := range extraConfig.SeriesList {
  734. var maxDate time.Time
  735. // 系列中的指标数据
  736. tmpSeriesEdbInfoList := make([]data_manage.SectionScatterEdbItemResp, 0)
  737. var minXVal, maxXVal, minYVal, maxYVal float64
  738. for _, edbConf := range seriesItem.EdbInfoList {
  739. tmpItem := data_manage.SectionScatterEdbItemResp{
  740. IsShow: edbConf.IsShow,
  741. Name: edbConf.Name,
  742. NameEn: edbConf.NameEn,
  743. } //单个坐标点的数据
  744. //X轴的数据
  745. {
  746. edbInfoId := edbConf.XEdbInfoId //X轴的指标
  747. edbMappingInfo, ok := edbMappingMap[edbInfoId]
  748. if !ok {
  749. continue
  750. }
  751. findDate := edbConf.XDate //需要的日期值
  752. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  753. if len(dataList) <= 0 {
  754. // 没有数据的指标id
  755. //findDataList = append(findDataList, 0)
  756. continue
  757. }
  758. tmpItem.XEdbInfoId = edbInfoId
  759. tmpItem.XName = edbMappingInfo.EdbName
  760. tmpItem.XNameEn = edbMappingInfo.EdbNameEn
  761. switch edbConf.XDateType {
  762. case 1: //最新值
  763. dataList := edbDataListMap[edbInfoId]
  764. findDate = dataList[len(dataList)-1].DataTime
  765. case 2: //近期几天
  766. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  767. if tmpErr != nil {
  768. err = tmpErr
  769. return
  770. }
  771. findDateTime = findDateTime.AddDate(0, 0, -edbConf.XDateValue)
  772. lenData := len(dataList) - 1
  773. for i := lenData; i >= 0; i-- {
  774. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  775. if tmpErr != nil {
  776. err = tmpErr
  777. return
  778. }
  779. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  780. findDate = dataList[i].DataTime
  781. break
  782. }
  783. }
  784. case 3: // 固定日期
  785. //最早的日期
  786. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  787. if tmpErr != nil {
  788. err = tmpErr
  789. return
  790. }
  791. //寻找固定日期的数据
  792. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.XDate, time.Local)
  793. if tmpErr != nil {
  794. err = tmpErr
  795. return
  796. }
  797. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  798. tmpDate := tmpDateTime.Format(utils.FormatDate)
  799. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  800. findDate = tmpDate
  801. break
  802. }
  803. }
  804. default:
  805. err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.XDate))
  806. return
  807. }
  808. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  809. if maxDate.IsZero() {
  810. maxDate = findDateTime
  811. } else {
  812. if findDateTime.After(maxDate) {
  813. maxDate = findDateTime
  814. }
  815. }
  816. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  817. tmpItem.XDate = findDate
  818. tmpItem.XValue = tmpValue
  819. } else {
  820. continue
  821. }
  822. }
  823. //Y轴的数据
  824. {
  825. edbInfoId := edbConf.YEdbInfoId //Y轴的指标
  826. edbMappingInfo, ok := edbMappingMap[edbInfoId]
  827. if !ok {
  828. continue
  829. }
  830. findDate := edbConf.YDate //需要的日期值
  831. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  832. if len(dataList) <= 0 {
  833. // 没有数据的指标id
  834. //findDataList = append(findDataList, 0)
  835. continue
  836. }
  837. tmpItem.YEdbInfoId = edbInfoId
  838. tmpItem.YName = edbMappingInfo.EdbName
  839. tmpItem.YNameEn = edbMappingInfo.EdbNameEn
  840. switch edbConf.YDateType {
  841. case 1: //最新值
  842. dataList := edbDataListMap[edbInfoId]
  843. findDate = dataList[len(dataList)-1].DataTime
  844. case 2: //近期几天
  845. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  846. if tmpErr != nil {
  847. err = tmpErr
  848. return
  849. }
  850. findDateTime = findDateTime.AddDate(0, 0, -edbConf.YDateValue)
  851. lenData := len(dataList) - 1
  852. for i := lenData; i >= 0; i-- {
  853. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  854. if tmpErr != nil {
  855. err = tmpErr
  856. return
  857. }
  858. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  859. findDate = dataList[i].DataTime
  860. break
  861. }
  862. }
  863. case 3: // 固定日期
  864. //最早的日期
  865. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  866. if tmpErr != nil {
  867. err = tmpErr
  868. return
  869. }
  870. //寻找固定日期的数据
  871. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.YDate, time.Local)
  872. if tmpErr != nil {
  873. err = tmpErr
  874. return
  875. }
  876. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  877. tmpDate := tmpDateTime.Format(utils.FormatDate)
  878. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  879. findDate = tmpDate
  880. break
  881. }
  882. }
  883. default:
  884. err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.YDate))
  885. return
  886. }
  887. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  888. if maxDate.IsZero() {
  889. maxDate = findDateTime
  890. } else {
  891. if findDateTime.After(maxDate) {
  892. maxDate = findDateTime
  893. }
  894. }
  895. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  896. tmpItem.YDate = findDate
  897. tmpItem.YValue = tmpValue
  898. } else {
  899. continue
  900. }
  901. }
  902. // 获取当前系列的X轴的最大最小值
  903. {
  904. if tmpItem.XValue < minXVal {
  905. minXVal = tmpItem.XValue
  906. }
  907. if tmpItem.XValue > maxXVal {
  908. maxXVal = tmpItem.XValue
  909. }
  910. if tmpItem.YValue < minYVal {
  911. minYVal = tmpItem.YValue
  912. }
  913. if tmpItem.YValue > maxYVal {
  914. maxYVal = tmpItem.YValue
  915. }
  916. }
  917. tmpSeriesEdbInfoList = append(tmpSeriesEdbInfoList, tmpItem)
  918. }
  919. trendLimitData := make([]data_manage.CoordinatePoint, 0) //趋势线的前后坐标点
  920. var trendLine, rSquare string
  921. // 生成线性方程式
  922. var a, b float64
  923. {
  924. coordinateData := make([]utils.Coordinate, 0)
  925. for _, tmpSeriesEdbInfo := range tmpSeriesEdbInfoList {
  926. tmpCoordinate1 := utils.Coordinate{
  927. X: tmpSeriesEdbInfo.XValue,
  928. Y: tmpSeriesEdbInfo.YValue,
  929. }
  930. coordinateData = append(coordinateData, tmpCoordinate1)
  931. }
  932. // 只有存在两个坐标点的时候,才能去计算线性方程和R平方
  933. if len(coordinateData) >= 2 {
  934. a, b = utils.GetLinearResult(coordinateData)
  935. if !math.IsNaN(a) || !math.IsNaN(b) {
  936. if b > 0 {
  937. trendLine = fmt.Sprintf("y=%sx+%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
  938. } else {
  939. trendLine = fmt.Sprintf("y=%sx%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
  940. }
  941. minYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(minXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
  942. maxYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(maxXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
  943. }
  944. // 计算R平方
  945. rSquare = fmt.Sprint(utils.CalculationDecisive(coordinateData))
  946. }
  947. trendLimitData = append(trendLimitData, data_manage.CoordinatePoint{
  948. X: minXVal,
  949. Y: minYVal,
  950. }, data_manage.CoordinatePoint{
  951. X: maxXVal,
  952. Y: maxYVal,
  953. })
  954. }
  955. dataListResp = append(dataListResp, data_manage.SectionScatterSeriesItemResp{
  956. Name: seriesItem.Name,
  957. NameEn: seriesItem.NameEn,
  958. Color: seriesItem.Color,
  959. EdbInfoList: tmpSeriesEdbInfoList,
  960. ShowTrendLine: seriesItem.ShowTrendLine,
  961. ShowFitEquation: seriesItem.ShowFitEquation,
  962. ShowRSquare: seriesItem.ShowRSquare,
  963. TrendLine: trendLine,
  964. RSquare: rSquare,
  965. TrendLimitData: trendLimitData,
  966. })
  967. }
  968. chartDataResp = data_manage.SectionScatterInfoResp{
  969. XName: extraConfig.XName,
  970. XNameEn: extraConfig.XNameEn,
  971. XUnitName: extraConfig.XUnitName,
  972. XUnitNameEn: extraConfig.XUnitNameEn,
  973. YName: extraConfig.YName,
  974. YNameEn: extraConfig.YNameEn,
  975. YUnitName: extraConfig.YUnitName,
  976. YUnitNameEn: extraConfig.YUnitNameEn,
  977. XMinValue: extraConfig.XMinValue,
  978. XMaxValue: extraConfig.XMaxValue,
  979. YMinValue: extraConfig.YMinValue,
  980. YMaxValue: extraConfig.YMaxValue,
  981. DataList: dataListResp,
  982. }
  983. return
  984. }