chart_info.go 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  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.EdbNameEn = v.EdbNameEn
  263. item.Frequency = v.Frequency
  264. item.FrequencyEn = GetFrequencyEn(v.Frequency)
  265. if v.Unit != `无` {
  266. item.Unit = v.Unit
  267. }
  268. item.UnitEn = v.UnitEn
  269. item.StartDate = v.StartDate
  270. item.EndDate = v.EndDate
  271. item.ModifyTime = v.ModifyTime
  272. item.EdbInfoCategoryType = v.EdbInfoCategoryType
  273. item.PredictChartColor = v.PredictChartColor
  274. if chartInfoId <= 0 {
  275. item.IsAxis = 1
  276. item.LeadValue = 0
  277. item.LeadUnit = ""
  278. //item.ChartEdbMappingId = 0
  279. item.ChartInfoId = 0
  280. item.IsOrder = false
  281. item.EdbInfoType = 1
  282. item.ChartStyle = ""
  283. item.ChartColor = ""
  284. item.ChartWidth = 0
  285. item.MaxData = v.MaxValue
  286. item.MinData = v.MinValue
  287. } else {
  288. item.IsAxis = v.IsAxis
  289. item.EdbInfoType = v.EdbInfoType
  290. item.LeadValue = v.LeadValue
  291. item.LeadUnit = v.LeadUnit
  292. item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
  293. //item.ChartEdbMappingId = v.ChartEdbMappingId
  294. item.ChartInfoId = v.ChartInfoId
  295. item.ChartStyle = v.ChartStyle
  296. item.ChartColor = v.ChartColor
  297. item.ChartWidth = v.ChartWidth
  298. item.IsOrder = v.IsOrder
  299. item.MaxData = v.MaxData
  300. item.MinData = v.MinData
  301. }
  302. item.LatestValue = v.LatestValue
  303. item.LatestDate = v.LatestDate
  304. item.UniqueCode = v.UniqueCode
  305. var startDateReal string
  306. var diffSeconds int64
  307. if chartType == 2 { //季节性图
  308. startDateReal = startDate
  309. } else {
  310. if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
  311. var startTimeRealTemp time.Time
  312. startDateParse, _ := time.Parse(utils.FormatDate, startDate)
  313. switch v.LeadUnit {
  314. case "天":
  315. startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
  316. case "月":
  317. startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
  318. case "季":
  319. startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
  320. case "周":
  321. startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
  322. case "年":
  323. startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
  324. }
  325. if startTimeRealTemp.Before(startDateParse) {
  326. startDateReal = startTimeRealTemp.Format(utils.FormatDate)
  327. diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
  328. } else {
  329. startDateReal = startDate
  330. diffSeconds = 0
  331. }
  332. } else {
  333. startDateReal = startDate
  334. }
  335. }
  336. //fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
  337. calendarPreYear := 0
  338. if calendar == "农历" {
  339. newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
  340. if err != nil {
  341. fmt.Println("time.Parse:" + err.Error())
  342. }
  343. calendarPreYear = newStartDateReal.Year() - 1
  344. newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
  345. startDateReal = newStartDateReal.Format(utils.FormatDate)
  346. }
  347. dataList := make([]*models.EdbDataList, 0)
  348. //fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
  349. switch v.EdbInfoCategoryType {
  350. case 0:
  351. dataList, err = models.GetEdbDataList(v.Source, v.EdbInfoId, startDateReal, endDate)
  352. case 1:
  353. _, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, startDateReal, endDate, false)
  354. default:
  355. err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoCategoryType))
  356. }
  357. if err != nil {
  358. return
  359. }
  360. edbDataListMap[v.EdbInfoId] = dataList
  361. if diffSeconds != 0 && v.EdbInfoType == 0 {
  362. dataListLen := len(dataList)
  363. for i := 0; i < dataListLen; i++ {
  364. dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
  365. }
  366. }
  367. if chartType == 2 {
  368. latestDateStr := v.LatestDate //实际数据的截止日期
  369. latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
  370. if tmpErr != nil {
  371. err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
  372. return
  373. }
  374. latestDateYear := latestDate.Year() //实际数据截止年份
  375. if calendar == "农历" {
  376. if len(dataList) <= 0 {
  377. result := new(models.EdbDataResult)
  378. item.DataList = result
  379. } else {
  380. result, tmpErr := models.AddCalculateQuarterV5(dataList)
  381. if tmpErr != nil {
  382. err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
  383. return
  384. }
  385. // 处理季节图的截止日期
  386. for k, edbDataItems := range result.List {
  387. var cuttingDataTimestamp int64
  388. // 切割的日期时间字符串
  389. cuttingDataTimeStr := latestDate.AddDate(0, 0, edbDataItems.BetweenDay).Format(utils.FormatDate)
  390. //如果等于最后的实际日期,那么遍历找到该日期对应的时间戳,并将其赋值为 切割时间戳
  391. if edbDataItems.Year >= latestDateYear {
  392. for _, tmpData := range edbDataItems.Items {
  393. if tmpData.DataTime == cuttingDataTimeStr {
  394. cuttingDataTimestamp = tmpData.DataTimestamp
  395. break
  396. }
  397. }
  398. }
  399. edbDataItems.CuttingDataTimestamp = cuttingDataTimestamp
  400. result.List[k] = edbDataItems
  401. }
  402. if result.List[0].Year != calendarPreYear {
  403. itemList := make([]*models.EdbDataList, 0)
  404. items := new(models.EdbDataItems)
  405. //items.Year = calendarPreYear
  406. items.Items = itemList
  407. newResult := new(models.EdbDataResult)
  408. newResult.List = append(newResult.List, items)
  409. newResult.List = append(newResult.List, result.List...)
  410. item.DataList = newResult
  411. } else {
  412. item.DataList = result
  413. }
  414. }
  415. } else {
  416. currentYear := time.Now().Year()
  417. quarterDataList := make([]*models.QuarterData, 0)
  418. quarterMap := make(map[int][]*models.EdbDataList)
  419. var quarterArr []int
  420. for _, v := range dataList {
  421. itemDate, tmpErr := time.Parse(utils.FormatDate, v.DataTime)
  422. if tmpErr != nil {
  423. err = errors.New("季度指标日期转换,Err:" + tmpErr.Error() + ";DataTime:" + v.DataTime)
  424. return
  425. }
  426. year := itemDate.Year()
  427. newItemDate := itemDate.AddDate(currentYear-year, 0, 0)
  428. timestamp := newItemDate.UnixNano() / 1e6
  429. v.DataTimestamp = timestamp
  430. if findVal, ok := quarterMap[year]; !ok {
  431. quarterArr = append(quarterArr, year)
  432. findVal = append(findVal, v)
  433. quarterMap[year] = findVal
  434. } else {
  435. findVal = append(findVal, v)
  436. quarterMap[year] = findVal
  437. }
  438. }
  439. for _, v := range quarterArr {
  440. itemList := quarterMap[v]
  441. quarterItem := new(models.QuarterData)
  442. quarterItem.Year = v
  443. quarterItem.DataList = itemList
  444. //如果等于最后的实际日期,那么将切割时间戳记录
  445. if v == latestDateYear {
  446. var cuttingDataTimestamp int64
  447. for _, tmpData := range itemList {
  448. if tmpData.DataTime == latestDateStr {
  449. cuttingDataTimestamp = tmpData.DataTimestamp
  450. break
  451. }
  452. }
  453. quarterItem.CuttingDataTimestamp = cuttingDataTimestamp
  454. } else if v > latestDateYear {
  455. //如果大于最后的实际日期,那么第一个点就是切割的时间戳
  456. if len(itemList) > 0 {
  457. quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
  458. }
  459. }
  460. quarterDataList = append(quarterDataList, quarterItem)
  461. }
  462. item.DataList = quarterDataList
  463. }
  464. } else if chartType == 7 { //柱方图
  465. //item.DataList = dataList
  466. } else {
  467. item.DataList = dataList
  468. }
  469. edbList = append(edbList, item)
  470. }
  471. return
  472. }
  473. // BarChartData 柱方图的数据处理
  474. 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) {
  475. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  476. edbDataMap := make(map[int]map[string]float64)
  477. for edbInfoId, edbDataList := range edbDataListMap {
  478. edbDateData := make(map[string]float64)
  479. for _, edbData := range edbDataList {
  480. edbDateData[edbData.DataTime] = edbData.Value
  481. }
  482. edbDataMap[edbInfoId] = edbDateData
  483. }
  484. // edbIdList 指标展示顺序;x轴的指标顺序
  485. edbIdList = make([]int, 0)
  486. //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
  487. dateData := make(map[int]float64)
  488. if barChartInfoSort.Sort == 0 {
  489. for _, v := range mappingList {
  490. edbIdList = append(edbIdList, v.EdbInfoId)
  491. }
  492. } else {
  493. lenBarChartInfoDateList := len(barChartInfoDateList)
  494. if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
  495. err = errors.New("排序日期异常")
  496. return
  497. }
  498. notDataEdbIdList := make([]int, 0) //没有数据的指标id
  499. // 日期配置
  500. barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
  501. for edbInfoId, dataList := range edbDataListMap {
  502. if len(dataList) <= 0 {
  503. // 没有数据的指标id
  504. notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
  505. continue
  506. }
  507. findDate := barChartInfoDate.Date
  508. switch barChartInfoDate.Type {
  509. case 1: //最新值
  510. findDate = dataList[len(dataList)-1].DataTime
  511. case 2: //近期几天
  512. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  513. if tmpErr != nil {
  514. err = tmpErr
  515. return
  516. }
  517. findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  518. lenData := len(dataList) - 1
  519. for i := lenData; i >= 0; i-- {
  520. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  521. if tmpErr != nil {
  522. err = tmpErr
  523. return
  524. }
  525. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  526. findDate = dataList[i].DataTime
  527. break
  528. }
  529. }
  530. case 3: // 固定日期
  531. //最早的日期
  532. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  533. if tmpErr != nil {
  534. err = tmpErr
  535. return
  536. }
  537. //寻找固定日期的数据
  538. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  539. if tmpErr != nil {
  540. err = tmpErr
  541. return
  542. }
  543. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  544. tmpDate := tmpDateTime.Format(utils.FormatDate)
  545. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  546. findDate = tmpDate
  547. break
  548. }
  549. }
  550. default:
  551. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  552. return
  553. }
  554. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  555. dateData[edbInfoId] = tmpValue
  556. } else {
  557. // 没有数据的指标id
  558. notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
  559. }
  560. }
  561. //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
  562. // 排序
  563. dateDataSort := utils.NewMapSorter(dateData)
  564. sort.Sort(dateDataSort)
  565. if barChartInfoSort.Sort == 1 {
  566. // 先将没有数据的指标id放在最前面
  567. if len(notDataEdbIdList) > 0 {
  568. edbIdList = append(edbIdList, notDataEdbIdList...)
  569. }
  570. for _, v := range dateDataSort {
  571. edbIdList = append(edbIdList, v.Key)
  572. }
  573. } else {
  574. for i := len(dateDataSort) - 1; i >= 0; i-- {
  575. edbIdList = append(edbIdList, dateDataSort[i].Key)
  576. }
  577. // 再将没有数据的指标id放在最后面
  578. if len(notDataEdbIdList) > 0 {
  579. edbIdList = append(edbIdList, notDataEdbIdList...)
  580. }
  581. }
  582. }
  583. yDataList = make([]models.YData, 0) //y轴的数据列表
  584. for _, barChartInfoDate := range barChartInfoDateList {
  585. var maxDate time.Time
  586. findDataList := make([]float64, 0) // 当前日期的数据值
  587. for _, edbInfoId := range edbIdList {
  588. findDate := barChartInfoDate.Date //需要的日期值
  589. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  590. if len(dataList) <= 0 {
  591. // 没有数据的指标id
  592. findDataList = append(findDataList, 0)
  593. continue
  594. }
  595. switch barChartInfoDate.Type {
  596. case 1: //最新值
  597. dataList := edbDataListMap[edbInfoId]
  598. findDate = dataList[len(dataList)-1].DataTime
  599. case 2: //近期几天
  600. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  601. if tmpErr != nil {
  602. err = tmpErr
  603. return
  604. }
  605. findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  606. lenData := len(dataList) - 1
  607. for i := lenData; i >= 0; i-- {
  608. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  609. if tmpErr != nil {
  610. err = tmpErr
  611. return
  612. }
  613. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  614. findDate = dataList[i].DataTime
  615. break
  616. }
  617. }
  618. case 3: // 固定日期
  619. //最早的日期
  620. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  621. if tmpErr != nil {
  622. err = tmpErr
  623. return
  624. }
  625. //寻找固定日期的数据
  626. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  627. if tmpErr != nil {
  628. err = tmpErr
  629. return
  630. }
  631. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  632. tmpDate := tmpDateTime.Format(utils.FormatDate)
  633. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  634. findDate = tmpDate
  635. break
  636. }
  637. }
  638. default:
  639. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  640. return
  641. }
  642. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  643. if maxDate.IsZero() {
  644. maxDate = findDateTime
  645. } else {
  646. if findDateTime.After(maxDate) {
  647. maxDate = findDateTime
  648. }
  649. }
  650. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  651. findDataList = append(findDataList, tmpValue)
  652. } else {
  653. findDataList = append(findDataList, 0)
  654. }
  655. }
  656. yDate := "0000-00-00"
  657. if !maxDate.IsZero() {
  658. yDate = maxDate.Format(utils.FormatDate)
  659. }
  660. yDataList = append(yDataList, models.YData{
  661. Date: yDate,
  662. Value: findDataList,
  663. Color: barChartInfoDate.Color,
  664. Name: barChartInfoDate.Name,
  665. })
  666. }
  667. return
  668. }
  669. // ChartInfoRefreshV2 图表刷新
  670. // @author Roc
  671. // @datetime 2022-09-16 10:15:38
  672. // @description 将原来自己写的一套获取所有关联指标,然后刷新指标逻辑 改成 只获取使用的指标id,然后遍历去调用“指标刷新服务”
  673. func ChartInfoRefreshV2(chartInfoId int) (err error) {
  674. var errmsg string
  675. defer func() {
  676. if err != nil {
  677. go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errmsg, 3)
  678. //go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "ChartInfoRefresh:"+errmsg, utils.EmailSendToUsers)
  679. fmt.Println("ChartInfoRefresh Err:" + errmsg)
  680. }
  681. }()
  682. edbMappingList, err := data_manage.GetChartEdbMappingList(chartInfoId)
  683. if err != nil {
  684. errmsg = "获取需要刷新的指标失败:Err:" + err.Error()
  685. return
  686. }
  687. edbIdList := make([]int, 0)
  688. for _, v := range edbMappingList {
  689. edbIdList = append(edbIdList, v.EdbInfoId)
  690. }
  691. // 批量刷新
  692. err, errmsg = EdbInfoRefreshAllFromBase(edbIdList, false)
  693. if err != nil {
  694. return
  695. }
  696. return
  697. }
  698. // GetSectionScatterChartData 柱方图的数据处理
  699. func GetSectionScatterChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, extraConfig data_manage.SectionScatterReq) (edbIdList []int, chartDataResp data_manage.SectionScatterInfoResp, err error) {
  700. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  701. edbDataMap := make(map[int]map[string]float64)
  702. for edbInfoId, edbDataList := range edbDataListMap {
  703. edbDateData := make(map[string]float64)
  704. for _, edbData := range edbDataList {
  705. edbDateData[edbData.DataTime] = edbData.Value
  706. }
  707. edbDataMap[edbInfoId] = edbDateData
  708. }
  709. // edbIdList 指标展示顺序;x轴的指标顺序
  710. edbIdList = make([]int, 0)
  711. edbMappingMap := make(map[int]*models.ChartEdbInfoMapping)
  712. for _, v := range mappingList {
  713. edbIdList = append(edbIdList, v.EdbInfoId)
  714. edbMappingMap[v.EdbInfoId] = v
  715. }
  716. //SectionScatterSeriesInfoResp
  717. dataListResp := make([]data_manage.SectionScatterSeriesItemResp, 0) //y轴的数据列表
  718. for _, seriesItem := range extraConfig.SeriesList {
  719. var maxDate time.Time
  720. // 系列中的指标数据
  721. tmpSeriesEdbInfoList := make([]data_manage.SectionScatterEdbItemResp, 0)
  722. var minXVal, maxXVal, minYVal, maxYVal float64
  723. for _, edbConf := range seriesItem.EdbInfoList {
  724. tmpItem := data_manage.SectionScatterEdbItemResp{
  725. IsShow: edbConf.IsShow,
  726. Name: edbConf.Name,
  727. NameEn: edbConf.NameEn,
  728. } //单个坐标点的数据
  729. //X轴的数据
  730. {
  731. edbInfoId := edbConf.XEdbInfoId //X轴的指标
  732. edbMappingInfo, ok := edbMappingMap[edbInfoId]
  733. if !ok {
  734. continue
  735. }
  736. findDate := edbConf.XDate //需要的日期值
  737. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  738. if len(dataList) <= 0 {
  739. // 没有数据的指标id
  740. //findDataList = append(findDataList, 0)
  741. continue
  742. }
  743. tmpItem.XEdbInfoId = edbInfoId
  744. tmpItem.XName = edbMappingInfo.EdbName
  745. tmpItem.XNameEn = edbMappingInfo.EdbNameEn
  746. switch edbConf.XDateType {
  747. case 1: //最新值
  748. dataList := edbDataListMap[edbInfoId]
  749. findDate = dataList[len(dataList)-1].DataTime
  750. case 2: //近期几天
  751. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  752. if tmpErr != nil {
  753. err = tmpErr
  754. return
  755. }
  756. findDateTime = findDateTime.AddDate(0, 0, -edbConf.XDateValue)
  757. lenData := len(dataList) - 1
  758. for i := lenData; i >= 0; i-- {
  759. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  760. if tmpErr != nil {
  761. err = tmpErr
  762. return
  763. }
  764. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  765. findDate = dataList[i].DataTime
  766. break
  767. }
  768. }
  769. case 3: // 固定日期
  770. //最早的日期
  771. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  772. if tmpErr != nil {
  773. err = tmpErr
  774. return
  775. }
  776. //寻找固定日期的数据
  777. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.XDate, time.Local)
  778. if tmpErr != nil {
  779. err = tmpErr
  780. return
  781. }
  782. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  783. tmpDate := tmpDateTime.Format(utils.FormatDate)
  784. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  785. findDate = tmpDate
  786. break
  787. }
  788. }
  789. default:
  790. err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.XDate))
  791. return
  792. }
  793. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  794. if maxDate.IsZero() {
  795. maxDate = findDateTime
  796. } else {
  797. if findDateTime.After(maxDate) {
  798. maxDate = findDateTime
  799. }
  800. }
  801. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  802. tmpItem.XDate = findDate
  803. tmpItem.XValue = tmpValue
  804. } else {
  805. continue
  806. }
  807. }
  808. //Y轴的数据
  809. {
  810. edbInfoId := edbConf.YEdbInfoId //Y轴的指标
  811. edbMappingInfo, ok := edbMappingMap[edbInfoId]
  812. if !ok {
  813. continue
  814. }
  815. findDate := edbConf.YDate //需要的日期值
  816. dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  817. if len(dataList) <= 0 {
  818. // 没有数据的指标id
  819. //findDataList = append(findDataList, 0)
  820. continue
  821. }
  822. tmpItem.YEdbInfoId = edbInfoId
  823. tmpItem.YName = edbMappingInfo.EdbName
  824. tmpItem.YNameEn = edbMappingInfo.EdbNameEn
  825. switch edbConf.YDateType {
  826. case 1: //最新值
  827. dataList := edbDataListMap[edbInfoId]
  828. findDate = dataList[len(dataList)-1].DataTime
  829. case 2: //近期几天
  830. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
  831. if tmpErr != nil {
  832. err = tmpErr
  833. return
  834. }
  835. findDateTime = findDateTime.AddDate(0, 0, -edbConf.YDateValue)
  836. lenData := len(dataList) - 1
  837. for i := lenData; i >= 0; i-- {
  838. currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  839. if tmpErr != nil {
  840. err = tmpErr
  841. return
  842. }
  843. if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
  844. findDate = dataList[i].DataTime
  845. break
  846. }
  847. }
  848. case 3: // 固定日期
  849. //最早的日期
  850. minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  851. if tmpErr != nil {
  852. err = tmpErr
  853. return
  854. }
  855. //寻找固定日期的数据
  856. findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.YDate, time.Local)
  857. if tmpErr != nil {
  858. err = tmpErr
  859. return
  860. }
  861. for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  862. tmpDate := tmpDateTime.Format(utils.FormatDate)
  863. if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
  864. findDate = tmpDate
  865. break
  866. }
  867. }
  868. default:
  869. err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.YDate))
  870. return
  871. }
  872. findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
  873. if maxDate.IsZero() {
  874. maxDate = findDateTime
  875. } else {
  876. if findDateTime.After(maxDate) {
  877. maxDate = findDateTime
  878. }
  879. }
  880. if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
  881. tmpItem.YDate = findDate
  882. tmpItem.YValue = tmpValue
  883. } else {
  884. continue
  885. }
  886. }
  887. // 获取当前系列的X轴的最大最小值
  888. {
  889. if tmpItem.XValue < minXVal {
  890. minXVal = tmpItem.XValue
  891. }
  892. if tmpItem.XValue > maxXVal {
  893. maxXVal = tmpItem.XValue
  894. }
  895. if tmpItem.YValue < minYVal {
  896. minYVal = tmpItem.YValue
  897. }
  898. if tmpItem.YValue > maxYVal {
  899. maxYVal = tmpItem.YValue
  900. }
  901. }
  902. tmpSeriesEdbInfoList = append(tmpSeriesEdbInfoList, tmpItem)
  903. }
  904. trendLimitData := make([]data_manage.CoordinatePoint, 0) //趋势线的前后坐标点
  905. var trendLine, rSquare string
  906. // 生成线性方程式
  907. var a, b float64
  908. {
  909. coordinateData := make([]utils.Coordinate, 0)
  910. for _, tmpSeriesEdbInfo := range tmpSeriesEdbInfoList {
  911. tmpCoordinate1 := utils.Coordinate{
  912. X: tmpSeriesEdbInfo.XValue,
  913. Y: tmpSeriesEdbInfo.YValue,
  914. }
  915. coordinateData = append(coordinateData, tmpCoordinate1)
  916. }
  917. // 只有存在两个坐标点的时候,才能去计算线性方程和R平方
  918. if len(coordinateData) >= 2 {
  919. a, b = utils.GetLinearResult(coordinateData)
  920. if !math.IsNaN(a) || !math.IsNaN(b) {
  921. if b > 0 {
  922. trendLine = fmt.Sprintf("y=%sx+%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
  923. } else {
  924. trendLine = fmt.Sprintf("y=%sx%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
  925. }
  926. minYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(minXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
  927. maxYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(maxXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
  928. }
  929. // 计算R平方
  930. rSquare = fmt.Sprint(utils.CalculationDecisive(coordinateData))
  931. }
  932. trendLimitData = append(trendLimitData, data_manage.CoordinatePoint{
  933. X: minXVal,
  934. Y: minYVal,
  935. }, data_manage.CoordinatePoint{
  936. X: maxXVal,
  937. Y: maxYVal,
  938. })
  939. }
  940. dataListResp = append(dataListResp, data_manage.SectionScatterSeriesItemResp{
  941. Name: seriesItem.Name,
  942. NameEn: seriesItem.NameEn,
  943. Color: seriesItem.Color,
  944. EdbInfoList: tmpSeriesEdbInfoList,
  945. ShowTrendLine: seriesItem.ShowTrendLine,
  946. ShowFitEquation: seriesItem.ShowFitEquation,
  947. ShowRSquare: seriesItem.ShowRSquare,
  948. TrendLine: trendLine,
  949. RSquare: rSquare,
  950. TrendLimitData: trendLimitData,
  951. })
  952. }
  953. chartDataResp = data_manage.SectionScatterInfoResp{
  954. XName: extraConfig.XName,
  955. XNameEn: extraConfig.XNameEn,
  956. XUnitName: extraConfig.XUnitName,
  957. XUnitNameEn: extraConfig.XUnitNameEn,
  958. YName: extraConfig.YName,
  959. YNameEn: extraConfig.YNameEn,
  960. YUnitName: extraConfig.YUnitName,
  961. YUnitNameEn: extraConfig.YUnitNameEn,
  962. XMinValue: extraConfig.XMinValue,
  963. XMaxValue: extraConfig.XMaxValue,
  964. YMinValue: extraConfig.YMinValue,
  965. YMaxValue: extraConfig.YMaxValue,
  966. DataList: dataListResp,
  967. }
  968. return
  969. }