index.vue 6.7 KB
<script setup lang="ts">
  import { ref } from 'vue';
  import LineChart from './components/LineChart.vue';
  import PieChart from './components/PieChart.vue';
  import Table from './components/Table.vue';
  import Total from './components/Total.vue';
  import TimeLineChart from './components/TimeLineChart.vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { onMounted, reactive } from 'vue';
  import { getApplicationRecordClassify, getApplicationRecordTop } from '/@/api/application/record';
  import {
    ApplicationRecordTopItemType,
    ClassifyDtsItemType,
    ClassifyItemType,
    TopItemType,
  } from '/@/api/application/model/record';
  import { Empty } from 'ant-design-vue';
  import moment from 'moment';
  import { formatClassifyText } from '../api/config';
  import total1 from '/@/assets/images/total1.png';
  import total2 from '/@/assets/images/total2.png';
  import total3 from '/@/assets/images/total3.png';

  const { t } = useI18n();

  interface ChartData {
    lineChartData: Recordable[];
    pieChartData: Recordable[];
    timeLineChartData: Recordable[];
    totalData: Recordable[];
    timeLineXAxisData?: string[];
  }

  const chartData = reactive<ChartData>({
    lineChartData: [],
    pieChartData: [],
    timeLineChartData: [],
    totalData: [],
    timeLineXAxisData: [],
  });

  // API统计
  const getTop = async () => {
    const res = (await getApplicationRecordTop()) as any as ApplicationRecordTopItemType;
    chartData.totalData = [
      {
        image: total1,
        title: t('application.record.text.totalText.t1'),
        count: res.count,
      },
      {
        image: total2,
        title: t('application.record.text.totalText.t2'),
        count: res.successCount,
      },
      {
        image: total3,
        title: t('application.record.text.totalText.t3'),
        count: res.failCount,
      },
    ];
    if (Array.isArray(res.tops) && res.tops.length !== 0) {
      chartData.lineChartData = res.tops?.slice(0, 5)?.map((topItem: TopItemType) => ({
        label: topItem.name,
        value: topItem.recordNum,
      }));
      // 取服务端前5个数据
      chartData.pieChartData = res.tops?.slice(0, 5)?.map((topItem: TopItemType) => ({
        name: topItem.name,
        value: topItem.recordProportion,
      }));
      // 其他应用等于取服务端数组长度为5后面所有数值相加
      const otherApplicationCount = res?.tops
        ?.slice(5)
        ?.map((topItem: TopItemType) => ({
          name: topItem.name,
          value: topItem.recordProportion,
        }))
        ?.map((topItem) => topItem.value)
        ?.reduce((sum, curr) => sum + curr);
      // 相加总共
      if (res.tops && res.tops.length > 5) {
        chartData.pieChartData.push({
          name: '其他应用',
          value: otherApplicationCount,
        });
      }
    }
  };

  //1小时->5分钟间隔  1天->2小时间隔  7天->1天间隔 30天->1天间隔
  const timeFormat = (type, config) => {
    let startT: any = null;
    let endT: any = null;
    let interval: any = null; //分割间隔
    if (type == 'hour') {
      interval = 5;
      startT = moment().subtract(1, config.text);
      endT = moment().format('HH:mm');
    } else if (type == 'day') {
      interval = 2;
      startT = moment().subtract(1, config.text);
      endT = moment().format('HH:mm');
    } else if (type == 'week') {
      interval = 1;
      startT = moment().subtract(1, config.text);
      endT = moment().format('HH:mm');
    } else if (type == 'month') {
      interval = 1;
      startT = moment().subtract(1, config.text);
      endT = moment().format('HH:mm');
    }
    let starTime = moment(startT, 'HH:mm');
    let endTime = moment(endT, 'HH:mm');
    let diff = endTime.diff(starTime, config.diffText);
    let num = Math.ceil(diff / interval);
    let times: any = [];
    for (let i = 1; i <= num; i++) {
      let timeFrom = starTime.clone().add((i - 1) * interval, config.timeText) as any;
      times.push(timeFrom.format('YYYY-MM-DD HH:mm'));
    }
    return times;
  };

  const configTime = [
    {
      name: 'hour',
      value: {
        text: 'hours',
        diffText: 'minutes',
        timeText: 'minutes',
      },
    },
    {
      name: 'day',
      value: {
        text: 'days',
        diffText: 'hours',
        timeText: 'hours',
      },
    },
    {
      name: 'week',
      value: {
        text: 'weeks',
        diffText: 'days',
        timeText: 'days',
      },
    },
    {
      name: 'month',
      value: {
        text: 'months',
        diffText: 'days',
        timeText: 'days',
      },
    },
  ];
  //代码保留

  const timeType = ref('');

  // 接口调用历史
  const getClassify = async (type?: string) => {
    timeType.value = type as string;
    const findValue = configTime.find((configItem) => configItem.name === type)?.value;
    chartData.timeLineXAxisData = timeFormat(type, findValue);
    const res = (await getApplicationRecordClassify(type)) as any as ClassifyItemType[];
    chartData.timeLineChartData = res?.map((classifyItem: ClassifyItemType) => ({
      type: 'line',
      name: formatClassifyText[classifyItem.classify],
      data: classifyItem?.dts?.map((dtsItem: ClassifyDtsItemType) => [
        moment(dtsItem.time).format('YYYY-MM-DD HH:mm:ss'),
        dtsItem.count,
      ]),
      connectNulls: true,
    }));
  };

  const handleReceiveTimeRange = (value: string) => {
    getClassify(value);
  };

  onMounted(() => {
    getTop();
    getClassify('week'); // 默认查询一周
  });
</script>
<template>
  <div class="flex flex-col m-4 gap-4">
    <div class="flex w-full h-full items-center justify-between gap-4">
      <Total :seriesData="chartData.totalData" />
      <a-card :title="t('application.record.text.pieTitle')" class="h-99" style="width: 40%">
        <PieChart v-if="chartData.pieChartData.length" :seriesData="chartData.pieChartData" />
        <div class="w-full h-72 flex justify-center items-center" v-else
          ><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE"
        /></div>
      </a-card>
      <a-card :title="t('application.record.text.lineTitle')" class="h-99" style="width: 45%">
        <LineChart v-if="chartData.lineChartData.length" :seriesData="chartData.lineChartData" />
        <div class="w-full h-72 flex justify-center items-center" v-else
          ><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE"
        /></div>
      </a-card>
    </div>
    <div>
      <TimeLineChart
        @emitTimeRange="handleReceiveTimeRange"
        :seriesData="chartData.timeLineChartData"
        :timeLineXAxisData="chartData.timeLineXAxisData"
        :timeType="timeType"
      />
    </div>
    <div>
      <a-card class="w-full h-140">
        <Table />
      </a-card>
    </div>
  </div>
</template>

<style scoped></style>