TimeLineChart.vue 3.12 KB
<script setup lang="ts">
  import { ref, Ref, onMounted, computed, watch } from 'vue';
  import { useECharts } from '/@/hooks/web/useECharts';
  import { useAppStore } from '/@/store/modules/app';
  import { useI18n } from '/@/hooks/web/useI18n';

  const { t } = useI18n();

  const props = defineProps({
    seriesData: {
      type: Array,
      default: () => [],
    },
  });

  const emits = defineEmits(['emitTimeRange']);

  const appStore = useAppStore();

  const timeRange = ref('week');

  const timeRangeList = ref([
    { label: `1${t('home.index.timeUnit.hour')}`, value: 'hour', interval: 1000 * 60 * 5 },
    {
      label: `7${t('home.index.timeUnit.day')}`,
      value: 'week',
      interval: 1000 * 60 * 60 * 2,
    },
    {
      label: `30${t('home.index.timeUnit.day')}`,
      value: 'month',
      interval: 1000 * 60 * 60 * 24,
    },
  ]);

  const skinName = computed(() => {
    return appStore.getDarkMode === 'light' ? '#ffffff' : '#151515';
  });

  const chartRef = ref<HTMLDivElement | null>(null);

  const { setOptions, resize } = useECharts(chartRef as Ref<HTMLDivElement>);

  const getOptions: any = () => {
    return {
      backgroundColor: skinName.value,
      tooltip: {
        trigger: 'axis',
      },
      grid: {
        left: '1%',
        right: '2%',
        bottom: '1%',
        containLabel: true,
      },
      xAxis: {
        type: 'time',
        splitLine: { show: false },
        lineStyle: {
          width: 2,
        },
        axisTick: {
          show: false,
        },
        axisLabel: {
          formatter: '{yyyy}-{MM}-{dd}',
          showMinLabel: true,
          showMaxLabel: true, // 固定显示X轴的最后一条数据
        },
      },
      yAxis: {
        type: 'value',
        axisLabel: { formatter: '{value} %' },
      },
      series: props.seriesData,
    };
  };

  watch(
    () => appStore.getDarkMode,
    (target) => {
      const backgroundColor = target === 'light' ? '#ffffff' : '#151515';
      setOptions &&
        setOptions({
          ...getOptions(),
          backgroundColor,
        });
    }
  );

  watch(
    () => props.seriesData,
    () => {
      setOptions(getOptions());
    },
    {
      deep: true,
    }
  );

  onMounted(() => {
    setOptions(getOptions());
    //自适应
    window.addEventListener('resize', () => resize());
  });

  const handleTimeRangeChange = (e: any) => {
    const startTs = Date.now() - e.target.value;
    const endTs = Date.now();
    emits('emitTimeRange', e.target.value, startTs, endTs);
  };
</script>
<template>
  <a-card :title="t('application.record.text.timeLineTitle')" class="w-full h-120">
    <template #extra>
      <a-radio-group @change="handleTimeRangeChange" v-model:value="timeRange" button-style="solid">
        <template v-for="(timeItem, index) in timeRangeList" :key="timeItem.value">
          <div style="display: none">{{ index }}</div>
          <a-radio-button :value="timeItem.value">
            {{ timeItem.label }}
          </a-radio-button>
        </template>
      </a-radio-group>
    </template>
    <div ref="chartRef" class="w-full h-80"></div>
  </a-card>
</template>

<style scoped></style>