Riku
2025-09-20 32eedf2857255cf29985ffc0cc73e75eccda39bf
src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue
@@ -1,33 +1,189 @@
<template>
  <BaseProdProcess
    v-model:active="active"
    @onStep1="onStep1"
    @onStep2="onStep2"
    @onStep3="onStep3"
    :loading="loading"
  >
    <template #step1>
      <ProdQueryOptCompare @submit="onStep1"></ProdQueryOptCompare>
    <template #step1="{ onSearch }">
      <ProdQueryOptCompare :loading="loading" @submit="onSearch"></ProdQueryOptCompare>
    </template>
    <template #step2="{ contentHeight }">
      <el-scrollbar :height="contentHeight">
        <el-table
          id="prod-problem-count-table"
          :data="tableData"
          v-loading="loading"
          table-layout="fixed"
          :show-overflow-tooltip="true"
          size="small"
          border
        >
          <el-table-column fixed="left" type="index" label="编号" width="50">
          </el-table-column>
          <el-table-column
            fixed="left"
            prop="districtName"
            label="区县"
            width="110"
          >
          </el-table-column>
          <el-table-column prop="townName" label="街镇" width="110" />
          <el-table-column
            prop="sceneCount"
            label="本期场景数"
            min-width="70"
          />
          <el-table-column
            prop="lastSceneCount"
            label="上期场景数"
            min-width="70"
          />
          <el-table-column
            prop="problemCount"
            label="本期问题数"
            min-width="70"
          />
          <el-table-column
            prop="lastProblemCount"
            label="上期问题数"
            min-width="70"
          />
          <el-table-column
            prop="ratio"
            label="本期问题数均值"
            min-width="70"
            :formatter="ratioFormat"
          />
          <el-table-column
            prop="lastRatio"
            label="上期问题数均值"
            min-width="70"
            :formatter="ratioFormat"
          />
        </el-table>
        <el-row justify="center">
          <div
            ref="chartRef"
            style="height: 400px; width: 100%; max-width: 800px"
          ></div>
        </el-row>
      </el-scrollbar>
    </template>
  </BaseProdProcess>
</template>
<script setup>
import { ref } from 'vue';
import { computed, ref } from 'vue';
import * as echarts from 'echarts';
import dayjs from 'dayjs';
import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue';
import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js';
import { conversionFromTable } from '@/utils/excel';
import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js';
import { barChartOption, downloadChartImage } from '@/utils/echart-util.js';
import ProdQueryOptCompare from '@/views/fysp/data-product/components/ProdQueryOptCompare.vue';
const { active, changeActive } = useProdStepChange();
const loading = ref(false);
const tableData1 = ref([]);
const tableData2 = ref([]);
const chartRef = ref(null);
let chart;
const tableData = computed(() => {
  return tableData1.value.map((item) => {
    const last = tableData2.value.find(
      (item2) => item2.townCode === item.townCode
    );
    item.ratio = Math.round(item.ratio * 10) / 10 || 0;
    return {
      ...item,
      lastSceneCount: last?.sceneCount || 0,
      lastProblemCount: last?.problemCount || 0,
      lastRatio: Math.round(item.ratio * 10) / 10 || 0
    };
  });
});
function onStep1(opts) {
  console.log('onStep1', opts);
  loading.value = true;
  const p1 = dataprodmiddleApi.fetchProblemCountByArea(opts[0]).then((res) => {
    if (res.success) {
      tableData1.value = res.data;
    }
  });
  const p2 = dataprodmiddleApi.fetchProblemCountByArea(opts[1]).then((res) => {
    if (res.success) {
      tableData2.value = res.data;
    }
  });
  Promise.all([p1, p2])
    .then(() => {
      changeActive();
      setTimeout(() => {
        genChart(opts[0], opts[1]);
      }, 500);
    })
    .finally(() => {
      loading.value = false;
    });
}
function onStep2() {
  changeActive();
}
function onStep3(val) {}
function onStep3(val) {
  if (val.downloadType == '1') {
    loading.value = true;
    conversionFromTable('prod-problem-count-table', '扬尘污染问题数均值对比');
    downloadChartImage(chart, '扬尘污染问题数均值对比');
    loading.value = false;
  }
}
function genChart(opt1, opt2) {
  if (chart == undefined) {
    chart = echarts.init(chartRef.value);
  }
  const year = dayjs(opt1.startTime).year();
  const month1 = dayjs(opt1.startTime).month() + 1;
  const month2 = dayjs(opt2.startTime).month() + 1;
  const time = `${year}年${month1}月、${month2}月`;
  const option = barChartOption();
  option.title.text = `${time}各街道(镇)${opt1.sceneTypeName}扬尘污染问题数均值对比`;
  option.xAxis.name = '街道(镇)';
  option.xAxis.data = tableData.value.map((item) => item.townName);
  option.yAxis.name = '问题数均值';
  option.series = [
    {
      name: `${month1}月`,
      type: 'bar', // 图表类型改为柱状图
      data: tableData1.value.map((item) => item.ratio),
      label: {
        show: true,
        position: 'top', // 标签显示在柱子顶部
        formatter: '{c}' // 标签格式:数量
      }
    },
    {
      name: `${month2}月`,
      type: 'bar', // 图表类型改为柱状图
      data: tableData1.value.map((item) => item.ratio),
      label: {
        show: true,
        position: 'top', // 标签显示在柱子顶部
        formatter: '{c}' // 标签格式:数量
      }
    }
  ];
  chart.setOption(option);
}
function ratioFormat(row, column, cellValue, index) {
  return Math.round(cellValue * 10) / 10;
}
</script>