index.vue 4.6 KB
<script setup lang="ts">
  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[];
  }

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

  // 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,
      }));
      chartData.pieChartData = res.tops?.slice(0, 4)?.map((topItem: TopItemType) => ({
        name: topItem.name,
        value: topItem.recordProportion,
      }));
      // 总共Top5,取服务端前4个数据,加上其他应用
      const otherApplicationCount = chartData.pieChartData
        ?.map((topItem) => topItem.value)
        ?.reduce((sum, curr) => sum + curr);
      chartData.pieChartData.push({
        name: '其他应用',
        value: 100 - otherApplicationCount,
      });
    }
  };

  // 接口调用历史
  const getClassify = async (type?: string) => {
    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
        v-if="chartData.timeLineChartData.length"
        @emitTimeRange="handleReceiveTimeRange"
        :seriesData="chartData.timeLineChartData"
      />
      <a-card v-else :title="t('application.record.text.timeLineTitle')" class="w-full h-120">
        <div class="w-full h-72 flex justify-center items-center"
          ><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE"
        /></div>
      </a-card>
    </div>
    <div>
      <a-card class="w-full h-140">
        <Table />
      </a-card>
    </div>
  </div>
</template>

<style scoped></style>