From 32eedf2857255cf29985ffc0cc73e75eccda39bf Mon Sep 17 00:00:00 2001 From: Riku <risaku@163.com> Date: 星期六, 20 九月 2025 22:18:15 +0800 Subject: [PATCH] 2025.9.20 完成现场巡查基础数据产品和月度巡查简报的中间数据产品 --- src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 161 insertions(+), 5 deletions(-) diff --git a/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue index fe5212f..83aac7e 100644 --- a/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue +++ b/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> -- Gitblit v1.9.3