overview.vue 5.37 KB
<template>
  <a-card :body-style="{ padding: '10px 20px 0 20px' }" :header-style="{ paddingBottom: 0 }" class="general-card" title="试听概览">
    <template #extra>
      <a-space size="12">
        <export-button :on-download="onDownload" />
        <a-range-picker
          v-model="createBetween"
          :allow-clear="false"
          :disabled-date="disabledDate"
          style="width: 260px"
          value-format="YYYY-MM-DD"
          @change="onFetch"
          @select="onSelect"
        />
      </a-space>
    </template>
    <Chart :option="chartOption" height="328px" />
  </a-card>
</template>

<script lang="ts" setup>
  import Chart from '@/components/chart/index.vue';
  import useChartOption from '@/hooks/chart-option';
  import { ToolTipFormatterParams } from '@/types/echarts';
  import { onMounted, ref } from 'vue';
  import dayjs from 'dayjs';
  import { sum } from 'lodash';
  import useDashboardApi from '@/http/dashboard';

  const createBetween = ref([dayjs().subtract(7, 'day').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]);

  const disabledDate = (current?: Date) => {
    const date = createBetween.value;

    if (date && date.length) {
      return (
        dayjs(current).isBefore(dayjs(date[0]).subtract(15, 'day')) ||
        dayjs(current).isAfter(dayjs(date[0]).add(15, 'day')) ||
        dayjs(current).isAfter(dayjs())
      );
    }
    return dayjs(current).isAfter(dayjs());
  };

  const onSelect = (value: any[]) => {
    createBetween.value = value;
  };

  const tooltipItemsHtmlString = (items: ToolTipFormatterParams[]) => {
    return items
      .reverse()
      .map(
        (el) => `<div class="content-panel">
        <p>
          <span style="background-color: ${el.color}" class="tooltip-item-icon"></span><span>${el.seriesName}</span>
        </p>
        <span class="tooltip-value">${el.value?.toLocaleString()}</span>
      </div>`
      )
      .reverse()
      .join('');
  };

  const record = ref<{
    time: string[];
    listen_user_count: number[];
    listen_count: number[];
    like_count: number[];
    submit_count: number[];
  }>({
    time: [],
    listen_user_count: [],
    listen_count: [],
    like_count: [],
    submit_count: [],
  });

  const { chartOption } = useChartOption((isDark) => {
    return {
      grid: {
        left: '40',
        right: '40',
        top: '40',
        bottom: '40',
      },
      legend: {
        top: 0,
        right: 0,
        bottom: 0,
        icon: 'rect',
        textStyle: {
          color: '#4E5969',
        },
        formatter: (name) => {
          switch (name) {
            case '试听用户':
              return `${name}(${sum(record.value.listen_user_count)})`;
            case '试听次数':
              return `${name}(${sum(record.value.listen_count)})`;
            case '收藏次数':
              return `${name}(${sum(record.value.like_count)})`;
            case '提交作品':
              return `${name}(${sum(record.value.submit_count)})`;
            default:
              return name;
          }
        },
      },
      tooltip: {
        trigger: 'axis',
        formatter(params) {
          const [firstElement] = params as ToolTipFormatterParams[];
          return `<div>
            <p class="tooltip-title">${firstElement.axisValueLabel}</p>
            ${tooltipItemsHtmlString(params as ToolTipFormatterParams[])}
          </div>`;
        },
        className: 'echarts-tooltip-diy',
      },
      xAxis: [
        {
          type: 'category',
          boundaryGap: true,
          axisLine: {
            lineStyle: { color: isDark ? '#3f3f3f' : '#A9AEB8' },
          },
          axisTick: {
            show: true,
            alignWithLabel: true,
            lineStyle: { color: '#86909C' },
          },
          axisLabel: { color: '#86909C' },
          data: record.value.time,
        },
      ],
      yAxis: {
        show: true,
        type: 'value',
        axisLabel: { color: '#86909C' },
        splitLine: {
          lineStyle: { color: isDark ? '#3F3F3F' : '#E5E6EB' },
        },
      },
      series: [
        {
          name: '试听用户',
          type: 'bar',
          data: record.value.listen_user_count,
          color: '#01629f',
          seriesLayoutBy: 'row',
          barWidth: 14,
        },
        {
          name: '试听次数',
          type: 'bar',
          data: record.value.listen_count,
          color: '#246EFF',
          seriesLayoutBy: 'row',
          barWidth: 14,
        },
        {
          name: '收藏次数',
          type: 'bar',
          data: record.value.like_count,
          color: '#00B2FF',
          seriesLayoutBy: 'row',
          barWidth: 14,
        },
        {
          name: '提交作品',
          type: 'bar',
          data: record.value.submit_count,
          color: '#81c0ff',
          seriesLayoutBy: 'row',
          barWidth: 14,
        },
      ],
    };
  });

  const onFetch = async () => {
    record.value = await useDashboardApi.overview({ createBetween: createBetween.value });
  };

  const onDownload = async () => useDashboardApi.getOverviewExport('活动数据', { createBetween: createBetween.value });

  onMounted(() => onFetch());
</script>

<style lang="less" scoped>
  .title {
    line-height: normal;
    font-weight: 500;
    font-size: 16px;
    color: var(--color-text-1);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
</style>