useChartRender.ts 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. import { reactive, toRefs, onMounted, ref,watch } from "vue";
  2. import _ from "lodash";
  3. import {
  4. IChartType,
  5. IDataProps,
  6. IParams,
  7. ISeasonDataItemProps,
  8. } from "@/types";
  9. import Highcharts from "highcharts";
  10. import { defaultOpts, seasonOptions } from "@/utils/chartOptions";
  11. import moment from "moment";
  12. import router from '@/router'
  13. // 散点x
  14. const scatterXAxis = {
  15. tickPosition: "inside",
  16. lineColor: "#bfbfbf",
  17. tickColor: "#bfbfbf",
  18. tickLength: 5,
  19. ordinal: false,
  20. type: "linear",
  21. };
  22. //基础y轴
  23. const basicYAxis = {
  24. tickLength: 5,
  25. lineWidth: 1,
  26. lineColor: "#bfbfbf",
  27. tickColor: "#bfbfbf",
  28. // offset: 0,
  29. visible: true,
  30. gridLineWidth: 0,
  31. tickPosition: "inside",
  32. endOnTick: false,
  33. startOnTick: false,
  34. showLastLabel: true,
  35. };
  36. interface StateProps {
  37. chartLimit: {
  38. min?: number;
  39. max?: number;
  40. x_min?:number;
  41. x_max?:number;
  42. }
  43. dataList: any[];
  44. chartInfo: any
  45. }
  46. /**
  47. * useChartRender 处理图表渲染 返回options
  48. * @param Data 详情数据 lange中英文
  49. * @param {
  50. * Source 1 //ETA图 ChartType: 1曲线图 2季节图 3面积图 4柱状图 5散点图 6组合图 7柱形 10截面散点 11雷达图
  51. * 2 商品价格
  52. * 3 相关性
  53. * 4 滚动相关性
  54. * 5 商品利润
  55. * 6 拟合方程
  56. * 7 统计特征/标准差
  57. * 8 统计特征/百分位
  58. * 9 统计特征/频率
  59. * 10 跨品种分析
  60. * }
  61. *
  62. */
  63. //依赖数据
  64. const state = reactive<StateProps>({
  65. chartInfo: {},
  66. dataList: [],
  67. chartLimit: {},
  68. })
  69. const language = ref('')
  70. const routeQuery = ref<any>({});//路由参
  71. watch(() => router.currentRoute.value.query,(nval) => {
  72. routeQuery.value = nval
  73. })
  74. export const useChartRender = (Data,lang='ch',) => {
  75. state.chartInfo = Data.ChartInfo
  76. state.dataList = Data.ChartInfo.Source === 1 ? Data.EdbInfoList : [Data.EdbInfoList[0]];
  77. language.value = lang
  78. let chartOptions:any;
  79. //eta图
  80. if (Data.ChartInfo.Source === 1) {
  81. const typeMap = {
  82. 1: setDefaultLineOptions,
  83. 2: setSeasonOptions,
  84. 3: setStackOrCombinChart,
  85. 4: setStackOrCombinChart,
  86. 5: setScatterChartOptions,
  87. 6: setStackOrCombinChart,
  88. 7: initBarData,
  89. 10: initSectionScatterData,
  90. 11: initRadarData
  91. };
  92. chartOptions = typeMap[state.chartInfo.ChartType] && typeMap[state.chartInfo.ChartType](Data);
  93. }else {
  94. //其他source图
  95. const sourceTypeMap = {
  96. 2: initCommodityData,
  97. 3: initRelevanceChartData,
  98. 4: initStatisticChartData,
  99. 5: initCommodityData,
  100. 6: initFittingEquation,
  101. 7: initStatisticChartData,
  102. 8: initStatisticChartData,
  103. 9: initStatisticChartData,
  104. 10: initCrossVarietyChartData,
  105. };
  106. chartOptions = sourceTypeMap[Data.ChartInfo.Source] &&
  107. sourceTypeMap[Data.ChartInfo.Source](Data);
  108. }
  109. return chartOptions
  110. };
  111. /* 曲线图 */
  112. const setDefaultLineOptions = () => {
  113. const { dataList,chartInfo } = state;
  114. /* 主题样式*/
  115. const chartTheme = chartInfo.ChartThemeStyle ? JSON.parse(chartInfo.ChartThemeStyle) : null;
  116. //拼接标题 数据列
  117. let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
  118. let rightTwoIndex = dataList.findIndex(item => item.IsAxis ===2);
  119. // const chartData = _.cloneDeep(dataList);
  120. //有右二轴时排个序 按照左 右 右2的顺序
  121. let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);
  122. chartData.forEach((item:IDataProps ,index:number) => {
  123. //轴位置值相同的下标
  124. let sameSideIndex = chartData.findIndex(
  125. (i:IDataProps) => i.IsAxis === item.IsAxis
  126. );
  127. //y轴
  128. let textEn = item.Unit?item.UnitEn:''
  129. let yItem = {
  130. ...basicYAxis,
  131. labels: {
  132. formatter: function (ctx: any) {
  133. let val = ctx.value;
  134. return sameSideIndex !== index ? '' : val;
  135. },
  136. align: 'center',
  137. x: [0,2].includes(item.IsAxis) ? 5 : -5,
  138. style: {
  139. ...chartTheme&&chartTheme.yAxisOptions.style,
  140. }
  141. },
  142. title: {
  143. text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
  144. style:{
  145. ...chartTheme&&chartTheme.yAxisOptions.style
  146. },
  147. align: 'high',
  148. rotation: 0,
  149. y: -12,
  150. x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
  151. textAlign: item.IsAxis===1 ? 'left' : 'right',
  152. reserveSpace: false
  153. },
  154. opposite: [0,2].includes(item.IsAxis),
  155. reversed: item.IsOrder,
  156. min: Number(chartData[sameSideIndex].MinData),
  157. max: Number(chartData[sameSideIndex].MaxData),
  158. tickWidth: 1,
  159. visible: sameSideIndex === index,
  160. plotBands: setAxisPlotAreas(item.IsAxis),
  161. plotLines: setAxisPlotLines(item.IsAxis)
  162. }
  163. // //拼接标题 判断相同指标名称拼接来源
  164. let dynamic_title = item.EdbName;
  165. let dynamic_arr = chartData.filter(
  166. (item: IDataProps) => dynamic_title === item.EdbName
  167. );
  168. // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
  169. let dynamic_tag = concatDynamicTag(item)
  170. // 英文后缀
  171. let dynamic_tag_en = concatDynamicTag(item,'en')
  172. //数据列
  173. let nameCh:String = dynamic_arr.length > 1
  174. ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
  175. : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`
  176. let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
  177. let name :String=language.value == 'ch'?nameCh:nameEn
  178. //预测指标配置
  179. let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item) : {};
  180. let obj = {
  181. data: [] as any[],
  182. type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
  183. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  184. yAxis: sameSideIndex,
  185. name,
  186. color: item.ChartColor,
  187. lineWidth: Number(item.ChartWidth),
  188. ...predict_params
  189. };
  190. item.DataList = item.DataList || []
  191. for (let i of item.DataList) {
  192. obj.data.push([i.DataTimestamp, i.Value]);
  193. }
  194. if(item.DataList.length){
  195. minTimeArr.push(item.DataList[0].DataTimestamp)
  196. maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
  197. }
  198. data.push(obj);
  199. ydata.push(yItem);
  200. })
  201. // 范围为1年内 x轴显示为月/日 否则默认年/月
  202. let xAxis:any = {};
  203. const isLessThanOneYear:boolean = xTimeDiffer();
  204. let minTime: number=Math.min(...minTimeArr);
  205. let maxTime=Math.max(...maxTimeArr);
  206. let step = setXaxisStep(maxTime-minTime);
  207. xAxis = {
  208. ...defaultOpts.xAxis,
  209. tickInterval: screen.value === 'phone' ? step : undefined,
  210. labels: {
  211. formatter: function (ctx: any) {
  212. return isLessThanOneYear
  213. ? Highcharts.dateFormat('%m/%d', ctx.value)
  214. : Highcharts.dateFormat('%y/%m', ctx.value);
  215. },
  216. style: {
  217. ...chartTheme&&chartTheme.xAxisOptions.style
  218. }
  219. },
  220. plotBands: setAxisPlotAreas(3,'datetime'),
  221. plotLines: setAxisPlotLines(3,'datetime')
  222. }
  223. let options:any = {};
  224. options = {
  225. series: data,
  226. yAxis: ydata,
  227. xAxis
  228. };
  229. //滚动相关性独立tooltip
  230. if(chartInfo.Source === 4) {
  231. const relevanceUnitEnMap={
  232. '年': 'Year',
  233. '季': 'Season',
  234. '月': 'Month',
  235. '周': 'Week',
  236. '天': 'Day',
  237. }
  238. const { LeadValue,LeadUnit } = statisticFrequencyRenderData.value;
  239. options.tooltip = {
  240. formatter: function() {
  241. let that:any = this;
  242. let str = '';
  243. if(language.value=='ch'){
  244. str = `${Highcharts.dateFormat('%Y/%m/%d',that.x)}<br><p>相关性系数:${that.y.toFixed(4)}</p><br><p>领先${LeadValue+LeadUnit}</p>`
  245. }else{
  246. str = `${Highcharts.dateFormat('%Y/%m/%d',that.x)}<br><p>Correlation coefficient:${that.y.toFixed(4)}</p><br><p>lead${LeadValue+relevanceUnitEnMap[LeadUnit]}</p>`
  247. }
  248. return str
  249. },
  250. }
  251. }
  252. return options;
  253. }
  254. /* 季节图 */
  255. const screen = ref(document.body.clientWidth < 1200 ? 'phone' : 'pc');
  256. const setSeasonOptions = () => {
  257. const chartData = state.dataList[0];
  258. // 农历数据需要去除第一项 在ETA1.0.5之后,除了这里 农历和公历处理逻辑一样
  259. if(!chartData.DataList){
  260. return
  261. }
  262. const chartDataHandle=state.chartInfo.Calendar === '农历'?
  263. chartData.DataList.filter((item:ISeasonDataItemProps, index:number) => index > 0):
  264. chartData.DataList
  265. let seasonYdata:any[] = [],
  266. seasonData:any[] = [];
  267. /* 主题样式*/
  268. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  269. /*处理数据列*/
  270. for (let j of chartDataHandle) {
  271. //预测指标配置
  272. let predict_params = chartData.EdbInfoCategoryType === 1 ? getSeasonPredictParams(j.CuttingDataTimestamp) : {};
  273. let serie_item = {
  274. data: [] as any[],
  275. type: (chartTheme&&chartTheme.lineOptions.lineType) || chartData.ChartStyle,
  276. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  277. yAxis: 0,
  278. name: j.ChartLegend,
  279. lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 1,
  280. ...predict_params
  281. };
  282. const data_array = _.cloneDeep(j.DataList);
  283. data_array &&
  284. data_array.forEach((item: IParams) => {
  285. serie_item.data.push([item.DataTimestamp, item.Value]);
  286. });
  287. seasonData.push(serie_item);
  288. }
  289. //y轴
  290. seasonYdata = [{
  291. ...defaultOpts.yAxis,
  292. labels: {
  293. formatter: function (ctx: any) {
  294. let val = ctx.value;
  295. return val;
  296. },
  297. align: 'center',
  298. style: {
  299. ...chartTheme&&chartTheme.yAxisOptions.style
  300. }
  301. },
  302. title: {
  303. text:language.value=='ch'?`${chartData.Unit}`:chartData.UnitEn,
  304. align: 'high',
  305. rotation: 0,
  306. y: -12,
  307. x: 0,
  308. textAlign: 'left',
  309. reserveSpace: false,
  310. style:{
  311. ...chartTheme&&chartTheme.yAxisOptions.style
  312. },
  313. },
  314. max: Number(chartData.MaxData),
  315. min: Number(chartData.MinData),
  316. plotBands: setAxisPlotAreas(1),
  317. plotLines: setAxisPlotLines(1)
  318. }];
  319. // 季节图x轴显示月/日
  320. const xAxis = {
  321. ...defaultOpts.xAxis,
  322. tickInterval: screen.value === 'phone' ? 24 * 3600 * 1000 * 60 : undefined,
  323. labels: {
  324. formatter: function (ctx: any) {
  325. return Highcharts.dateFormat('%m/%d', ctx.value);
  326. },
  327. style: {
  328. ...chartTheme&&chartTheme.xAxisOptions.style
  329. }
  330. },
  331. plotBands: setAxisPlotAreas(3,'datetime'),
  332. plotLines: setAxisPlotLines(3,'datetime')
  333. };
  334. const tooltip = {
  335. ...defaultOpts.tooltip,
  336. dateTimeLabelFormats: {
  337. // 时间格式化字符
  338. day: '%m/%d',
  339. week: '%m/%d',
  340. month: '%m/%d',
  341. year: '%m/%d',
  342. },
  343. xDateFormat: '%m/%d',
  344. }
  345. return {
  346. colors:chartTheme.colorsOptions.slice(-chartDataHandle.length),
  347. series: seasonData,
  348. yAxis: seasonYdata,
  349. xAxis,
  350. tooltip
  351. };
  352. }
  353. /* 堆叠图/组合图设置
  354. 本来和曲线图逻辑基本一致兼容下即可 为了以后便于维护和阅读还是拆开写吧
  355. */
  356. const setStackOrCombinChart = () => {
  357. const { dataList,chartInfo } = state;
  358. /* 主题样式*/
  359. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  360. //拼接标题 数据列
  361. let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
  362. // const chartData = _.cloneDeep(dataList);
  363. //有右二轴时排个序 按照左 右 右2的顺序
  364. let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);
  365. //支持的图表类型
  366. const chartTypeMap: IChartType = {
  367. 3: 'areaspline',
  368. 4: 'column',
  369. 6: ''
  370. };
  371. let chartStyle = chartTypeMap[chartInfo.ChartType];
  372. chartData.forEach((item:IDataProps ,index:number) => {
  373. //轴位置值相同的下标
  374. let sameSideIndex = chartData.findIndex(
  375. (i:IDataProps) => i.IsAxis === item.IsAxis
  376. );
  377. //堆叠图的yAxis必须一致 数据列所对应的y轴
  378. let serie_yIndex = index;
  379. if([3,4].includes(chartInfo.ChartType)) {
  380. // 类型为堆叠图时公用第一个指标y轴
  381. serie_yIndex = 0;
  382. } else if(chartInfo.ChartType ===6 && ['areaspline','column'].includes(item.ChartStyle)) {
  383. // 组合图找第一个堆叠柱状或面积的作为公用
  384. serie_yIndex = chartData.findIndex((i:IDataProps) => i.ChartStyle === item.ChartStyle);
  385. }
  386. //数据对应的y轴是公用轴则配置也共享
  387. item.IsAxis = serie_yIndex === index ? item.IsAxis : chartData[serie_yIndex].IsAxis;
  388. item.IsOrder = serie_yIndex === index ? item.IsOrder : chartData[serie_yIndex].IsOrder;
  389. // 右2轴下标
  390. let rightTwoIndex = [3,4].includes(chartInfo.ChartType)
  391. ? -1
  392. : dataList.findIndex(item => item.IsAxis===2);
  393. //y轴
  394. let textEn = item.Unit?item.UnitEn:''
  395. let yItem = {
  396. ...basicYAxis,
  397. labels: {
  398. formatter: function (ctx: any) {
  399. let val = ctx.value;
  400. return sameSideIndex !== index ? '' : val;
  401. },
  402. align: 'center',
  403. x: [0,2].includes(item.IsAxis) ? 5 : -5,
  404. style:{
  405. ...chartTheme&&chartTheme.yAxisOptions.style
  406. },
  407. },
  408. title: {
  409. text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
  410. // text: null,
  411. align: 'high',
  412. rotation: 0,
  413. y: -12,
  414. x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
  415. textAlign: item.IsAxis===1 ? 'left' : 'right',
  416. reserveSpace: false,
  417. style:{
  418. ...chartTheme&&chartTheme.yAxisOptions.style
  419. },
  420. },
  421. opposite: [0,2].includes(item.IsAxis),
  422. reversed: item.IsOrder,
  423. min: Number(chartData[sameSideIndex].MinData),
  424. max: Number(chartData[sameSideIndex].MaxData),
  425. tickWidth: sameSideIndex !== index ? 0 : 1,
  426. visible: serie_yIndex === index && sameSideIndex ===index,
  427. plotBands: setAxisPlotAreas(item.IsAxis),
  428. plotLines: setAxisPlotLines(item.IsAxis)
  429. }
  430. // //拼接标题 判断相同指标名称拼接来源
  431. let dynamic_title = item.EdbName;
  432. let dynamic_arr = chartData.filter(
  433. (item: IDataProps) => dynamic_title === item.EdbName
  434. );
  435. // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
  436. let dynamic_tag = concatDynamicTag(item)
  437. // 英文后缀
  438. let dynamic_tag_en = concatDynamicTag(item,'en')
  439. //数据列
  440. let nameCh:String = dynamic_arr.length > 1
  441. ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
  442. : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`
  443. let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
  444. let name :String=language.value == 'ch'?nameCh:nameEn
  445. //预测指标配置
  446. let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item,chartStyle) : {};
  447. let obj = {
  448. data: [] as any[],
  449. type: chartStyle || item.ChartStyle,
  450. yAxis: serie_yIndex,
  451. name,
  452. color: item.ChartColor,
  453. lineWidth: Number(item.ChartWidth),
  454. fillColor: (chartInfo.ChartType === 3 || (chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
  455. zIndex: (chartInfo.ChartType === 6 && ['line','spline'].includes(item.ChartStyle)) ? 1 : 0, //防止组合图曲线被遮住
  456. borderWidth: 1,
  457. borderColor: item.ChartColor,
  458. ...predict_params
  459. };
  460. item.DataList = item.DataList || []
  461. for (let i of item.DataList) {
  462. obj.data.push([i.DataTimestamp, i.Value]);
  463. }
  464. if(item.DataList.length){
  465. minTimeArr.push(item.DataList[0].DataTimestamp)
  466. maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
  467. }
  468. data.push(obj);
  469. ydata.push(yItem);
  470. })
  471. // 范围为1年内 x轴显示为月/日 否则默认年/月
  472. let xAxis:any = {};
  473. const isLessThanOneYear:boolean = xTimeDiffer();
  474. let minTime: number=Math.min(...minTimeArr);
  475. let maxTime=Math.max(...maxTimeArr);
  476. let step = setXaxisStep(maxTime-minTime);
  477. xAxis = {
  478. ...defaultOpts.xAxis,
  479. tickInterval: screen.value === 'phone' ? step : undefined,
  480. labels: {
  481. formatter: function (ctx: any) {
  482. return isLessThanOneYear
  483. ? Highcharts.dateFormat('%m/%d', ctx.value)
  484. : Highcharts.dateFormat('%y/%m', ctx.value);
  485. },
  486. style: {
  487. ...chartTheme&&chartTheme.xAxisOptions.style
  488. }
  489. },
  490. plotBands: setAxisPlotAreas(3,'datetime'),
  491. plotLines: setAxisPlotLines(3,'datetime')
  492. }
  493. return {
  494. series: data,
  495. yAxis: ydata,
  496. xAxis
  497. };
  498. }
  499. /* 散点图 第一个指标值为x轴 第二个指标为y轴*/
  500. const setScatterChartOptions = () => {
  501. const { dataList,chartInfo } = state;
  502. /* 主题样式*/
  503. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  504. // 取2个指标中日期相同的数据
  505. const real_data: any[] = [];
  506. let tmpData_date: any = {};//用来取点对应的日期
  507. let data1 = _.cloneDeep(dataList)[0].DataList || [];
  508. let data2 = _.cloneDeep(dataList)[1].DataList || [];
  509. data1.forEach((_item: IParams) => {
  510. data2.forEach((_item2: IParams) => {
  511. if(_item.DataTimestamp === _item2.DataTimestamp) {
  512. //日期
  513. let itemIndex =_item.Value + "_" +_item2.Value
  514. if(tmpData_date[itemIndex]) {
  515. tmpData_date[itemIndex].push( moment(_item.DataTimestamp).format('YYYY/MM/DD'))
  516. } else {
  517. tmpData_date[itemIndex] = [moment(_item.DataTimestamp).format('YYYY/MM/DD')]
  518. }
  519. //值
  520. real_data.push({
  521. x: _item.Value,
  522. y: _item2.Value
  523. })
  524. }
  525. })
  526. })
  527. real_data.sort((x,y) => x-y);
  528. //悬浮窗 拼接日期 原始指标名称
  529. let tooltip = {
  530. formatter: function() {
  531. const that: any = this;
  532. return language.value=='ch'?
  533. `<strong>${ tmpData_date[that.x+'_'+that.y].length > 4 ? tmpData_date[that.x+'_'+that.y].slice(0,4).join()+'...' : tmpData_date[that.x+'_'+that.y].join() }</strong><br>
  534. ${dataList[0].EdbName}: <span style="font-weight: 600"> ${that.x}</span><br>
  535. ${dataList[1].EdbName}: <span style="font-weight: 600"> ${that.y}</span>
  536. `:
  537. `<strong>${ tmpData_date[that.x+'_'+that.y].length > 4 ? tmpData_date[that.x+'_'+that.y].slice(0,4).join()+'...' : tmpData_date[that.x+'_'+that.y].join() }</strong><br>
  538. ${dataList[0].EdbNameEn}: <span style="font-weight: 600"> ${that.x}</span><br>
  539. ${dataList[1].EdbNameEn}: <span style="font-weight: 600"> ${that.y}</span>
  540. `
  541. }
  542. }
  543. const { IsOrder,ChartColor } = dataList[0];
  544. //y轴
  545. let yAxis = {
  546. title: {
  547. text: language.value=='ch'?`${dataList[1].Unit}`:dataList[1].Unit?dataList[1].UnitEn:'',
  548. // text: null,
  549. align: 'high',
  550. rotation: 0,
  551. y: -5,
  552. x:0,
  553. textAlign: 'left',
  554. reserveSpace: false,
  555. style:{
  556. ...chartTheme&&chartTheme.yAxisOptions.style
  557. },
  558. },
  559. labels: {
  560. formatter: function (ctx: any) {
  561. return ctx.value;
  562. },
  563. align: 'center',
  564. style:{
  565. ...chartTheme&&chartTheme.yAxisOptions.style
  566. },
  567. },
  568. opposite: false,
  569. reversed: IsOrder,
  570. min: Number(dataList[0].MinData),
  571. max: Number(dataList[0].MaxData),
  572. tickWidth: 1,
  573. tickLength: 5,
  574. lineWidth: 1,
  575. lineColor: '#bfbfbf',
  576. tickColor: '#bfbfbf',
  577. offset: 0,
  578. visible: true,
  579. gridLineWidth: 0,
  580. tickPosition: 'inside',
  581. endOnTick: false,
  582. startOnTick: false,
  583. showLastLabel: true,
  584. tickPixelInterval: 50,
  585. plotBands: setAxisPlotAreas(1),
  586. plotLines: setAxisPlotLines(1)
  587. }
  588. //数据列
  589. let series: any = {
  590. data: [],
  591. type: 'scatter',
  592. name: language.value == 'ch'?`${chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`:`${chartInfo.ChartNameEn}${IsOrder ? '(reserve)' : ''}`,
  593. color: ChartColor,
  594. chartType: 'linear',
  595. marker: {
  596. radius: (chartTheme&&chartTheme.lineOptions.radius)||5,
  597. },
  598. }
  599. real_data.forEach(_ => {
  600. series.data.push([_.x,_.y])
  601. })
  602. return {
  603. title: {
  604. text:''
  605. },
  606. series: [ series ],
  607. yAxis,
  608. xAxis: {
  609. ...scatterXAxis,
  610. title: {
  611. text: language.value=='ch'?`${dataList[0].Unit}`:dataList[0].Unit?dataList[0].UnitEn:'',
  612. align: 'high',
  613. rotation: 0,
  614. x: 0,
  615. offset: 20,
  616. style: {
  617. ...chartTheme&&chartTheme.xAxisOptions.style
  618. },
  619. },
  620. labels: {
  621. style: {
  622. ...chartTheme&&chartTheme.xAxisOptions.style
  623. }
  624. },
  625. plotBands: setAxisPlotAreas(3),
  626. plotLines: setAxisPlotLines(3)
  627. },
  628. tooltip
  629. }
  630. }
  631. /* 奇怪柱状图
  632. 获取图表详情后赋值奇怪柱状图数据 */
  633. const barChartRenderData = ref<any>({})
  634. const initBarData = (data: { XEdbIdValue: number[]; YDataList: any; EdbInfoList: any; ChartInfo: any; }) => {
  635. const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data;
  636. barChartRenderData.value = {
  637. barDateList: YDataList,
  638. barXIdData: XEdbIdValue,
  639. barEdbData: EdbInfoList,
  640. chartInfo: ChartInfo
  641. }
  642. state.chartLimit = {
  643. min: Number(ChartInfo.LeftMin),
  644. max: Number(ChartInfo.LeftMax),
  645. }
  646. return setBarChart()
  647. }
  648. const setBarChart = () => {
  649. const {barDateList,barXIdData,chartLimit,barEdbData,chartInfo} = barChartRenderData.value;
  650. let seriesData: { data: any; type: string; yAxis: number; name: any; color: any; chartType: string; }[] = [];
  651. const data = _.cloneDeep(barDateList);
  652. /* 主题样式*/
  653. const chartTheme = chartInfo.ChartThemeStyle ? JSON.parse(chartInfo.ChartThemeStyle) : null;
  654. let categories = language.value==='ch'
  655. ? barXIdData.map((_:number) => barEdbData.find((edb: { EdbInfoId: number; }) => edb.EdbInfoId===_).EdbAliasName)
  656. : barXIdData.map((_:number) => barEdbData.find((edb: { EdbInfoId: number; }) => edb.EdbInfoId===_).EdbNameEn)
  657. //x轴
  658. let xAxis = {
  659. ...scatterXAxis,
  660. categories,
  661. tickWidth: 1,
  662. labels: {
  663. style: {
  664. ...chartTheme&&chartTheme.xAxisOptions.style
  665. }
  666. }
  667. }
  668. const { max,min } = chartLimit;
  669. console.log(max,min)
  670. //y轴
  671. let yAxis = {
  672. ...basicYAxis,
  673. title: {
  674. text: language.value==='ch' ? chartInfo.Unit : chartInfo.UnitEn,
  675. align: 'high',
  676. rotation: 0,
  677. y: -12,
  678. x:0,
  679. textAlign: 'left',
  680. reserveSpace: false,
  681. style:{
  682. ...chartTheme&&chartTheme.yAxisOptions.style
  683. },
  684. },
  685. labels: {
  686. formatter: function (ctx:any) {
  687. let val = ctx.value;
  688. return val;
  689. },
  690. align: 'center',
  691. style:{
  692. ...chartTheme&&chartTheme.yAxisOptions.style
  693. },
  694. },
  695. min: Number(min),
  696. max: Number(max),
  697. opposite: false,
  698. tickWidth: 1,
  699. plotBands: setAxisPlotAreas(1),
  700. plotLines: setAxisPlotLines(1)
  701. }
  702. //数据列
  703. data.forEach((item: { Value: number; Name: string; Date: string; Color: string; }) => {
  704. let serie_item = {
  705. data: item.Value,
  706. type: 'column',
  707. yAxis: 0,
  708. name: language.value==='ch' ? (item.Name || item.Date) : item.Date,
  709. color: item.Color,
  710. chartType: 'linear'
  711. };
  712. seriesData.push(serie_item)
  713. })
  714. return {
  715. title: {
  716. text:''
  717. },
  718. plotOptions: {
  719. column:{
  720. stacking: null,
  721. },
  722. },
  723. series: seriesData,
  724. yAxis: [ yAxis ],
  725. xAxis
  726. }
  727. }
  728. /* 散点截面图 */
  729. const sectionScatterRenderData = ref<any>({});
  730. const initSectionScatterData = (data: { DataResp:any,EdbInfoList:any[] }) => {
  731. sectionScatterRenderData.value = data.DataResp;
  732. state.chartLimit.min=Number(data.DataResp.YMinValue)
  733. state.chartLimit.max=Number(data.DataResp.YMaxValue)
  734. state.chartLimit.x_min=Number(data.DataResp.XMinValue)
  735. state.chartLimit.x_max=Number(data.DataResp.XMaxValue)
  736. //校验英文名称是否完整
  737. if(routeQuery.value.fromPage === 'en' && language.value==='en') {
  738. const { XNameEn,XUnitNameEn,YNameEn,YUnitNameEn } = data.DataResp;
  739. // DataList可能是null
  740. const DataList = data.DataResp.DataList||[]
  741. let isAllEn = true;
  742. if(!XNameEn || !XUnitNameEn || !YNameEn || !YUnitNameEn) isAllEn = false;
  743. if(DataList.some(_ => !_.NameEn)) isAllEn = false;
  744. console.log(isAllEn)
  745. language.value = isAllEn ? 'en' : 'ch';
  746. }
  747. return setSectionScatterChart()
  748. }
  749. /* 截面散点图设置 sectionScatterData */
  750. const setSectionScatterChart = () => {
  751. const { chartLimit } = state;
  752. const { DataList,XName,XNameEn,YName,YNameEn } = sectionScatterRenderData.value;
  753. /* 主题样式*/
  754. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  755. if(!DataList){
  756. return
  757. }
  758. const { min,max,x_min,x_max } = chartLimit;
  759. //y轴
  760. let yAxis = {
  761. ...basicYAxis,
  762. title: {
  763. text: language.value === 'ch' ? YName : YNameEn,
  764. align: 'middle',
  765. style:{
  766. ...chartTheme&&chartTheme.yAxisOptions.style
  767. },
  768. },
  769. labels: {
  770. style:{
  771. ...chartTheme&&chartTheme.yAxisOptions.style
  772. },
  773. },
  774. opposite: false,
  775. reversed: false,
  776. min: Number(min),
  777. max: Number(max),
  778. tickWidth: 1,
  779. plotBands: setAxisPlotAreas(1),
  780. plotLines: setAxisPlotLines(1)
  781. }
  782. //x轴
  783. let xAxis = {
  784. ...scatterXAxis,
  785. title: {
  786. text: language.value === 'ch' ? XName : XNameEn,
  787. align: 'middle',
  788. style: {
  789. ...chartTheme&&chartTheme.xAxisOptions.style
  790. },
  791. },
  792. labels: {
  793. style:{
  794. ...chartTheme&&chartTheme.xAxisOptions.style
  795. },
  796. },
  797. min: Number(x_min),
  798. max: Number(x_max),
  799. plotBands: setAxisPlotAreas(3),
  800. plotLines: setAxisPlotLines(3)
  801. }
  802. //数据列
  803. let series: any[] = [];
  804. DataList.forEach(item => {
  805. //数据列
  806. let series_item = {
  807. data: [] as any[],
  808. type: 'scatter',
  809. name: language.value === 'ch' ? item.Name : item.NameEn,
  810. color: item.Color,
  811. lineWidth: 0,
  812. chartType: 'linear',
  813. zIndex:1,
  814. marker: {
  815. radius: (chartTheme&&chartTheme.lineOptions.radius)||5,
  816. },
  817. visible: true
  818. }
  819. item.EdbInfoList.forEach(_ => {
  820. series_item.data.push({
  821. x: _.XValue,
  822. y: _.YValue,
  823. dataLabels: {
  824. enabled: _.IsShow,
  825. allowOverlap: true,
  826. align: 'left',
  827. format: language.value === 'ch' ? _.Name : _.NameEn
  828. }
  829. })
  830. })
  831. series.push(series_item);
  832. //趋势线
  833. if(item.ShowTrendLine) {
  834. let trend_data = item.TrendLimitData.map((_,_index) => (
  835. _index === item.TrendLimitData.length-1 ? {
  836. x: _.X,
  837. y: _.Y,
  838. dataLabels: {
  839. enabled: item.ShowRSquare || item.ShowFitEquation,
  840. align: 'left',
  841. color: '#666',
  842. x: 20,
  843. y: 30,
  844. zIndex: 9,
  845. allowOverlap: true,
  846. formatter: function(){
  847. let tag = '';
  848. item.ShowRSquare && item.ShowFitEquation
  849. ? tag =`<span>${item.TrendLine}</span><br><span>R²=${item.RSquare}</span>`
  850. : item.ShowRSquare && !item.ShowFitEquation
  851. ? tag =`<span>R²=${item.RSquare}</span>`
  852. : item.ShowFitEquation && !item.ShowRSquare
  853. ? tag =`<span>${item.TrendLine}</span>`
  854. : ''
  855. return tag
  856. }
  857. }
  858. } : {
  859. x: _.X,
  860. y: _.Y,
  861. }
  862. ))
  863. let trend_item = {
  864. data: trend_data,
  865. type: 'spline',
  866. linkedTo: ':previous',
  867. color: item.Color,
  868. lineWidth: 1,
  869. chartType: 'linear',
  870. enableMouseTracking: false,
  871. dashStyle:'Dash',
  872. zIndex: 2,
  873. visible: true,
  874. marker: {
  875. enabled: false
  876. }
  877. }
  878. series.push(trend_item)
  879. }
  880. })
  881. let tooltip = {
  882. formatter: function() {
  883. const that:any = this;
  884. let str = '';
  885. if(language.value === 'ch') {
  886. let series_obj = DataList.find(_ => _.Name === that.series.name);
  887. let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===that.x && _.YValue===that.y);
  888. str=`<b>${ ponit_obj.Name }</b>`;
  889. str += `<br><span style="color:${that.color}">\u25CF</span>${ponit_obj.XName}: ${that.x} ${ponit_obj.XDate}<br>`;
  890. str += `<span style="color:${that.color}">\u25CF</span>${ponit_obj.YName}: ${that.y} ${ponit_obj.YDate}`;
  891. }else {
  892. let series_obj = DataList.find(_ => _.NameEn === that.series.name);
  893. let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===that.x && _.YValue===that.y);
  894. str=`<b>${ ponit_obj.NameEn }</b>`;
  895. str += `<br><span style="color:${that.color}">\u25CF</span>${ponit_obj.XNameEn}: ${that.x} ${ponit_obj.XDate}<br>`;
  896. str += `<span style="color:${that.color}">\u25CF</span>${ponit_obj.YNameEn}: ${that.y} ${ponit_obj.YDate}`;
  897. }
  898. return str
  899. }
  900. }
  901. return {
  902. title: {
  903. text:''
  904. },
  905. series,
  906. yAxis: [yAxis],
  907. xAxis,
  908. tooltip
  909. }
  910. }
  911. /* 商品价格曲线/利润曲线
  912. */
  913. const commodityChartRenderData = ref<any>({})
  914. const initCommodityData = (data: { XDataList: any[]; YDataList: any; EdbInfoList: any; ChartInfo: any; DataResp?:any }) => {
  915. const { XDataList,YDataList,EdbInfoList,ChartInfo,DataResp } = data;
  916. commodityChartRenderData.value = {
  917. commodityEdbList: EdbInfoList,
  918. commodityChartData: ChartInfo.Source===5?DataResp.YDataList:YDataList,
  919. commodityXData: ChartInfo.Source===5?DataResp.XDataList:XDataList
  920. }
  921. if(ChartInfo.Source===5) {
  922. state.chartInfo = {
  923. ...state.chartInfo,
  924. ProfitName: DataResp.ProfitName,
  925. ProfitNameEn: DataResp.ProfitNameEn
  926. }
  927. }
  928. state.chartLimit = {
  929. min: Number(ChartInfo.LeftMin),
  930. max: Number(ChartInfo.LeftMax)
  931. }
  932. return setCommodityChart();
  933. }
  934. /* 商品价格曲线设置 绘图逻辑同奇怪柱形图*/
  935. const setCommodityChart = () => {
  936. const {chartLimit,chartInfo} = state;
  937. const { commodityChartData,commodityXData,commodityEdbList } = commodityChartRenderData.value;
  938. let seriesData:any[] = [];
  939. const data = _.cloneDeep(commodityChartData);
  940. /* 主题样式*/
  941. const chartTheme = chartInfo.ChartThemeStyle ? JSON.parse(chartInfo.ChartThemeStyle) : null;
  942. //x轴
  943. let xAxis = {
  944. ...scatterXAxis,
  945. categories: commodityXData.map(_ => language.value === 'ch' ? _.Name:_.NameEn),
  946. tickWidth: 1,
  947. labels: {
  948. style: {
  949. ...chartTheme&&chartTheme.xAxisOptions.style
  950. }
  951. }
  952. }
  953. const { max,min } = chartLimit;
  954. //y轴
  955. let yAxis = {
  956. ...basicYAxis,
  957. title: {
  958. text: language.value === 'ch' ? commodityEdbList[0].Unit : commodityEdbList[0].UnitEn,
  959. align: 'high',
  960. rotation: 0,
  961. y: -12,
  962. textAlign: 'left',
  963. reserveSpace: false,
  964. style:{
  965. ...chartTheme&&chartTheme.yAxisOptions.style
  966. },
  967. },
  968. labels: {
  969. formatter: function (ctx:any) {
  970. let val = ctx.value;
  971. return val;
  972. },
  973. align: 'center',
  974. style:{
  975. ...chartTheme&&chartTheme.yAxisOptions.style
  976. },
  977. },
  978. min: Number(min),
  979. max: Number(max),
  980. opposite: false,
  981. tickWidth: 1,
  982. }
  983. //数据列
  984. data.forEach((item: { Value: number[]; Name: string; Date: string; Color: string;NameEn: string,XEdbInfoIdList: number[],NoDataEdbList: number[] }) => {
  985. //处理首或/尾全是无效数据的以null填充
  986. let filterData = filterInvalidData(item)
  987. let serie_item = {
  988. data: filterData,
  989. type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
  990. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  991. yAxis: 0,
  992. name: language.value === 'ch' ? item.Name : item.NameEn,
  993. color: item.Color,
  994. chartType: 'linear',
  995. lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 3,
  996. marker: {
  997. enabled: false
  998. }
  999. };
  1000. seriesData.push(serie_item)
  1001. })
  1002. //tooltip
  1003. let tooltip = {
  1004. formatter: function() {
  1005. const ctx: any = this;
  1006. let str: string = '';
  1007. if(language.value === 'ch') {
  1008. ctx.points.forEach((item: { series:{name: string},y: number,color: string }) => {
  1009. let obj_item = data.find((_:any) => _.Name === item.series.name);
  1010. let index = commodityXData.findIndex(_ => _.Name === ctx.x);
  1011. //合约显示
  1012. let haveContract = obj_item.XEdbInfoIdList[index];
  1013. if(haveContract) {
  1014. // 利润曲线指标名
  1015. let edb_name = chartInfo.Source === 5
  1016. ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitName}(${obj_item.NameList[index]})`)
  1017. : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbName;
  1018. str+=`<b>${ edb_name }</b>`
  1019. if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) {
  1020. str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: ${item.y}<br>`
  1021. }else {
  1022. str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: 无<br>`
  1023. }
  1024. }
  1025. })
  1026. }else {
  1027. ctx.points.forEach((item: { series:{name: string},y: number,color: string }) => {
  1028. let obj_item = data.find((_: any) => _.NameEn === item.series.name);
  1029. let index = commodityXData.findIndex(_ => _.NameEn === ctx.x);
  1030. let haveContract = obj_item.XEdbInfoIdList[index];
  1031. if(haveContract) {
  1032. let edb_name = chartInfo.Source === 5
  1033. ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitNameEn}(${obj_item.NameList[index]})`)
  1034. : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbNameEn;
  1035. str+=`<b>${ edb_name }</b>`
  1036. if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) {
  1037. str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: ${item.y}<br>`
  1038. }else {
  1039. str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: 无<br>`
  1040. }
  1041. }
  1042. })
  1043. }
  1044. return str || '无合约'
  1045. },
  1046. shared: true
  1047. }
  1048. return {
  1049. title: {
  1050. text:''
  1051. },
  1052. series: seriesData,
  1053. yAxis: [ yAxis ],
  1054. xAxis,
  1055. tooltip
  1056. }
  1057. };
  1058. /* 处理无效数据为null */
  1059. const filterInvalidData = (item:{ Value: number[]; Name: string; Date: string; Color: string;NameEn: string,XEdbInfoIdList: number[],NoDataEdbList: number[] })=> {
  1060. let validateArr = item.XEdbInfoIdList.filter(_ => _&&!item.NoDataEdbList.includes(_));
  1061. let first_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[0]);
  1062. let last_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[validateArr.length-1]);
  1063. console.log('first_index',first_index)
  1064. console.log('last_index',last_index)
  1065. let arr = item.Value.map((item,index:number) => {
  1066. if(index < first_index || index > last_index) {
  1067. return null
  1068. }else {
  1069. return item
  1070. }
  1071. })
  1072. return arr;
  1073. }
  1074. /* 相关性图表 */
  1075. const initRelevanceChartData=(data)=>{
  1076. /* 主题样式*/
  1077. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  1078. const relevanceUnitEnMap={
  1079. '年': 'Year',
  1080. '季': 'Season',
  1081. '月': 'Month',
  1082. '周': 'Week',
  1083. '天': 'Day',
  1084. }
  1085. // 处理X轴
  1086. let xAxis={
  1087. categories: data.ChartInfo.Source===3 ? data.XEdbIdValue : data.DataResp.XDateTimeValue,
  1088. tickWidth: 1,
  1089. title: {
  1090. text: data.ChartInfo.Source===3 ? (language.value=='ch'?`期数(${data.CorrelationChartInfo.LeadUnit})`:`stage(${relevanceUnitEnMap[data.CorrelationChartInfo.LeadUnit]})`):null,
  1091. align: 'high',
  1092. rotation: 0,
  1093. style: {
  1094. ...chartTheme&&chartTheme.xAxisOptions.style
  1095. }
  1096. },
  1097. labels: {
  1098. style: {
  1099. ...chartTheme&&chartTheme.xAxisOptions.style
  1100. }
  1101. },
  1102. tickInterval: 1,
  1103. offset:0,
  1104. tickmarkPlacement:'on'
  1105. }
  1106. // 处理Y轴
  1107. let yAxis={
  1108. ...basicYAxis,
  1109. title: {
  1110. text: language.value=='ch'?'相关性系数':'Correlation coefficient',
  1111. align: 'high',
  1112. rotation: 0,
  1113. y: -12,
  1114. textAlign: 'left',
  1115. reserveSpace: false,
  1116. style:{
  1117. ...chartTheme&&chartTheme.yAxisOptions.style
  1118. },
  1119. },
  1120. labels: {
  1121. formatter: function (ctx) {
  1122. let val = ctx.value;
  1123. return val;
  1124. },
  1125. align: 'center',
  1126. style:{
  1127. ...chartTheme&&chartTheme.yAxisOptions.style
  1128. },
  1129. },
  1130. opposite: false,
  1131. tickWidth: 1,
  1132. }
  1133. //处理series
  1134. let seriesData:any[]=[]
  1135. data.YDataList.forEach(item=>{
  1136. let serie_item = {
  1137. data: item.Value,
  1138. type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
  1139. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  1140. yAxis: 0,
  1141. name: language.value=='ch'?data.ChartInfo.ChartName:data.ChartInfo.ChartNameEn,
  1142. color: item.Color,
  1143. chartType: 'linear',
  1144. lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 3,
  1145. marker: {
  1146. enabled: false
  1147. }
  1148. };
  1149. seriesData.push(serie_item)
  1150. })
  1151. const { LeadValue,LeadUnit } = data.CorrelationChartInfo;
  1152. let tooltip = {
  1153. formatter: function() {
  1154. const that:any = this;
  1155. let str='';
  1156. if(language.value=='ch'){
  1157. str = `<p>相关性系数:${that.y.toFixed(4)}</p><br><p>领先${ data.ChartInfo.Source===3 ?that.x+'期' : LeadValue+LeadUnit}</p>`
  1158. }else{
  1159. str = `<p>Correlation coefficient:${that.y.toFixed(4)}</p><br><p>lead${ data.ChartInfo.Source===3 ? that.x+'stage' : LeadValue+relevanceUnitEnMap[LeadUnit]}</p>`
  1160. }
  1161. return str
  1162. },
  1163. }
  1164. return {
  1165. isRelevanceChart:data.ChartInfo.Source===3,
  1166. title: {
  1167. text:'',
  1168. },
  1169. series: seriesData,
  1170. yAxis: [yAxis] ,
  1171. xAxis:xAxis,
  1172. tooltip
  1173. }
  1174. }
  1175. /* 统计特征
  1176. 标准差
  1177. 百分比
  1178. 频率
  1179. 滚动相关性*/
  1180. const statisticFrequencyRenderData = ref<any>({});
  1181. const initStatisticChartData = (data: { DataResp:any,ChartInfo:any,CorrelationChartInfo:any }) => {
  1182. if(data.ChartInfo.Source === 9) { //频率图
  1183. statisticFrequencyRenderData.value = data.DataResp;
  1184. return setStatisticFrequency();
  1185. }else {
  1186. state.dataList = [data.DataResp];
  1187. if(data.ChartInfo.Source === 4) statisticFrequencyRenderData.value = data.CorrelationChartInfo;
  1188. return setDefaultLineOptions();
  1189. }
  1190. }
  1191. /* 统计频率图 */
  1192. const setStatisticFrequency = () => {
  1193. const { DataList,LeftMaxValue,LeftMinValue,RightMaxValue,RightMinValue } = statisticFrequencyRenderData.value
  1194. if(!DataList){
  1195. return
  1196. }
  1197. /* 主题样式*/
  1198. const chartTheme = state.chartInfo.ChartThemeStyle ? JSON.parse(state.chartInfo.ChartThemeStyle) : null;
  1199. let xAxis = {
  1200. ...scatterXAxis,
  1201. tickWidth: 1,
  1202. labels: {
  1203. style: {
  1204. ...chartTheme&&chartTheme.xAxisOptions.style
  1205. }
  1206. }
  1207. }
  1208. //y和系列
  1209. let yAxis:any[] = [],series:any[] = [];
  1210. DataList.forEach((item,index) => {
  1211. let y_item = {
  1212. ...basicYAxis,
  1213. title: {
  1214. text: language.value === 'ch' ? item.Unit : item.UnitEn,
  1215. align: 'high',
  1216. rotation: 0,
  1217. y: -12,
  1218. reserveSpace: false,
  1219. style:{
  1220. ...chartTheme&&chartTheme.yAxisOptions.style
  1221. },
  1222. },
  1223. labels: {
  1224. style:{
  1225. ...chartTheme&&chartTheme.yAxisOptions.style
  1226. },
  1227. },
  1228. opposite: item.IsAxis===1?false:true,
  1229. min: index===0? Number(LeftMinValue):Number(RightMinValue),
  1230. max: index===0? Number(LeftMaxValue):Number(RightMaxValue),
  1231. tickWidth: 1,
  1232. }
  1233. let series_item = {
  1234. data: item.Value.map(_ =>[_.X,_.Y]),
  1235. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  1236. type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
  1237. yAxis: index,
  1238. name: language.value === 'ch' ? item.Name : item.NameEn,
  1239. color: item.Color,
  1240. lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth)||3,
  1241. chartType: 'linear',
  1242. zIndex:1
  1243. }
  1244. series.push(series_item);
  1245. yAxis.push(y_item)
  1246. })
  1247. let tooltip = {
  1248. formatter: function() {
  1249. let that:any = this;
  1250. let xList = DataList[0].Value.map(_ =>_.X);
  1251. let step = xList[1]-xList[0];
  1252. let data_interval = `[${Number(that.x).toFixed(2)},${Number(that.x+step).toFixed(2)}]`;
  1253. let str=`<b>${ data_interval }</b>`;
  1254. that.points.forEach(item => {
  1255. str += `<br><span style="color:${item.color}">\u25CF</span>${item.series.name}: ${item.y}%`
  1256. })
  1257. return str
  1258. },
  1259. shared: true
  1260. }
  1261. return {
  1262. title: {
  1263. text:''
  1264. },
  1265. tooltip,
  1266. series,
  1267. yAxis,
  1268. xAxis
  1269. }
  1270. }
  1271. /* 拟合方程曲线 曲线图绘图逻辑*/
  1272. const initFittingEquation = (data) => {
  1273. state.dataList = [data.DataResp];
  1274. return setDefaultLineOptions();
  1275. }
  1276. /* 跨品种分析 */
  1277. const crossVarietyChartRenderData = ref<any>({})
  1278. const initCrossVarietyChartData = (data:{ DataResp:any,ChartInfo:any,EdbInfoList:any }) => {
  1279. state.dataList = data.EdbInfoList;
  1280. crossVarietyChartRenderData.value = data.DataResp;
  1281. state.chartLimit.min=Number(data.DataResp.YMinValue)
  1282. state.chartLimit.max=Number(data.DataResp.YMaxValue)
  1283. state.chartLimit.x_min=Number(data.DataResp.XMinValue)
  1284. state.chartLimit.x_max=Number(data.DataResp.XMaxValue)
  1285. //二次校验英文配置是否完整
  1286. if(routeQuery.value.fromPage === 'en' && language.value==='en') {
  1287. const { XNameEn,YNameEn,DataList } = data.DataResp;
  1288. let isAllEn = true;
  1289. let haveOneNoEn = DataList.some(_ => !_.NameEn);
  1290. if(!XNameEn || !YNameEn || haveOneNoEn) isAllEn = false;
  1291. language.value = isAllEn ? 'en' : 'ch';
  1292. }
  1293. return setCrossVarietyChart()
  1294. }
  1295. /* 跨品种分析 */
  1296. const setCrossVarietyChart = () => {
  1297. const { chartLimit,dataList,chartInfo } = state;
  1298. /* 主题样式*/
  1299. const chartTheme = chartInfo.ChartThemeStyle ? JSON.parse(chartInfo.ChartThemeStyle) : null;
  1300. const { min,max,x_min,x_max } = chartLimit;
  1301. const { DataList,XName,YName,XNameEn,YNameEn } = crossVarietyChartRenderData.value;
  1302. //y轴
  1303. let yAxis = {
  1304. ...basicYAxis,
  1305. title: {
  1306. text: language.value === 'ch' ? YName : YNameEn,
  1307. align: 'middle',
  1308. style: {
  1309. ...chartTheme&&chartTheme.xAxisOptions.style
  1310. }
  1311. },
  1312. labels: {
  1313. style: {
  1314. ...chartTheme&&chartTheme.xAxisOptions.style
  1315. }
  1316. },
  1317. opposite: false,
  1318. reversed: false,
  1319. min: Number(min),
  1320. max: Number(max),
  1321. tickWidth: 1,
  1322. }
  1323. // x轴
  1324. let xAxis = {
  1325. ...scatterXAxis,
  1326. title: {
  1327. text: language.value === 'ch' ? XName : XNameEn,
  1328. align: 'middle',
  1329. style: {
  1330. ...chartTheme&&chartTheme.xAxisOptions.style
  1331. }
  1332. },
  1333. labels: {
  1334. style: {
  1335. ...chartTheme&&chartTheme.xAxisOptions.style
  1336. }
  1337. },
  1338. min: Number(x_min),
  1339. max: Number(x_max),
  1340. }
  1341. //数据列
  1342. let series:any[] = [];
  1343. DataList.forEach(item => {
  1344. //数据列
  1345. let series_item = {
  1346. data: [] as any[],
  1347. type: 'scatter',
  1348. name: language.value === 'ch' ? item.Name : item.NameEn,
  1349. color: item.Color,
  1350. lineWidth: 0,
  1351. chartType: 'linear',
  1352. zIndex:1
  1353. }
  1354. item.CoordinatePointData.forEach(_ => {
  1355. series_item.data.push({x: _.X,y: _.Y,})
  1356. })
  1357. series.push(series_item);
  1358. })
  1359. let tooltip = {
  1360. formatter: function() {
  1361. let that:any = this;
  1362. let str = '';
  1363. if(language.value === 'ch') {
  1364. let series_obj = DataList.find(_ => _.Name === that.series.name);
  1365. let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===that.x && _.Y===that.y);
  1366. let xEdbInfo = dataList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
  1367. let yEdbInfo = dataList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
  1368. str=`<b>${ that.series.name }</b>`;
  1369. str += `<br><span style="color:${that.color}">\u25CF</span>${xEdbInfo.EdbName}: ${that.x} ${ponit_obj.XDate}<br>`;
  1370. str += `<span style="color:${that.color}">\u25CF</span>${yEdbInfo.EdbName}: ${that.y} ${ponit_obj.YDate}`;
  1371. }else {
  1372. let series_obj = DataList.find(_ => _.NameEn === that.series.name);
  1373. let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===that.x && _.Y===that.y);
  1374. let xEdbInfo = dataList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
  1375. let yEdbInfo = dataList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
  1376. str=`<b>${ that.series.name }</b>`;
  1377. str += `<br><span style="color:${that.color}">\u25CF</span>${xEdbInfo.EdbNameEn}: ${that.x} ${ponit_obj.XDate}<br>`;
  1378. str += `<span style="color:${that.color}">\u25CF</span>${yEdbInfo.EdbNameEn}: ${that.y} ${ponit_obj.YDate}`;
  1379. }
  1380. return str
  1381. }
  1382. }
  1383. return {
  1384. title: {
  1385. text:''
  1386. },
  1387. series,
  1388. yAxis: [yAxis],
  1389. xAxis,
  1390. tooltip
  1391. }
  1392. }
  1393. /* 雷达图 */
  1394. const radarChartRenderData = ref<any>({})
  1395. const initRadarData = (data) => {
  1396. const { DataResp,EdbInfoList,ChartInfo } = data;
  1397. radarChartRenderData.value = {
  1398. YDataList: DataResp.YDataList,
  1399. XDataList: EdbInfoList.filter(_ => DataResp.XEdbIdValue.includes(_.EdbInfoId))
  1400. }
  1401. state.chartLimit.min=Number(ChartInfo.LeftMin)
  1402. state.chartLimit.max=Number(ChartInfo.LeftMax)
  1403. return setRadarChart();
  1404. }
  1405. const setRadarChart = () => {
  1406. const { YDataList,XDataList } = radarChartRenderData.value;
  1407. const { chartLimit,dataList,chartInfo } = state;
  1408. /* 主题样式*/
  1409. const chartTheme = chartInfo.ChartThemeStyle ? JSON.parse(chartInfo.ChartThemeStyle) : null;
  1410. let categories = language.value==='ch'
  1411. ? XDataList.map(_ => _.EdbAliasName||_.EdbName)
  1412. : XDataList.map(_ => _.EdbNameEn)
  1413. //x轴
  1414. let xAxis = {
  1415. lineWidth: 0,
  1416. tickLength: 0,
  1417. tickmarkPlacement: 'on',
  1418. categories,
  1419. labels: {
  1420. allowOverlap: true,
  1421. autoRotationLimit: 40,
  1422. style: {
  1423. ...chartTheme&&chartTheme.xAxisOptions.style
  1424. }
  1425. }
  1426. }
  1427. //y轴
  1428. const { max,min } = chartLimit;
  1429. let yAxis = [{
  1430. gridLineInterpolation: 'polygon',
  1431. gridLineWidth: 1,
  1432. lineWidth: 0,
  1433. endOnTick: false,
  1434. startOnTick: false,
  1435. showLastLabel: true,
  1436. // tickAmount:4,
  1437. title: {
  1438. text: language.value==='ch' ? chartInfo.Unit : chartInfo.UnitEn,
  1439. align: 'high',
  1440. rotation: 0,
  1441. y: 5,
  1442. x:10,
  1443. textAlign: 'left',
  1444. reserveSpace: false,
  1445. style:{
  1446. ...chartTheme&&chartTheme.yAxisOptions.style
  1447. },
  1448. },
  1449. labels: {
  1450. allowOverlap: true,
  1451. style:{
  1452. ...chartTheme&&chartTheme.yAxisOptions.style
  1453. }
  1454. },
  1455. min: Number(min),
  1456. max: Number(max),
  1457. }]
  1458. //系列
  1459. let series:any[] = [];
  1460. YDataList.forEach(item => {
  1461. let serie_item = {
  1462. data: item.Value,
  1463. pointPlacement: 'on',
  1464. type: (chartTheme&&chartTheme.lineOptions.lineType) || 'line',
  1465. dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
  1466. yAxis: 0,
  1467. name: language.value==='ch' ? (item.Name || item.Date) : item.Date,
  1468. color: item.Color,
  1469. lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 1,
  1470. chartType: 'linear'
  1471. };
  1472. series.push(serie_item)
  1473. })
  1474. return {
  1475. chart: {
  1476. ...defaultOpts.chart,
  1477. ...chartTheme.drawOption,
  1478. spacing: [2,10,2,10],
  1479. polar:true,
  1480. },
  1481. title: {
  1482. text:''
  1483. },
  1484. pane: {
  1485. size: '85%'
  1486. },
  1487. series,
  1488. yAxis,
  1489. xAxis
  1490. }
  1491. }
  1492. // 曲线图x轴显示计算年限差 >1年 显示年/月 <=1 显示月/日
  1493. const xTimeDiffer = () => {
  1494. const end_date = state.chartInfo.DateType === 5
  1495. ? state.chartInfo.EndDate
  1496. : state.chartInfo.DateType === 6
  1497. ? new Date()
  1498. : '';
  1499. //年限差
  1500. const year_differ = moment(end_date).diff(
  1501. moment(state.chartInfo.StartDate),
  1502. 'years',
  1503. true
  1504. );
  1505. // console.log(year_differ)
  1506. if ([5, 6].includes(state.chartInfo.DateType) && year_differ <= 1) {
  1507. return true
  1508. } else {
  1509. return false
  1510. }
  1511. }
  1512. /* 设置x轴步长 刻度数量多一点 */
  1513. const setXaxisStep = (timestamp: number) => {
  1514. return timestamp / 6;
  1515. }
  1516. /* 指标顺序调整 IsAxis: 0右轴 1左轴 2右2*/
  1517. const changeEdbOrder = (data: any[]) => {
  1518. // 左轴指标
  1519. let left_edbs = data.filter(_ => _.IsAxis===1);
  1520. //右轴指标
  1521. let right_edbs = data.filter(_ => !_.IsAxis);
  1522. // 右2轴指标
  1523. let right_two_edbs = data.filter(_ => _.IsAxis === 2);
  1524. // 按 左 右 右2顺序排列
  1525. return [left_edbs,right_edbs,right_two_edbs].flat(Infinity);
  1526. }
  1527. /* 拼接动态的指标名称小标签 */
  1528. const concatDynamicTag = (
  1529. { IsAxis, IsOrder, EdbInfoType, LeadValue, LeadUnit }: IDataProps,
  1530. lang: String = "ch"
  1531. ): string => {
  1532. // IsAxis左轴1 右轴0 2右2轴
  1533. //IsOrder正序false 逆序true
  1534. //EdbInfoType是否是领先指标
  1535. const axisLabelMap: any =
  1536. lang == "ch"
  1537. ? {
  1538. 0: "右轴",
  1539. 2: "右2轴",
  1540. }
  1541. : {
  1542. 0: "RHS",
  1543. 2: "2-RHS",
  1544. };
  1545. const orderLabelMap: any =
  1546. lang == "ch"
  1547. ? {
  1548. 1: "逆序",
  1549. }
  1550. : {
  1551. 1: "REV",
  1552. };
  1553. const edbInfoMap: any =
  1554. lang == "ch"
  1555. ? {
  1556. 0: "领先",
  1557. }
  1558. : {
  1559. 0: "Lead",
  1560. };
  1561. const leadUnitEnMap: any = {
  1562. 年: "Y",
  1563. 季: "Q",
  1564. 月: "M",
  1565. 周: "W",
  1566. 天: "D",
  1567. };
  1568. //英文领先单位转换
  1569. const edbLeadUnit = lang == "ch" ? LeadUnit : leadUnitEnMap[LeadUnit];
  1570. let axis_tag = axisLabelMap[IsAxis] || "";
  1571. //逆序拼接
  1572. let order_tag = orderLabelMap[Number(IsOrder)]
  1573. ? `${axis_tag ? "," : ""}${orderLabelMap[Number(IsOrder)]}`
  1574. : "";
  1575. //领先拼接
  1576. let edb_tag = edbInfoMap[EdbInfoType]
  1577. ? `${axis_tag || order_tag ? "," : ""}${
  1578. edbInfoMap[EdbInfoType]
  1579. } ${LeadValue}${edbLeadUnit}`
  1580. : "";
  1581. return axis_tag || order_tag || edb_tag
  1582. ? `(${axis_tag}${order_tag}${edb_tag})`
  1583. : "";
  1584. };
  1585. /* 预测配置 分区 */
  1586. const getPredictParams = (
  1587. { LatestDate, MoveLatestDate, PredictChartColor, ChartStyle }: IDataProps,
  1588. chartStyle = ""
  1589. ) => {
  1590. return {
  1591. zoneAxis: "x",
  1592. zones: [
  1593. {
  1594. value: new Date(MoveLatestDate || LatestDate).getTime() + 1,
  1595. },
  1596. {
  1597. dashStyle: "ShortDot",
  1598. color:
  1599. ChartStyle === "column" || chartStyle === "column"
  1600. ? "transparent"
  1601. : PredictChartColor,
  1602. },
  1603. ],
  1604. };
  1605. };
  1606. /* 季节图预测数据 年份=分割点年份做分割 年份>分割点年份全为预测 */
  1607. const getSeasonPredictParams = (timestamp: number) => {
  1608. return timestamp
  1609. ? {
  1610. zoneAxis: "x",
  1611. zones: [
  1612. {
  1613. value: new Date(timestamp).getTime() + 1,
  1614. },
  1615. {
  1616. dashStyle: "ShortDot",
  1617. },
  1618. ],
  1619. }
  1620. : {};
  1621. };
  1622. /* 处理轴的标识线结构 在指定轴位置上拼接标识线
  1623. 0:右轴 1:左轴 2:右2轴 x轴固定3
  1624. axisType表示x轴类型 处理时间轴的值 datetime/null
  1625. */
  1626. const setAxisPlotLines = (axis: number, axisType: any = null) => {
  1627. const { MarkersLines, ChartType } = state.chartInfo;
  1628. if (!MarkersLines) return [];
  1629. let markerLines = JSON.parse(MarkersLines);
  1630. let arr = markerLines.filter((_) => _.isShow && _.axis === axis);
  1631. let plotLines = arr.map((_) => {
  1632. //是否是x时间轴
  1633. let isXDateAxis = axis === 3 && axisType === "datetime";
  1634. let markerValue:number;
  1635. if (isXDateAxis) {
  1636. //季节图x轴额外拼个年份
  1637. let nowYear = new Date().getFullYear();
  1638. markerValue =
  1639. ChartType === 2
  1640. ? new Date(`${nowYear}-${_.value}`).getTime()
  1641. : new Date(_.value).getTime();
  1642. } else {
  1643. markerValue = Number(_.value);
  1644. }
  1645. return {
  1646. value: markerValue,
  1647. dashStyle: _.dashStyle,
  1648. width: Number(_.lineWidth),
  1649. color: _.color,
  1650. label: {
  1651. text: _.text || "",
  1652. verticalAlign: _.textPosition,
  1653. style: {
  1654. color: _.textColor,
  1655. fontSize: _.textFontSize,
  1656. },
  1657. },
  1658. };
  1659. });
  1660. return plotLines;
  1661. };
  1662. /* 处理标识区拼接 axisType表示x轴类型处理时间轴的值 datetime/null */
  1663. const setAxisPlotAreas = (axis: number, axisType: any = null) => {
  1664. const { MarkersAreas, ChartType } = state.chartInfo;
  1665. if (!MarkersAreas) return [];
  1666. let markerAreas = JSON.parse(MarkersAreas);
  1667. let arr = markerAreas.filter((_) => _.isShow && _.axis === axis);
  1668. let plotBands = arr.map((_) => {
  1669. //是否是x时间轴
  1670. let isXDateAxis = axis === 3 && axisType === "datetime";
  1671. let fromMarkerValue:number, toMarkerValue:number;
  1672. if (isXDateAxis) {
  1673. //季节图x轴额外拼个年份
  1674. let nowYear = new Date().getFullYear();
  1675. fromMarkerValue =
  1676. ChartType === 2
  1677. ? new Date(`${nowYear}-${_.fromValue}`).getTime()
  1678. : new Date(_.fromValue).getTime();
  1679. toMarkerValue =
  1680. ChartType === 2
  1681. ? new Date(`${nowYear}-${_.toValue}`).getTime()
  1682. : new Date(_.toValue).getTime();
  1683. } else {
  1684. fromMarkerValue = Number(_.fromValue);
  1685. toMarkerValue = Number(_.toValue);
  1686. }
  1687. //默认label有些偏移 重新归正下
  1688. let positionMapValue = {
  1689. 'top': 12,
  1690. 'middle': 0,
  1691. 'bottom': -10
  1692. }
  1693. return {
  1694. from: fromMarkerValue,
  1695. to: toMarkerValue,
  1696. color: _.color,
  1697. label: {
  1698. text: _.text || "",
  1699. verticalAlign: _.textPosition,
  1700. y: positionMapValue[_.textPosition],
  1701. style: {
  1702. color: _.textColor,
  1703. fontSize: _.textFontSize,
  1704. },
  1705. },
  1706. };
  1707. });
  1708. return plotBands;
  1709. };