/* 图表配置设置 */ import Highcharts from 'highcharts'; import { defaultOpts, seasonOptions,getTerminal,browser } from '@/utils/defaultOptions'; // 散点x轴 const scatterXAxis = { tickPosition: 'inside', lineColor: '#bfbfbf', tickColor: '#bfbfbf', tickLength:5, ordinal: false, type: 'linear' } // y轴静态配置 const basicYAxis = { tickLength: 5, lineWidth: 1, lineColor: '#bfbfbf', tickColor: '#bfbfbf', // offset: 0, visible: true, gridLineWidth: 0, tickPosition: 'inside', endOnTick: false, startOnTick: false, showLastLabel: true, tickPixelInterval: 50, } export default { data() { return { bgList:[ {image_url:require('@/assets/img/ppt_m/bg3.jpg')}, {image_url:require('@/assets/img/ppt_m/bg4.jpg')}, {image_url:require('@/assets/img/ppt_m/bg5.jpg')}, // {image_url:'https://hzstatic.hzinsights.com/ppt/bg3.jpg'}, // {image_url:'https://hzstatic.hzinsights.com/ppt/bg4.jpg'}, // {image_url:'https://hzstatic.hzinsights.com/ppt/bg5.jpg'}, ],//首页背景 //领先频度对应英文 leadUnitEnMap: { '年': 'Y', '季': 'Q', '月': 'M', '周': 'W', '天': 'D', }, /* 奇怪柱形图 */ barDateList: [],//柱形图的绘图数据 barXIdData: [],//柱形图的x轴 barEdbData: [],//柱形图的表格数据 只用于取值 chartLimit: {}, /* 商品价格曲线 */ commodityChartData: [], commodityXData: [], commodityEdbList: [], /* 时间截面散点图 */ sectionScatterData: {}, relevanceChartData:null,//相关性图表 relevanceUnitEnMap:{ '年': 'Year', '季': 'Season', '月': 'Month', '周': 'Week', '天': 'Day', }, /* 统计频率图 */ statisticFrequencyData: {} } }, methods: { /* 设置options 曲线图 季节图*/ setOptions() { // ChartType: 1曲线图 2季节图 3面积 4柱状 5散点 6组合 季节图中公历和农历数据结构不同 const chartSetMap = { 1: this.setDefaultChart, 2: this.setSeasonChart, 3: this.setStackOrCombinChart, 4: this.setStackOrCombinChart, 5: this.setScatterChart, 6: this.setStackOrCombinChart }; chartSetMap[this.chartInfo.ChartType]&&chartSetMap[this.chartInfo.ChartType]() }, /* 曲线 */ setDefaultChart() { //拼接标题 数据列 let data = [], ydata = []; let rightTwoIndex = this.dataList.findIndex((item) => item.IsAxis ===2); // const chartData = _.cloneDeep(this.dataList); let chartData = this.dataList.some(_ =>_.IsAxis===2) ? this.changeEdbOrder(this.dataList) : _.cloneDeep(this.dataList); chartData.forEach((item, index) => { //轴位置值相同的下标 let sameSideIndex = chartData.findIndex(i => i.IsAxis === item.IsAxis); //y轴 let yItem = { ...basicYAxis, title: { text: item.Unit, textCh:item.Unit,//中文单位 textEn:item.Unit?item.UnitEn:'',//英文单位,但如果无中文单位则不显示 // text: null, align: 'high', rotation: 0, y: -15, x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0, textAlign: item.IsAxis===1 ? 'left' : 'right', reserveSpace: false }, labels: { formatter: function (ctx) { let val = ctx.value; return val; }, align: 'center', x: [0,2].includes(item.IsAxis) ? 5 : -5, style: { fontSize: '10px', }, }, opposite: [0,2].includes(item.IsAxis), reversed: item.IsOrder, min: Number(item.MinData), max: Number(item.MaxData), tickWidth: 1, visible: sameSideIndex === index }; // //拼接标题 判断相同指标名称拼接来源 let dynamic_title = item.EdbName; let dynamic_arr = chartData.filter( (item) => dynamic_title === item.EdbName ); // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标 let dynamic_tag = this.concatDynamicTag(item); let dynamic_tag_en = this.concatDynamicTag(item,'en'); //预测指标配置 let predict_params = item.EdbInfoCategoryType === 1 ? this.getPredictParams(item) : {}; //中英文名称 const nameCh = dynamic_arr.length > 1 ? `${item.EdbName}(${item.SourceName})${dynamic_tag}` : `${item.EdbName}${dynamic_tag}` const nameEn = item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:'' //数据列 let obj = { data: [], type: 'spline', yAxis: sameSideIndex, name:nameCh, nameCh:nameCh, nameEn:nameEn, color: item.ChartColor, lineWidth: Number(item.ChartWidth), ...predict_params }; item.DataList = item.DataList || []; for (let i of item.DataList) { obj.data.push([i.DataTimestamp, i.Value]); } data.push(obj); ydata.push(yItem); }); // 范围为1年内 x轴显示为月/日 否则默认年/月 this.xTimeDiffer(); this.options = { series: data, yAxis: ydata }; //滚动相关性独立tooltip if(this.chartInfo.Source === 4) { const { LeadValue,LeadUnit } = this.relevanceChartData.CorrelationChartInfo; let relevanceUnitEnMap = this.relevanceUnitEnMap; this.options.tooltip = { formatter: function() { let str = `${Highcharts.dateFormat('%Y/%m/%d',this.x)}

相关性系数:${this.y.toFixed(4)}


领先${LeadValue+LeadUnit}

` return str }, formatterCh: function() { let str = `${Highcharts.dateFormat('%Y/%m/%d',this.x)}

相关性系数:${this.y.toFixed(4)}


领先${LeadValue+LeadUnit}

` return str }, formatterEn: function() { let str = `${Highcharts.dateFormat('%Y/%m/%d',this.x)}

Correlation coefficient:${this.y.toFixed(4)}


lead${LeadValue+relevanceUnitEnMap[LeadUnit]}

` return str } } } }, /* 堆叠柱 堆叠面积 组合图 */ setStackOrCombinChart() { const chartTypeMap = { 3: 'areaspline', 4: 'column', 6: '' }; let chartStyle = chartTypeMap[this.chartInfo.ChartType]; //拼接标题 数据列 let data = [], ydata = []; let chartData = this.dataList.some(_ =>_.IsAxis===2) ? this.changeEdbOrder(this.dataList) : _.cloneDeep(this.dataList); chartData.forEach((item, index) => { //轴位置值相同的下标 let sameSideIndex = chartData.findIndex(i => i.IsAxis === item.IsAxis); //堆叠图的yAxis必须一致 数据列所对应的y轴 let serie_yIndex = index; if([3,4].includes(this.chartInfo.ChartType)) { // 类型为堆叠图时公用第一个指标y轴 serie_yIndex = 0; } else if(this.chartInfo.ChartType ===6 && ['areaspline','column'].includes(item.ChartStyle)) { // 组合图找第一个堆叠柱状或面积的作为公用 serie_yIndex = chartData.findIndex(i => i.ChartStyle === item.ChartStyle); } //数据对应的y轴是公用轴则配置也共享 item.IsAxis = serie_yIndex === index ? item.IsAxis : chartData[serie_yIndex].IsAxis; item.IsOrder = serie_yIndex === index ? item.IsOrder : chartData[serie_yIndex].IsOrder; let rightTwoIndex = [3,4].includes(this.chartInfo.ChartType) ? -1 : this.dataList.findIndex((item) => item.IsAxis===2); //y轴 let yItem = { ...basicYAxis, title: { //text: sameSideIndex !== index ? '' : `${item.Unit}`, text:item.Unit, textCh:item.Unit,//中文单位 textEn:item.Unit?item.UnitEn:'',//英文单位,但如果无中文单位则不显示 // text: null, align: 'high', rotation: 0, y: -15, x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0, textAlign: item.IsAxis===1 ? 'left' : 'right', reserveSpace: false }, labels: { formatter: function (ctx) { let val = ctx.value; return sameSideIndex !== index ? '' : val; }, align: 'center', x: [0,2].includes(item.IsAxis) ? 5 : -5, style: { fontSize: '10px', }, }, opposite: [0,2].includes(item.IsAxis), reversed: item.IsOrder, min: Number(chartData[sameSideIndex].MinData), max: Number(chartData[sameSideIndex].MaxData), tickWidth: sameSideIndex !== index ? 0 : 1, visible: serie_yIndex === index && sameSideIndex ===index }; // //拼接标题 判断相同指标名称拼接来源 let dynamic_title = item.EdbName; let dynamic_arr = chartData.filter( (item) => dynamic_title === item.EdbName ); // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标 let dynamic_tag = this.concatDynamicTag(item); let dynamic_tag_en = this.concatDynamicTag(item,'en'); //预测指标配置 let predict_params = item.EdbInfoCategoryType === 1 ? this.getPredictParams(item,chartStyle) : {}; //中英文名称 const nameCh = dynamic_arr.length > 1 ? `${item.EdbName}(${item.SourceName})${dynamic_tag}` : `${item.EdbName}${dynamic_tag}` const nameEn = item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:'' //数据列 let obj = { data: [], type: chartStyle || item.ChartStyle, yAxis: serie_yIndex, name:nameCh, nameCh:nameCh, nameEn:nameEn, color: item.ChartColor, lineWidth: (this.chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? Number(item.ChartWidth) : 0, fillColor: (this.chartInfo.ChartType === 3 || (this.chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined, borderWidth: 1, borderColor: item.ChartColor, zIndex: (this.chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? 1 : 0, //防止组合图曲线被遮住 ...predict_params }; item.DataList = item.DataList || []; for (let i of item.DataList) { obj.data.push([i.DataTimestamp, i.Value]); } data.push(obj); ydata.push(yItem); }); // 范围为1年内 x轴显示为月/日 否则默认年/月 this.xTimeDiffer() this.options = { series: data, yAxis: ydata }; }, /* 季节图配置 */ setSeasonChart() { /* 季节性图的图表配置 */ const chartData = this.dataList[0]; let seasonYdata = [], seasonData = [], chart = { spacing: [5, 8, 2, 8], }; /* 公历数据处理 处理数据列 y轴 */ if (this.chartInfo.Calendar === '公历') for (let j of chartData.DataList) { //预测指标配置 let predict_params = chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {}; let serie_item = { data: [], type: chartData.ChartStyle, yAxis: 0, name: j.Year, ...predict_params }; const data_array = _.cloneDeep(j.DataList); data_array && data_array.forEach((item) => { serie_item.data.push([item.DataTimestamp, item.Value]); }); const index = chartData.DataList.findIndex( (item) => item.Year === j.Year ); const s_yItem = { title: { text: `${chartData.Unit}`, textCh:chartData.Unit, textEn:chartData.Unit?chartData.UnitEn:'', // text: null, align: 'high', rotation: 0, y: -15, offset: -(12 * chartData.Unit.length), }, labels: { formatter: function (ctx) { let val = ctx.value; return index !== 0 ? '' : val; }, align: 'center', style: { fontSize: '10px', }, x: -5, }, max: Number(chartData.MaxData), min: Number(chartData.MinData), ...seasonOptions.yAxis, }; seasonData.push(serie_item); seasonYdata.push(s_yItem); } /* 农历数据处理 */ let filterArr = this.chartInfo.Calendar === '农历' ? chartData.DataList.List.filter((item, index) => index > 0) : []; if (this.chartInfo.Calendar === '农历') for (let j of filterArr) { //预测指标配置 let predict_params = chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {}; let serie_item = { data: [], type: chartData.ChartStyle, yAxis: 0, name: j.Year, ...predict_params }; const data_array = _.cloneDeep(j.Items); data_array && data_array.forEach((item) => { serie_item.data.push([item.DataTimestamp, item.Value]); }); const index = filterArr.findIndex((item) => item.Year === j.Year); const s_yItem = { title: { text: `${chartData.Unit}`, textCh:chartData.Unit, textEn:chartData.Unit?chartData.UnitEn:'', // text: null, align: 'high', rotation: 0, y: -15, offset: -(12 * chartData.Unit.length), }, labels: { formatter: function (ctx) { let val = ctx.value; return index !== 0 ? '' : val; }, align: 'center', style: { fontSize: '10px', }, x: -5, }, max: Number(chartData.MaxData), min: Number(chartData.MinData), ...seasonOptions.yAxis, }; seasonData.push(serie_item); seasonYdata.push(s_yItem); } // 季节图x轴显示月/日 周度指标额外处理时间轴显示 const xAxis = { ...defaultOpts.xAxis, labels: { formatter: function (ctx) { return Highcharts.dateFormat('%m/%d', ctx.value); }, style: { fontSize: '10px', }, }, }; // 季节图提示框显示 月/日 defaultOpts.tooltip = { split: false, shared: true, dateTimeLabelFormats: { // 时间格式化字符 day: '%m/%d', week: '%m/%d', month: '%m/%d', year: '%m/%d', }, xDateFormat: '%m/%d', valueDecimals: 2, }; //农历默认选中一年数据并隐藏按钮 公历显示全部数据 let rangeSelector = this.chartInfo.Calendar === '农历' ? { enabled: true, selected: 0, inputStyle: { display: 'none', }, labelStyle: { display: 'none', }, buttonTheme: { style: { display: 'none', }, }, buttons: [ { type: 'month', count: 12, text: '12月', }, { type: 'month', count: 15, text: '15月', }, { type: 'all', text: '全部', }, ], } : { enabled: false, }; this.options = { colors: this.chartInfo.Calendar === '公历' ? seasonOptions.colors.slice(-chartData.DataList.length) : seasonOptions.colors.slice(-filterArr.length), series: seasonData, yAxis: seasonYdata, xAxis, rangeSelector }; }, /* 散点图设置 只允许2指标画图第一个指标值为x轴 第二个指标为y轴 */ setScatterChart() { const chartData = _.cloneDeep(this.dataList); // 取2个指标中日期相同的数据 let real_data = []; let tmpData_date = {};//用来取点对应的日期 let data1 = _.cloneDeep(chartData)[0].DataList || []; let data2 = _.cloneDeep(chartData)[1].DataList || []; data1.forEach(_item => { data2.forEach(_item2 => { if(_item.DataTimestamp === _item2.DataTimestamp) { _item.DataTime = _item.DataTime.replace(/-/g,'/'); //日期 let itemIndex =_item.Value + "_" +_item2.Value if(tmpData_date[itemIndex]) { tmpData_date[itemIndex].push(_item.DataTime) } else { tmpData_date[itemIndex] = [_item.DataTime] } //值 real_data.push({ x: _item.Value, y: _item2.Value }) } }) }) real_data.sort((x,y) => x-y); //悬浮窗 拼接日期 原始指标名称 let tooltip = { formatter: function() { return `${ tmpData_date[this.x+'_'+this.y].length > 4 ? tmpData_date[this.x+'_'+this.y].slice(0,4).join()+'...' : tmpData_date[this.x+'_'+this.y].join() }
${chartData[0].EdbName}: ${this.x}
${chartData[1].EdbName}: ${this.y} ` }, // 中文 formatterCh: function() { return `${ tmpData_date[this.x+'_'+this.y].length > 4 ? tmpData_date[this.x+'_'+this.y].slice(0,4).join()+'...' : tmpData_date[this.x+'_'+this.y].join() }
${chartData[0].EdbName}: ${this.x}
${chartData[1].EdbName}: ${this.y} ` }, // 英文 formatterEn: function() { let str1 = `${chartData[0].EdbNameEn}` let str2 = `${chartData[1].EdbNameEn}` return `${ tmpData_date[this.x+'_'+this.y].length > 4 ? tmpData_date[this.x+'_'+this.y].slice(0,4).join()+'...' : tmpData_date[this.x+'_'+this.y].join() }
${str1}: ${this.x}
${str2}: ${this.y} ` } } const { IsOrder,ChartColor,MaxData,MinData } = chartData[0]; //y轴 let yAxis = { title: { text: `${chartData[1].Unit}`, textCh:chartData[1].Unit, textEn:chartData[1].Unit?chartData[1].UnitEn:'', // text: null, align: 'high', rotation: 0, y: -15, offset: -(12 * chartData[1].Unit.length), }, labels: { formatter: function (ctx) { return ctx.value; }, align: 'center', }, opposite: false, reversed: IsOrder, min: Number(MinData), max: Number(MaxData), tickWidth: 1, tickLength: 5, lineWidth: 1, lineColor: '#bfbfbf', tickColor: '#bfbfbf', offset: 0, visible: true, gridLineWidth: 0, tickPosition: 'inside', endOnTick: false, startOnTick: false, showLastLabel: true, tickPixelInterval: 50 } //数据列 let series = { data: [], type: 'scatter', name: `${this.chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`, nameCh:`${this.chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`, nameEn:this.chartInfo.ChartNameEn?`${this.chartInfo.ChartNameEn}${IsOrder ? '(reverse)' : ''}`:'', color: ChartColor, lineWidth: 0 } real_data.forEach(_ => { series.data.push([_.x,_.y]) }) this.options = { title: { text:'' }, series: [ series ], yAxis, xAxis: { ...scatterXAxis, title: { text: `${chartData[0].Unit}`, textCh:chartData[0].Unit, textEn:chartData[0].Unit?chartData[0].UnitEn:'', // text: null, align: 'high', rotation: 0, x: 0, offset: 15, }, }, tooltip } }, /* 奇怪柱状图 和以上逻辑无公用点 依赖数据为单独的数据 x轴为指标名称的柱形图 以日期作为series */ setBarChart() { let seriesData = []; const data = _.cloneDeep(this.barDateList); //x轴 let xAxis = { ...scatterXAxis, categories: this.barXIdData.map(_ => this.barEdbData.find(edb => edb.EdbInfoId===_).EdbAliasName), tickWidth: 1, title: { text: ``, align: 'high', rotation: 0, x: 0, offset: 20, }, } const { max,min } = this.chartLimit; //y轴 let yAxis = { ...basicYAxis, title: { text: this.chartInfo.Unit, textCh: this.chartInfo.Unit, textEn: this.chartInfo.UnitEn, align: 'high', rotation: 0, y: -15, offset: 0, }, labels: { formatter: function (ctx) { let val = ctx.value; return val; }, align: 'center', }, min: Number(min), max: Number(max), opposite: false, tickWidth: 1, } //数据列 data.forEach(item => { let serie_item = { data: item.Value, type: 'column', yAxis: 0, name: item.Name || item.Date, nameCh: item.Name || item.Date, nameEn: item.Date, color: item.Color, chartType: 'linear' }; seriesData.push(serie_item) }) this.options = { title: { text:'', }, plotOptions: { column:{ stacking: null, }, }, series: seriesData, yAxis: [ yAxis ], xAxis } }, /* 获取图表详情后赋值柱状图数据 */ initBarData(data) { const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data; // let xData = XEdbIdValue.map(_ => EdbInfoList.find(edb => edb.EdbInfoId===_).EdbAliasName) this.barDateList = YDataList; this.barXIdData = XEdbIdValue; this.barEdbData = EdbInfoList; this.chartLimit = { min: Number(ChartInfo.LeftMin), max: Number(ChartInfo.LeftMax) } this.setBarChart(); }, /* 商品价格曲线设置 绘图逻辑同奇怪柱形图*/ setCommodityChart() { let seriesData = []; const data = _.cloneDeep(this.commodityChartData); //x轴 let xAxis = { ...scatterXAxis, categories: this.commodityXData.map(_ =>_.Name), tickWidth: 1, title: { text: ``, align: 'high', rotation: 0, x: 0, offset: 20, }, } const { max,min } = this.chartLimit; //y轴 let yAxis = { ...basicYAxis, title: { text: this.commodityEdbList[0].Unit, textCh: this.commodityEdbList[0].Unit, textEn: this.commodityEdbList[0].Unit?(this.commodityEdbList[0].UnitEn||'英文单位'):'', align: 'high', rotation: 0, y: -15, offset: 0, }, labels: { formatter: function (ctx) { let val = ctx.value; return val; }, align: 'center', }, min: Number(min), max: Number(max), opposite: false, tickWidth: 1, } //数据列 data.forEach(item => { //处理首或/尾全是无效数据的以null填充 let filterData = this.filterInvalidData(item) let serie_item = { data: filterData, type: 'spline', yAxis: 0, name: item.Name, nameCh: item.Name, nameEn: item.NameEn, color: item.Color, chartType: 'linear', lineWidth: 3, marker: { enabled: false } }; seriesData.push(serie_item) }) //tooltip let commodityEdbList = this.commodityEdbList; let commodityXData = this.commodityXData; let chartInfo = this.chartInfo; let tooltip = { formatter: function() { let str = ''; this.points.forEach(item => { let obj_item = data.find(_ => _.Name === item.series.name); let index = commodityXData.findIndex(_ => _.Name === this.x); //合约显示 let haveContract = obj_item.XEdbInfoIdList[index]; if(haveContract) { // 利润曲线指标名 let edb_name = chartInfo.Source === 5 ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitName}(${obj_item.NameList[index]})`) : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbName; str+=`${ edb_name }` if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) { str += `
\u25CF${obj_item.Date}: ${item.y}
` }else { str += `
\u25CF${obj_item.Date}: 无
` } } }) return str||'无合约' }, formatterCh: function() { let str = ''; this.points.forEach(item => { let obj_item = data.find(_ => _.Name === item.series.name); let index = commodityXData.findIndex(_ => _.Name === this.x); //合约显示 let haveContract = obj_item.XEdbInfoIdList[index]; if(haveContract) { // 利润曲线指标名 let edb_name = chartInfo.Source === 5 ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitName}(${obj_item.NameList[index]})`) : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbName; str+=`${ edb_name }` if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) { str += `
\u25CF${obj_item.Date}: ${item.y}
` }else { str += `
\u25CF${obj_item.Date}: 无
` } } }) return str||'无合约' }, formatterEn: function() { let str = ''; this.points.forEach(item => { let obj_item = data.find(_ => _.NameEn === item.series.name); let index = commodityXData.findIndex(_ => _.NameEn === this.x); //合约显示 let haveContract = obj_item.XEdbInfoIdList[index]; if(haveContract) { // 利润曲线指标名 let edb_name = chartInfo.Source === 5 ? (index === 0 ? obj_item.NameList[index] : `${chartInfo.ProfitNameEn}(${obj_item.NameList[index]})`) : commodityEdbList.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbNameEn; str+=`${ edb_name }` if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) { str += `
\u25CF${obj_item.Date}: ${item.y}
` }else { str += `
\u25CF${obj_item.Date}: 无
` } } }) return str||'无合约' }, shared: true } this.options = { title: { text:'' }, series: seriesData, yAxis: [ yAxis ], xAxis, tooltip } }, /* 处理无效数据为null */ filterInvalidData(item) { //找出第一个有效数据和最后一个有效数据的index index1 index2 //0到index1全填null index2到最后一个全为null let validateArr = item.XEdbInfoIdList.filter(_ =>_&&!item.NoDataEdbList.includes(_)); let first_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[0]); let last_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[validateArr.length-1]); console.log('first_index',first_index) console.log('last_index',last_index) let arr = item.Value.map((item,index) => { if(index < first_index || index > last_index) { return null }else { return item } }) return arr; }, /* 商品价格曲线获取详情赋值 */ initCommodityData(data) { const { XDataList,YDataList,EdbInfoList,ChartInfo,DataResp } = data; this.commodityEdbList = EdbInfoList; this.commodityChartData = ChartInfo.Source===5?DataResp.YDataList:YDataList; this.commodityXData = ChartInfo.Source===5?DataResp.XDataList:XDataList; this.chartLimit = { min: Number(ChartInfo.LeftMin), max: Number(ChartInfo.LeftMax) } this.setCommodityChart() }, /* 相关性图表初始化 */ initRelevanceChartData(){ // 处理X轴 let xAxis={ categories: this.relevanceChartData.XEdbIdValue, tickWidth: 1, title: { text: this.relevanceChartData.ChartInfo.Source===3 ?`期数(${this.relevanceChartData.CorrelationChartInfo.LeadUnit})` : null, textCh:this.relevanceChartData.ChartInfo.Source===3 ? `期数(${this.relevanceChartData.CorrelationChartInfo.LeadUnit})`:null, textEn:this.relevanceChartData.ChartInfo.Source===3 ? `stage(${this.relevanceUnitEnMap[this.relevanceChartData.CorrelationChartInfo.LeadUnit]})`:null, align: 'high', rotation: 0, x: 0, y:10, offset: 20, }, tickInterval: 1, offset:0, tickmarkPlacement:'on' } // 处理Y轴 let yAxis={ ...basicYAxis, title: { text: '相关性系数', textCh: '相关性系数', textEn: 'Correlation coefficient', align: 'high', rotation: 0, y: -15, offset: 0, }, labels: { formatter: function (ctx) { let val = ctx.value; return val; }, align: 'center', }, // min: -1, // max: 1, opposite: false, tickWidth: 1, // tickInterval:0.2, } //处理series let seriesData=[] this.relevanceChartData.YDataList.forEach(item=>{ let serie_item = { data: item.Value, type: 'spline', yAxis: 0, name: item.Name, nameCh: item.Name, nameEn: item.NameEn, color: item.Color, chartType: 'linear', lineWidth: 3, marker: { enabled: false } }; seriesData.push(serie_item) }) const { LeadValue,LeadUnit } = this.relevanceChartData.CorrelationChartInfo; const { Source } = this.relevanceChartData.ChartInfo; let relevanceUnitEnMap = this.relevanceUnitEnMap; let tooltip = { formatter: function() { let str = `

相关性系数:${this.y.toFixed(4)}


领先${ Source===3 ?this.x+'期' : LeadValue+LeadUnit}

` return str }, formatterCh: function() { let str = `

相关性系数:${this.y.toFixed(4)}


领先${ Source===3 ?this.x+'期' : LeadValue+LeadUnit}

` return str }, formatterEn: function() { let str = `

Correlation coefficient:${this.y.toFixed(4)}


lead${ Source===3 ? this.x+'stage' : LeadValue+relevanceUnitEnMap[LeadUnit]}

` return str } } this.options = { isRelevanceChart: Source===3, title: { text:'' }, series: seriesData, yAxis: [yAxis] , xAxis:xAxis, tooltip } }, /* 截面散点图获取详情赋值 */ initSectionScatterData({ DataResp }) { this.chartLimit = { min: Number(DataResp.YMinValue), max: Number(DataResp.YMaxValue), x_min: Number(DataResp.XMinValue), x_max: Number(DataResp.XMaxValue) } this.sectionScatterData = DataResp; this.setSectionScatterChart(); }, /* 截面散点图设置 sectionScatterData */ setSectionScatterChart() { const { DataList,XName,XNameEn,XUnitName,XUnitNameEn,YName,YNameEn,YUnitName,YUnitNameEn } = this.sectionScatterData; const { min,max,x_min,x_max } = this.chartLimit; //y轴 let yAxis = { ...basicYAxis, title: { text: YName, textCh:YName,// 中文 textEn:YNameEn, style:{}, styleEn:{cursor:'pointer'}, align: 'middle', }, opposite: false, reversed: false, min: Number(min), max: Number(max), tickWidth: 1, } //x轴 let xAxis = { ...scatterXAxis, title: { text: XName, textCh:XName,// 中文 textEn:XNameEn, style:{}, styleEn:{cursor:'pointer'}, align: 'middle', }, min: Number(x_min), max: Number(x_max), } //数据列 let series = []; DataList.forEach(item => { //数据列 let series_item = { data: [], type: 'scatter', name: item.Name, nameCh: item.Name, nameEn: item.NameEn, color: item.Color, lineWidth: 0, chartType: 'linear', zIndex:1 } item.EdbInfoList.forEach(_ => { series_item.data.push({ x: _.XValue, y: _.YValue, dataLabels: { enabled: _.IsShow, allowOverlap: true, align: 'left', format: _.Name, formatCh: _.Name, formatEn: _.NameEn } }) }) series.push(series_item); //趋势线 if(item.ShowTrendLine) { let trend_data = item.TrendLimitData.map((_,_index) => ( _index === item.TrendLimitData.length-1 ? { x: _.X, y: _.Y, dataLabels: { enabled: item.ShowRSquare || item.ShowFitEquation, align: 'left', color: '#666', x: 20, y: 30, zIndex: 9, allowOverlap: true, formatter: function(){ let tag = ''; item.ShowRSquare && item.ShowFitEquation ? tag =`${item.TrendLine}
R²=${item.RSquare}` : item.ShowRSquare && !item.ShowFitEquation ? tag =`R²=${item.RSquare}` : item.ShowFitEquation && !item.ShowRSquare ? tag =`${item.TrendLine}` : '' return tag } } } : { x: _.X, y: _.Y, } )) let trend_item = { data: trend_data, type: 'spline', linkedTo: ':previous', color: item.Color, lineWidth: 1, chartType: 'linear', enableMouseTracking: false, dashStyle:'Dash', zIndex: 2, marker: { enabled: false } } series.push(trend_item) } }) let tooltip = { formatter: function() { let series_obj = DataList.find(_ => _.Name === this.series.name); let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===this.x && _.YValue===this.y); let str=`${ ponit_obj.Name }`; str += `
\u25CF${ponit_obj.XName}: ${this.x} ${ponit_obj.XDate}
`; str += `\u25CF${ponit_obj.YName}: ${this.y} ${ponit_obj.YDate}`; return str }, formatterCh: function() { let series_obj = DataList.find(_ => _.Name === this.series.name); let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===this.x && _.YValue===this.y); let str=`${ ponit_obj.Name }`; str += `
\u25CF${ponit_obj.XName}: ${this.x} ${ponit_obj.XDate}
`; str += `\u25CF${ponit_obj.YName}: ${this.y} ${ponit_obj.YDate}`; return str }, formatterEn: function() { let series_obj = DataList.find(_ => _.NameEn === this.series.name); let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===this.x && _.YValue===this.y); let str=`${ ponit_obj.NameEn }`; str += `
\u25CF${ponit_obj.XNameEn}: ${this.x} ${ponit_obj.XDate}
`; str += `\u25CF${ponit_obj.YNameEn}: ${this.y} ${ponit_obj.YDate}`; return str } } this.options = { title: { text:'' }, series, yAxis: [yAxis], xAxis, tooltip } }, /* 统计频率图 */ setStatisticFrequency() { const { DataList,LeftMaxValue,LeftMinValue,RightMaxValue,RightMinValue } = this.statisticFrequencyData; let xAxis = { ...scatterXAxis, tickWidth: 1, title: { text: ``, align: 'high', rotation: 0, x: 0, offset: 20, } } //y和系列 let yAxis = [],series = []; DataList.forEach((item,index) => { let y_item = { ...basicYAxis, title: { text: item.Unit, textCh:item.Unit,// 中文 textEn:item.UnitEn||item.Unit, align: 'high', rotation: 0, y: -15, offset: 0, }, opposite: item.IsAxis===1?false:true, min: index===0? Number(LeftMinValue):Number(RightMinValue), max: index===0? Number(LeftMaxValue):Number(RightMaxValue), tickWidth: 1, } let series_item = { data: item.Value.map(_ =>[_.X,_.Y]), type: 'spline', yAxis: index, name: item.Name, nameCh: item.Name, nameEn: item.NameEn||item.Name, color: item.Color, lineWidth: 3, chartType: 'linear', zIndex:1 } series.push(series_item); yAxis.push(y_item) }) let tooltip = { formatter: function() { let xList = DataList[0].Value.map(_ =>_.X); let step = xList[1]-xList[0]; let data_interval = `[${this.x},${this.x+step}]`; let str=`${ data_interval }`; this.points.forEach(item => { str += `
\u25CF${item.series.name}: ${item.y}%
` }) return str }, shared: true } this.options = { title: { text:'' }, tooltip, series, yAxis, xAxis } }, /* 查询范围为1年内 x轴显示为月/日 否则默认年/月 */ xTimeDiffer() { const end_date = this.chartInfo.DateType === 5 ? this.chartInfo.EndDate : this.chartInfo.DateType === 6 ? new Date() : ''; //年限差 const year_differ = this.$moment(end_date).diff( this.$moment(this.chartInfo.StartDate), 'years', true ); // console.log(year_differ) if ([5, 6].includes(this.chartInfo.DateType) && year_differ <= 1) { // return true; defaultOpts.xAxis.labels = { formatter: function () { return Highcharts.dateFormat('%m/%d', this.value); }, style: { fontSize: '10px', }, }; } else { // return false; defaultOpts.xAxis.labels = { style: { fontSize: '10px', }, }; } }, /* 拼接动态的指标名称小标签 */ concatDynamicTag({ IsAxis,IsOrder,EdbInfoType,LeadValue,LeadUnit },lang='ch') { // IsAxis左轴1 右轴0 2右2轴 //IsOrder正序false 逆序true //EdbInfoType是否是领先指标 // lang ch 中文 en 英文 const axisLabelMap = lang=='ch'?{ 0: '右轴', 2: '右2轴' }:{ 0: 'RHS', 2: '2-RHS' } const orderLabelMap = lang=='ch'?{ 1: '逆序' }:{ 1: 'REV' } const edbInfoMap = lang=='ch'?{ 0: '领先' }:{ 0: 'Lead' } //英文领先单位转换 const leadUnit = lang==='ch' ? LeadUnit : this.leadUnitEnMap[LeadUnit]; let axis_tag = axisLabelMap[IsAxis] || ''; //逆序拼接 let order_tag = orderLabelMap[Number(IsOrder)] ? `${axis_tag ? ',': ''}${orderLabelMap[Number(IsOrder)]}` : '' //领先拼接 let edb_tag = edbInfoMap[EdbInfoType] ? `${(axis_tag||order_tag) ? ',' : '' }${edbInfoMap[EdbInfoType]} ${LeadValue}${leadUnit}` : ''; return (axis_tag || order_tag || edb_tag) ? `(${axis_tag}${order_tag}${edb_tag})` : '' }, /* 指标顺序调整 IsAxis: 0右轴 1左轴 2右2*/ changeEdbOrder(data) { // 左轴指标 let left_edbs = data.filter(_ => _.IsAxis===1); //右轴指标 let right_edbs = data.filter(_ => !_.IsAxis); // 右2轴指标 let right_two_edbs = data.filter(_ => _.IsAxis === 2); // 按 左 右 右2顺序排列 return [left_edbs,right_edbs,right_two_edbs].flat(Infinity); }, /* 获取轴数值的最大长度 通过真实数据推测而已 也不准确 */ getLabelMaxLen(data) { let value_arr = data.map(_ => String(Math.abs(_.Value))); let max_len_value = value_arr.reduce((a,b)=> (a.length > b.length ? a : b)) let num = Number(max_len_value) > 1 ? String(parseInt(Number(max_len_value))) : max_len_value return num.length }, /* 预测配置 分区 */ getPredictParams({LatestDate,MoveLatestDate,PredictChartColor,ChartStyle},chartStyle='') { return { zoneAxis: 'x', zones: [{ value: new Date(MoveLatestDate||LatestDate).getTime()+1 }, { dashStyle: 'ShortDot', color:(ChartStyle==='column' || chartStyle==='column') ? 'transparent' : PredictChartColor }], } }, /* 季节图预测数据 年份=分割点年份做分割 年份>分割点年份全为预测 */ getSeasonPredictParams(timestamp) { return timestamp ? { zoneAxis: 'x', zones: [{ value: new Date(timestamp).getTime()+1, }, { dashStyle: 'ShortDot', }] } : {} } }, };