chart_info.go 29 KB

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