<template>
|
<BaseProdProcess
|
v-model:active="active"
|
@onStep1="onStep1"
|
@onStep2="onStep2"
|
@onStep3="onStep3"
|
:loading="loading"
|
>
|
<template #step1="{ onSearch }">
|
<ProdQueryOptCompare
|
:loading="loading"
|
@submit="onSearch"
|
></ProdQueryOptCompare>
|
</template>
|
<template #step2="{ contentHeight }">
|
<el-scrollbar :height="contentHeight">
|
<el-card shadow="never"> Nothing </el-card>
|
</el-scrollbar>
|
</template>
|
<template #step3="{ onDownload, queryOpt }">
|
<ProdDownload
|
:loading="loading"
|
:queryOpt="queryOpt"
|
:downloadTypeValid="['2']"
|
defaultDownloadType="2"
|
@submit="onDownload"
|
></ProdDownload>
|
</template>
|
</BaseProdProcess>
|
</template>
|
<script setup>
|
/**
|
* 月度现场巡查简报
|
*/
|
import { ref } from 'vue';
|
import dayjs from 'dayjs';
|
import { exportDocx } from '@/utils/doc';
|
import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue';
|
import ProdQueryOptCompare from '@/views/fysp/data-product/components/ProdQueryOptCompare.vue';
|
import ProdDownload from '@/views/fysp/data-product/components/ProdDownload.vue';
|
import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js';
|
import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js';
|
import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js';
|
import {
|
pieChartOption,
|
barChartOption,
|
getChartUrl
|
} from '@/utils/echart-util.js';
|
import ProdProblemCountSummaryProxy from '@/views/fysp/data-product/middle-data-product/ProdProblemCountSummaryProxy.js';
|
|
const { active, changeActive } = useProdStepChange();
|
const loading = ref(false);
|
const templateParam = {
|
districtName: '',
|
year: '',
|
month: '',
|
compareMonth: '',
|
sceneType: '工地',
|
// 巡查情况汇总
|
sceneCount: 0,
|
pointCount: 0,
|
reviewPointCount: 0,
|
stopSceneCount: 0,
|
completeSceneCount: 0,
|
// 问题类型汇总
|
problemTypeCount: 0,
|
problemCount: 0,
|
proTypeSum:
|
'道路扬尘47个(占本月问题总数40.5%),较上月增加约3%;出入口(道路)扬尘22个(占本月问题总数19.0%),较上月增加约4%;',
|
proTypeSumChartUrl: '',
|
// 问题数量汇总
|
townCount: 0,
|
topThree:
|
'共和新路街道(2.4个)、芷江西路街道(2.14个)、曹家渡街道和天目西路街道(2.0个)。',
|
problemCountByAreaChartUrl: '',
|
// 评估情况汇总
|
evalLevelABCountSum: 0, // 规范工地(含基本规范)家次
|
evalLevelABRatioSum: '0%', // 规范率
|
evalLevelABRatioDiff: '降低约7%', // 较上月规范率变化
|
evalLevelCDCountSum: 0, // 不规范类(含严重不规范)家次
|
evalLevelCDRatioSum: '0%', // 不规范率
|
evalLevelCDRatioDiff: '增加约10%', // 较上月不规范率变化
|
// 各街镇场景规范性排行(较好在前)
|
evaluationByArea: [
|
{
|
index: 1,
|
townName: '石门二路街道',
|
validSceneCount: 2,
|
evaluationCount: 2,
|
evalLevelACount: 2,
|
evalLevelBCount: 0,
|
evalLevelCCount: 0,
|
evalLevelDCount: 0,
|
evalLevelRatioAB: '100%'
|
}
|
],
|
// 各街镇场景规范性总计
|
validSceneCountSum: 0,
|
evaluationCountSum: 0,
|
evalLevelACountSum: 0,
|
evalLevelBCountSum: 0,
|
evalLevelCCountSum: 0,
|
evalLevelDCountSum: 0,
|
|
// 整改情况
|
proChangeRatioSum: '0%', // 整体问题整改率
|
sceneChangeRatioSum: '0%', // (家次)整改占比
|
// 扬尘防治问题及规范性评估清单(含复核)
|
changeAndEvalList: [
|
{
|
index: 1,
|
sceneName: '',
|
address: '',
|
townName: '',
|
score: 0,
|
scoreLevel: '',
|
problemCount: 0,
|
problemList: [
|
{
|
index: 1,
|
problemName: ''
|
}
|
]
|
}
|
],
|
// 未整改清单
|
unchangeSceneList: [
|
{
|
index: 1,
|
sceneName: '',
|
address: '',
|
townName: '',
|
problemCount: 0,
|
problemList: [
|
{
|
index: 1,
|
problemName: ''
|
}
|
]
|
}
|
]
|
};
|
|
function onStep1(opts) {
|
const [opt, compareOpt] = opts;
|
loading.value = true;
|
templateParam.districtName = opt.districtName;
|
templateParam.year = dayjs(opt.startTime).year();
|
templateParam.month = dayjs(opt.startTime).month() + 1;
|
templateParam.compareMonth = dayjs(compareOpt.startTime).month() + 1;
|
templateParam.sceneType = opt.sceneTypeName;
|
const p1 = dataprodmiddleApi.fetchInspectionSummary(opt).then((res) => {
|
if (res.success) {
|
Object.assign(templateParam, res.data);
|
}
|
});
|
const p2 = dataprodmiddleApi
|
.fetchProblemTypeSummary(opt)
|
.then(async (res) => {
|
if (res.success) {
|
const data = res.data.sort((a, b) => b.count - a.count);
|
templateParam.problemTypeCount = data.length;
|
templateParam.problemCount = data.reduce(
|
(acc, cur) => acc + cur.count,
|
0
|
);
|
templateParam.proTypeSum =
|
data
|
.map((item) => {
|
let _ratioDiff;
|
if (item.ratioDiff > 0) {
|
_ratioDiff = `增加约${(Math.abs(item.ratioDiff) * 100).toFixed(
|
1
|
)}%`;
|
} else if (item.ratioDiff < 0) {
|
_ratioDiff = `减少约${(Math.abs(item.ratioDiff) * 100).toFixed(
|
1
|
)}%`;
|
} else {
|
_ratioDiff = '基本持平';
|
}
|
return `${item.typeName}${item.count}个(占本月问题总数${(
|
item.ratio * 100
|
).toFixed(1)}%),较上月${_ratioDiff};`;
|
})
|
.join(';') + '。';
|
templateParam.proTypeSumChartUrl = await genChartProblemTypeSummary(
|
opt,
|
data
|
);
|
}
|
});
|
const p3 = dataprodmiddleApi
|
.fetchProblemCountByArea(opt)
|
.then(async (res) => {
|
if (res.success) {
|
const data = res.data.sort((a, b) => b.ratio - a.ratio);
|
templateParam.townCount = data.length;
|
templateParam.topThree =
|
data
|
.slice(0, 3)
|
.map((item) => `${item.townName}(${item.ratio.toFixed(1)}个)`)
|
.join('、') + '。';
|
|
const res2 =
|
await dataprodmiddleApi.fetchProblemCountByArea(compareOpt);
|
if (res2.success) {
|
const data2 = res2.data.sort((a, b) => b.ratio - a.ratio);
|
const combineData = ProdProblemCountSummaryProxy.combineData(
|
data,
|
data2
|
);
|
templateParam.problemCountByAreaChartUrl =
|
await genChartProblemCountByArea(opt, compareOpt, combineData);
|
}
|
}
|
});
|
const p4 = dataprodmiddleApi.fetchEvaluationByArea(opt).then(async (res) => {
|
if (res.success) {
|
templateParam.evaluationByArea = [];
|
res.data
|
.sort((a, b) => {
|
return b.evalLevelRatioAB - a.evalLevelRatioAB;
|
})
|
.forEach((item, index) => {
|
templateParam.evaluationByArea.push({
|
index: index + 1,
|
townName: item.townName,
|
validSceneCount: item.validSceneCount,
|
evaluationCount: item.evaluationCount,
|
evalLevelACount: item.evalLevelACount,
|
evalLevelBCount: item.evalLevelBCount,
|
evalLevelCCount: item.evalLevelCCount,
|
evalLevelDCount: item.evalLevelDCount,
|
evalLevelRatioAB: `${(item.evalLevelRatioAB * 100).toFixed(1)}%`
|
});
|
templateParam.validSceneCountSum += item.validSceneCount;
|
templateParam.evaluationCountSum += item.evaluationCount;
|
templateParam.evalLevelACountSum += item.evalLevelACount;
|
templateParam.evalLevelBCountSum += item.evalLevelBCount;
|
templateParam.evalLevelCCountSum += item.evalLevelCCount;
|
templateParam.evalLevelDCountSum += item.evalLevelDCount;
|
});
|
templateParam.evalLevelABCountSum =
|
templateParam.evalLevelACountSum + templateParam.evalLevelBCountSum;
|
templateParam.evalLevelABRatioSum = `${(
|
(templateParam.evalLevelABCountSum / templateParam.evaluationCountSum) *
|
100
|
).toFixed(1)}%`;
|
templateParam.evalLevelCDCountSum =
|
templateParam.evalLevelCCountSum + templateParam.evalLevelDCountSum;
|
templateParam.evalLevelCDRatioSum = `${(
|
(templateParam.evalLevelCDCountSum / templateParam.evaluationCountSum) *
|
100
|
).toFixed(1)}%`;
|
|
// 和上月情况进行对比
|
const res2 = await dataprodmiddleApi.fetchEvaluationByArea(compareOpt);
|
if (res2.success) {
|
const compareData = {
|
validSceneCountSum: 0,
|
evaluationCountSum: 0,
|
evalLevelACountSum: 0,
|
evalLevelBCountSum: 0,
|
evalLevelCCountSum: 0,
|
evalLevelDCountSum: 0
|
};
|
res2.data
|
.sort((a, b) => {
|
return b.evalLevelRatioAB - a.evalLevelRatioAB;
|
})
|
.forEach((item, index) => {
|
compareData.validSceneCountSum += item.validSceneCount;
|
compareData.evaluationCountSum += item.evaluationCount;
|
compareData.evalLevelACountSum += item.evalLevelACount;
|
compareData.evalLevelBCountSum += item.evalLevelBCount;
|
compareData.evalLevelCCountSum += item.evalLevelCCount;
|
compareData.evalLevelDCountSum += item.evalLevelDCount;
|
});
|
const ratioABDiff =
|
((compareData.evalLevelACountSum + compareData.evalLevelBCountSum) /
|
compareData.evaluationCountSum) *
|
100 -
|
parseFloat(templateParam.evalLevelABRatioSum.replace('%', ''));
|
|
const ratioCDDiff =
|
((compareData.evalLevelCCountSum + compareData.evalLevelDCountSum) /
|
compareData.evaluationCountSum) *
|
100 -
|
parseFloat(templateParam.evalLevelCDRatioSum.replace('%', ''));
|
|
if (ratioABDiff > 0) {
|
templateParam.evalLevelABRatioDiff = `增加约${Math.abs(
|
ratioABDiff
|
).toFixed(1)}%`;
|
} else if (ratioABDiff < 0) {
|
templateParam.evalLevelABRatioDiff = `减少约${Math.abs(
|
ratioABDiff
|
).toFixed(1)}%`;
|
} else {
|
templateParam.evalLevelABRatioDiff = '基本持平';
|
}
|
if (ratioCDDiff > 0) {
|
templateParam.evalLevelCDRatioDiff = `增加约${Math.abs(
|
ratioCDDiff
|
).toFixed(1)}%`;
|
} else if (ratioCDDiff < 0) {
|
templateParam.evalLevelCDRatioDiff = `减少约${Math.abs(
|
ratioCDDiff
|
).toFixed(1)}%`;
|
} else {
|
templateParam.evalLevelCDRatioDiff = '基本持平';
|
}
|
}
|
}
|
});
|
const p5 = dataprodbaseApi.fetchProdInspectionInfo(opt).then(async (res) => {
|
if (res.success) {
|
// 计算问题整改率和场景整改占比
|
const problemSum = {
|
// 问题总数
|
proTotalCount: 0,
|
// 整改问题数
|
proChangeCount: 0,
|
// 总巡查点次数(相同场景巡查多次也会计算)
|
sceneTotalCount: 0,
|
// 整改点次(或家次)数
|
sceneChangeCount: 0
|
};
|
|
templateParam.changeAndEvalList = [];
|
templateParam.unchangeSceneList = [];
|
// 获取评估结果
|
const evalInfo = await dataprodbaseApi.fetchProdEvaluateInfo(opt);
|
const sceneInfo = await dataprodbaseApi.fetchProdSceneInfo(opt);
|
if (evalInfo.success) {
|
const evalData = evalInfo.data.sort(
|
(a, b) =>
|
parseInt(a.evaluate.resultscorebef) -
|
parseInt(b.evaluate.resultscorebef)
|
);
|
evalData.forEach((item, index) => {
|
// 查找对应的巡查任务记录
|
const inspItem = res.data.find(
|
(i) => i.subTask.stguid === item.subTask.stguid
|
);
|
// 查找对应的监管场景信息
|
const sceneItem = sceneInfo.data.find(
|
(i) => i.scene.guid === item.subTask.scenseid
|
);
|
// 生成模板参数
|
const changeAndEvalItem = {
|
sceneName: item.subTask.scensename,
|
address: item.subTask.scenseaddress,
|
townName: item.subTask.townname
|
};
|
// 根据场景的运营状态,决定参数内容
|
if (sceneItem.statusBool) {
|
const obj = {
|
score: parseInt(item.evaluate.resultscorebef),
|
scoreLevel: item.scoreLevel,
|
problemCount: inspItem.problems.length,
|
// problemsDes: inspItem.problems
|
// .map((p, i) => `${i + 1}、${p.problemname}`)
|
// .join('\r\n'),
|
problemList:
|
inspItem.problems.length > 0
|
? inspItem.problems.map((p, i) => {
|
return {
|
index: i + 1,
|
problemName: p.problemname
|
};
|
})
|
: [
|
{
|
index: '',
|
problemName: '检查当天现场无明显问题'
|
}
|
]
|
};
|
Object.assign(changeAndEvalItem, obj);
|
|
// 更新问题整改率和场景整改占比
|
problemSum.proTotalCount += inspItem.problems.length;
|
problemSum.sceneTotalCount += 1;
|
const unchangeProList = inspItem.problems.filter(
|
(p) => !p.ischanged
|
);
|
problemSum.proChangeCount +=
|
inspItem.problems.length - unchangeProList.length;
|
// 除了全部问题都没整改的场景,都算整改点次(或家次)数
|
problemSum.sceneChangeCount +=
|
inspItem.problems.length > 0 &&
|
inspItem.problems.length == unchangeProList.length
|
? 0
|
: 1;
|
|
if (unchangeProList.length > 0) {
|
templateParam.unchangeSceneList.push({
|
index: templateParam.unchangeSceneList.length + 1,
|
sceneName: item.subTask.scensename,
|
address: item.subTask.scenseaddress,
|
townName: item.subTask.townname,
|
problemCount: unchangeProList.length,
|
problemList: unchangeProList.map((p, i) => {
|
return {
|
index: i + 1,
|
problemName: p.problemname
|
};
|
})
|
});
|
}
|
} else {
|
const obj = {
|
score: '/',
|
scoreLevel: '/',
|
problemCount: '/',
|
// problemsDes: inspItem.problems
|
// .map((p, i) => `${i + 1}、${p.problemname}`)
|
// .join('\r\n'),
|
problemList: [
|
{
|
index: '',
|
problemName: sceneItem.status
|
}
|
]
|
};
|
Object.assign(changeAndEvalItem, obj);
|
}
|
templateParam.changeAndEvalList.push({
|
index: index + 1,
|
...changeAndEvalItem
|
});
|
});
|
}
|
|
templateParam.proChangeRatioSum = `${(
|
(problemSum.proChangeCount / problemSum.proTotalCount) *
|
100
|
).toFixed(1)}%`;
|
templateParam.sceneChangeRatioSum = `${(
|
(problemSum.sceneChangeCount / problemSum.sceneTotalCount) *
|
100
|
).toFixed(1)}%`;
|
}
|
});
|
Promise.all([p1, p2, p3, p4, p5])
|
.then(() => {
|
changeActive();
|
changeActive();
|
})
|
.finally(() => {
|
loading.value = false;
|
});
|
}
|
|
function onStep2() {
|
changeActive();
|
// ElMessage.error('暂不提供下载');
|
}
|
|
function onStep3(val) {
|
if (val.downloadType == '2') {
|
loading.value = true;
|
exportDocx(
|
'/扬尘污染监管简报模板.docx',
|
templateParam,
|
`${templateParam.districtName}${
|
templateParam.month
|
}月扬尘污染监管简报-${dayjs().format('YYYYMMDD')}.docx`,
|
{
|
horizontalHeight: 300,
|
verticalWidth: 600,
|
scale: 2
|
}
|
).finally(() => (loading.value = false));
|
}
|
}
|
|
function genChartProblemTypeSummary(opt, data) {
|
const startTime = dayjs(opt.startTime).format('YYYY年MM月');
|
const option = pieChartOption();
|
option.title.text = `${startTime}${opt.districtName}扬尘污染问题类型占比`;
|
option.legend.data = data.map((item) => item.typeName);
|
option.series[0].name = '问题类型';
|
option.series[0].data = data.map((item) => ({
|
name: item.typeName,
|
value: item.count
|
}));
|
return getChartUrl(option);
|
}
|
|
function genChartProblemCountByArea(opt1, opt2, combineData) {
|
const option = ProdProblemCountSummaryProxy.genChartOption(
|
opt1,
|
opt2,
|
combineData
|
);
|
return getChartUrl(option);
|
}
|
</script>
|