useChartRender.ts 54 KB

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