index.vue 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  1. <!-- -->
  2. <template>
  3. <div class="chart-show">
  4. <header class="chart-header" @click="openNew">
  5. <span class="chart-title" @click.stop @dblclick="copyText">{{ chartInfo.ChartType === 7 ? chartInfo.ChartName : language == 'ch'?chartInfo.ChartName: chartInfo.ChartNameEn}}</span>
  6. </header>
  7. <template v-if="haveData">
  8. <div
  9. class="chart-wrapper"
  10. id="chart-wrapper"
  11. v-loading="loading"
  12. element-loading-spinner="el-icon-loading"
  13. element-loading-text="加载中..."
  14. >
  15. <chart :options="options" :chartId="chartInfo.ChartInfoId || 0" />
  16. <div class="mark"></div>
  17. </div>
  18. </template>
  19. <div class="chart-wrapper notfound" v-else>
  20. <i class="el-icon-warning"></i>哎吆,你的图飞了,赶快去找管理员救命吧~
  21. </div>
  22. <div class="bootom-source">
  23. <strong style="flex-shrink: 0;">source: <em> {{sourceName}}弘则研究</em></strong>
  24. <ul class="right-action" @click.stop>
  25. <li v-if="$route.query.source==='ybxcx'"><collectBtn/></li>
  26. <li @click="copyUrl" class="copy" v-if="isShare"><i class="el-icon-share"/>分享</li>
  27. <li @click="refreshChart" v-if="chartInfo.UniqueCode"><i class="el-icon-refresh"/>刷新</li>
  28. </ul>
  29. </div>
  30. </div>
  31. </template>
  32. <script lang="ts">
  33. import { defineComponent, reactive, toRefs, onMounted, ref } from 'vue';
  34. import { ElMessage } from 'element-plus';
  35. import _ from 'lodash';
  36. import { useRoute } from 'vue-router';
  37. import chart from '@/components/chart.vue';
  38. import { IState } from './typing';
  39. import { ChartApi } from '@/request/api';
  40. import { IChartType, IDataProps, ILunarItem, IParams, ISeasonDataItemProps } from '@/types';
  41. import Highcharts from 'highcharts';
  42. import { defaultOpts, seasonOptions } from '@/utils/chartOptions';
  43. import moment from 'moment';
  44. import collectBtn from './components/collectBtn.vue'
  45. // 散点x
  46. const scatterXAxis = {
  47. tickPosition: 'inside',
  48. lineColor: '#bfbfbf',
  49. tickColor: '#bfbfbf',
  50. tickLength:5,
  51. ordinal: false,
  52. type: 'linear',
  53. }
  54. //基础y轴
  55. const basicYAxis = {
  56. tickLength:5,
  57. lineWidth: 1,
  58. lineColor: '#bfbfbf',
  59. tickColor: '#bfbfbf',
  60. // offset: 0,
  61. visible: true,
  62. gridLineWidth: 0,
  63. tickPosition: 'inside',
  64. endOnTick: false,
  65. startOnTick: false,
  66. showLastLabel: true
  67. }
  68. export default defineComponent({
  69. components: {
  70. chart,
  71. collectBtn
  72. },
  73. setup() {
  74. const route = useRoute();
  75. const loading = ref(false);
  76. const haveData = ref(true);
  77. const code = ref(route.query.code);
  78. const isShare = ref(route.query.fromType === 'share');
  79. // 语言 中英文 ch en 默认中文
  80. const language = ref(route.query.lang || 'ch');
  81. const screen = ref(document.body.clientWidth < 1200 ? 'phone' : 'pc');
  82. const state = reactive<IState>({
  83. options: {},
  84. chartInfo: {},
  85. dataList: [],
  86. sourceName: '',
  87. /* 奇怪柱形图 */
  88. barDateList: [],//柱形图的绘图数据
  89. barXData: [],//柱形图的x轴
  90. barEdbData: [],//柱形图的表格数据 只用于取值
  91. barLimit: {},
  92. /* 商品价格曲线 */
  93. commodityChartData: [],
  94. commodityXData: [],
  95. commodityEdbList: [],
  96. });
  97. onMounted((): void => {
  98. getChartInfo();
  99. });
  100. // 打开新窗口
  101. const openNew = (): void => {
  102. window.open(window.location.href,'_blank');
  103. }
  104. /* 处理图表来源 只限第三方 */
  105. const dealSourceHandle = (): void => {
  106. // 取出第三方来源
  107. const arr = state.dataList.filter(item => item.EdbType === 1 && item.Source!== 9).map(item => ({
  108. key: item.Source,
  109. name: item.SourceName,
  110. })
  111. );
  112. let res_arr = arr.length ? _.uniqBy(arr,'key') : [];
  113. let str = '';
  114. res_arr.forEach((item: any) => {
  115. str += `${item.name}, `
  116. })
  117. state.sourceName = str;
  118. }
  119. /* 获取图表数据信息 */
  120. const getChartInfo = async (type='') => {
  121. if(!code.value) {
  122. haveData.value = false;
  123. return
  124. }
  125. loading.value = true;
  126. try {
  127. const { Data } = await ChartApi.getChart({
  128. UniqueCode: code.value || '',
  129. });
  130. loading.value = false;
  131. state.chartInfo = Data.ChartInfo;
  132. state.dataList = Data.ChartInfo.Source === 1 ? Data.EdbInfoList : [Data.EdbInfoList[0]];
  133. //处理英文研报英文设置不全就展示中文
  134. setLangFromEnReport();
  135. document.title = state.chartInfo.ChartType === 7
  136. ? Data.ChartInfo.ChartName
  137. : language.value==='ch'?Data.ChartInfo.ChartName:Data.ChartInfo.ChartNameEn;
  138. if(Data.ChartInfo.Source === 1) {
  139. state.chartInfo.ChartType === 7 ? initBarData(Data) : setOptions();
  140. }else if(Data.ChartInfo.Source === 2) {
  141. initCommodityData(Data)
  142. }else if(Data.ChartInfo.Source === 3){
  143. initRelevanceChartData(Data)
  144. }
  145. dealSourceHandle();
  146. haveData.value = true;
  147. type === 'refresh' && ElMessage.success('刷新成功');
  148. }catch (e) {
  149. loading.value = false;
  150. haveData.value = false;
  151. }
  152. };
  153. /* 相关性图表 */
  154. const initRelevanceChartData=(data)=>{
  155. const relevanceUnitEnMap={
  156. '年': 'Year',
  157. '季': 'Season',
  158. '月': 'Month',
  159. '周': 'Week',
  160. '天': 'Day',
  161. }
  162. // 处理X轴
  163. let xAxis={
  164. categories: data.XEdbIdValue,
  165. tickWidth: 1,
  166. title: {
  167. text: language.value=='ch'?`期数(${data.CorrelationChartInfo.LeadUnit})`:`stage(${relevanceUnitEnMap[data.CorrelationChartInfo.LeadUnit]})`,
  168. align: 'high',
  169. rotation: 0,
  170. x: 0,
  171. y:10,
  172. offset: 20,
  173. },
  174. tickInterval: 1,
  175. offset:-85,
  176. tickmarkPlacement:'on'
  177. }
  178. // 处理Y轴
  179. let yAxis={
  180. ...basicYAxis,
  181. title: {
  182. text: language.value=='ch'?'相关性系数':'Correlation coefficient',
  183. // textCh: '相关性系数',
  184. // textEn: 'Correlation coefficient',
  185. align: 'high',
  186. rotation: 0,
  187. y: -15,
  188. offset: 0,
  189. },
  190. labels: {
  191. formatter: function (ctx) {
  192. let val = ctx.value;
  193. return val;
  194. },
  195. align: 'center',
  196. },
  197. min: -1,
  198. max: 1,
  199. opposite: false,
  200. tickWidth: 1,
  201. tickInterval:0.2,
  202. }
  203. //处理series
  204. let seriesData=[]
  205. data.YDataList.forEach(item=>{
  206. let serie_item = {
  207. data: item.Value,
  208. type: 'spline',
  209. yAxis: 0,
  210. name: language.value=='ch'?data.ChartInfo.ChartName:data.ChartInfo.ChartNameEn,
  211. // nameCh: data.ChartInfo.ChartName,
  212. // nameEn: data.ChartInfo.ChartNameEn,
  213. color: item.Color,
  214. chartType: 'linear',
  215. lineWidth: 3,
  216. marker: {
  217. enabled: false
  218. }
  219. };
  220. seriesData.push(serie_item)
  221. })
  222. let tooltip = {
  223. formatter: function() {
  224. let str=''
  225. if(language.value=='ch'){
  226. str = `<p>相关性系数:${this.y.toFixed(4)}</p><br><p>领先${this.x}期</p>`
  227. }else{
  228. str = `<p>Correlation coefficient:${this.y.toFixed(4)}</p><br><p>lead${this.x}stage</p>`
  229. }
  230. return str
  231. },
  232. // formatterCh: function() {
  233. // let str = `<p>相关性系数:${this.y.toFixed(4)}</p><br><p>领先${this.x}期</p>`
  234. // return str
  235. // },
  236. // formatterEn: function() {
  237. // let str = `<p>Correlation coefficient:${this.y.toFixed(4)}</p><br><p>lead${this.x}stage</p>`
  238. // return str
  239. // }
  240. }
  241. state.options = {
  242. isRelevanceChart:true,
  243. title: {
  244. text:''
  245. },
  246. series: seriesData,
  247. yAxis: [yAxis] ,
  248. xAxis:xAxis,
  249. tooltip
  250. }
  251. }
  252. /* 获取图表详情后赋值柱状图数据 */
  253. const initBarData = (data: { XEdbIdValue: number[]; YDataList: any; EdbInfoList: any; ChartInfo: any; }) => {
  254. const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data;
  255. let xData = XEdbIdValue.map((_:number) => EdbInfoList.find((edb: { EdbInfoId: number; }) => edb.EdbInfoId===_).EdbAliasName)
  256. console.log(xData)
  257. state.barDateList = YDataList;
  258. state.barXData = xData;
  259. state.barEdbData = EdbInfoList;
  260. state.barLimit = {
  261. min: Number(ChartInfo.LeftMin),
  262. max: Number(ChartInfo.LeftMax)
  263. }
  264. setBarChart();
  265. }
  266. /* 商品价格曲线获取详情赋值 */
  267. const initCommodityData = (data: { XEdbIdValue: number[]; YDataList: any; EdbInfoList: any; ChartInfo: any; }) => {
  268. const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data;
  269. let xData = EdbInfoList.map(_ => _.EdbAliasName);
  270. state.commodityEdbList = EdbInfoList;
  271. state.commodityChartData = YDataList;
  272. state.commodityXData = xData;
  273. state.barLimit = {
  274. min: Number(ChartInfo.LeftMin),
  275. max: Number(ChartInfo.LeftMax)
  276. }
  277. setCommodityChart();
  278. }
  279. //处理英文研报的图表英文设置不全的情况
  280. const setLangFromEnReport = () => {
  281. //来源于英文研报
  282. if(route.query.fromPage === 'en') {
  283. let is_name_en = state.chartInfo.ChartNameEn ? true : false;//名称是否有英文
  284. let is_target_en = [2,9].includes(state.chartInfo.ChartType) ? true : state.dataList.every(_ => _.EdbNameEn ? true : false);//指标是否有英文
  285. console.log(is_name_en,is_target_en)
  286. language.value = (is_name_en && is_target_en) ? 'en' : 'ch';
  287. }
  288. }
  289. // 曲线图x轴显示计算年限差 >1年 显示年/月 <=1 显示月/日
  290. const xTimeDiffer = () => {
  291. const end_date = state.chartInfo.DateType === 5
  292. ? state.chartInfo.EndDate
  293. : state.chartInfo.DateType === 6
  294. ? new Date()
  295. : '';
  296. //年限差
  297. const year_differ = moment(end_date).diff(
  298. moment(state.chartInfo.StartDate),
  299. 'years',
  300. true
  301. );
  302. // console.log(year_differ)
  303. if ([5, 6].includes(state.chartInfo.DateType) && year_differ <= 1) {
  304. return true
  305. } else {
  306. return false
  307. }
  308. }
  309. /* 曲线图 */
  310. const setDefaultLineOptions = () => {
  311. const { dataList,chartInfo } = state;
  312. //拼接标题 数据列
  313. let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
  314. let rightTwoIndex = dataList.findIndex(item => item.IsAxis ===2);
  315. // const chartData = _.cloneDeep(dataList);
  316. //有右二轴时排个序 按照左 右 右2的顺序
  317. let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);
  318. chartData.forEach((item:IDataProps ,index:number) => {
  319. //轴位置值相同的下标
  320. let sameSideIndex = chartData.findIndex(
  321. (i:IDataProps) => i.IsAxis === item.IsAxis
  322. );
  323. //y轴
  324. let textEn = item.Unit?item.UnitEn:''
  325. let yItem = {
  326. ...basicYAxis,
  327. labels: {
  328. formatter: function (ctx: any) {
  329. let val = ctx.value;
  330. return sameSideIndex !== index ? '' : val;
  331. },
  332. align: 'center',
  333. x: [0,2].includes(item.IsAxis) ? 5 : -5,
  334. style: {
  335. fontSize: '10px',
  336. },
  337. },
  338. title: {
  339. text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
  340. // text: null,
  341. align: 'high',
  342. rotation: 0,
  343. y: -15,
  344. x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
  345. textAlign: item.IsAxis===1 ? 'left' : 'right',
  346. reserveSpace: false
  347. },
  348. opposite: [0,2].includes(item.IsAxis),
  349. reversed: item.IsOrder,
  350. min: Number(chartData[sameSideIndex].MinData),
  351. max: Number(chartData[sameSideIndex].MaxData),
  352. tickWidth: sameSideIndex !== index ? 0 : 1,
  353. visible: sameSideIndex === index
  354. }
  355. // //拼接标题 判断相同指标名称拼接来源
  356. let dynamic_title = item.EdbName;
  357. let dynamic_arr = chartData.filter(
  358. (item: IDataProps) => dynamic_title === item.EdbName
  359. );
  360. // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
  361. let dynamic_tag = concatDynamicTag(item)
  362. // 英文后缀
  363. let dynamic_tag_en = concatDynamicTag(item,'en')
  364. //数据列
  365. let nameCh:String = dynamic_arr.length > 1
  366. ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
  367. : `${item.EdbName}${dynamic_tag}`
  368. let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
  369. let name :String=language.value == 'ch'?nameCh:nameEn
  370. //预测指标配置
  371. let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item) : {};
  372. let obj = {
  373. data: [] as any[],
  374. type: 'spline',
  375. yAxis: sameSideIndex,
  376. name,
  377. color: item.ChartColor,
  378. lineWidth: Number(item.ChartWidth),
  379. ...predict_params
  380. };
  381. item.DataList = item.DataList || []
  382. for (let i of item.DataList) {
  383. obj.data.push([i.DataTimestamp, i.Value]);
  384. }
  385. if(item.DataList.length){
  386. minTimeArr.push(item.DataList[0].DataTimestamp)
  387. maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
  388. }
  389. data.push(obj);
  390. ydata.push(yItem);
  391. })
  392. // 范围为1年内 x轴显示为月/日 否则默认年/月
  393. let xAxis:any = {};
  394. const bool_time:boolean = xTimeDiffer();
  395. let minTime: number=Math.min(...minTimeArr);
  396. let maxTime=Math.max(...maxTimeArr);
  397. let step = setXaxisStep(maxTime-minTime);
  398. xAxis = bool_time ? {
  399. ...defaultOpts.xAxis,
  400. tickInterval: screen.value === 'phone' ? step : undefined,
  401. labels: {
  402. formatter: function (ctx: any) {
  403. return Highcharts.dateFormat('%m/%d', ctx.value);
  404. },
  405. style: {
  406. fontSize: '10px',
  407. },
  408. }
  409. } : {
  410. ...defaultOpts.xAxis,
  411. tickInterval: screen.value === 'phone' ? step : undefined,
  412. labels: {
  413. style: {
  414. fontSize: '10px',
  415. },
  416. },
  417. }
  418. state.options = {
  419. series: data,
  420. yAxis: ydata,
  421. xAxis
  422. };
  423. }
  424. /* 设置x轴步长 刻度数量多一点 */
  425. const setXaxisStep = (timestamp: number) => {
  426. // return timestamp / 6 < 24 * 3600 * 1000 * 30 ? 24 * 3600 * 1000 * 30 : timestamp / 6;
  427. return timestamp / 6;
  428. }
  429. /* 指标顺序调整 IsAxis: 0右轴 1左轴 2右2*/
  430. const changeEdbOrder = (data: any[]) => {
  431. // 左轴指标
  432. let left_edbs = data.filter(_ => _.IsAxis===1);
  433. //右轴指标
  434. let right_edbs = data.filter(_ => !_.IsAxis);
  435. // 右2轴指标
  436. let right_two_edbs = data.filter(_ => _.IsAxis === 2);
  437. // 按 左 右 右2顺序排列
  438. return [left_edbs,right_edbs,right_two_edbs].flat(Infinity);
  439. }
  440. const getLabelMaxLen = (data : any[]) => {
  441. let value_arr = data.map(_ => String(Math.abs(_.Value)));
  442. let max_len_value = value_arr.reduce((a,b)=> (a.length > b.length ? a : b))
  443. let num = Number(max_len_value) > 1 ? String(Math.floor(Number(max_len_value))) : max_len_value
  444. return num.length
  445. }
  446. /* 堆叠图/组合图设置
  447. 本来和曲线图逻辑基本一致兼容下即可 为了以后便于维护和阅读还是拆开写吧
  448. */
  449. const setStackOrCombinChart = () => {
  450. const { dataList,chartInfo } = state;
  451. //拼接标题 数据列
  452. let data = [] as any[],ydata = [] as any[],minTimeArr: number[] = [],maxTimeArr: number[] = [];
  453. // const chartData = _.cloneDeep(dataList);
  454. //有右二轴时排个序 按照左 右 右2的顺序
  455. let chartData = dataList.some(_ =>_.IsAxis===2) ? changeEdbOrder(dataList) : _.cloneDeep(dataList);
  456. //支持的图表类型
  457. const chartTypeMap: IChartType = {
  458. 3: 'areaspline',
  459. 4: 'column',
  460. 6: ''
  461. };
  462. let chartStyle = chartTypeMap[chartInfo.ChartType];
  463. chartData.forEach((item:IDataProps ,index:number) => {
  464. //轴位置值相同的下标
  465. let sameSideIndex = chartData.findIndex(
  466. (i:IDataProps) => i.IsAxis === item.IsAxis
  467. );
  468. //堆叠图的yAxis必须一致 数据列所对应的y轴
  469. let serie_yIndex = index;
  470. if([3,4].includes(chartInfo.ChartType)) {
  471. // 类型为堆叠图时公用第一个指标y轴
  472. serie_yIndex = 0;
  473. } else if(chartInfo.ChartType ===6 && ['areaspline','column'].includes(item.ChartStyle)) {
  474. // 组合图找第一个堆叠柱状或面积的作为公用
  475. serie_yIndex = chartData.findIndex((i:IDataProps) => i.ChartStyle === item.ChartStyle);
  476. }
  477. //数据对应的y轴是公用轴则配置也共享
  478. item.IsAxis = serie_yIndex === index ? item.IsAxis : chartData[serie_yIndex].IsAxis;
  479. item.IsOrder = serie_yIndex === index ? item.IsOrder : chartData[serie_yIndex].IsOrder;
  480. // 右2轴下标
  481. let rightTwoIndex = [3,4].includes(chartInfo.ChartType)
  482. ? -1
  483. : dataList.findIndex(item => item.IsAxis===2);
  484. //y轴
  485. let textEn = item.Unit?item.UnitEn:''
  486. let yItem = {
  487. ...basicYAxis,
  488. labels: {
  489. formatter: function (ctx: any) {
  490. let val = ctx.value;
  491. return sameSideIndex !== index ? '' : val;
  492. },
  493. align: 'center',
  494. x: [0,2].includes(item.IsAxis) ? 5 : -5,
  495. style: {
  496. fontSize: '10px',
  497. },
  498. },
  499. title: {
  500. text:language.value=='ch'?sameSideIndex !== index ? '' : `${item.Unit}`:textEn,
  501. // text: null,
  502. align: 'high',
  503. rotation: 0,
  504. y: -15,
  505. x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
  506. textAlign: item.IsAxis===1 ? 'left' : 'right',
  507. reserveSpace: false
  508. },
  509. opposite: [0,2].includes(item.IsAxis),
  510. reversed: item.IsOrder,
  511. min: Number(chartData[sameSideIndex].MinData),
  512. max: Number(chartData[sameSideIndex].MaxData),
  513. tickWidth: sameSideIndex !== index ? 0 : 1,
  514. visible: serie_yIndex === index && sameSideIndex ===index
  515. }
  516. // //拼接标题 判断相同指标名称拼接来源
  517. let dynamic_title = item.EdbName;
  518. let dynamic_arr = chartData.filter(
  519. (item: IDataProps) => dynamic_title === item.EdbName
  520. );
  521. // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
  522. let dynamic_tag = concatDynamicTag(item)
  523. // 英文后缀
  524. let dynamic_tag_en = concatDynamicTag(item,'en')
  525. //数据列
  526. let nameCh:String = dynamic_arr.length > 1
  527. ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
  528. : `${item.EdbName}${dynamic_tag}`
  529. let nameEn:String=item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
  530. let name :String=language.value == 'ch'?nameCh:nameEn
  531. //预测指标配置
  532. let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item) : {};
  533. let obj = {
  534. data: [] as any[],
  535. type: chartStyle || item.ChartStyle,
  536. yAxis: serie_yIndex,
  537. name,
  538. color: item.ChartColor,
  539. lineWidth: (chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? Number(item.ChartWidth) : 0,
  540. fillColor: (chartInfo.ChartType === 3 || (chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
  541. zIndex: (chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? 1 : 0, //防止组合图曲线被遮住
  542. ...predict_params
  543. };
  544. item.DataList = item.DataList || []
  545. for (let i of item.DataList) {
  546. obj.data.push([i.DataTimestamp, i.Value]);
  547. }
  548. if(item.DataList.length){
  549. minTimeArr.push(item.DataList[0].DataTimestamp)
  550. maxTimeArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
  551. }
  552. data.push(obj);
  553. ydata.push(yItem);
  554. })
  555. // 范围为1年内 x轴显示为月/日 否则默认年/月
  556. let xAxis:any = {};
  557. const bool_time:boolean = xTimeDiffer();
  558. let minTime: number=Math.min(...minTimeArr);
  559. let maxTime=Math.max(...maxTimeArr);
  560. let step = setXaxisStep(maxTime-minTime);
  561. xAxis = bool_time ? {
  562. ...defaultOpts.xAxis,
  563. tickInterval: screen.value === 'phone' ? step : undefined,
  564. labels: {
  565. formatter: function (ctx: any) {
  566. return Highcharts.dateFormat('%m/%d', ctx.value);
  567. },
  568. style: {
  569. fontSize: '10px',
  570. },
  571. }
  572. } : {
  573. ...defaultOpts.xAxis,
  574. tickInterval: screen.value === 'phone' ? step : undefined,
  575. labels: {
  576. style: {
  577. fontSize: '10px',
  578. },
  579. },
  580. }
  581. state.options = {
  582. series: data,
  583. yAxis: ydata,
  584. xAxis
  585. };
  586. }
  587. /* 季节图 */
  588. const setSeasonOptions = () => {
  589. const chartData = state.dataList[0];
  590. let seasonYdata = [],
  591. seasonData = [],
  592. chart = {
  593. spacing: [5, 8, 2, 8],
  594. };
  595. /* 公历数据处理 处理数据列 y轴 */
  596. if (state.chartInfo.Calendar === '公历')
  597. for (let j of chartData.DataList) {
  598. //预测指标配置
  599. let predict_params = chartData.EdbInfoCategoryType === 1 ? getSeasonPredictParams(j.CuttingDataTimestamp) : {};
  600. let serie_item = {
  601. data: [] as any[],
  602. type: chartData.ChartStyle,
  603. yAxis: 0,
  604. name: j.Year,
  605. ...predict_params
  606. };
  607. const data_array = _.cloneDeep(j.DataList);
  608. data_array &&
  609. data_array.forEach((item: IParams) => {
  610. serie_item.data.push([item.DataTimestamp, item.Value]);
  611. });
  612. const index = chartData.DataList.findIndex(
  613. (item: ISeasonDataItemProps) => item.Year === j.Year
  614. );
  615. let textEn = chartData.Unit?chartData.UnitEn:''
  616. const s_yItem = {
  617. labels: {
  618. formatter: function (ctx: any) {
  619. let val = ctx.value;
  620. return index !== 0 ? '' : val;
  621. },
  622. align: 'center',
  623. style: {
  624. fontSize: '10px',
  625. },
  626. x: -5,
  627. },
  628. title: {
  629. text:language.value=='ch'?`${chartData.Unit}`:textEn,
  630. // text: null,
  631. align: 'high',
  632. rotation: 0,
  633. y: -15,
  634. offset: -(10 * chartData.Unit.length),
  635. },
  636. max: Number(chartData.MaxData),
  637. min: Number(chartData.MinData),
  638. ...defaultOpts.yAxis,
  639. };
  640. seasonData.push(serie_item);
  641. seasonYdata.push(s_yItem);
  642. }
  643. /* 农历数据处理 */
  644. let filterArr =
  645. state.chartInfo.Calendar === '农历'
  646. ? chartData.DataList.List.filter(
  647. (item: ILunarItem, index: number) => index > 0
  648. )
  649. : [];
  650. if (state.chartInfo.Calendar === '农历')
  651. for (let j of filterArr) {
  652. //预测指标配置
  653. let predict_params = chartData.EdbInfoCategoryType === 1 ? getSeasonPredictParams(j.CuttingDataTimestamp) : {};
  654. let serie_item = {
  655. data: [] as any[],
  656. type: chartData.ChartStyle,
  657. yAxis: 0,
  658. name: j.Year,
  659. ...predict_params
  660. };
  661. const data_array = _.cloneDeep(j.Items);
  662. data_array &&
  663. data_array.forEach((item: IParams) => {
  664. serie_item.data.push([item.DataTimestamp, item.Value]);
  665. });
  666. const index = filterArr.findIndex(
  667. (item: ILunarItem) => item.Year === j.Year
  668. );
  669. let textEn = chartData.Unit?chartData.UnitEn:''
  670. const s_yItem = {
  671. labels: {
  672. formatter: function (ctx: any) {
  673. let val = ctx.value;
  674. return index !== 0 ? '' : val;
  675. },
  676. align: 'center',
  677. style: {
  678. fontSize: '10px',
  679. },
  680. x: -5,
  681. },
  682. title: {
  683. text:language.value=='ch'?`${chartData.Unit}`:textEn,
  684. // text: null,
  685. align: 'high',
  686. rotation: 0,
  687. y: -15,
  688. offset: -(10 * chartData.Unit.length),
  689. },
  690. max: Number(chartData.MaxData),
  691. min: Number(chartData.MinData),
  692. ...defaultOpts.yAxis,
  693. };
  694. seasonData.push(serie_item);
  695. seasonYdata.push(s_yItem);
  696. }
  697. // 季节图x轴显示月/日 周度指标额外处理时间轴显示
  698. const xAxis = {
  699. ...defaultOpts.xAxis,
  700. tickInterval: screen.value === 'phone' ? 24 * 3600 * 1000 * 60 : undefined,
  701. labels: {
  702. formatter: function (ctx: any) {
  703. return Highcharts.dateFormat('%m/%d', ctx.value);
  704. },
  705. style: {
  706. fontSize: '10px',
  707. },
  708. },
  709. };
  710. // 季节图提示框显示 月/日
  711. defaultOpts.tooltip = {
  712. split: false,
  713. shared: true,
  714. dateTimeLabelFormats: {
  715. // 时间格式化字符
  716. day: '%m/%d',
  717. week: '%m/%d',
  718. month: '%m/%d',
  719. year: '%m/%d',
  720. },
  721. xDateFormat: '%m/%d',
  722. // valueDecimals: 2,
  723. };
  724. //农历默认选中一年数据并隐藏按钮 公历显示全部数据
  725. let rangeSelector = state.chartInfo.Calendar === '农历'
  726. ? {
  727. enabled: true,
  728. selected: 0,
  729. inputStyle: {
  730. display: 'none',
  731. },
  732. labelStyle: {
  733. display: 'none',
  734. },
  735. buttonTheme: {
  736. style: {
  737. display: 'none',
  738. },
  739. },
  740. buttons: [
  741. {
  742. type: 'month',
  743. count: 12,
  744. text: '12月',
  745. },
  746. {
  747. type: 'month',
  748. count: 15,
  749. text: '15月',
  750. },
  751. {
  752. type: 'all',
  753. text: '全部',
  754. },
  755. ],
  756. }
  757. : {
  758. enabled: false,
  759. };
  760. state.options = {
  761. colors:
  762. state.chartInfo.Calendar === '公历'
  763. ? seasonOptions.colors.slice(-chartData.DataList.length)
  764. : seasonOptions.colors.slice(-filterArr.length),
  765. series: seasonData,
  766. yAxis: seasonYdata,
  767. xAxis,
  768. rangeSelector,
  769. chart
  770. };
  771. }
  772. /* 散点图 第一个指标值为x轴 第二个指标为y轴*/
  773. const setScatterChartOptions = () => {
  774. const { dataList,chartInfo } = state;
  775. // 取2个指标中日期相同的数据
  776. const real_data: any[] = [];
  777. let tmpData_date: any = {};//用来取点对应的日期
  778. let data1 = _.cloneDeep(dataList)[0].DataList || [];
  779. let data2 = _.cloneDeep(dataList)[1].DataList || [];
  780. data1.forEach((_item: IParams) => {
  781. data2.forEach((_item2: IParams) => {
  782. if(_item.DataTimestamp === _item2.DataTimestamp) {
  783. //日期
  784. let itemIndex =_item.Value + "_" +_item2.Value
  785. if(tmpData_date[itemIndex]) {
  786. tmpData_date[itemIndex].push( moment(_item.DataTimestamp).format('YYYY/MM/DD'))
  787. } else {
  788. tmpData_date[itemIndex] = [moment(_item.DataTimestamp).format('YYYY/MM/DD')]
  789. }
  790. //值
  791. real_data.push({
  792. x: _item.Value,
  793. y: _item2.Value
  794. })
  795. }
  796. })
  797. })
  798. real_data.sort((x,y) => x-y);
  799. //悬浮窗 拼接日期 原始指标名称
  800. let tooltip = {
  801. formatter: function() {
  802. const that: any = this;
  803. return language.value=='ch'?
  804. `<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>
  805. ${dataList[0].EdbName}: <span style="font-weight: 600"> ${that.x}</span><br>
  806. ${dataList[1].EdbName}: <span style="font-weight: 600"> ${that.y}</span>
  807. `:
  808. `<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>
  809. ${dataList[0].EdbNameEn}: <span style="font-weight: 600"> ${that.x}</span><br>
  810. ${dataList[1].EdbNameEn}: <span style="font-weight: 600"> ${that.y}</span>
  811. `
  812. }
  813. }
  814. const { IsOrder,ChartColor } = dataList[0];
  815. //y轴
  816. let yAxis = {
  817. title: {
  818. text: language.value=='ch'?`${dataList[1].Unit}`:dataList[1].Unit?dataList[1].UnitEn:'',
  819. // text: null,
  820. align: 'high',
  821. rotation: 0,
  822. y: -5,
  823. offset: -(10 * dataList[1].Unit.length),
  824. },
  825. labels: {
  826. formatter: function (ctx: any) {
  827. return ctx.value;
  828. },
  829. align: 'center',
  830. },
  831. opposite: false,
  832. reversed: IsOrder,
  833. min: Number(dataList[0].MinData),
  834. max: Number(dataList[0].MaxData),
  835. tickWidth: 1,
  836. tickLength: 5,
  837. lineWidth: 1,
  838. lineColor: '#bfbfbf',
  839. tickColor: '#bfbfbf',
  840. offset: 0,
  841. visible: true,
  842. gridLineWidth: 0,
  843. tickPosition: 'inside',
  844. endOnTick: false,
  845. startOnTick: false,
  846. showLastLabel: true,
  847. tickPixelInterval: 50
  848. }
  849. //数据列
  850. let series: any = {
  851. data: [],
  852. type: 'scatter',
  853. name: language.value == 'ch'?`${chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`:`${chartInfo.ChartNameEn}${IsOrder ? '(reserve)' : ''}`,
  854. color: ChartColor,
  855. lineWidth: 0
  856. }
  857. real_data.forEach(_ => {
  858. series.data.push([_.x,_.y])
  859. })
  860. state.options = {
  861. title: {
  862. text:''
  863. },
  864. series: [ series ],
  865. yAxis,
  866. xAxis: {
  867. ...scatterXAxis,
  868. title: {
  869. text: language.value=='ch'?`${dataList[0].Unit}`:dataList[0].Unit?dataList[0].UnitEn:'',
  870. // text: null,
  871. align: 'high',
  872. rotation: 0,
  873. x: 0,
  874. offset: 20,
  875. },
  876. },
  877. tooltip
  878. }
  879. console.log(state.options)
  880. }
  881. /* 奇怪柱状图 和以上逻辑无公用点 依赖数据为单独的数据
  882. x轴为指标名称的柱形图 以日期作为series
  883. */
  884. const setBarChart = () => {
  885. const {barDateList,barXData,barLimit} = state;
  886. let seriesData: { data: any; type: string; yAxis: number; name: any; color: any; chartType: string; }[] = [];
  887. const data = _.cloneDeep(barDateList);
  888. //x轴
  889. let xAxis = {
  890. ...scatterXAxis,
  891. categories: barXData,
  892. tickWidth: 1,
  893. title: {
  894. text: ``,
  895. align: 'high',
  896. rotation: 0,
  897. x: 0,
  898. offset: 20,
  899. },
  900. }
  901. const { max,min } = barLimit;
  902. console.log(max,min)
  903. //y轴
  904. let yAxis = {
  905. ...basicYAxis,
  906. title: {
  907. text: ``,
  908. align: 'high',
  909. rotation: 0,
  910. y: -15,
  911. offset: 0,
  912. },
  913. labels: {
  914. formatter: function (ctx:any) {
  915. let val = ctx.value;
  916. return val;
  917. },
  918. align: 'center',
  919. },
  920. min: Number(min),
  921. max: Number(max),
  922. opposite: false,
  923. tickWidth: 1,
  924. }
  925. //数据列
  926. data.forEach((item: { Value: number; Name: string; Date: string; Color: string; }) => {
  927. let serie_item = {
  928. data: item.Value,
  929. type: 'column',
  930. yAxis: 0,
  931. name: item.Name || item.Date,
  932. color: item.Color,
  933. chartType: 'linear'
  934. };
  935. seriesData.push(serie_item)
  936. })
  937. state.options = {
  938. title: {
  939. text:''
  940. },
  941. plotOptions: {
  942. column:{
  943. stacking: null,
  944. },
  945. },
  946. series: seriesData,
  947. yAxis: [ yAxis ],
  948. xAxis
  949. }
  950. }
  951. /* 商品价格曲线设置 绘图逻辑同奇怪柱形图*/
  952. const setCommodityChart = () => {
  953. const {barLimit,commodityChartData,commodityXData,commodityEdbList} = state;
  954. let seriesData:any[] = [];
  955. const data = _.cloneDeep(commodityChartData);
  956. //x轴
  957. let xAxis = {
  958. ...scatterXAxis,
  959. categories: commodityEdbList.map(_ => language.value === 'ch' ? _.EdbAliasName:_.EdbAliasNameEn),
  960. tickWidth: 1,
  961. title: {
  962. text: ``,
  963. align: 'high',
  964. rotation: 0,
  965. x: 0,
  966. offset: 20,
  967. },
  968. }
  969. const { max,min } = barLimit;
  970. //y轴
  971. let yAxis = {
  972. ...basicYAxis,
  973. title: {
  974. text: language.value === 'ch' ? commodityEdbList[0].Unit : commodityEdbList[0].UnitEn,
  975. align: 'high',
  976. rotation: 0,
  977. y: -15,
  978. offset: 0,
  979. },
  980. labels: {
  981. formatter: function (ctx:any) {
  982. let val = ctx.value;
  983. return val;
  984. },
  985. align: 'center',
  986. },
  987. min: Number(min),
  988. max: Number(max),
  989. opposite: false,
  990. tickWidth: 1,
  991. }
  992. //数据列
  993. data.forEach((item: { Value: number; Name: string; Date: string; Color: string;NameEn: string }) => {
  994. //处理首或/尾全是无效数据的以null填充
  995. let filterData = filterInvalidData(item)
  996. let serie_item = {
  997. data: filterData,
  998. type: 'spline',
  999. yAxis: 0,
  1000. name: language.value === 'ch' ? item.Name : item.NameEn,
  1001. color: item.Color,
  1002. chartType: 'linear',
  1003. lineWidth: 3,
  1004. marker: {
  1005. enabled: false
  1006. }
  1007. };
  1008. seriesData.push(serie_item)
  1009. })
  1010. //tooltip
  1011. let tooltip = {
  1012. formatter: function() {
  1013. const ctx: any = this;
  1014. let str: string;
  1015. if(language.value === 'ch') {
  1016. str = `<strong>${ commodityEdbList.find(_ => _.EdbAliasName === ctx.x).EdbName }</strong>`;
  1017. ctx.points.forEach((item:{ series:{name: string},y: number }) => {
  1018. let obj_item = data.find((_:any) => _.Name === item.series.name);
  1019. if(!obj_item.NoDataEdbList.includes(commodityEdbList.find(_ => _.EdbAliasName === ctx.x).EdbInfoId)) {
  1020. str += `<br>${obj_item.Date}: ${item.y}`
  1021. }else {
  1022. str += `<br>${obj_item.Date}: 无`
  1023. }
  1024. })
  1025. }else {
  1026. str = `<strong>${ commodityEdbList.find(_ => _.EdbAliasNameEn === ctx.x).EdbNameEn }</strong>`
  1027. ctx.points.forEach((item:{ series:{name: string},y: number }) => {
  1028. let obj_item = data.find((_:any) => _.NameEn === item.series.name);
  1029. if(!obj_item.NoDataEdbList.includes(commodityEdbList.find(_ => _.EdbAliasNameEn === ctx.x).EdbInfoId)) {
  1030. str += `<br>${obj_item.Date}: ${item.y}`
  1031. }else {
  1032. str += `<br>${obj_item.Date}: 无`
  1033. }
  1034. })
  1035. }
  1036. return str
  1037. },
  1038. shared: true
  1039. }
  1040. state.options = {
  1041. title: {
  1042. text:''
  1043. },
  1044. series: seriesData,
  1045. yAxis: [ yAxis ],
  1046. xAxis,
  1047. tooltip
  1048. }
  1049. };
  1050. /* 处理无效数据为null */
  1051. const filterInvalidData = (item:any)=> {
  1052. const { commodityEdbList } = state;
  1053. let validateArr = commodityEdbList.filter(_ =>!item.NoDataEdbList.includes(_.EdbInfoId));
  1054. let first_index = commodityEdbList.findIndex(_ => _.EdbInfoId === validateArr[0].EdbInfoId);
  1055. let last_index = commodityEdbList.findIndex(_ => _.EdbInfoId === validateArr[validateArr.length-1].EdbInfoId);
  1056. console.log('first_index',first_index)
  1057. console.log('last_index',last_index)
  1058. let arr = item.Value.map((item:any,index:number) => {
  1059. if(index < first_index || index > last_index) {
  1060. return null
  1061. }else {
  1062. return item
  1063. }
  1064. })
  1065. return arr;
  1066. }
  1067. /* 设置options */
  1068. const setOptions = () => {
  1069. // ChartType: 1曲线图 2季节图 3面积图 4柱状图 5散点图 6组合图 季节图中公历和农历数据结构不同
  1070. const { chartInfo } = state;
  1071. const chartSetMap: any = {
  1072. 1: setDefaultLineOptions,
  1073. 2: setSeasonOptions,
  1074. 3: setStackOrCombinChart,
  1075. 4: setStackOrCombinChart,
  1076. 5: setScatterChartOptions,
  1077. 6: setStackOrCombinChart
  1078. };
  1079. chartSetMap[chartInfo.ChartType]()
  1080. };
  1081. /* 拼接动态的指标名称小标签 */
  1082. const concatDynamicTag = ({ IsAxis,IsOrder,EdbInfoType,LeadValue,LeadUnit }: IDataProps,lang:String='ch'): string => {
  1083. // IsAxis左轴1 右轴0 2右2轴
  1084. //IsOrder正序false 逆序true
  1085. //EdbInfoType是否是领先指标
  1086. const axisLabelMap:any = lang=='ch'?{
  1087. 0: '右轴',
  1088. 2: '右2轴'
  1089. }:{
  1090. 0: 'RHS',
  1091. 2: '2-RHS'
  1092. }
  1093. const orderLabelMap:any = lang=='ch'?{
  1094. 1: '逆序'
  1095. }:{
  1096. 1: 'REV'
  1097. }
  1098. const edbInfoMap:any = lang=='ch'?{
  1099. 0: '领先'
  1100. }:{
  1101. 0: 'Lead'
  1102. }
  1103. const leadUnitEnMap:any = {
  1104. '年': 'Y',
  1105. '季': 'Q',
  1106. '月': 'M',
  1107. '周': 'W',
  1108. '天': 'D',
  1109. }
  1110. //英文领先单位转换
  1111. const edbLeadUnit = lang=='ch' ? LeadUnit : leadUnitEnMap[LeadUnit];
  1112. let axis_tag = axisLabelMap[IsAxis] || '';
  1113. //逆序拼接
  1114. let order_tag = orderLabelMap[Number(IsOrder)] ? `${axis_tag ? ',': ''}${orderLabelMap[Number(IsOrder)]}` : ''
  1115. //领先拼接
  1116. let edb_tag = edbInfoMap[EdbInfoType] ? `${(axis_tag||order_tag) ? ',' : '' }${edbInfoMap[EdbInfoType]} ${LeadValue}${edbLeadUnit}` : '';
  1117. return (axis_tag || order_tag || edb_tag) ? `(${axis_tag}${order_tag}${edb_tag})` : ''
  1118. }
  1119. /* 预测配置 分区 */
  1120. const getPredictParams = ({LatestDate,PredictChartColor}: IDataProps) => {
  1121. return {
  1122. zoneAxis: 'x',
  1123. zones: [{
  1124. value: new Date(LatestDate).getTime()+1
  1125. }, {
  1126. dashStyle: 'ShortDot',
  1127. color: PredictChartColor
  1128. }]
  1129. }
  1130. }
  1131. /* 季节图预测数据 年份=分割点年份做分割 年份>分割点年份全为预测 */
  1132. const getSeasonPredictParams = (timestamp: number) => {
  1133. return timestamp
  1134. ? {
  1135. zoneAxis: 'x',
  1136. zones: [{
  1137. value: new Date(timestamp).getTime()+1
  1138. }, {
  1139. dashStyle: 'ShortDot',
  1140. }]
  1141. }
  1142. : {}
  1143. }
  1144. /* 复制标题 */
  1145. const copyText = () => {
  1146. const { chartInfo } = state;
  1147. let input = document.createElement("input");
  1148. input.value = chartInfo.ChartName;
  1149. document.body.appendChild(input)
  1150. input.select();
  1151. document.execCommand('copy');
  1152. document.body.removeChild(input);
  1153. ElMessage.success('复制标题成功')
  1154. }
  1155. /* 分享链接 */
  1156. const copyUrl = () => {
  1157. let input = document.createElement("input");
  1158. input.value = location.href;
  1159. document.body.appendChild(input)
  1160. input.select();
  1161. document.execCommand('copy');
  1162. document.body.removeChild(input);
  1163. ElMessage.success('复制链接成功')
  1164. }
  1165. const refreshChart = _.debounce(async () => {
  1166. loading.value = true;
  1167. let Ret=null
  1168. if(state.chartInfo.Source === 1){
  1169. Ret=await ChartApi.refreshChart({UniqueCode: state.chartInfo.UniqueCode})
  1170. }else if(state.chartInfo.Source === 2){
  1171. Ret=await ChartApi.refreshCommordityChart({UniqueCode: state.chartInfo.UniqueCode});
  1172. }else if(state.chartInfo.Source === 3){
  1173. Ret=await ChartApi.refreshRelevanceChart({UniqueCode: state.chartInfo.UniqueCode});
  1174. }
  1175. Ret === 200 && getChartInfo('refresh');
  1176. },400)
  1177. return {
  1178. ...toRefs(state),
  1179. loading,
  1180. haveData,
  1181. getChartInfo,
  1182. openNew,
  1183. copyUrl,
  1184. isShare,
  1185. language,
  1186. refreshChart,
  1187. copyText
  1188. };
  1189. },
  1190. });
  1191. </script>
  1192. <style scoped lang="less">
  1193. @import './index.less';
  1194. </style>