|
@@ -0,0 +1,379 @@
|
|
|
+<!-- -->
|
|
|
+<template>
|
|
|
+ <div class="chart-show">
|
|
|
+ <header class="chart-header" @click="openNew">
|
|
|
+ {{ chartInfo.ChartName }}
|
|
|
+ </header>
|
|
|
+ <template v-if="haveData">
|
|
|
+ <div
|
|
|
+ class="chart-wrapper"
|
|
|
+ v-loading="loading"
|
|
|
+ element-loading-spinner="el-icon-loading"
|
|
|
+ element-loading-text="加载中..."
|
|
|
+ >
|
|
|
+ <chart :options="options" :chartId="1" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="chart-wrapper notfound" v-else>
|
|
|
+ <i class="el-icon-warning"></i>哎吆,你的图飞了,赶快去找管理员救命吧~
|
|
|
+ </div>
|
|
|
+ <!-- <div class="bootom-source">source: <strong><em> 弘则研究</em></strong></div> -->
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts">
|
|
|
+import { defineComponent, reactive, toRefs, onMounted, ref } from 'vue';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+import chart from '@/components/chart.vue';
|
|
|
+import { IState } from './typing';
|
|
|
+import { ChartApi } from '@/request/api';
|
|
|
+import _ from 'lodash';
|
|
|
+import { IDataProps, ILunarItem, IParams, ISeasonDataItemProps } from '@/types';
|
|
|
+import Highcharts from 'Highcharts';
|
|
|
+import { defaultOpts, seasonOptions } from '@/utils/chartOptions';
|
|
|
+import moment from 'moment';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ components: {
|
|
|
+ chart,
|
|
|
+ },
|
|
|
+ setup() {
|
|
|
+ const route = useRoute();
|
|
|
+
|
|
|
+ const loading = ref(false);
|
|
|
+
|
|
|
+ const haveData = ref(true);
|
|
|
+
|
|
|
+ // const code = ref('b9ce50bc8a64fd6ff88d361ed44d2de7');//公历
|
|
|
+ // const code = ref('3df87f3b906c074780a643dcd46dcc22'); //农历
|
|
|
+ // const code = ref('5292157e53beaa7a1146e8090cae308d'); //曲线
|
|
|
+ const code = ref(route.query.code);
|
|
|
+
|
|
|
+ const state = reactive<IState>({
|
|
|
+ options: {},
|
|
|
+ chartInfo: {},
|
|
|
+ dataList: [],
|
|
|
+ });
|
|
|
+
|
|
|
+ onMounted((): void => {
|
|
|
+ getChartInfo();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 打开新窗口
|
|
|
+ const openNew = (): void => {
|
|
|
+ window.open(window.location.href,'_blank');
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 获取图表数据信息 */
|
|
|
+ const getChartInfo = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const { Data } = await ChartApi.getChart({
|
|
|
+ UniqueCode: code.value || '',
|
|
|
+ });
|
|
|
+ loading.value = false;
|
|
|
+ state.chartInfo = Data.ChartInfo;
|
|
|
+ state.dataList = Data.EdbInfoList;
|
|
|
+ document.title = Data.ChartInfo.ChartName;
|
|
|
+ haveData.value = true;
|
|
|
+ setOptions();
|
|
|
+ }catch (e) {
|
|
|
+ loading.value = false;
|
|
|
+ haveData.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ // 曲线图x轴显示计算年限差 >1年 显示年/月 <=1 显示月/日
|
|
|
+ const xTimeDiffer = () => {
|
|
|
+ const end_date = state.chartInfo.DateType === 5
|
|
|
+ ? state.chartInfo.EndDate
|
|
|
+ : state.chartInfo.DateType === 6
|
|
|
+ ? new Date()
|
|
|
+ : '';
|
|
|
+ //年限差
|
|
|
+ const year_differ = moment(end_date).diff(
|
|
|
+ moment(state.chartInfo.StartDate),
|
|
|
+ 'years',
|
|
|
+ true
|
|
|
+ );
|
|
|
+ // console.log(year_differ)
|
|
|
+ if (
|
|
|
+ state.chartInfo.DateType === 4 ||
|
|
|
+ ([5, 6].includes(state.chartInfo.DateType) && year_differ <= 1)
|
|
|
+ ) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 设置options 曲线图 季节图*/
|
|
|
+ const setOptions = () => {
|
|
|
+ // ChartType: 1曲线图 2季节图 季节图中公历和农历数据结构不同
|
|
|
+ if (state.chartInfo.ChartType === 1) {
|
|
|
+
|
|
|
+ //拼接标题 数据列
|
|
|
+ let data = [] as any[],ydata = [] as any[];
|
|
|
+ const chartData = _.cloneDeep(state.dataList);
|
|
|
+
|
|
|
+ chartData.forEach((item:IDataProps ,index:number) => {
|
|
|
+
|
|
|
+ //轴位置值相同的下标
|
|
|
+ let sameSideIndex = chartData.findIndex(
|
|
|
+ (i:IDataProps) => i.IsAxis === item.IsAxis
|
|
|
+ );
|
|
|
+ //y轴
|
|
|
+ let yItem = {
|
|
|
+ labels: {
|
|
|
+ formatter: function (ctx: any) {
|
|
|
+ let val = ctx.value < 1000 ? ctx.value : ctx.value / 1000 + 'k';
|
|
|
+ return sameSideIndex !== index ? '' : val;
|
|
|
+ },
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ opposite: item.IsAxis === 0,
|
|
|
+ reversed: item.IsOrder,
|
|
|
+ min: Number(chartData[sameSideIndex].MinData),
|
|
|
+ max: Number(chartData[sameSideIndex].MaxData),
|
|
|
+ tickWidth: sameSideIndex !== index ? 0 : 1,
|
|
|
+ lineWidth: 1,
|
|
|
+ lineColor: '#bfbfbf',
|
|
|
+ tickColor: '#bfbfbf',
|
|
|
+ offset: 0,
|
|
|
+ visible: true,
|
|
|
+ gridLineWidth: 0,
|
|
|
+ tickPosition: 'inside',
|
|
|
+ endOnTick: false,
|
|
|
+ startOnTick: false,
|
|
|
+ }
|
|
|
+
|
|
|
+ // //拼接标题 判断相同指标名称拼接来源
|
|
|
+ let dynamic_title = item.EdbName;
|
|
|
+ let dynamic_arr = chartData.filter(
|
|
|
+ (item: IDataProps) => dynamic_title === item.EdbName
|
|
|
+ );
|
|
|
+
|
|
|
+ // 拼接配置 IsAxis左轴1 右轴0 IsOrder正序false 逆序true EdbInfoType是否是领先指标
|
|
|
+ let dynamic_tag: string = item.IsAxis && item.IsOrder && item.EdbInfoType
|
|
|
+ ? '(逆序)'
|
|
|
+ : !item.IsAxis && item.IsOrder && item.EdbInfoType
|
|
|
+ ? '(右轴,逆序)'
|
|
|
+ : !item.IsAxis && !item.IsOrder && item.EdbInfoType
|
|
|
+ ? '(右轴)'
|
|
|
+ : !item.IsAxis && !item.IsOrder && !item.EdbInfoType
|
|
|
+ ? `(右轴,领先${item.LeadValue}${item.LeadUnit})`
|
|
|
+ : !item.IsAxis && item.IsOrder && !item.EdbInfoType
|
|
|
+ ? `(右轴,逆序,领先${item.LeadValue}${item.LeadUnit})`
|
|
|
+ : item.IsAxis && item.IsOrder && !item.EdbInfoType
|
|
|
+ ? `(逆序,领先${item.LeadValue}${item.LeadUnit})`
|
|
|
+ : item.IsAxis && !item.IsOrder && !item.EdbInfoType
|
|
|
+ ? `(领先${item.LeadValue}${item.LeadUnit})`
|
|
|
+ : '';
|
|
|
+
|
|
|
+ //数据列
|
|
|
+ let obj = {
|
|
|
+ data: [] as any[],
|
|
|
+ type: item.ChartStyle,
|
|
|
+ yAxis: index,
|
|
|
+ name:
|
|
|
+ dynamic_arr.length > 1
|
|
|
+ ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
|
|
|
+ : `${item.EdbName}${dynamic_tag}`,
|
|
|
+ color: item.ChartColor,
|
|
|
+ lineWidth: Number(item.ChartWidth),
|
|
|
+ };
|
|
|
+ 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轴显示为月/日 否则默认年/月
|
|
|
+ let xAxis:any = {};
|
|
|
+ const bool_time:boolean = xTimeDiffer();
|
|
|
+ xAxis = bool_time ? {
|
|
|
+ ...defaultOpts.xAxis,
|
|
|
+ labels: {
|
|
|
+ formatter: function (ctx: any) {
|
|
|
+ return Highcharts.dateFormat('%m/%d', ctx.value);
|
|
|
+ },
|
|
|
+ }
|
|
|
+ } : {
|
|
|
+ ...defaultOpts.xAxis,
|
|
|
+ labels: {},
|
|
|
+ }
|
|
|
+
|
|
|
+ state.options = {
|
|
|
+ series: data,
|
|
|
+ yAxis: ydata,
|
|
|
+ xAxis
|
|
|
+ };
|
|
|
+
|
|
|
+ } else {
|
|
|
+ /* 季节性图的图表配置 */
|
|
|
+ const chartData = state.dataList[0];
|
|
|
+ let seasonYdata = [],
|
|
|
+ seasonData = [],
|
|
|
+ chart = {};
|
|
|
+
|
|
|
+ /* 公历数据处理 处理数据列 y轴 */
|
|
|
+ if (state.chartInfo.Calendar === '公历')
|
|
|
+ for (let j of chartData.DataList) {
|
|
|
+ let serie_item = {
|
|
|
+ data: [] as any[],
|
|
|
+ type: chartData.ChartStyle,
|
|
|
+ yAxis: 0,
|
|
|
+ name: j.Year,
|
|
|
+ };
|
|
|
+ const data_array = _.cloneDeep(j.DataList);
|
|
|
+ data_array &&
|
|
|
+ data_array.forEach((item: IParams) => {
|
|
|
+ serie_item.data.push([item.DataTimestamp, item.Value]);
|
|
|
+ });
|
|
|
+ const index = chartData.DataList.findIndex(
|
|
|
+ (item: ISeasonDataItemProps) => item.Year === j.Year
|
|
|
+ );
|
|
|
+ const s_yItem = {
|
|
|
+ labels: {
|
|
|
+ formatter: function (ctx: any) {
|
|
|
+ let val = ctx.value < 1000 ? ctx.value : ctx.value / 1000 + 'k';
|
|
|
+ return index !== 0 ? '' : val;
|
|
|
+ },
|
|
|
+ align: 'center',
|
|
|
+ x: -5,
|
|
|
+ },
|
|
|
+ max: Number(chartData.MaxData),
|
|
|
+ min: Number(chartData.MinData),
|
|
|
+ ...defaultOpts.yAxis,
|
|
|
+ };
|
|
|
+ seasonData.push(serie_item);
|
|
|
+ seasonYdata.push(s_yItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 农历数据处理 */
|
|
|
+ let filterArr =
|
|
|
+ state.chartInfo.Calendar === '农历'
|
|
|
+ ? chartData.DataList.List.filter(
|
|
|
+ (item: ILunarItem, index: number) => index > 0
|
|
|
+ )
|
|
|
+ : [];
|
|
|
+ if (state.chartInfo.Calendar === '农历')
|
|
|
+ for (let j of filterArr) {
|
|
|
+ let serie_item = {
|
|
|
+ data: [] as any[],
|
|
|
+ type: chartData.ChartStyle,
|
|
|
+ yAxis: 0,
|
|
|
+ name: j.Year,
|
|
|
+ };
|
|
|
+ const data_array = _.cloneDeep(j.Items);
|
|
|
+ data_array &&
|
|
|
+ data_array.forEach((item: IParams) => {
|
|
|
+ serie_item.data.push([item.DataTimestamp, item.Value]);
|
|
|
+ });
|
|
|
+ const index = filterArr.findIndex(
|
|
|
+ (item: ILunarItem) => item.Year === j.Year
|
|
|
+ );
|
|
|
+
|
|
|
+ const s_yItem = {
|
|
|
+ labels: {
|
|
|
+ formatter: function (ctx: any) {
|
|
|
+ let val = ctx.value < 1000 ? ctx.value : ctx.value / 1000 + 'k';
|
|
|
+ return index !== 0 ? '' : val;
|
|
|
+ },
|
|
|
+ align: 'center',
|
|
|
+ x: -5,
|
|
|
+ },
|
|
|
+ max: Number(chartData.MaxData),
|
|
|
+ min: Number(chartData.MinData),
|
|
|
+ ...defaultOpts.yAxis,
|
|
|
+ };
|
|
|
+ seasonData.push(serie_item);
|
|
|
+ seasonYdata.push(s_yItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 季节图x轴显示月/日
|
|
|
+ const xAxis = {
|
|
|
+ ...defaultOpts.xAxis,
|
|
|
+ labels: {
|
|
|
+ formatter: function (ctx: any) {
|
|
|
+ return Highcharts.dateFormat('%m/%d', ctx.value);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // 季节图提示框显示 月/日
|
|
|
+ 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 = state.chartInfo.Calendar === '农历'
|
|
|
+ ? {
|
|
|
+ enabled: true,
|
|
|
+ selected: 0,
|
|
|
+ buttons: [
|
|
|
+ {
|
|
|
+ type: 'month',
|
|
|
+ count: 12,
|
|
|
+ text: '12月',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'month',
|
|
|
+ count: 15,
|
|
|
+ text: '15月',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'all',
|
|
|
+ text: '全部',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+ : {
|
|
|
+ enabled: false,
|
|
|
+ };
|
|
|
+
|
|
|
+ //农历图调整顶部缩进
|
|
|
+ if (state.chartInfo.Calendar === '农历') chart = {
|
|
|
+ spacingTop: -24,
|
|
|
+ }
|
|
|
+
|
|
|
+ state.options = {
|
|
|
+ colors:
|
|
|
+ state.chartInfo.Calendar === '公历'
|
|
|
+ ? seasonOptions.colors.slice(-chartData.DataList.length)
|
|
|
+ : seasonOptions.colors.slice(-filterArr.length),
|
|
|
+ series: seasonData,
|
|
|
+ yAxis: seasonYdata,
|
|
|
+ xAxis,
|
|
|
+ rangeSelector,
|
|
|
+ chart
|
|
|
+ };
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...toRefs(state),
|
|
|
+ loading,
|
|
|
+ haveData,
|
|
|
+ openNew
|
|
|
+ };
|
|
|
+ },
|
|
|
+});
|
|
|
+</script>
|
|
|
+<style scoped lang="less">
|
|
|
+@import './index.less';
|
|
|
+</style>
|