From 9169a74e1d7b2d24d20d708b4498d7ca17eda9d8 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期一, 28 四月 2025 13:42:52 +0800 Subject: [PATCH] 1. 新增自动评估监测数据统计导入功能 2. 修改问题审核界面巡查点次统计没有根据场景类型切换的问题 --- src/views/fysp/evaluation/components/CompDataResultEdit.vue | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 483 insertions(+), 32 deletions(-) diff --git a/src/views/fysp/evaluation/components/CompDataResultEdit.vue b/src/views/fysp/evaluation/components/CompDataResultEdit.vue index 8837f56..8cb5a18 100644 --- a/src/views/fysp/evaluation/components/CompDataResultEdit.vue +++ b/src/views/fysp/evaluation/components/CompDataResultEdit.vue @@ -1,64 +1,297 @@ <template> - <el-row align="top"> - <el-upload - ref="upload" - class="upload-file" - :limit="1" - :on-change="handleChange" - :on-exceed="handleExceed" - :auto-upload="false" + <el-row align="top" justify="space-between"> + <el-row align="top"> + <el-upload + ref="upload" + class="upload-file" + :limit="1" + accept=".xls,.xlsx" + :on-change="handleChange" + :on-exceed="handleExceed" + :auto-upload="false" + > + <template #trigger> + <el-button type="success" :loading="tableLoading">瀵煎叆鏂囦欢</el-button> + </template> + <template #tip> + <div> + <el-text type="danger">{{ tips }}</el-text> + </div> + </template> + </el-upload> + <div v-if="tableLoading"> + <el-icon class="is-loading"><Loading /></el-icon> + <el-text>{{ loadTxt }}</el-text> + </div> + </el-row> + <el-button type="default" icon="download" @click="downloadTemplate" + >涓嬭浇瀵煎叆妯℃澘</el-button > - <template #trigger> - <el-button type="primary">涓婁紶鐩戞祴鏁版嵁缁熻缁撴灉</el-button> - </template> - </el-upload> - <el-text>{{ loadTxt }}</el-text> </el-row> <el-table ref="tableRef" :data="data" - v-loading="loading" + v-loading="tableLoading" table-layout="fixed" - :stripe="true" + row-key="id" + :expand-row-keys="expandRowKeys" + :row-class-name="tableRowClassName" size="small" height="60vh" border > + <!-- <el-table-column type="expand"> + <template #default="{ row }"> + {{ row.drSceneName }} + </template> + </el-table-column> --> + <el-table-column + v-if="isUploadNewFile" + prop="isFound" + label="鍚堣" + width="30" + > + <template #default="{ row }"> + <el-icon class="is-loading" v-if="row.loading"> + <Loading color="#409eff" /> + </el-icon> + <el-icon v-else> + <Check v-if="row.isFound" /> + <Close v-else /> + </el-icon> + </template> + </el-table-column> + <el-table-column + v-if="isUploadNewFile" + :show-overflow-tooltip="true" + prop="sceneIndex" + label="鍞竴缂栧彿" + width="70" + > + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.sceneIndex" + @change="(e) => handleSceneNameChange(e, row)" + /> + <span v-else>{{ row.sceneIndex }}</span> + </template> + </el-table-column> <el-table-column :show-overflow-tooltip="true" prop="drSceneName" - label="鍚嶇О" - width="300" - /> - <el-table-column prop="drDeviceCode" label="璁惧鍙�" width="130" /> - <el-table-column prop="drTime" label="鏃堕棿" width="100"> + label="鍦烘櫙鍚嶇О" + > <template #default="{ row }"> - <span>{{ $fm.formatYMD(row.drTime) }}</span> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drSceneName" + /> + <span v-else>{{ row.drSceneName }}</span> </template> </el-table-column> - <el-table-column prop="drExceedTimes" label="瓒呮爣娆℃暟" /> - <el-table-column prop="drAvg" label="骞冲潎鍊�" /> - <el-table-column prop="drMax" label="鏈�澶у��" /> - <el-table-column prop="drMin" label="鏈�灏忓��" /> - <el-table-column prop="drOverAvgPer" label="瓒呭尯鍧囧�肩櫨鍒嗘瘮" /> - <el-table-column prop="drDataNum" label="鏁版嵁閲�" /> - <el-table-column prop="drEffectiveRate" label="鏈夋晥鐜�" /> + <el-table-column + v-if="isUploadNewFile" + :show-overflow-tooltip="true" + prop="drDeviceCode" + label="璁惧鍚嶇О" + > + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.deviceName" + /> + <span v-else>{{ row.deviceName }}</span> + </template> + </el-table-column> + <el-table-column prop="drDeviceCode" label="璁惧鍙�" width="130"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drDeviceCode" + /> + <span v-else>{{ row.drDeviceCode }}</span> + </template> + </el-table-column> + <el-table-column prop="drTime" label="鏃堕棿" width="70"> + <template #default="{ row }"> + <span>{{ $fm.formatYM(row.drTime) }}</span> + </template> + </el-table-column> + <el-table-column prop="drExceedTimes" label="瓒呮爣娆℃暟" width="50"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drExceedTimes" + /> + <span v-else>{{ row.drExceedTimes }}</span> + </template> + </el-table-column> + <el-table-column prop="drAvg" label="骞冲潎鍊�" width="65"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drAvg" + /> + <span v-else>{{ row.drAvg }}</span> + </template> + </el-table-column> + <el-table-column prop="drMax" label="鏈�澶у��" width="65"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drMax" + /> + <span v-else>{{ row.drMax }}</span> + </template> + </el-table-column> + <el-table-column prop="drMin" label="鏈�灏忓��" width="65"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drMin" + /> + <span v-else>{{ row.drMin }}</span> + </template> + </el-table-column> + <el-table-column prop="drOverAvgPer" label="瓒呭尯鍧囧�肩櫨鍒嗘瘮" width="70"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drOverAvgPer" + /> + <span v-else>{{ row.drOverAvgPer }}</span> + </template> + </el-table-column> + <el-table-column prop="drDataNum" label="鏁版嵁閲�" width="65"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drDataNum" + /> + <span v-else>{{ row.drDataNum }}</span> + </template> + </el-table-column> + <el-table-column prop="drEffectiveRate" label="鏈夋晥鐜�" width="65"> + <template #default="{ row }"> + <el-input + v-if="isUploadNewFile && !row.isFound" + size="small" + v-model="row.drEffectiveRate" + placeholder="鍦烘櫙鍚嶇О" + /> + <span v-else>{{ row.drEffectiveRate }}</span> + </template> + </el-table-column> + <el-table-column v-if="isUploadNewFile" type="expand"> + <template #default="{ row }"> + <div class="p-v-4"> + <div v-if="!row.isFound" class="p-h-16"> + <div v-if="row.notSure"> + <el-text type="warning" size="small" + >鏍规嵁鍞竴缂栧彿鍙婅鏀垮尯鍒掓壘鍒颁簡鐩稿叧鍦烘櫙锛屼絾涓庡凡鏈夊満鏅悕绉颁笉鍖归厤锛岃纭畾鏄摢涓満鏅�</el-text + > + <div class="m-t-8"> + <el-button + v-for="(v, i) in row.sourceScene" + :key="v.guid" + type="primary" + text + bg + size="small" + class="m-b-2" + @click="handleRadioChange(v, row)" + > + {{ v.name }} + </el-button> + <!-- <el-radio-group v-model="row.radioValue"> + <el-radio + v-for="(v, i) in row.sourceScene" + :key="v.guid" + :value="i" + size="small" + border + @change="handleRadioChange(v, row)" + >{{ v.name }}</el-radio + > + </el-radio-group> --> + </div> + </div> + <div v-else> + <el-text type="danger" size="small" + >鏍规嵁鍞竴缂栧彿鍙婅鏀垮尯鍒掓湭鎵惧埌鐩稿叧鍦烘櫙锛岃淇敼鍞竴缂栧彿</el-text + > + </div> + </div> + <div v-else class="p-h-16"> + <el-text type="success" size="small"> 宸叉纭尮閰嶅埌璇ュ満鏅� </el-text> + <el-text v-if="row.remark" type="success" size="small"> + {{ '锛�' + row.remark }} + </el-text> + </div> + </div> + </template> + </el-table-column> </el-table> + <el-button + class="m-t-8" + type="primary" + :loading="uploadLoading" + :disabled="!isUploadNewFile" + icon="upload" + @click="uploadFile" + >涓婁紶缁熻缁撴灉</el-button + > </template> <script setup> -import { ref, watch, onMounted } from 'vue'; +import { ref, reactive, watch, onMounted, getCurrentInstance } from 'vue'; +import { useMessageBoxTip, useMessageBox } from '@/composables/messageBox'; import { genFileId } from 'element-plus'; import monitordataApi from '@/api/fysp/monitordataApi'; +import sceneApi from '@/api/fysp/sceneApi'; import * as XLSX from 'xlsx'; +import { exportDocx } from '@/utils/doc'; + +const cns = getCurrentInstance(); +const $fm = cns.appContext.config.globalProperties.$fm; const props = defineProps({ areaInfo: { type: Object } }); let workbook; +const isUploadNewFile = ref(false); const data = ref([]); +const expandRowKeys = ref([]); const upload = ref(); +const tableLoading = ref(false); const loadTxt = ref(''); +const tips = ref(''); +const uploadLoading = ref(false); + +const tableRowClassName = ({ row, rowIndex }) => { + if (row.loading) { + return 'loading-row'; + } else if (row.isFound == undefined) { + return ''; + } else { + return row.isFound + ? 'success-row' + : row.notSure + ? 'warning-row' + : 'danger-row'; + } +}; // 鑾峰彇鍘嗗彶缁熻缁撴灉 function fetchDustDataResult() { @@ -74,19 +307,199 @@ upload.value.handleStart(file); } +/** + * 澶勭悊涓婁紶鏂囦欢瑙f瀽 + * @param uploadFile + * @param uploadFiles + */ function handleChange(uploadFile, uploadFiles) { + expandRowKeys.value = []; + tableLoading.value = true; + loadTxt.value = '鏂囦欢瑙f瀽涓�...'; // console.log(uploadFile, uploadFiles); const fileReader = new FileReader(); fileReader.onload = (file) => { - const data = file.target.result; - workbook = XLSX.read(data, { type: 'array' }); + const fileData = file.target.result; + workbook = XLSX.read(fileData, { type: 'array' }); console.log(workbook.SheetNames); + if (workbook.SheetNames.length == 0) { + tips.value = 'excel鏂囦欢閿欒锛屾病鏈塻heet琛ㄥ崟'; + return; + } + const worksheet = workbook.Sheets[workbook.SheetNames[0]]; + const tableData = XLSX.utils.sheet_to_json(worksheet); + const _data = tableData.map((v, i) => { + return { + id: i, + sceneIndex: v['鍞竴缂栧彿'], + drSceneName: v['鍦烘櫙鍚嶇О'], + deviceName: v['璁惧鍚嶇О'], + drDeviceCode: v['璁惧鍙�'], + drTime: $fm.formatDateFromExcel(v['鏃堕棿'], '-'), + drExceedTimes: v['瓒呮爣娆℃暟'], + drAvg: v['骞冲潎鍊�'], + drMax: v['鏈�澶у��'], + drMin: v['鏈�灏忓��'], + drOverAvgPer: v['瓒呭尯鍧囧�肩櫨鍒嗘瘮'], + drDataNum: v['鏁版嵁閲�'], + drEffectiveRate: v['鏈夋晥鐜�'] + }; + }); + data.value = combineSameScene(_data); + // console.log(tableData); + setTimeout(() => { + tableLoading.value = false; + isUploadNewFile.value = true; + data.value.forEach((d) => { + searchScene(d); + }); + }, 1000); }; fileReader.readAsArrayBuffer(uploadFile.raw); } +/** + * 鍚堝苟鐩稿悓鍦烘櫙鐨勫鍙扮洃娴嬭澶囷紝榛樿鍙栧尯鍧囧�兼渶楂樼殑涓�鍙拌澶� + */ +function combineSameScene(dataList) { + // 鏍规嵁鍦烘櫙鍞竴缂栧彿杩涜鐩稿悓璁惧褰掔被 + const tempMap = new Map(); + dataList.forEach((d) => { + if (!tempMap.has(d.sceneIndex)) { + tempMap.set(d.sceneIndex, []); + } + tempMap.get(d.sceneIndex).push(d); + }); + const res = []; + // 鐩稿悓鍦烘櫙涓嬶紝鍙栧尯鍧囧�兼渶楂樼殑涓�鍙拌澶囦綔涓虹粨鏋� + for (const [k, v] of tempMap) { + v.sort((a, b) => b.drAvg - a.drAvg); + if (v.length > 1) { + v[0].remark = `鏈満鏅叡鏈�${v.length}鍙拌澶囷紝宸茶嚜鍔ㄩ�夋嫨鍖哄潎鍊兼渶楂樼殑涓�鍙颁负缁熻缁撴灉`; + } + res.push(reactive(v[0])); + } + return res; +} + +// 鏌ヨ浠庢枃浠朵笂浼犵殑姣忎釜鍦烘櫙鏄惁鑳藉湪绯荤粺涓壘鍒板搴旂殑鍦烘櫙淇℃伅 +function searchScene(d) { + d.loading = true; + // 鏍规嵁鍦烘櫙鐨勫敮涓�缂栧彿銆佽鏀垮尯鍒掑拰鍦烘櫙绫诲瀷杩涜鏌ユ壘 + if (!d.sceneIndex) { + d.isFound = false; + d.loading = false; + return Promise; + } else { + sceneApi + .findScene({ + // name: d.drSceneName, + typeid: props.areaInfo.scensetypeid, + provincecode: props.areaInfo.provincecode, + citycode: props.areaInfo.citycode, + districtcode: props.areaInfo.districtcode, + towncode: props.areaInfo.towncode, + index: d.sceneIndex, + // 绛涢�夋煡璇㈠湪绾跨殑鍦烘櫙 + extension1: '1' + }) + .then((res) => { + setTimeout(() => { + if (res.length > 0) { + // 1. 鏍规嵁鍦烘櫙鍞竴缂栧彿杩涜鏌ヨ鏃讹紝涓�鑸儏鍐典笅搴旇鍙湁涓�涓敮涓�缁撴灉 + // 2-1. 褰撲笂浼犳枃浠朵腑鍦烘櫙鍚嶇О涓虹┖鐧芥椂锛岃嚜鍔ㄥ尮閰嶆煡璇㈡墍寰楀満鏅� + // 2-2. 褰撲笂浼犳枃浠朵腑鍦烘櫙鍚嶇О涓嶄负绌虹櫧鏃讹紝姣斿涓よ�呯殑鍦烘櫙鍚嶇О锛岃嫢涓嶅悓鍒欒繘琛岃鍛婃彁绀� + if (res.length == 1) { + const findRes = res[0]; + if (!d.drSceneName || d.drSceneName == '') { + d.drSceneId = findRes.guid; + d.drSceneName = findRes.name; + d.isFound = true; + d.notSure = false; + if (d.remark) expandRowKeys.value.push(d.id); + } else { + if (d.drSceneName == findRes.name) { + d.drSceneId = findRes.guid; + d.isFound = true; + d.notSure = false; + } else { + d.isFound = false; + d.notSure = true; + expandRowKeys.value.push(d.id); + } + } + } else { + d.isFound = false; + d.notSure = true; + expandRowKeys.value.push(d.id); + } + d.sourceScene = res; + + // const findRes = res.find((v) => v.name == d.drSceneName); + // if (findRes) { + // d.drSceneId = findRes.guid; + // d.isFound = true; + // } else { + // d.isFound = false; + // d.notSure = true; + // expandRowKeys.value.push(d.id); + // } + // d.sourceScene = res; + } else { + d.isFound = false; + d.notSure = false; + expandRowKeys.value.push(d.id); + } + d.loading = false; + }, 1000); + }) + .finally(() => { + setTimeout(() => { + d.loading = false; + }, 1000); + }); + } +} + +function handleSceneNameChange(newName, row) { + searchScene(row); +} + +function handleRadioChange(value, row) { + const scene = value; + row.sceneIndex = scene.index; + row.drSceneId = scene.guid; + row.drSceneName = scene.name; + searchScene(row); +} + // 涓婁紶缁熻缁撴灉鏂囨。 -function uploadFile() {} +function uploadFile() { + useMessageBoxTip({ + confirmMsg: `鏄惁纭涓婁紶锛焋, + confirmTitle: '涓婁紶', + onConfirm: () => { + uploadLoading.value = true; + return monitordataApi + .uploadDustDataResult(data.value) + .finally(() => (uploadLoading.value = false)); + } + }); +} + +/** + * 涓嬭浇妯℃澘鏂囦欢 + */ +function downloadTemplate() { + const fName = '鎵皹鐩戞祴鏁版嵁鏈堝害缁熻妯℃澘.xlsx'; + const path = `/${fName}`; + const link = document.createElement('a'); + link.href = path; + link.download = fName; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} onMounted(() => { fetchDustDataResult(); @@ -102,4 +515,42 @@ :deep(.el-text) { align-self: auto; } + +:deep(.el-table__expanded-cell) { + padding: 0; + /* background-color: var(--el-bg-color-page); */ +} + +/* :deep(.el-table__body tr>td.hover-cell) { + background-color: red !important; +} */ +/* .el-table--enable-row-hover + .el-table__body + tr:hover + > td + :deep(.el-table__cell) { + background-color: red !important; +} */ +</style> +<style> +.el-table .warning-row { + --el-table-tr-bg-color: var(--el-color-warning-light-5); +} +.el-table .success-row { + --el-table-tr-bg-color: var(--el-color-success-light-7); +} +.el-table .danger-row { + --el-table-tr-bg-color: var(--el-color-danger-light-5); +} +.el-table .loading-row { + color: var(--el-text-color-disabled); + /* --el-table-tr-bg-color: var(--el-text-color-placeholder); */ + --el-table-tr-bg-color: var(--el-bg-color); +} +/* .el-table__body tr>td.hover-cell { + background-color: red !important; +} */ +/* .el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell { + background-color: unset; +} */ </style> -- Gitblit v1.9.3