|  | @@ -1,67 +1,63 @@
 | 
	
		
			
				|  |  |  <script lang="ts" setup>
 | 
	
		
			
				|  |  | -import { ref,onMounted, onBeforeUnmount, Ref, unref, watch, computed } from 'vue'
 | 
	
		
			
				|  |  | -import * as echarts from 'echarts'
 | 
	
		
			
				|  |  | -import {sbCampaignMetricsEnum, spCampaignMetricsEnum} from '/@/views/adManage/utils/enum.js'
 | 
	
		
			
				|  |  | -import MetricsCards from '/@/components/MetricsCards/index.vue'
 | 
	
		
			
				|  |  | -import XEUtils from 'xe-utils'
 | 
	
		
			
				|  |  | -import { buildChartOpt, parseQueryParams } from '/@/views/adManage/utils/tools.js'
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// import { useShopInfo } from '/@/stores/shopInfo'
 | 
	
		
			
				|  |  | -// import { usePublicData } from '/@/stores/publicData'
 | 
	
		
			
				|  |  | -// import { storeToRefs } from 'pinia'
 | 
	
		
			
				|  |  | +import { computed, onBeforeUnmount, onMounted, Ref, ref, watch } from 'vue';
 | 
	
		
			
				|  |  | +import * as echarts from 'echarts';
 | 
	
		
			
				|  |  | +import { spCampaignMetricsEnum } from '/@/views/adManage/utils/enum.js';
 | 
	
		
			
				|  |  | +import MetricsCards from '/@/components/MetricsCards/index.vue';
 | 
	
		
			
				|  |  | +import XEUtils from 'xe-utils';
 | 
	
		
			
				|  |  | +import { parseQueryParams } from '/@/views/adManage/utils/tools.js';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  defineOptions({
 | 
	
		
			
				|  |  | -  name: "DataTendencyChart"
 | 
	
		
			
				|  |  | -})
 | 
	
		
			
				|  |  | +  name: 'DataTendencyChart',
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  interface Props {
 | 
	
		
			
				|  |  | -  fetchCard: Function,
 | 
	
		
			
				|  |  | -  fetchLine: Function,
 | 
	
		
			
				|  |  | -  fetchLineMonth?: Function,
 | 
	
		
			
				|  |  | -  fetchLineWeek?: Function,
 | 
	
		
			
				|  |  | -  query: {[key: string]: any},
 | 
	
		
			
				|  |  | -  initMetric?: ShowMetric[],
 | 
	
		
			
				|  |  | -  metricEnum?: {[key: string]: string}[]
 | 
	
		
			
				|  |  | +  fetchCard: Function;
 | 
	
		
			
				|  |  | +  fetchLine: Function;
 | 
	
		
			
				|  |  | +  fetchLineMonth?: Function;
 | 
	
		
			
				|  |  | +  fetchLineWeek?: Function;
 | 
	
		
			
				|  |  | +  query: { [key: string]: any };
 | 
	
		
			
				|  |  | +  initMetric?: ShowMetric[];
 | 
	
		
			
				|  |  | +  metricEnum?: { [key: string]: string }[];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const props = withDefaults(defineProps<Props>(), {
 | 
	
		
			
				|  |  |    initMetric: () => [
 | 
	
		
			
				|  |  | -    {metric: 'Impression', color: '#0085ff', 'label': '曝光量'},
 | 
	
		
			
				|  |  | -    {metric: 'Click', color: '#3fd4cf', 'label': '点击量'},
 | 
	
		
			
				|  |  | -    {metric: 'Spend', color: '#ff9500', 'label': '花费'},
 | 
	
		
			
				|  |  | +    { metric: 'Impression', color: '#0085ff', label: '曝光量' },
 | 
	
		
			
				|  |  | +    { metric: 'Click', color: '#3fd4cf', label: '点击量' },
 | 
	
		
			
				|  |  | +    { metric: 'Spend', color: '#ff9500', label: '花费' },
 | 
	
		
			
				|  |  |    ],
 | 
	
		
			
				|  |  | -  metricEnum: () => sbCampaignMetricsEnum
 | 
	
		
			
				|  |  | -})
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const metrics = ref(props.initMetric)
 | 
	
		
			
				|  |  | -// const shopInfo = useShopInfo()
 | 
	
		
			
				|  |  | -// const publicData = usePublicData()
 | 
	
		
			
				|  |  | -// const { dateRange } = storeToRefs(publicData)
 | 
	
		
			
				|  |  | -const metricsItems: Ref<MetricData[]> = ref([])
 | 
	
		
			
				|  |  | -let chartObj:any
 | 
	
		
			
				|  |  | -const chartRef = ref()
 | 
	
		
			
				|  |  | -const statDim = ref('day')
 | 
	
		
			
				|  |  | +  metricEnum: () => spCampaignMetricsEnum,
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const metrics = ref(props.initMetric);
 | 
	
		
			
				|  |  | +const metricsItems: Ref<MetricData[]> = ref([]);
 | 
	
		
			
				|  |  | +let chartObj: any;
 | 
	
		
			
				|  |  | +const chartRef = ref();
 | 
	
		
			
				|  |  | +const statDim = ref('day');
 | 
	
		
			
				|  |  |  const option: any = {
 | 
	
		
			
				|  |  |    dataset: {
 | 
	
		
			
				|  |  | -    source: []
 | 
	
		
			
				|  |  | +    source: [],
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    tooltip: {
 | 
	
		
			
				|  |  |      trigger: 'axis',
 | 
	
		
			
				|  |  |      axisPointer: {
 | 
	
		
			
				|  |  |        label: {
 | 
	
		
			
				|  |  | -        backgroundColor: '#6a7985'
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +        backgroundColor: '#6a7985',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    legend: {
 | 
	
		
			
				|  |  | -    selected: {},  // 控制显隐
 | 
	
		
			
				|  |  | -    show: false
 | 
	
		
			
				|  |  | +    selected: {}, // 控制显隐
 | 
	
		
			
				|  |  | +    show: false,
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    grid: {
 | 
	
		
			
				|  |  | -    top: 50, right: 150, bottom: 30, left: 65,
 | 
	
		
			
				|  |  | +    top: 50,
 | 
	
		
			
				|  |  | +    right: 150,
 | 
	
		
			
				|  |  | +    bottom: 30,
 | 
	
		
			
				|  |  | +    left: 65,
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    xAxis: {
 | 
	
		
			
				|  |  | -    type: 'category'
 | 
	
		
			
				|  |  | +    type: 'category',
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    yAxis: [
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -69,13 +65,13 @@ const option: any = {
 | 
	
		
			
				|  |  |        type: 'value',
 | 
	
		
			
				|  |  |        name: '',
 | 
	
		
			
				|  |  |        splitLine: {
 | 
	
		
			
				|  |  | -        show: true // 设置显示分割线
 | 
	
		
			
				|  |  | +        show: true, // 设置显示分割线
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        axisLine: {
 | 
	
		
			
				|  |  |          show: true,
 | 
	
		
			
				|  |  | -				lineStyle: { color: '' }
 | 
	
		
			
				|  |  | +        lineStyle: { color: '' },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      show: true
 | 
	
		
			
				|  |  | +      show: true,
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        id: 1,
 | 
	
	
		
			
				|  | @@ -83,15 +79,15 @@ const option: any = {
 | 
	
		
			
				|  |  |        name: '',
 | 
	
		
			
				|  |  |        position: 'right',
 | 
	
		
			
				|  |  |        splitLine: {
 | 
	
		
			
				|  |  | -        show: false
 | 
	
		
			
				|  |  | +        show: false,
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        axisLine: {
 | 
	
		
			
				|  |  |          show: true,
 | 
	
		
			
				|  |  | -				lineStyle: {
 | 
	
		
			
				|  |  | -					color: ''
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | +        lineStyle: {
 | 
	
		
			
				|  |  | +          color: '',
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      show: true
 | 
	
		
			
				|  |  | +      show: true,
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        id: 2,
 | 
	
	
		
			
				|  | @@ -100,16 +96,16 @@ const option: any = {
 | 
	
		
			
				|  |  |        offset: 90,
 | 
	
		
			
				|  |  |        name: '',
 | 
	
		
			
				|  |  |        splitLine: {
 | 
	
		
			
				|  |  | -        show: false
 | 
	
		
			
				|  |  | +        show: false,
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        axisLine: {
 | 
	
		
			
				|  |  |          show: true,
 | 
	
		
			
				|  |  | -				lineStyle: {
 | 
	
		
			
				|  |  | -					color: ''
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | +        lineStyle: {
 | 
	
		
			
				|  |  | +          color: '',
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  | -      show: true
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +      show: true,
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    ],
 | 
	
		
			
				|  |  |    series: [
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -118,14 +114,14 @@ const option: any = {
 | 
	
		
			
				|  |  |        type: 'bar',
 | 
	
		
			
				|  |  |        encode: {
 | 
	
		
			
				|  |  |          x: 'Name',
 | 
	
		
			
				|  |  | -        y: ''
 | 
	
		
			
				|  |  | +        y: '',
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        barWidth: '18px',
 | 
	
		
			
				|  |  |        yAxisIndex: 0,
 | 
	
		
			
				|  |  |        itemStyle: {
 | 
	
		
			
				|  |  |          color: '',
 | 
	
		
			
				|  |  | -        borderRadius: 4,
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +        borderRadius: [4, 4, 4, 4],
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        id: 1,
 | 
	
	
		
			
				|  | @@ -133,7 +129,7 @@ const option: any = {
 | 
	
		
			
				|  |  |        type: 'line',
 | 
	
		
			
				|  |  |        encode: {
 | 
	
		
			
				|  |  |          x: 'Name',
 | 
	
		
			
				|  |  | -        y: ''
 | 
	
		
			
				|  |  | +        y: '',
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        symbolSize: 6,
 | 
	
		
			
				|  |  |        symbol: 'circle',
 | 
	
	
		
			
				|  | @@ -150,8 +146,8 @@ const option: any = {
 | 
	
		
			
				|  |  |          // ]),
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        emphasis: {
 | 
	
		
			
				|  |  | -        focus:'series'
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +        focus: 'series',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        id: 2,
 | 
	
	
		
			
				|  | @@ -159,7 +155,7 @@ const option: any = {
 | 
	
		
			
				|  |  |        type: 'line',
 | 
	
		
			
				|  |  |        encode: {
 | 
	
		
			
				|  |  |          x: 'Name',
 | 
	
		
			
				|  |  | -        y: ''
 | 
	
		
			
				|  |  | +        y: '',
 | 
	
		
			
				|  |  |        },
 | 
	
		
			
				|  |  |        symbolSize: 6,
 | 
	
		
			
				|  |  |        symbol: 'circle',
 | 
	
	
		
			
				|  | @@ -168,126 +164,223 @@ const option: any = {
 | 
	
		
			
				|  |  |        itemStyle: {},
 | 
	
		
			
				|  |  |        areaStyle: {},
 | 
	
		
			
				|  |  |        emphasis: {
 | 
	
		
			
				|  |  | -        focus:'series'
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  ]
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -const loading = ref(true)
 | 
	
		
			
				|  |  | -const queryParams = computed(() => parseQueryParams(props.query))
 | 
	
		
			
				|  |  | +        focus: 'series',
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +  ],
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +const loading = ref(true);
 | 
	
		
			
				|  |  | +const queryParams = computed(() => parseQueryParams(props.query));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  onMounted(() => {
 | 
	
		
			
				|  |  | -  getMetricsItems()
 | 
	
		
			
				|  |  | -	addResize()
 | 
	
		
			
				|  |  | +  getMetricsItems();
 | 
	
		
			
				|  |  | +  addResize();
 | 
	
		
			
				|  |  |    // initLine()
 | 
	
		
			
				|  |  | -  setTimeout(() => { initLine() }, 0)
 | 
	
		
			
				|  |  | -})
 | 
	
		
			
				|  |  | +  setTimeout(() => {
 | 
	
		
			
				|  |  | +    initLine();
 | 
	
		
			
				|  |  | +  }, 0);
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  onBeforeUnmount(() => {
 | 
	
		
			
				|  |  | -	if(chartObj) {
 | 
	
		
			
				|  |  | -		chartObj.dispose()
 | 
	
		
			
				|  |  | -    chartObj = null
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -  removeResize()
 | 
	
		
			
				|  |  | -})
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const initLine = async () => {
 | 
	
		
			
				|  |  | -	chartObj = echarts.init(chartRef.value)
 | 
	
		
			
				|  |  | -	const items = await getDataset()
 | 
	
		
			
				|  |  | -	option.dataset.source = items
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  XEUtils.arrayEach(option.series, (info:any, index) => {
 | 
	
		
			
				|  |  | -    const color = metrics.value[index].color
 | 
	
		
			
				|  |  | -    info.name = metrics.value[index].label
 | 
	
		
			
				|  |  | -    info.encode.y = metrics.value[index].metric
 | 
	
		
			
				|  |  | -    if (info.type === 'bar') {
 | 
	
		
			
				|  |  | -      info.itemStyle.color = color
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      info.itemStyle = { color: color, borderColor: color }
 | 
	
		
			
				|  |  | -      info.areaStyle = {
 | 
	
		
			
				|  |  | -        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
	
		
			
				|  |  | -          { offset: 0, color: color + '53' },
 | 
	
		
			
				|  |  | -          { offset: 1, color: color + '03' },
 | 
	
		
			
				|  |  | -        ])
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  })
 | 
	
		
			
				|  |  | -  XEUtils.arrayEach(option.yAxis, (info:any, index) => {
 | 
	
		
			
				|  |  | -    info.name = metrics.value[index].label
 | 
	
		
			
				|  |  | -    info.axisLine.lineStyle.color = metrics.value[index].color
 | 
	
		
			
				|  |  | -  })
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  XEUtils.arrayEach(props.metricEnum, info => {
 | 
	
		
			
				|  |  | -    option.legend.selected[info.label] = false
 | 
	
		
			
				|  |  | -  })
 | 
	
		
			
				|  |  | -  for(const info of metrics.value) {
 | 
	
		
			
				|  |  | -    option.legend.selected[info.label] = true
 | 
	
		
			
				|  |  | +  if (chartObj) {
 | 
	
		
			
				|  |  | +    chartObj.dispose();
 | 
	
		
			
				|  |  | +    chartObj = null;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  // console.log(option)
 | 
	
		
			
				|  |  | -	chartObj.setOption(option)
 | 
	
		
			
				|  |  | -  loading.value = false
 | 
	
		
			
				|  |  | +  removeResize();
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const metricColors = {
 | 
	
		
			
				|  |  | +  Impression: '#0085ff',
 | 
	
		
			
				|  |  | +  Click: '#3fd4cf',
 | 
	
		
			
				|  |  | +  Spend: '#ff9500',
 | 
	
		
			
				|  |  | +  // ... 其他指标的颜色
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function getColorForMetric(metric: string): string {
 | 
	
		
			
				|  |  | +  return metricColors[metric] || '#999999'; // 如果没有预定义的颜色,返回一个默认颜色
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +async function initLine() {
 | 
	
		
			
				|  |  | +  chartObj = echarts.init(chartRef.value);
 | 
	
		
			
				|  |  | +  option.dataset.source = await getDataset();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 初始化系列和 y 轴
 | 
	
		
			
				|  |  | +  option.series = metrics.value.map((metric, index) => ({
 | 
	
		
			
				|  |  | +    id: index,
 | 
	
		
			
				|  |  | +    name: metric.label,
 | 
	
		
			
				|  |  | +    type: index === 0 ? 'bar' : 'line',
 | 
	
		
			
				|  |  | +    encode: { x: 'Name', y: metric.metric },
 | 
	
		
			
				|  |  | +    yAxisIndex: index,
 | 
	
		
			
				|  |  | +    itemStyle: { color: option.series.type == 'bar' ? '#0085ff' : metric.color, borderRadius: [6, 6, 6, 6] },
 | 
	
		
			
				|  |  | +    lineStyle: { color: metric.color },
 | 
	
		
			
				|  |  | +    barWidth: '10%',
 | 
	
		
			
				|  |  | +    areaStyle:
 | 
	
		
			
				|  |  | +      index !== 0
 | 
	
		
			
				|  |  | +        ? {
 | 
	
		
			
				|  |  | +            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
	
		
			
				|  |  | +              { offset: 0, color: metric.color + '53' },
 | 
	
		
			
				|  |  | +              { offset: 1, color: metric.color + '03' },
 | 
	
		
			
				|  |  | +            ]),
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        : undefined,
 | 
	
		
			
				|  |  | +  }));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  option.yAxis = metrics.value.map((metric, index) => ({
 | 
	
		
			
				|  |  | +    id: index,
 | 
	
		
			
				|  |  | +    name: metric.label,
 | 
	
		
			
				|  |  | +    type: 'value',
 | 
	
		
			
				|  |  | +    position: index === 0 ? 'left' : 'right',
 | 
	
		
			
				|  |  | +    offset: index > 1 ? (index - 1) * 80 : 0,
 | 
	
		
			
				|  |  | +    axisLine: { show: true, lineStyle: { color: metric.color } },
 | 
	
		
			
				|  |  | +    splitLine: {
 | 
	
		
			
				|  |  | +      show: index === 0,
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    show: true,
 | 
	
		
			
				|  |  | +  }));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 初始化图例
 | 
	
		
			
				|  |  | +  option.legend.selected = props.metricEnum.reduce((acc, metric) => {
 | 
	
		
			
				|  |  | +    acc[metric.label] = metrics.value.some((m) => m.metric === metric.value);
 | 
	
		
			
				|  |  | +    return acc;
 | 
	
		
			
				|  |  | +  }, {});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  chartObj.setOption(option);
 | 
	
		
			
				|  |  | +  loading.value = false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -const getDataset = async () => {
 | 
	
		
			
				|  |  | -	if (statDim.value === 'week') {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +async function getDataset() {
 | 
	
		
			
				|  |  | +  if (statDim.value === 'week') {
 | 
	
		
			
				|  |  |      if (props.fetchLineWeek) {
 | 
	
		
			
				|  |  | -      const resp = await props.fetchLineWeek(queryParams.value)
 | 
	
		
			
				|  |  | -      return resp.data
 | 
	
		
			
				|  |  | +      const resp = await props.fetchLineWeek(queryParams.value);
 | 
	
		
			
				|  |  | +      return resp.data;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    } else if (statDim.value === 'month') {
 | 
	
		
			
				|  |  |      if (props.fetchLineMonth) {
 | 
	
		
			
				|  |  | -      const resp = await props.fetchLineMonth(queryParams.value)
 | 
	
		
			
				|  |  | -      return resp.data
 | 
	
		
			
				|  |  | +      const resp = await props.fetchLineMonth(queryParams.value);
 | 
	
		
			
				|  |  | +      return resp.data;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    const resp = await props.fetchLine(queryParams.value)
 | 
	
		
			
				|  |  | -    return resp.data
 | 
	
		
			
				|  |  | +    const resp = await props.fetchLine(queryParams.value);
 | 
	
		
			
				|  |  | +    return resp.data;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -const getMetricsItems = async () => {
 | 
	
		
			
				|  |  | -	const resp = await props.fetchCard(queryParams.value)
 | 
	
		
			
				|  |  | -	const data = resp.data
 | 
	
		
			
				|  |  | -  metricsItems.value.length = 0
 | 
	
		
			
				|  |  | -	XEUtils.arrayEach(props.metricEnum, info => {
 | 
	
		
			
				|  |  | -		const tmp:MetricData = {
 | 
	
		
			
				|  |  | -			label: info.label,
 | 
	
		
			
				|  |  | -			value: info.value,
 | 
	
		
			
				|  |  | -			metricVal: data[info.value],
 | 
	
		
			
				|  |  | -			gapVal: data[`gap${info.value}`],
 | 
	
		
			
				|  |  | -			preVal: data[`prev${info.value}`],
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		metricsItems.value.push(tmp)
 | 
	
		
			
				|  |  | -	})
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const changeMetric = () => {
 | 
	
		
			
				|  |  | -  const opt = buildChartOpt(option, metrics.value)
 | 
	
		
			
				|  |  | -  chartObj.setOption(opt)
 | 
	
		
			
				|  |  | +async function getMetricsItems() {
 | 
	
		
			
				|  |  | +  const resp = await props.fetchCard(queryParams.value);
 | 
	
		
			
				|  |  | +  const data = resp.data;
 | 
	
		
			
				|  |  | +  metricsItems.value.length = 0;
 | 
	
		
			
				|  |  | +  XEUtils.arrayEach(props.metricEnum, (info) => {
 | 
	
		
			
				|  |  | +    const tmp: MetricData = {
 | 
	
		
			
				|  |  | +      label: info.label,
 | 
	
		
			
				|  |  | +      value: info.value,
 | 
	
		
			
				|  |  | +      metricVal: data[info.value],
 | 
	
		
			
				|  |  | +      gapVal: data[`gap${info.value}`],
 | 
	
		
			
				|  |  | +      preVal: data[`prev${info.value}`],
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    metricsItems.value.push(tmp);
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const changeStatDim = async () => {
 | 
	
		
			
				|  |  | -  loading.value = true
 | 
	
		
			
				|  |  | -  let source = await getDataset()
 | 
	
		
			
				|  |  | -  if (source.length > 0) {
 | 
	
		
			
				|  |  | -    chartObj.setOption({dataset: {source: source}})
 | 
	
		
			
				|  |  | +// const changeMetric = () => {
 | 
	
		
			
				|  |  | +//   const opt = buildChartOpt(option, metrics.value)
 | 
	
		
			
				|  |  | +//   chartObj.setOption(opt)
 | 
	
		
			
				|  |  | +// }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function changeMetric() {
 | 
	
		
			
				|  |  | +  // 更新图例选中状态
 | 
	
		
			
				|  |  | +  option.legend.selected = props.metricEnum.reduce((acc, metric) => {
 | 
	
		
			
				|  |  | +    acc[metric.label] = metrics.value.some((m) => m.metric === metric.value);
 | 
	
		
			
				|  |  | +    return acc;
 | 
	
		
			
				|  |  | +  }, {});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 重新创建 series 数组,只包含选中的指标
 | 
	
		
			
				|  |  | +  option.series = metrics.value.map((metric, index) => {
 | 
	
		
			
				|  |  | +    const baseConfig = {
 | 
	
		
			
				|  |  | +      id: index,
 | 
	
		
			
				|  |  | +      name: metric.label,
 | 
	
		
			
				|  |  | +      type: metric.color === '#0085ff' ? 'bar' : 'line',
 | 
	
		
			
				|  |  | +      encode: { x: 'Name', y: metric.metric },
 | 
	
		
			
				|  |  | +      yAxisIndex: index,
 | 
	
		
			
				|  |  | +      itemStyle: { color: metric.color, borderRadius: [6, 6, 6, 6] },
 | 
	
		
			
				|  |  | +      lineStyle: { color: metric.color },
 | 
	
		
			
				|  |  | +      barWidth: '10%',
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (baseConfig != 'bar') {
 | 
	
		
			
				|  |  | +      baseConfig.areaStyle = {
 | 
	
		
			
				|  |  | +        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
	
		
			
				|  |  | +          { offset: 0, color: metric.color + '53' },
 | 
	
		
			
				|  |  | +          { offset: 1, color: metric.color + '03' },
 | 
	
		
			
				|  |  | +        ]),
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return baseConfig;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 更新 y 轴显示状态
 | 
	
		
			
				|  |  | +  option.yAxis = metrics.value.map((metric, index) => ({
 | 
	
		
			
				|  |  | +    id: index,
 | 
	
		
			
				|  |  | +    name: metric.label,
 | 
	
		
			
				|  |  | +    type: 'value',
 | 
	
		
			
				|  |  | +    position: index === 0 ? 'left' : 'right',
 | 
	
		
			
				|  |  | +    offset: index > 1 ? (index - 1) * 80 : 0,
 | 
	
		
			
				|  |  | +    axisLine: {
 | 
	
		
			
				|  |  | +      show: true,
 | 
	
		
			
				|  |  | +      lineStyle: { color: metric.color },
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    splitLine: {
 | 
	
		
			
				|  |  | +      show: index === 0,
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    show: true,
 | 
	
		
			
				|  |  | +  }));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 确保只有必要的 y 轴
 | 
	
		
			
				|  |  | +  while (option.yAxis.length > metrics.value.length) {
 | 
	
		
			
				|  |  | +    option.yAxis.pop();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  loading.value = false
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  chartObj.setOption(option, true); // 使用 true 作为第二个参数,强制完全刷新
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  watch(
 | 
	
		
			
				|  |  | -  props.query,
 | 
	
		
			
				|  |  | -  async () => {
 | 
	
		
			
				|  |  | -    // console.log("------watch-----queryParams", props.query)
 | 
	
		
			
				|  |  | -    loading.value = true
 | 
	
		
			
				|  |  | -    await getMetricsItems()
 | 
	
		
			
				|  |  | -    const items = await getDataset()
 | 
	
		
			
				|  |  | -    const opt = { dataset: { source: items } }
 | 
	
		
			
				|  |  | -    chartObj.setOption(opt)
 | 
	
		
			
				|  |  | -    loading.value = false
 | 
	
		
			
				|  |  | +  metrics,
 | 
	
		
			
				|  |  | +  () => {
 | 
	
		
			
				|  |  | +    changeMetric();
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  { deep: true }
 | 
	
		
			
				|  |  | +);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +async function changeStatDim() {
 | 
	
		
			
				|  |  | +  loading.value = true;
 | 
	
		
			
				|  |  | +  let source = await getDataset();
 | 
	
		
			
				|  |  | +  if (source.length > 0) {
 | 
	
		
			
				|  |  | +    chartObj.setOption({ dataset: { source: source } });
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | +  loading.value = false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const resizeChart = () => { chartObj.resize() }
 | 
	
		
			
				|  |  | -const addResize = () => { window.addEventListener('resize', resizeChart) }
 | 
	
		
			
				|  |  | -const removeResize = () => { window.removeEventListener('resize', resizeChart) }
 | 
	
		
			
				|  |  | +watch(props.query, async () => {
 | 
	
		
			
				|  |  | +  // console.log("------watch-----queryParams", props.query)
 | 
	
		
			
				|  |  | +  loading.value = true;
 | 
	
		
			
				|  |  | +  await getMetricsItems();
 | 
	
		
			
				|  |  | +  const items = await getDataset();
 | 
	
		
			
				|  |  | +  const opt = { dataset: { source: items } };
 | 
	
		
			
				|  |  | +  chartObj.setOption(opt);
 | 
	
		
			
				|  |  | +  loading.value = false;
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function resizeChart() {
 | 
	
		
			
				|  |  | +  chartObj.resize();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function addResize() {
 | 
	
		
			
				|  |  | +  window.addEventListener('resize', resizeChart);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function removeResize() {
 | 
	
		
			
				|  |  | +  window.removeEventListener('resize', resizeChart);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  </script>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <template>
 | 
	
	
		
			
				|  | @@ -298,8 +391,8 @@ const removeResize = () => { window.removeEventListener('resize', resizeChart) }
 | 
	
		
			
				|  |  |        <el-radio-button label="week" :disabled="!props.fetchLineWeek">周</el-radio-button>
 | 
	
		
			
				|  |  |        <el-radio-button label="month" :disabled="!props.fetchLineWeek">月</el-radio-button>
 | 
	
		
			
				|  |  |      </el-radio-group>
 | 
	
		
			
				|  |  | -    <div style="height: 350px;" ref="chartRef"></div>
 | 
	
		
			
				|  |  | -</div>
 | 
	
		
			
				|  |  | +    <div style="height: 350px" ref="chartRef"></div>
 | 
	
		
			
				|  |  | +  </div>
 | 
	
		
			
				|  |  |  </template>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <style scoped>
 |