| | |
| | | ></OptionLocation2> |
| | | </el-form-item> |
| | | <OptionTime v-model="formObj.timeArray"></OptionTime> |
| | | <el-form-item label="区县筛选" prop="removeOtherDistrict"> |
| | | <el-checkbox v-model="formObj.removeOtherDistrict" |
| | | >移除其他区县</el-checkbox |
| | | > |
| | | </el-form-item> |
| | | <el-form-item label="污染源筛选" prop="removeNoPollutedSource"> |
| | | <el-checkbox v-model="formObj.removeNoPollutedSource" |
| | | >移除未发现污染源的线索</el-checkbox |
| | | > |
| | | </el-form-item> |
| | | <el-form-item label="隐患区域" prop="showPollutedArea"> |
| | | <el-checkbox v-model="formObj.showPollutedArea" |
| | | >将典型隐患区域表格作为附件展示</el-checkbox |
| | | > |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | |
| | | > |
| | | 下载报告 |
| | | </el-button> |
| | | <el-button |
| | | <!-- <el-button |
| | | type="primary" |
| | | class="el-button-custom" |
| | | @click="handleGenerateImg" |
| | | :loading="docLoading" |
| | | > |
| | | 生成图片 |
| | | </el-button> --> |
| | | </el-form-item> |
| | | <!-- <el-form-item> |
| | | <el-image :src="base64Url" fit="fill" :preview-src-list="[base64Url]" /> |
| | | </el-form-item> --> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | class="el-button-custom" |
| | | @click="handleMixClick" |
| | | :loading="docLoading" |
| | | > |
| | | 生成网格图片 |
| | | </el-button> |
| | | <el-form-item> |
| | | <el-form-item> |
| | | <el-image |
| | | :src="gridBase64Url" |
| | | fit="fill" |
| | | :preview-src-list="[gridBase64Url]" |
| | | /> |
| | | </el-form-item> |
| | | </el-form-item> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-form-item> |
| | | <el-image :src="base64Url" fit="fill" :preview-src-list="[base64Url]" /> |
| | | </el-form-item> |
| | | </CardDialog> |
| | | </template> |
| | | <script setup> |
| | | import { computed, ref } from 'vue'; |
| | | import moment from 'moment'; |
| | | import dataAnalysisApi from '@/api/dataAnalysisApi'; |
| | | import gridApi from '@/api/gridApi'; |
| | | import { exportDocx } from '@/utils/doc'; |
| | | import { radioOptions } from '@/constant/radio-options'; |
| | | import { TYPE0 } from '@/constant/device-type'; |
| | | import { FactorDatas } from '@/model/FactorDatas'; |
| | | import factorDataParser from '@/utils/chart/factor-data-parser'; |
| | | import chartToImg from '@/utils/chart/chart-to-img'; |
| | | import chartMap from '@/utils/chart/chart-map'; |
| | | import chartMapAmap from '@/utils/chart/chart-map-amap'; |
| | | import { Legend } from '@/model/Legend'; |
| | | import { getHexColor, getColorBetweenTwoColors } from '@/utils/color'; |
| | | import { getGridDataDetailFactorValue } from '@/model/GridDataDetail'; |
| | | import { factorName } from '@/constant/factor-name'; |
| | | |
| | | // 借用卫星遥测模块中的100米网格 |
| | | const props = defineProps({ |
| | | groupId: { |
| | | type: Number, |
| | | default: import.meta.env.VITE_DATA_MODE == 'jingan' ? 2 : 3 |
| | | } |
| | | }); |
| | | |
| | | const formObj = ref({ |
| | | timeArray: [new Date('2025-07-01T00:00:00'), new Date('2025-08-31T23:59:59')], |
| | | timeArray: [new Date('2025-07-01T00:00:00'), new Date('2025-09-30T23:59:59')], |
| | | location: {} |
| | | }); |
| | | |
| | | const docLoading = ref(false); |
| | | |
| | | const base64Url = ref(null); |
| | | const gridBase64Url = ref(null); |
| | | |
| | | const gridCellList = ref([]); |
| | | |
| | | const params = computed(() => { |
| | | return { |
| | |
| | | cityName: formObj.value.location.cName, |
| | | districtCode: formObj.value.location.dCode, |
| | | districtName: formObj.value.location.dName |
| | | } |
| | | }, |
| | | removeOtherDistrict: formObj.value.removeOtherDistrict, |
| | | removeNoPollutedSource: formObj.value.removeNoPollutedSource, |
| | | factorTypes: radioOptions(TYPE0).map((e) => e.name) |
| | | }; |
| | | }); |
| | | |
| | |
| | | srySceneCount: 5, |
| | | sryProbByFactor: |
| | | '颗粒物(PM)相关X处,占比 %,主要涉及工地扬尘污染问题、道路扬尘污染问题等;VOC相关X处,占比 %,主要涉及加油站油气泄露、餐饮油烟污染等', |
| | | sryFocusRegion: '聚焦区域', |
| | | missionInfoList: [ |
| | | { |
| | | missionCode: '', |
| | |
| | | _airQulity: 'AQI:30(优)', |
| | | mainFactor: '', |
| | | _abnormalFactors: '', |
| | | sceneCount: 0 |
| | | sceneCount: 0, |
| | | _kilometres: '1000', |
| | | _keyScene: '1个国控点(静安监测站)和2个市控点(和田中学、市北高新)', |
| | | exceptionCount: 0, |
| | | _focusScene: '' |
| | | } |
| | | ], |
| | | missionDetailList: [ |
| | | { |
| | | _index: 1, |
| | | missionCode: '', |
| | | _startTime: '2025年07月29日', |
| | | _time: '09:00至14:30', |
| | | _kilometres: '1000', |
| | | _keyScene: '1个国控点(静安监测站)和2个市控点(和田中学、市北高新)', |
| | | _dataStatistics: [ |
| | | { |
| | | factor: 'PM10', |
| | |
| | | avgValue: 38 |
| | | } |
| | | ], |
| | | _airQulity: 'AQI:30(优)', |
| | | aqi: 30, |
| | | pollutionDegree: '优' |
| | | } |
| | |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | clueList: [ |
| | | { |
| | | _factorNames: 'PM2.5', |
| | | _time: '10:22:28 - 10:22:34', |
| | | _riskRegion: '长宁区清溪路可乐东路', |
| | | _exceptionType: '快速上升', |
| | | _chart: '', |
| | | _conclusion: |
| | | '在10:22:28至10:22:34之间,出现快速上升,VOC最低值为135.95μg/m³,最高值为135.95μg/m³,均值为135.95μg/m³,发现3个风险源,包含2个加油站,1个汽修。', |
| | | _scenes: |
| | | '1.上海依德汽车维修有限公司,汽修企业,位于上海市长宁区北虹路1079号,距仙霞站1887米。\r\n……' |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | gridFusionByAQIList: [ |
| | | { |
| | | pollutionDegree: '优', |
| | | _areaDes: '走航区域大小', |
| | | _gridDes: '100米正方形网格', |
| | | _missionDes: '20250729、20250730两次', |
| | | highRiskGridList: [ |
| | | { |
| | | index: 1, |
| | | factor: 'PM2.5', |
| | | // 标准色网格图 |
| | | gridImgUrl1: '', |
| | | // 对比色网格图 |
| | | gridImgUrl2: '', |
| | | factorValue: 20, |
| | | // 四至范围,顺序为最小经度,最大经度,最小纬度,最大纬度 |
| | | bounds: [121.4945, 121.4955, 31.2304, 31.2314], |
| | | _boundsDes: '四至范围', |
| | | // 涉及街镇 |
| | | town: '', |
| | | _scenesDes: '涉及的污染场景' |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | |
| | | generateMissionList(params.value).then(() => { |
| | | generateMissionDetail(params.value).then(() => { |
| | | generateClueByRiskArea(params.value).then(() => { |
| | | generateDocx(); |
| | | generateGridFusion(params.value).then(() => { |
| | | generateDocx(); |
| | | }); |
| | | }); |
| | | }); |
| | | }); |
| | |
| | | }; |
| | | |
| | | const handleGenerateImg = () => { |
| | | generateClueByRiskArea(params.value).then(() => {}); |
| | | generateClueByRiskArea(params.value).then(() => { |
| | | generateDocx(); |
| | | }); |
| | | }; |
| | | |
| | | function generateMissionSummary(param) { |
| | |
| | | new Date(res.data.startTime), |
| | | new Date(res.data.endTime) |
| | | ); |
| | | templateParam.subTitle = |
| | | templateParam.sryTime.indexOf('季度') !== -1 |
| | | ? templateParam.sryTime.replace(/(.*)/, '') |
| | | : templateParam.sryTime; |
| | | templateParam.sryArea = res.data.area.districtName; |
| | | templateParam.sryCount = res.data.count; |
| | | templateParam.sryKm = Math.round(res.data.kilometres / 1000); |
| | |
| | | return `${item.first}相关${item.second}处,占比 ${Math.round(item.third * 1000) / 10}%,主要涉及${getPollutingProblemTypes(item.first)}等`; |
| | | }) |
| | | .join(';'); |
| | | templateParam.sryFocusRegion = res.data.focusRegion.join('、'); |
| | | }); |
| | | } |
| | | |
| | |
| | | return dataAnalysisApi.fetchMissionList(param).then((res) => { |
| | | templateParam.missionInfoList = res.data.map((item) => { |
| | | item._time = formatDateTimeRange(item.startTime, item.endTime); |
| | | item._airQulity = `AQI:${item.aqi}(${item.pollutionDegree})`; |
| | | item._airQulity = `${item.aqi}(${item.pollutionDegree})`; |
| | | item._abnormalFactors = item.abnormalFactors |
| | | .map((factor) => factor) |
| | | .map((factor) => factorName[factor]) |
| | | .join('、'); |
| | | return item; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function generateMissionDetail(param) { |
| | | return dataAnalysisApi.fetchMissionDetail(param).then((res) => { |
| | | templateParam.missionDetailList = res.data.map((item, index) => { |
| | | const t = formatDateTimeRange(item.startTime, item.endTime).split(' '); |
| | | item._index = index + 1; |
| | | item._startTime = t[0]; |
| | | item._time = t[1]; |
| | | item._kilometres = Math.round(item.kilometres / 1000); |
| | | |
| | | const keySceneMap = new Map(); |
| | |
| | | `${info.count}个${type}(${info.scenes.map((s) => s.name).join('、')})` |
| | | ) |
| | | .join('、'); |
| | | item._dataStat = item.dataStatistics |
| | | .map( |
| | | (e) => |
| | | `${e.factor.des}(范围${e.minValue}–${e.maxValue}μg/m³,均值${e.avgValue}μg/m³)` |
| | | ) |
| | | .join('、'); |
| | | item._focusScene = |
| | | item.scenes.length > 0 |
| | | ? item.scenes.map((s) => s.name).join('、') |
| | | : '道路交通密集区和部分施工周边'; |
| | | return item; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function generateMissionDetail(param) { |
| | | return dataAnalysisApi.fetchMissionDetail(param).then((res) => { |
| | | templateParam.missionDetailList = res.data.map((item, index) => { |
| | | const t = formatDateTimeRange(item.startTime, item.endTime).split(' '); |
| | | item._index = index + 1; |
| | | item._startTime = t[0]; |
| | | item._time = t[1]; |
| | | item._kilometres = Math.round(item.kilometres / 1000); |
| | | item._airQulity = `${item.aqi}(${item.pollutionDegree})`; |
| | | |
| | | const factorNames = radioOptions(TYPE0).map((e) => e.name); |
| | | item._dataStatistics = item.dataStatistics.filter((e) => { |
| | | return factorNames.indexOf(e.factor) != -1; |
| | | }); |
| | | |
| | | radioOptions(TYPE0).forEach((f) => { |
| | | const _factor = item.dataStatistics.find((e) => e.factor == f.name); |
| | | item[`avgValue_${f.name}`] = _factor?.avgValue.toFixed(0) ?? '-'; |
| | | item[`maxValue_${f.name}`] = _factor?.maxValue.toFixed(0) ?? '-'; |
| | | item[`minValue_${f.name}`] = _factor?.minValue.toFixed(0) ?? '-'; |
| | | }); |
| | | |
| | | return item; |
| | |
| | | } |
| | | |
| | | function generateClueByRiskArea(param) { |
| | | return dataAnalysisApi.fetchClueByRiskArea(param).then((res) => { |
| | | templateParam.clueByAreaList = res.data.map((item, index) => { |
| | | return { |
| | | _index: index + 1, |
| | | _area: item.sceneInfo.name + '周边', |
| | | clueByFactorList: item.clueByFactorList.map((cbf) => { |
| | | return { |
| | | factor: cbf.factor, |
| | | clues: cbf.clues.map((clue) => { |
| | | const indexArr = [ |
| | | 'A', |
| | | 'B', |
| | | 'C', |
| | | 'D', |
| | | 'E', |
| | | 'F', |
| | | 'G', |
| | | 'H', |
| | | 'I', |
| | | 'J', |
| | | 'K', |
| | | 'L', |
| | | 'M', |
| | | 'N', |
| | | 'O', |
| | | 'P', |
| | | 'Q', |
| | | 'R', |
| | | 'S', |
| | | 'T', |
| | | 'U', |
| | | 'V', |
| | | 'W', |
| | | 'X', |
| | | 'Y', |
| | | 'Z' |
| | | ]; |
| | | const _param = { |
| | | area: param.area, |
| | | startTime: param.startTime, |
| | | endTime: param.endTime, |
| | | removeOtherDistrict: param.removeOtherDistrict, |
| | | removeNoPollutedSource: param.removeNoPollutedSource |
| | | }; |
| | | return dataAnalysisApi.fetchClueByRiskArea(_param).then((res) => { |
| | | templateParam.showPollutedArea = formObj.value.showPollutedArea; |
| | | templateParam.clueByAreaList = res.data |
| | | .groupBy((e) => e.township) |
| | | .map((item, index) => { |
| | | const { key: township, values: clues } = item; |
| | | let typeCount = {}; |
| | | let lastSceneType; |
| | | let sceneIndex = 0; |
| | | |
| | | const _scenes = clues.flatMap((e) => |
| | | e.clue.pollutedSource.sceneList.map((s, index) => { |
| | | const i = lastSceneType == s.type ? ++sceneIndex : 0; |
| | | typeCount[s.type] = typeCount[s.type] ? typeCount[s.type] + 1 : 1; |
| | | lastSceneType = s.type; |
| | | return { |
| | | des: `${s.type}${i + 1}:${s.name},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | }; |
| | | }) |
| | | ); |
| | | let _sceneDes = `走航过程中溯源到${_scenes.length}个风险源`; |
| | | if (_scenes.length > 0) { |
| | | _sceneDes += ',其类型是'; |
| | | _sceneDes += Object.keys(typeCount) |
| | | .map((e) => `${e}(${typeCount[e]}个)`) |
| | | .join('、'); |
| | | _sceneDes += ':'; |
| | | } else { |
| | | _sceneDes = '走航过程中未溯源到风险源。'; |
| | | } |
| | | return { |
| | | _index: index + 1, |
| | | // _area: `${item.sceneInfo.type}${item.sceneInfo.name}周边`, |
| | | _area: `${township}`, |
| | | _sceneDes, |
| | | _scenes, |
| | | clueList: clues.map((item3, index3) => { |
| | | const clue = item3.clue; |
| | | let _riskRegion = ''; |
| | | if ( |
| | | clue.pollutedArea.address.indexOf( |
| | | clue.pollutedArea.streetNumber |
| | | ) == -1 |
| | | ) { |
| | | // _riskRegion += |
| | | // (clue.pollutedArea.address ?? '') + |
| | | // '(' + |
| | | // (clue.pollutedArea.street ?? '') + |
| | | // (clue.pollutedArea.streetNumber ?? '') + |
| | | // (clue.pollutedArea.direction ?? '') + |
| | | // ')'; |
| | | _riskRegion = clue.pollutedArea.address; |
| | | } else { |
| | | _riskRegion = clue.pollutedArea.address; |
| | | } |
| | | return { |
| | | index: indexArr[index3], |
| | | showPollutedArea: formObj.value.showPollutedArea, |
| | | _title: _riskRegion, |
| | | _factorNames: Object.keys(clue.pollutedData.statisticMap) |
| | | .map((e) => factorName[e]) |
| | | <<<<<<< HEAD |
| | | .join('、'), |
| | | _date: moment(clue.pollutedData.startTime).format('YYYY-MM-DD'), |
| | | _time: |
| | | moment(clue.pollutedData.startTime).format('HH:mm:ss') + |
| | | ' - ' + |
| | | moment(clue.pollutedData.endTime).format('HH:mm:ss'), |
| | | _riskRegion: _riskRegion, |
| | | _exceptionType: clue.pollutedData.exception, |
| | | _images: generateChartImg(clue.pollutedData), |
| | | _conclusion: clue.pollutedSource.conclusion.replace( |
| | | /,发现[0-9]*个风险源,包含[0-9]*个.*。/, |
| | | '。' |
| | | ), |
| | | _hasScene: clue.pollutedSource.sceneList.length > 0 |
| | | }; |
| | | }) |
| | | // clueByFactorList: clues |
| | | // .groupBy((e) => e.factorTag) |
| | | // .map((item2, index2) => { |
| | | // const { key: factorTag, values: clues2 } = item2; |
| | | // const factorNames = [...new Set(clues2.flatMap((e) => e.factors))] |
| | | // .map((e) => factorName[e]) |
| | | // .join('、'); |
| | | // return { |
| | | // index: index2 + 1, |
| | | // factor: factorNames, |
| | | // clues: clues2.map((item3, index3) => { |
| | | // const clue = item3.clue; |
| | | // let _riskRegion = ''; |
| | | // if ( |
| | | // clue.pollutedArea.address.indexOf( |
| | | // clue.pollutedArea.streetNumber |
| | | // ) == -1 |
| | | // ) { |
| | | // _riskRegion += |
| | | // (clue.pollutedArea.address ?? '') + |
| | | // '(' + |
| | | // (clue.pollutedArea.street ?? '') + |
| | | // (clue.pollutedArea.streetNumber ?? '') + |
| | | // (clue.pollutedArea.direction ?? '') + |
| | | // ')'; |
| | | // } else { |
| | | // _riskRegion = clue.pollutedArea.address; |
| | | // } |
| | | // return { |
| | | // index: index3 + 1 + '', |
| | | // showPollutedArea: formObj.value.showPollutedArea, |
| | | // _title: |
| | | // (clue.pollutedArea.street ?? '') + |
| | | // (clue.pollutedArea.streetNumber ?? '') + |
| | | // (clue.pollutedArea.direction ?? ''), |
| | | // _factorNames: Object.keys(clue.pollutedData.statisticMap) |
| | | // .map((e) => factorName[e]) |
| | | // .join('、'), |
| | | // _time: |
| | | // moment(clue.pollutedData.startTime).format( |
| | | // 'YYYY-MM-DD HH:mm:ss' |
| | | // ) + |
| | | // ' - ' + |
| | | // moment(clue.pollutedData.endTime).format('HH:mm:ss'), |
| | | // _riskRegion: _riskRegion, |
| | | // _exceptionType: clue.pollutedData.exception, |
| | | // _images: generateChartImg(clue.pollutedData), |
| | | // _conclusion: clue.pollutedSource.conclusion, |
| | | // _hasScene: clue.pollutedSource.sceneList.length > 0, |
| | | // // _scenes: |
| | | // // clue.pollutedSource.sceneList.length > 0 |
| | | // // ? clue.pollutedSource.sceneList |
| | | // // .map( |
| | | // // (s, index) => |
| | | // // `${index + 1}. ${s.name},${s.type},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | // // ) |
| | | // // .join('\r\n') |
| | | // // : '无', |
| | | // _scenes: clue.pollutedSource.sceneList.map((s, index) => { |
| | | // return { |
| | | // des: `${index + 1}. ${s.name},${s.type},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | // }; |
| | | // }) |
| | | // }; |
| | | // }) |
| | | // }; |
| | | // }) |
| | | ======= |
| | | .join('、'); |
| | | return { |
| | | _factorNames: Object.keys(clue.pollutedData.statisticMap) |
| | | .map((e) => e) |
| | | .join('、'), |
| | | _time: |
| | | moment(clue.pollutedData.startTime).format('HH:mm:ss') + |
| | | ' - ' + |
| | | moment(clue.pollutedData.endTime).format('HH:mm:ss'), |
| | | _riskRegion: clue.pollutedArea.address |
| | | ? clue.pollutedArea.address |
| | | : '', |
| | | _exceptionType: clue.pollutedData.exception, |
| | | _images: generateChartImg(clue.pollutedData), |
| | | _conclusion: clue.pollutedSource.conclusion, |
| | | _scenes: |
| | | clue.pollutedSource.sceneList.length > 0 |
| | | ? clue.pollutedSource.sceneList |
| | | .map( |
| | | (s, index) => |
| | | `${index + 1}. ${s.name},${s.type},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | ) |
| | | .join('\n') |
| | | : '无' |
| | | index: index2 + 1, |
| | | factor: factorNames, |
| | | clues: clues2.map((item3, index3) => { |
| | | const clue = item3.clue; |
| | | let _riskRegion = ''; |
| | | if ( |
| | | parseInt(clue.pollutedArea.distance) < |
| | | parseInt(clue.pollutedArea.distance2) |
| | | ) { |
| | | if ( |
| | | clue.pollutedArea.address.indexOf( |
| | | clue.pollutedArea.streetNumber |
| | | ) == -1 |
| | | ) { |
| | | _riskRegion += |
| | | (clue.pollutedArea.address ?? '') + |
| | | '(' + |
| | | (clue.pollutedArea.street ?? '') + |
| | | (clue.pollutedArea.streetNumber ?? '') + |
| | | (clue.pollutedArea.direction ?? '') + |
| | | ')'; |
| | | } else { |
| | | _riskRegion = clue.pollutedArea.address; |
| | | } |
| | | } else { |
| | | _riskRegion += |
| | | (clue.pollutedArea.address ?? '') + |
| | | '(' + |
| | | (clue.pollutedArea.street ?? '') + |
| | | (clue.pollutedArea.roadinter ?? '') + |
| | | ')'; |
| | | } |
| | | return { |
| | | index: index3 + 1 + '', |
| | | showPollutedArea: formObj.value.showPollutedArea, |
| | | _title: |
| | | // (clue.pollutedArea.street ?? '') + |
| | | // (clue.pollutedArea.streetNumber ?? '') + |
| | | // (clue.pollutedArea.direction ?? ''), |
| | | clue.pollutedArea.address ?? '', |
| | | _factorNames: Object.keys(clue.pollutedData.statisticMap) |
| | | .map((e) => factorName[e]) |
| | | .join('、'), |
| | | _time: |
| | | moment(clue.pollutedData.startTime).format( |
| | | 'YYYY-MM-DD HH:mm:ss' |
| | | ) + |
| | | ' - ' + |
| | | moment(clue.pollutedData.endTime).format('HH:mm:ss'), |
| | | _riskRegion: _riskRegion, |
| | | _exceptionType: clue.pollutedData.exception, |
| | | _images: generateChartImg(clue.pollutedData), |
| | | _conclusion: clue.pollutedSource.conclusion, |
| | | _hasScene: clue.pollutedSource.sceneList.length > 0, |
| | | // _scenes: |
| | | // clue.pollutedSource.sceneList.length > 0 |
| | | // ? clue.pollutedSource.sceneList |
| | | // .map( |
| | | // (s, index) => |
| | | // `${index + 1}. ${s.name},${s.type},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | // ) |
| | | // .join('\r\n') |
| | | // : '无', |
| | | _scenes: clue.pollutedSource.sceneList.map((s, index) => { |
| | | return { |
| | | des: `${index + 1}. ${s.name},${s.type},位于${s.location},距${s.closestStation.name}${parseInt(s.length)}米;` |
| | | }; |
| | | }) |
| | | }; |
| | | }) |
| | | }; |
| | | }) |
| | | }; |
| | | }) |
| | | }; |
| | | }); |
| | | >>>>>>> ce17d42203a17120736d796d0e83b3742c4ec441 |
| | | }; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | |
| | | factorDatas.setData(pollutedData.historyDataList, 0, () => { |
| | | for (const key in pollutedData.statisticMap) { |
| | | const value = pollutedData.statisticMap[key]; |
| | | const _chartOptions = factorDataParser.parseData(factorDatas, [ |
| | | { |
| | | label: value.factorName, |
| | | name: value.factorName, |
| | | value: value.factorId + '' |
| | | } |
| | | ]); |
| | | const _chartOptions = factorDataParser.parseData( |
| | | factorDatas, |
| | | [ |
| | | { |
| | | label: value.factorName, |
| | | name: value.factorName, |
| | | value: value.factorId + '' |
| | | } |
| | | ], |
| | | false |
| | | ); |
| | | _chartOptions.forEach((o) => { |
| | | images.push({ |
| | | url: chartToImg.generateEchartsImage(o, exceptionIndexArr, 20) |
| | |
| | | } |
| | | }); |
| | | return images; |
| | | } |
| | | |
| | | function generateGridFusion(param) { |
| | | return dataAnalysisApi.fetchGridFusion(param).then((res) => { |
| | | const promiseList = []; |
| | | templateParam.gridFusionByAQIList = []; |
| | | |
| | | res.data.forEach((item) => { |
| | | const scenes = []; |
| | | item.missionList.forEach((m) => { |
| | | m.keyScene.map((s) => { |
| | | if (scenes.indexOf(s.name) == -1) { |
| | | scenes.push(s.name); |
| | | } |
| | | }); |
| | | }); |
| | | const gfbAQI = { |
| | | pollutionDegree: item.pollutionDegree, |
| | | _areaDes: `走航区域经过${scenes.join('、')}`, |
| | | _gridDes: `${item.gridLen}米正方形网格`, |
| | | _missionDes: `${item.missionList.map((m) => m.missionCode).join('、')}共${item.missionList.length}次` |
| | | }; |
| | | const _highRiskGridList = []; |
| | | Object.keys(item.highRiskGridMap).forEach((key, i) => { |
| | | const g = item.highRiskGridMap[key][0]; |
| | | |
| | | const infoDes = item.highRiskGridMap[key].map((e) => { |
| | | return { |
| | | factorValue: e.factorValue, |
| | | // 四至范围,顺序为最小经度,最大经度,最小纬度,最大纬度 |
| | | _boundsDes: `经度${e.bounds[0]}至${e.bounds[1]},纬度${e.bounds[2]}至${e.bounds[3]}`, |
| | | // 涉及街镇 |
| | | town: e.town, |
| | | _scenesDes: |
| | | e.highRiskScenes.length > 0 |
| | | ? `涉及的污染场景包括${e.highRiskScenes.map((s) => s.name).join('、')}` |
| | | : '网格内可能存在隐藏风险源' |
| | | }; |
| | | }); |
| | | const infoDes2 = item.highRiskGridMap2[key].map((e) => { |
| | | return { |
| | | factorValue: e.factorValue, |
| | | // 四至范围,顺序为最小经度,最大经度,最小纬度,最大纬度 |
| | | _boundsDes: `经度${e.bounds[0]}至${e.bounds[1]},纬度${e.bounds[2]}至${e.bounds[3]}`, |
| | | // 涉及街镇 |
| | | town: e.town, |
| | | _scenesDes: |
| | | e.highRiskScenes.length > 0 |
| | | ? `涉及的污染场景包括${e.highRiskScenes.map((s) => s.name).join('、')}` |
| | | : '网格内可能存在隐藏风险源' |
| | | }; |
| | | }); |
| | | // }) |
| | | // item.highRiskGridList.forEach((g, i) => { |
| | | // const g = item.highRiskGridList[0]; |
| | | // const i = 0; |
| | | const p = generateGridFusionImg(g.factorType, item.gridFusionList).then( |
| | | (url) => { |
| | | const { url1, url2 } = url; |
| | | _highRiskGridList.push({ |
| | | index: i + 1, |
| | | factor: factorName[g.factorType], |
| | | // 标准色网格图 |
| | | gridImgUrl1: url1, |
| | | // 对比色网格图 |
| | | gridImgUrl2: url2, |
| | | infoDes: infoDes, |
| | | infoDes2: infoDes2 |
| | | }); |
| | | } |
| | | ); |
| | | promiseList.push(p); |
| | | }); |
| | | gfbAQI.highRiskGridList = _highRiskGridList; |
| | | templateParam.gridFusionByAQIList.push(gfbAQI); |
| | | }); |
| | | return Promise.all(promiseList).then(() => { |
| | | return templateParam.gridFusionByAQIList; |
| | | }); |
| | | // templateParam.gridFusionByAQIList = res.data.map((item) => { |
| | | // const scenes = []; |
| | | // item.missionList.forEach((m) => { |
| | | // m.keyScene.map((s) => { |
| | | // if (scenes.indexOf(s.name) == -1) { |
| | | // scenes.push(s.name); |
| | | // } |
| | | // }); |
| | | // }); |
| | | // return { |
| | | // pollutionDegree: item.pollutionDegree, |
| | | // _areaDes: `走航区域经过${scenes.join('、')}`, |
| | | // _gridDes: `${item.gridLen}米正方形网格`, |
| | | // _missionDes: `${item.missionList.map((m) => m.missioncode).join('、')}${item.missionList.length}次`, |
| | | // highRiskGridList: item.highRiskGridList.map(async (g, i) => { |
| | | // const { url1, url2 } = await generateGridFusionImg( |
| | | // g.factorType, |
| | | // item.gridFusionList |
| | | // ); |
| | | // return { |
| | | // index: i + 1, |
| | | // factor: g.factorType, |
| | | // // 标准色网格图 |
| | | // gridImgUrl1: url1, |
| | | // // 对比色网格图 |
| | | // gridImgUrl2: url2, |
| | | // factorValue: g.factorValue, |
| | | // // 四至范围,顺序为最小经度,最大经度,最小纬度,最大纬度 |
| | | // _boundsDes: `经度${g.bounds[0]}至${g.bounds[1]},纬度${g.bounds[2]}至${g.bounds[3]}`, |
| | | // // 涉及街镇 |
| | | // town: g.town, |
| | | // _scenesDes: g.highRiskScenes.map((s) => s.name).join('、') |
| | | // }; |
| | | // }) |
| | | // }; |
| | | // }); |
| | | }); |
| | | } |
| | | |
| | | async function generateGridFusionImg(factorName, dataList) { |
| | | let min = 1000000; |
| | | let max = 0; |
| | | dataList.forEach((v) => { |
| | | min = Math.min(min, getGridDataDetailFactorValue(v.data, factorName)); |
| | | max = Math.max(max, getGridDataDetailFactorValue(v.data, factorName)); |
| | | }); |
| | | |
| | | const gridDataStand = []; |
| | | const gridDataCustom = []; |
| | | dataList.forEach((v) => { |
| | | const data = getGridDataDetailFactorValue(v.data, factorName); |
| | | const grid = v.cell; |
| | | |
| | | // 标准色 |
| | | const { |
| | | color: color1, |
| | | nextColor: nextColor1, |
| | | range: range1, |
| | | nextRange: nextRange1 |
| | | } = Legend.getStandardColorAndNext(factorName, data); |
| | | const ratio1 = (data - range1) / (nextRange1 - range1); |
| | | const _color1 = getColorBetweenTwoColors( |
| | | color1.map((v) => v * 255), |
| | | nextColor1.map((v) => v * 255), |
| | | ratio1 |
| | | ); |
| | | |
| | | // 对比色 |
| | | const { color, nextColor, range, nextRange } = Legend.getCustomColorAndNext( |
| | | data, |
| | | min, |
| | | max |
| | | ); |
| | | const ratio = (data - range) / (nextRange - range); |
| | | const _color = getColorBetweenTwoColors( |
| | | color.map((v) => v * 255), |
| | | nextColor.map((v) => v * 255), |
| | | ratio |
| | | ); |
| | | |
| | | gridDataStand.push({ |
| | | centerLng: grid.longitude, |
| | | centerLat: grid.latitude, |
| | | value: _color1, |
| | | coordinates: [ |
| | | [grid.point1Lon, grid.point1Lat], |
| | | [grid.point2Lon, grid.point2Lat], |
| | | [grid.point3Lon, grid.point3Lat], |
| | | [grid.point4Lon, grid.point4Lat] |
| | | ] |
| | | }); |
| | | gridDataCustom.push({ |
| | | centerLng: grid.longitude, |
| | | centerLat: grid.latitude, |
| | | value: _color, |
| | | coordinates: [ |
| | | [grid.point1Lon, grid.point1Lat], |
| | | [grid.point2Lon, grid.point2Lat], |
| | | [grid.point3Lon, grid.point3Lat], |
| | | [grid.point4Lon, grid.point4Lat] |
| | | ] |
| | | }); |
| | | }); |
| | | const url1 = await chartMap.generateGridMap(gridDataStand); |
| | | const url2 = await chartMap.generateGridMap(gridDataCustom); |
| | | if (gridBase64Url.value == null) { |
| | | gridBase64Url.value = url1; |
| | | } |
| | | return { |
| | | url1, |
| | | url2 |
| | | }; |
| | | } |
| | | |
| | | function handleMixClick({ tags = [10, 11], factorName = 'PM25' }) { |
| | | generateGridFusion(params.value).then(() => {}); |
| | | } |
| | | |
| | | function generateDocx() { |
| | |
| | | |
| | | // 不是季度第一天则返回具体日期范围 |
| | | if (!quarter) { |
| | | return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | // return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | return startYear == endYear |
| | | ? `${startYear}年${startMonth + 1}月-${endMonth + 1}月` |
| | | : `${startYear}年${startMonth + 1}月-${endYear}年${endMonth + 1}月`; |
| | | } |
| | | |
| | | // 验证是否为对应季度最后一个月 |
| | | const expectedEndMonth = quarter * 3 - 1; // Q1:2(3月), Q2:5(6月), Q3:8(9月), Q4:11(12月) |
| | | if (endMonth !== expectedEndMonth) { |
| | | return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | // return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | return startYear == endYear |
| | | ? `${startYear}年${startMonth + 1}月-${endMonth + 1}月` |
| | | : `${startYear}年${startMonth + 1}月-${endYear}年${endMonth + 1}月`; |
| | | } |
| | | |
| | | // 验证是否为季度最后一天 |
| | | const lastDayOfEndMonth = new Date(endYear, endMonth + 1, 0).getDate(); |
| | | if (endDate !== lastDayOfEndMonth) { |
| | | return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | // return `${startYear}年${startMonth + 1}月${startDate}日-${endYear}年${endMonth + 1}月${endDate}日`; |
| | | return startYear == endYear |
| | | ? `${startYear}年${startMonth + 1}月-${endMonth + 1}月` |
| | | : `${startYear}年${startMonth + 1}月-${endYear}年${endMonth + 1}月`; |
| | | } |
| | | |
| | | const quarterNames = ['', '第一季度', '第二季度', '第三季度', '第四季度']; |
| | |
| | | return `${datePart} ${startTimePart}至${endTimePart}`; |
| | | } |
| | | </script> |
| | | <style scoped> |
| | | .el-checkbox { |
| | | --el-checkbox-text-color: white; |
| | | } |
| | | </style> |