| | |
| | | FYOptionTime: typeof import('./src/components/search-option/FYOptionTime.vue')['default'] |
| | | FYOptionTopTask: typeof import('./src/components/search-option/FYOptionTopTask.vue')['default'] |
| | | FYOptionUserType: typeof import('./src/components/search-option/FYOptionUserType.vue')['default'] |
| | | FYPageHeader: typeof import('./src/components/head/FYPageHeader.vue')['default'] |
| | | FYReconfrimButton: typeof import('./src/components/button/FYReconfrimButton.vue')['default'] |
| | | FYSearchBar: typeof import('./src/components/search-option/FYSearchBar.vue')['default'] |
| | | FYTable: typeof import('./src/components/table/FYTable.vue')['default'] |
| | |
| | | const FYOptionTime: typeof import('./src/components/search-option/FYOptionTime.vue')['default'] |
| | | const FYOptionTopTask: typeof import('./src/components/search-option/FYOptionTopTask.vue')['default'] |
| | | const FYOptionUserType: typeof import('./src/components/search-option/FYOptionUserType.vue')['default'] |
| | | const FYPageHeader: typeof import('./src/components/head/FYPageHeader.vue')['default'] |
| | | const FYReconfrimButton: typeof import('./src/components/button/FYReconfrimButton.vue')['default'] |
| | | const FYSearchBar: typeof import('./src/components/search-option/FYSearchBar.vue')['default'] |
| | | const FYTable: typeof import('./src/components/table/FYTable.vue')['default'] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-page-header @back="onBack" class="page-header"> |
| | | <template #content> |
| | | <span> {{ title }} </span> |
| | | </template> |
| | | </el-page-header> |
| | | <el-divider /> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | default: 'å½å为é»è®¤é¡µé¢æ é¢ï¼è¯·ä¼ å
¥æ é¢åå' |
| | | } |
| | | }, |
| | | methods: { |
| | | // åéé¡µé¢ |
| | | onBack() { |
| | | this.$router.back(); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | <span>设å¤å¨çº¿æ
åµ</span> |
| | | </div> |
| | | </template> |
| | | <el-row :gutter="20"> |
| | | <el-row :gutter="0"> |
| | | <el-col :span="12"> |
| | | <el-row :gutter="20"> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="12"> |
| | | <el-card class="status-card online-card" shadow="hover"> |
| | | <div class="status-content"> |
| | |
| | | formatter: '{a} <br/>{b}: {c} ({d}%)', |
| | | }, |
| | | legend: { |
| | | show: false, |
| | | bottom: '0%', |
| | | data: ['å¨çº¿è®¾å¤', '离线设å¤', 'æ£å¸¸è®¾å¤', 'æ
é设å¤'], |
| | | }, |
| | |
| | | { |
| | | name: 'å¨çº¿ç¶æ', |
| | | type: 'pie', |
| | | radius: ['40%', '70%'], |
| | | radius: ['20%', '40%'], |
| | | center: ['48%', '50%'], |
| | | startAngle: 270, |
| | | endAngle: 90, |
| | |
| | | { |
| | | name: 'è¿è¡ç¶æ', |
| | | type: 'pie', |
| | | radius: ['40%', '70%'], |
| | | radius: ['30%', '50%'], |
| | | center: ['52%', '50%'], |
| | | startAngle: 90, |
| | | endAngle: 270, |
| | |
| | | </el-radio-group> |
| | | </el-col> |
| | | </el-row> |
| | | <div ref="rankingChart" class="chart-container"></div> |
| | | <el-table :data="sortedRankingData" style="width: 100%" stripe class="ranking-table"> |
| | | <el-table-column label="æå" type="index" width="80" /> |
| | | <el-table-column prop="name" label="åºå¿åç§°" /> |
| | | <el-table-column prop="value" label="æµåº¦åå¼ (mg/m³)" /> |
| | | <el-table-column label="æååå" width="120"> |
| | | <template #default="scope"> |
| | | <div v-if="scope.row.rankChange > 0" class="rank-up"> |
| | | <el-icon><ArrowUp /></el-icon> {{ scope.row.rankChange }} |
| | | </div> |
| | | <div v-else-if="scope.row.rankChange < 0" class="rank-down"> |
| | | <el-icon><ArrowDown /></el-icon> {{ Math.abs(scope.row.rankChange) }} |
| | | </div> |
| | | <div v-else class="rank-no-change"> |
| | | <el-icon><Minus /></el-icon> 0 |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <div ref="rankingChart" class="chart-container"></div> |
| | | </el-col> |
| | | <el-col :span="14"> |
| | | <el-table :data="sortedRankingData" size="small" stripe class="ranking-table"> |
| | | <el-table-column label="æå" type="index" width="80" /> |
| | | <el-table-column prop="name" label="åºå¿åç§°" /> |
| | | <el-table-column prop="value" label="æµåº¦åå¼ (mg/m³)" /> |
| | | <el-table-column label="æååå" width="120"> |
| | | <template #default="scope"> |
| | | <div v-if="scope.row.rankChange > 0" class="rank-up"> |
| | | <el-icon><ArrowUp /></el-icon> {{ scope.row.rankChange }} |
| | | </div> |
| | | <div v-else-if="scope.row.rankChange < 0" class="rank-down"> |
| | | <el-icon><ArrowDown /></el-icon> {{ Math.abs(scope.row.rankChange) }} |
| | | </div> |
| | | <div v-else class="rank-no-change"> |
| | | <el-icon><Minus /></el-icon> 0 |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | </template> |
| | | |
| | |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | left: '0%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | bottom: '6%', |
| | | top: '4%', |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: this.sortedRankingData.map((item) => item.name), |
| | | type: 'value', |
| | | nameLocation: 'middle', |
| | | nameGap: 30, |
| | | name: this.rankingType === 'hourly' ? 'å°æ¶åå¼ (mg/m³)' : 'æåå¼ (mg/m³)', |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: this.rankingType === 'hourly' ? 'å°æ¶åå¼ (mg/m³)' : 'æåå¼ (mg/m³)', |
| | | type: 'category', |
| | | data: this.sortedRankingData.map((item) => item.name).reverse(), |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'æµåº¦åå¼', |
| | | type: 'bar', |
| | | data: this.sortedRankingData.map((item) => parseFloat(item.value)), |
| | | data: this.sortedRankingData.map((item) => parseFloat(item.value)).reverse(), |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [ |
| | | { offset: 0, color: '#83bff6' }, |
| | | { offset: 0.5, color: '#188df0' }, |
| | | { offset: 1, color: '#188df0' }, |
| | |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | <style scoped lang="scss"> |
| | | .section { |
| | | margin-bottom: 20px; |
| | | } |
| | |
| | | } |
| | | |
| | | .chart-container { |
| | | height: 300px; |
| | | height: 400px; |
| | | width: 100%; |
| | | } |
| | | |
| | |
| | | <span>设å¤å®æ¶æ°æ®</span> |
| | | </div> |
| | | </template> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-card class="realtime-data" shadow="hover"> |
| | | <template #header> |
| | | <span>宿¶åéæ°æ®</span> |
| | | </template> |
| | | <el-descriptions :column="1" v-if="currentDevice"> |
| | | <el-descriptions-item label="设å¤ç¼å·">{{ |
| | | currentDevice.deviceId |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="设å¤ä¾åºå">{{ |
| | | currentDevice.supplier |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ²¹çæµåº¦" |
| | | >{{ currentDevice.æ²¹çæµåº¦ }} mg/m³</el-descriptions-item |
| | | <el-space v-if="devices && devices.length > 0" justify="center" wrap> |
| | | <el-card |
| | | v-for="(device, index) in devices" |
| | | :key="device.deviceId" |
| | | class="device-card" |
| | | shadow="hover" |
| | | :class="{ 'abnormal-device': isDeviceAbnormal(device) }" |
| | | > |
| | | <template #header> |
| | | <div class="device-header"> |
| | | <span class="device-id">{{ device.deviceId }}</span> |
| | | <div class="device-status"> |
| | | <el-icon v-if="device.status === 'æ£å¸¸'" class="status-icon normal-icon" |
| | | ><iconify-icon icon="mdi:check-circle" |
| | | /></el-icon> |
| | | <el-icon v-else class="status-icon abnormal-icon" |
| | | ><iconify-icon icon="mdi:alert-circle" |
| | | /></el-icon> |
| | | <span>{{ device.status }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 宿¶åéæ°æ® --> |
| | | <div class="realtime-data"> |
| | | <div class="basic-info"> |
| | | <span class="supplier">{{ device.supplier }}</span> |
| | | <span class="monitor-time">{{ |
| | | device.monitorTime || new Date().toLocaleString() |
| | | }}</span> |
| | | </div> |
| | | <div class="monitor-values"> |
| | | <div |
| | | class="value-item" |
| | | :class="{ 'abnormal-value': isAbnormal('smokeDensity', device.smokeDensity) }" |
| | | > |
| | | <el-descriptions-item label="飿ºçµæµ" |
| | | >{{ currentDevice.飿ºçµæµ }} A</el-descriptions-item |
| | | <span class="value-label">æ²¹çæµåº¦</span> |
| | | <span class="value">{{ device.smokeDensity }} <span class="unit">mg/m³</span></span> |
| | | </div> |
| | | <div |
| | | class="value-item" |
| | | :class="{ 'abnormal-value': isAbnormal('fanCurrent', device.fanCurrent) }" |
| | | > |
| | | <el-descriptions-item label="ååå¨çµæµ" |
| | | >{{ currentDevice.ååå¨çµæµ }} A</el-descriptions-item |
| | | <span class="value-label">飿ºçµæµ</span> |
| | | <span class="value">{{ device.fanCurrent }} <span class="unit">A</span></span> |
| | | </div> |
| | | <div |
| | | class="value-item" |
| | | :class="{ 'abnormal-value': isAbnormal('purifierCurrent', device.purifierCurrent) }" |
| | | > |
| | | </el-descriptions> |
| | | </el-card> |
| | | </el-col> |
| | | <el-col :span="16"> |
| | | <el-card class="realtime-chart" shadow="hover"> |
| | | <template #header> |
| | | <span>è¿ä¸å°æ¶æ°æ®</span> |
| | | </template> |
| | | <div ref="hourlyChart" class="chart-container"></div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | <span class="value-label">ååå¨çµæµ</span> |
| | | <span class="value">{{ device.purifierCurrent }} <span class="unit">A</span></span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- è¿ä¸å°æ¶æ°æ® --> |
| | | <div class="hourly-charts"> |
| | | <el-popover |
| | | placement="left" |
| | | :width="600" |
| | | trigger="click" |
| | | @show="() => initDeviceCharts(device)" |
| | | > |
| | | <template #reference> |
| | | <div class="chart-header"> |
| | | <span class="date">{{ new Date().toLocaleDateString() }}</span> |
| | | <el-button size="small" type="primary" link> æ¥çè¿ä¸å°æ¶æ°æ® </el-button> |
| | | </div> |
| | | </template> |
| | | <div class="popover-content"> |
| | | <div class="popover-header"> |
| | | <h3>{{ device.deviceId }} è¿ä¸å°æ¶æ°æ®</h3> |
| | | </div> |
| | | <div ref="charts" :key="device.deviceId" class="charts-container"> |
| | | <div class="chart-item"> |
| | | <div class="chart-title">æ²¹çæµåº¦(mg/m³)</div> |
| | | <div ref="smokeChart" :data-device-id="device.deviceId" class="small-chart"></div> |
| | | </div> |
| | | <div class="chart-item"> |
| | | <div class="chart-title">飿ºçµæµ(A)</div> |
| | | <div ref="fanChart" :data-device-id="device.deviceId" class="small-chart"></div> |
| | | </div> |
| | | <div class="chart-item"> |
| | | <div class="chart-title">ååå¨çµæµ(A)</div> |
| | | <div |
| | | ref="purifierChart" |
| | | :data-device-id="device.deviceId" |
| | | class="small-chart" |
| | | ></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-popover> |
| | | </div> |
| | | </el-card> |
| | | </el-space> |
| | | <div v-else class="no-data"> |
| | | <el-empty description="ææ è®¾å¤æ°æ®" /> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | import { Icon } from '@iconify/vue' |
| | | |
| | | export default { |
| | | name: 'RealTimeData', |
| | | components: { |
| | | IconifyIcon: Icon, |
| | | }, |
| | | props: { |
| | | currentDevice: { |
| | | type: Object, |
| | | default: null, |
| | | }, |
| | | hourlyData: { |
| | | devices: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | hourlyChart: null, |
| | | charts: {}, |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.initChart() |
| | | // ä¸éè¦èªå¨åå§åå¾è¡¨ï¼åªå¨å¼¹åºæ¡æ¾ç¤ºæ¶åå§å |
| | | }, |
| | | beforeUnmount() { |
| | | if (this.hourlyChart) { |
| | | this.hourlyChart.dispose() |
| | | } |
| | | Object.values(this.charts).forEach((chart) => { |
| | | if (chart) { |
| | | chart.dispose() |
| | | } |
| | | }) |
| | | }, |
| | | watch: { |
| | | hourlyData() { |
| | | this.updateChart() |
| | | devices: { |
| | | handler(newDevices) { |
| | | // æ¸
餿§å¾è¡¨ |
| | | Object.values(this.charts).forEach((chart) => { |
| | | if (chart) { |
| | | chart.dispose() |
| | | } |
| | | }) |
| | | this.charts = {} |
| | | }, |
| | | deep: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | initChart() { |
| | | this.hourlyChart = echarts.init(this.$refs.hourlyChart) |
| | | this.updateChart() |
| | | initDeviceCharts(device) { |
| | | const deviceId = device.deviceId |
| | | |
| | | window.addEventListener('resize', () => { |
| | | this.hourlyChart.resize() |
| | | // æ¸
é¤è¯¥è®¾å¤çæ§å¾è¡¨ |
| | | Object.keys(this.charts).forEach((key) => { |
| | | if (key.startsWith(deviceId)) { |
| | | this.charts[key].dispose() |
| | | delete this.charts[key] |
| | | } |
| | | }) |
| | | |
| | | this.$nextTick(() => { |
| | | // æ²¹çæµåº¦å¾è¡¨ |
| | | const smokeChartEl = document.querySelector(`[data-device-id="${deviceId}"]`) |
| | | if (smokeChartEl) { |
| | | this.charts[`${deviceId}_smoke`] = echarts.init(smokeChartEl) |
| | | } |
| | | |
| | | // 飿ºçµæµå¾è¡¨ |
| | | const fanChartEl = document.querySelectorAll(`[data-device-id="${deviceId}"]`)[1] |
| | | if (fanChartEl) { |
| | | this.charts[`${deviceId}_fan`] = echarts.init(fanChartEl) |
| | | } |
| | | |
| | | // ååå¨çµæµå¾è¡¨ |
| | | const purifierChartEl = document.querySelectorAll(`[data-device-id="${deviceId}"]`)[2] |
| | | if (purifierChartEl) { |
| | | this.charts[`${deviceId}_purifier`] = echarts.init(purifierChartEl) |
| | | } |
| | | |
| | | this.updateDeviceCharts(device) |
| | | }) |
| | | }, |
| | | updateChart() { |
| | | if (!this.hourlyChart) return |
| | | updateCharts() { |
| | | this.devices.forEach((device) => { |
| | | this.updateDeviceCharts(device) |
| | | }) |
| | | }, |
| | | updateDeviceCharts(device) { |
| | | const deviceId = device.deviceId |
| | | const deviceHourlyData = device.hourlyData || [] |
| | | |
| | | const option = { |
| | | const _baseOption = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985', |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ['æ²¹çæµåº¦', '飿ºçµæµ', 'ååå¨çµæµ'], |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | left: '0%', |
| | | right: '0%', |
| | | top: '10%', |
| | | bottom: '0%', |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: this.hourlyData.map((item) => item.time), |
| | | data: deviceHourlyData.map((item) => item.time), |
| | | axisLabel: { |
| | | fontSize: 10, |
| | | }, |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: 'æ²¹çæµåº¦ (mg/m³)', |
| | | position: 'left', |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: 'çµæµ (A)', |
| | | position: 'right', |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | | name: 'æ²¹çæµåº¦', |
| | | type: 'line', |
| | | data: this.hourlyData.map((item) => parseFloat(item.æ²¹çæµåº¦)), |
| | | yAxisIndex: 0, |
| | | }, |
| | | { |
| | | name: '飿ºçµæµ', |
| | | type: 'line', |
| | | data: this.hourlyData.map((item) => parseFloat(item.飿ºçµæµ)), |
| | | yAxisIndex: 1, |
| | | }, |
| | | { |
| | | name: 'ååå¨çµæµ', |
| | | type: 'line', |
| | | data: this.hourlyData.map((item) => parseFloat(item.ååå¨çµæµ)), |
| | | yAxisIndex: 1, |
| | | }, |
| | | ], |
| | | } |
| | | |
| | | this.hourlyChart.setOption(option) |
| | | // æ´æ°æ²¹çæµåº¦å¾è¡¨ |
| | | if (this.charts[`${deviceId}_smoke`]) { |
| | | const smokeOption = { |
| | | ..._baseOption, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'mg/m³', |
| | | // nameLocation: 'middle', |
| | | // nameGap: 30, |
| | | axisLabel: { |
| | | fontSize: 10, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'æ²¹çæµåº¦', |
| | | type: 'line', |
| | | data: deviceHourlyData.map((item) => parseFloat(item.smokeDensity)), |
| | | smooth: true, |
| | | }, |
| | | ], |
| | | } |
| | | this.charts[`${deviceId}_smoke`].setOption(smokeOption) |
| | | } |
| | | |
| | | // æ´æ°é£æºçµæµå¾è¡¨ |
| | | if (this.charts[`${deviceId}_fan`]) { |
| | | const fanOption = { |
| | | ..._baseOption, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'A', |
| | | // nameLocation: 'middle', |
| | | // nameGap: 30, |
| | | axisLabel: { |
| | | fontSize: 10, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '飿ºçµæµ', |
| | | type: 'line', |
| | | data: deviceHourlyData.map((item) => parseFloat(item.fanCurrent)), |
| | | smooth: true, |
| | | }, |
| | | ], |
| | | } |
| | | this.charts[`${deviceId}_fan`].setOption(fanOption) |
| | | } |
| | | |
| | | // æ´æ°ååå¨çµæµå¾è¡¨ |
| | | if (this.charts[`${deviceId}_purifier`]) { |
| | | const purifierOption = { |
| | | ..._baseOption, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'A', |
| | | // nameLocation: 'middle', |
| | | // nameGap: 30, |
| | | axisLabel: { |
| | | fontSize: 10, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'ååå¨çµæµ', |
| | | type: 'line', |
| | | data: deviceHourlyData.map((item) => parseFloat(item.purifierCurrent)), |
| | | smooth: true, |
| | | }, |
| | | ], |
| | | } |
| | | this.charts[`${deviceId}_purifier`].setOption(purifierOption) |
| | | } |
| | | }, |
| | | isDeviceAbnormal(device) { |
| | | return ( |
| | | this.isAbnormal('smokeDensity', device.smokeDensity) || |
| | | this.isAbnormal('fanCurrent', device.fanCurrent) || |
| | | this.isAbnormal('purifierCurrent', device.purifierCurrent) |
| | | ) |
| | | }, |
| | | isAbnormal(type, value) { |
| | | // è¿éå¯ä»¥æ ¹æ®å®é
æ
åµå®ä¹å¼å¸¸å¼å¤æé»è¾ |
| | | const thresholds = { |
| | | smokeDensity: 10, |
| | | fanCurrent: 5, |
| | | purifierCurrent: 3, |
| | | } |
| | | return parseFloat(value) > (thresholds[type] || 0) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | <style scoped lang="scss"> |
| | | .section { |
| | | margin-bottom: 20px; |
| | | } |
| | |
| | | align-items: center; |
| | | } |
| | | |
| | | .chart-container { |
| | | height: 300px; |
| | | .device-card { |
| | | // width: 100%; |
| | | margin-bottom: 20px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .device-card:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .abnormal-device { |
| | | border-bottom: 4px solid #f56c6c; |
| | | } |
| | | |
| | | .device-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .device-id { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .device-status { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 5px; |
| | | } |
| | | |
| | | .status-icon { |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .normal-icon { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .abnormal-icon { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | .realtime-data { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .basic-info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 15px; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .supplier { |
| | | font-style: italic; |
| | | } |
| | | |
| | | .monitor-time { |
| | | font-family: monospace; |
| | | } |
| | | |
| | | .monitor-values { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .value-item { |
| | | flex: 1; |
| | | width: 60px; |
| | | text-align: center; |
| | | padding: 10px; |
| | | border-radius: 4px; |
| | | background-color: #f9f9f9; |
| | | border: 1px solid transparent; |
| | | } |
| | | |
| | | .value-label { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .value { |
| | | display: block; |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .unit { |
| | | font-size: 12px; |
| | | font-weight: normal; |
| | | color: #909399; |
| | | } |
| | | |
| | | .abnormal-value { |
| | | background-color: #fef0f0; |
| | | border: 1px solid #fbc4c4; |
| | | } |
| | | |
| | | .abnormal-value .value { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | .hourly-charts { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .chart-header { |
| | | margin-top: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 5px 0; |
| | | } |
| | | |
| | | .popover-content { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .popover-header { |
| | | margin-bottom: 15px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding-bottom: 10px; |
| | | } |
| | | |
| | | .popover-header h3 { |
| | | margin: 0; |
| | | font-size: 14px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .date { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | font-family: monospace; |
| | | } |
| | | |
| | | .charts-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 2px; |
| | | } |
| | | |
| | | .chart-item { |
| | | background-color: #f9f9f9; |
| | | border-radius: 4px; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .chart-title { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .small-chart { |
| | | height: 120px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .monitor-values { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .value-item { |
| | | width: 100%; |
| | | } |
| | | |
| | | .small-chart { |
| | | height: 100px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <el-row ref="searchRef"> |
| | | <FYSearchBar @search="onSearch"> |
| | | <template #options v-if="$slots.options"> |
| | |
| | | cellClassName: Function || String, |
| | | pagination: { |
| | | type: Boolean, |
| | | default: true |
| | | default: true, |
| | | }, |
| | | // '' | 'small' | 'default' | 'large' |
| | | size: { |
| | | type: String, |
| | | default: 'default' |
| | | default: 'default', |
| | | }, |
| | | data: { |
| | | type: Array, |
| | | default: () => [] |
| | | default: () => [], |
| | | }, |
| | | totalCount: { |
| | | type: Number, |
| | | default: 0 |
| | | default: 0, |
| | | }, |
| | | defaultPageSize: { |
| | | type: Number, |
| | | default: 20 |
| | | default: 20, |
| | | }, |
| | | // é¢å¤çé«åº¦ï¼ç¨äºè®¡ç®è¡¨æ ¼é«åº¦ |
| | | extraHeight: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | default: 0, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | |
| | | currentPage: 1, |
| | | pageSize: this.defaultPageSize, |
| | | loading: false, |
| | | fontSize: 'default' |
| | | }; |
| | | fontSize: 'default', |
| | | } |
| | | }, |
| | | emits: ['search', 'cellClick', 'tablePaste', 'sortChange'], |
| | | watch: { |
| | | currentPage(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.onSearch(); |
| | | this.onSearch() |
| | | } |
| | | }, |
| | | pageSize(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.onSearch(); |
| | | this.onSearch() |
| | | } |
| | | }, |
| | | size: { |
| | | handler(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.fontSize = nValue; |
| | | this.fontSize = nValue |
| | | } |
| | | }, |
| | | immediate: true |
| | | immediate: true, |
| | | }, |
| | | data(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.tableData = nValue; |
| | | this.tableData = nValue |
| | | } |
| | | }, |
| | | totalCount(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.total = nValue; |
| | | this.total = nValue |
| | | } |
| | | }, |
| | | extraHeight: { |
| | | handler(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.tableHeight = this.calcTableHeight(); |
| | | this.tableHeight = this.calcTableHeight() |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }, |
| | | computed: {}, |
| | | methods: { |
| | |
| | | * åè°å½æ°æ¥æ¶ä¸ä¸ªå¯¹è±¡ï¼å
æ¬è¡¨æ ¼æ°æ®æ°ç»dataåæ°æ®æ»æ°total |
| | | */ |
| | | onSearch() { |
| | | this.loading = true; |
| | | this.loading = true |
| | | this.$emit( |
| | | 'search', |
| | | { |
| | | currentPage: this.currentPage, |
| | | pageSize: this.pageSize |
| | | pageSize: this.pageSize, |
| | | }, |
| | | (res) => { |
| | | if (res) { |
| | | if (res.data) { |
| | | this.tableData = res.data; |
| | | this.tableData = res.data |
| | | } |
| | | if (res.total) { |
| | | this.total = res.total; |
| | | this.total = res.total |
| | | } |
| | | } |
| | | this.loading = false; |
| | | this.doLayout(); |
| | | } |
| | | ); |
| | | this.loading = false |
| | | this.doLayout() |
| | | }, |
| | | ) |
| | | }, |
| | | calcTableHeight() { |
| | | const h1 = this.$refs.searchRef.$el.offsetHeight; |
| | | const h2 = this.$refs.paginationRef |
| | | ? this.$refs.paginationRef.$el.offsetHeight |
| | | : 0; |
| | | const h3 = this.$refs.expandRef.$el.offsetHeight; |
| | | const h4 = this.$refs.expand2Ref.offsetHeight; |
| | | const h1 = this.$refs.searchRef.$el.offsetHeight |
| | | const h2 = this.$refs.paginationRef ? this.$refs.paginationRef.$el.offsetHeight : 0 |
| | | const h3 = this.$refs.expandRef.$el.offsetHeight |
| | | const h4 = this.$refs.expand2Ref.offsetHeight |
| | | |
| | | const h = h1 + h2 + h3 + h4 + this.extraHeight; |
| | | return this.contentMaxHeight.value - h + 'px'; |
| | | const h = h1 + h2 + h3 + h4 + this.extraHeight |
| | | return this.contentMaxHeight - h + 'px' |
| | | // return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; |
| | | }, |
| | | tableRowClassName({ row }) { |
| | | if (this.rowClassName) { |
| | | if (typeof this.rowClassName == 'string') { |
| | | return this.rowClassName; |
| | | return this.rowClassName |
| | | } else if (typeof this.rowClassName == 'function') { |
| | | return this.rowClassName({ row }); |
| | | return this.rowClassName({ row }) |
| | | } |
| | | } else { |
| | | return row.extension1 != '0' ? 'online-row' : 'offline-row'; |
| | | return row.extension1 != '0' ? 'online-row' : 'offline-row' |
| | | } |
| | | }, |
| | | cellClick(row, column, cell, event) { |
| | | this.$emit('cellClick', row, column, cell, event); |
| | | this.$emit('cellClick', row, column, cell, event) |
| | | }, |
| | | handlePaste(event) { |
| | | this.$emit('tablePaste', event); |
| | | this.$emit('tablePaste', event) |
| | | }, |
| | | doLayout() { |
| | | this.$refs.tableRef.doLayout(); |
| | | this.$refs.tableRef.doLayout() |
| | | }, |
| | | handleSortChange({ column, prop, order }) { |
| | | this.$emit('sortChange', { column, prop, order }); |
| | | this.$emit('sortChange', { column, prop, order }) |
| | | }, |
| | | clearSort() { |
| | | this.$refs.tableRef.clearSort(); |
| | | } |
| | | this.$refs.tableRef.clearSort() |
| | | }, |
| | | }, |
| | | mounted() { |
| | | setTimeout(() => { |
| | | this.tableHeight = this.calcTableHeight(); |
| | | }, 100); |
| | | this.onSearch(); |
| | | } |
| | | }; |
| | | this.tableHeight = this.calcTableHeight() |
| | | }, 100) |
| | | this.onSearch() |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç¯ä¿¡ç è½¬æ¢ |
| | | |
| | | function envCreditCode(score) { |
| | | const s = parseInt(score) |
| | | if (s <= 59) { |
| | | return { |
| | | value: 2, |
| | | name: '红ç ', |
| | | color: '#db2828' |
| | | }; |
| | | } else if (s <= 89) { |
| | | return { |
| | | value: 1, |
| | | name: 'é»ç ', |
| | | color: '#f7a62c' |
| | | }; |
| | | } else { |
| | | return { |
| | | value: 0, |
| | | name: '绿ç ', |
| | | color: '#21ba45' |
| | | }; |
| | | } |
| | | } |
| | | |
| | | export { envCreditCode }; |
| | |
| | | { |
| | | name: 'auto-evalution', |
| | | path: 'auto-evalution', |
| | | component: () => import('@/views/analysis/evalution/AutoEvalution.vue'), |
| | | component: () => import('@/views/analysis/evalution/EvalutationRecord.vue'), |
| | | }, |
| | | { |
| | | name: 'huanxincode-manage', |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FYPageHeader title="è¯ä¼°ç»æè¯¦æ
"></FYPageHeader> |
| | | <el-row v-for="item in evaluation" :key="item.id"> </el-row> |
| | | <div class="btns"> |
| | | <el-button type="primary" @click="submit" :disabled="!isUpdated">æäº¤</el-button> |
| | | </div> |
| | | <el-table |
| | | class="table-style" |
| | | :data="tableData" |
| | | ref="tableRef" |
| | | :span-method="objectSpanMethod" |
| | | table-layout="fixed" |
| | | :cell-style="cellClassName" |
| | | border |
| | | stripe |
| | | > |
| | | <el-table-column v-slot="scope" prop="one_title" label="ä¸çº§ææ " width="200"> |
| | | <!-- <el-checkbox v-model="scope.row.one_select" @change="checked => oneSelectChange(checked, scope.row)">{{ scope.row.one_title }}</el-checkbox> --> |
| | | </el-table-column> |
| | | <el-table-column prop="one_score" label="åå¼" width="55" /> |
| | | <el-table-column prop="one_maxScore" label="æå¤§åå¼" width="90" /> |
| | | <el-table-column v-slot="scope" prop="two_title" label="äºçº§ææ " width="200"> |
| | | <!-- <el-checkbox v-model="scope.row.two_select" @change="checked => twoSelectChange(checked, scope.row)">{{ scope.row.two_title }}</el-checkbox> --> |
| | | </el-table-column> |
| | | <el-table-column prop="two_score" label="åå¼" width="55" /> |
| | | <el-table-column prop="two_maxScore" label="æå¤§åå¼" width="90" /> |
| | | <el-table-column v-slot="scope" prop="three_title" label="å
·ä½é®é¢"> |
| | | <el-checkbox |
| | | v-model="scope.row.three_select" |
| | | @change="(checked) => threeSelectChange(checked, scope.row)" |
| | | >{{ scope.row.three_title }}</el-checkbox |
| | | > |
| | | </el-table-column> |
| | | <el-table-column prop="three_score" label="å项æ£å" width="90" /> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script> |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | import { useFetchData } from '@/composables/fetchData'; |
| | | import { ElMessage } from 'element-plus'; |
| | | export default { |
| | | setup() { |
| | | const { loading, fetchData } = useFetchData(); |
| | | return { loading, fetchData }; |
| | | }, |
| | | data() { |
| | | return { |
| | | tableData: [], |
| | | evaluation: [], |
| | | subTaskId: '', |
| | | isUpdated: false |
| | | }; |
| | | }, |
| | | created() { |
| | | // // watch è·¯ç±çåæ°ï¼ä»¥ä¾¿å次è·åæ°æ® |
| | | // this.$watch( |
| | | // () => this.$route.params, |
| | | // () => { |
| | | // this.getScore(); |
| | | // }, |
| | | // // ç»ä»¶å建å®åè·åæ°æ®ï¼ |
| | | // // æ¤æ¶ data å·²ç»è¢« observed äº |
| | | // { immediate: true } |
| | | // ); |
| | | }, |
| | | computed: { |
| | | // 已被å¾éçitem |
| | | checkedUpdatedList() { |
| | | var list = []; |
| | | for (let index = 0; index < this.tableData.length; index++) { |
| | | const element = this.tableData[index]; |
| | | if (element.three_select) { |
| | | list.push(element.three_id); |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getList(); |
| | | }, |
| | | methods: { |
| | | // æ¯ä¸ä¸ªåå
æ ¼çclass |
| | | cellClassName({ row, column, rowIndex, columnIndex }) { |
| | | if (column.property === 'one_score') { |
| | | if (row.one_score < 0) { |
| | | return { color: 'red' }; |
| | | } |
| | | } else if (column.property === 'two_score') { |
| | | if (row.two_score < 0) { |
| | | return { color: 'red' }; |
| | | } |
| | | } else if (column.property === 'three_score') { |
| | | if (row.three_score < 0) { |
| | | return { color: 'red' }; |
| | | } |
| | | } |
| | | return { color: 'black' }; |
| | | }, |
| | | /** æä»· */ |
| | | submit() { |
| | | evaluateApi |
| | | .updateScore({ |
| | | subTaskId: this.subTaskId, |
| | | itemList: this.checkedUpdatedList |
| | | }) |
| | | .then((res) => { |
| | | if (res.success) { |
| | | ElMessage({ |
| | | message: res.message, |
| | | type: 'success' |
| | | }); |
| | | }else { |
| | | ElMessage({ |
| | | message: res.message, |
| | | type: 'error' |
| | | }); |
| | | } |
| | | }); |
| | | setTimeout(() => { |
| | | this.getList(); |
| | | }, 1000); |
| | | }, |
| | | /** éè¿ç¬¬ä¸çº§çidè·åä¸çº§ä»¥å顶级 */ |
| | | getSuperObjByThreeId(threeId, list, path = []) { |
| | | for (let index = 0; index < list.length; index++) { |
| | | const item = list[index]; |
| | | // å°å½å项添å å°è·¯å¾ä¸ |
| | | const currentPath = path.concat(item); |
| | | if (item.id === threeId) { |
| | | // 妿æ¾å°å¹é
ç idï¼è¿åè·¯å¾æ°ç» |
| | | return currentPath; |
| | | } |
| | | const subList = item.subList; |
| | | if (subList) { |
| | | // é彿¥æ¾åå表 |
| | | const result = this.getSuperObjByThreeId(threeId, subList, currentPath); |
| | | if (result) { |
| | | return result; // 妿æ¾å°å¹é
ç idï¼è¿åç»æ |
| | | } |
| | | } |
| | | } |
| | | return null; // å¦ææ²¡ææ¾å°å¹é
ç idï¼è¿å null |
| | | }, |
| | | /** é®é¢éæ©æ¡ */ |
| | | threeSelectChange(isSelect, row) { |
| | | this.isUpdated = true; |
| | | }, |
| | | /** ååå¹¶ */ |
| | | objectSpanMethod({ row, column, rowIndex, columnIndex }) { |
| | | if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2) { |
| | | // 对 ä¸çº§ææ åè¿è¡åå¹¶ |
| | | let rowSpan = 1; |
| | | for (let i = rowIndex + 1; i < this.tableData.length; i++) { |
| | | if (this.tableData[i].one_id === row.one_id) { |
| | | rowSpan++; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | if (rowIndex > 0) { |
| | | if (this.tableData[rowIndex - 1].one_id === row.one_id) { |
| | | return { rowspan: 0, colspan: 0 }; |
| | | } |
| | | } |
| | | return { rowspan: rowSpan, colspan: 1 }; |
| | | } else if (columnIndex === 3 || columnIndex === 4 || columnIndex === 5) { |
| | | // 对 äºçº§ææ åè¿è¡åå¹¶ï¼ç¡®ä¿ ä¸çº§ææ 䏿 · |
| | | let rowSpan = 1; |
| | | for (let i = rowIndex + 1; i < this.tableData.length; i++) { |
| | | if (this.tableData[i].one_id === row.one_id && this.tableData[i].two_id === row.two_id) { |
| | | rowSpan++; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | if (rowIndex > 0) { |
| | | if ( |
| | | this.tableData[rowIndex - 1].one_id === row.one_id && |
| | | this.tableData[rowIndex - 1].two_id === row.two_id |
| | | ) { |
| | | return { rowspan: 0, colspan: 0 }; |
| | | } |
| | | } |
| | | return { rowspan: rowSpan, colspan: 1 }; |
| | | } |
| | | }, |
| | | /** å¯¹è±¡å±æ§æ·è´ */ |
| | | deepCopyWithPrefix(obj, target, prefix) { |
| | | // ç¡®ä¿ target æ¯ä¸ä¸ªå¯¹è±¡ |
| | | if (typeof target !== 'object' || target === null) { |
| | | target = {}; |
| | | } |
| | | |
| | | // éåå¯¹è±¡çææå±æ§ |
| | | for (const key in obj) { |
| | | if (obj.hasOwnProperty(key)) { |
| | | // ä¸ºå±æ§åå ä¸åç¼ |
| | | const newKey = prefix + key; |
| | | // 妿屿§å¼æ¯å¯¹è±¡ï¼åéå½å¤å¶ |
| | | if (typeof obj[key] === 'object' && obj[key] !== null) { |
| | | this.deepCopyWithPrefix(obj[key], (target[newKey] = {}), prefix); |
| | | } else { |
| | | // å¦åç´æ¥å¤å¶å±æ§ |
| | | target[newKey] = obj[key]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return target; |
| | | }, |
| | | /** @param data åè¡¨æ°æ® */ |
| | | genTableData(data) { |
| | | var result = []; |
| | | if (data) { |
| | | for (let i = 0; i < data.length; i++) { |
| | | const firstLevelItem = data[i]; |
| | | var secondLevel = firstLevelItem.subList; |
| | | if (secondLevel) { |
| | | for (let j = 0; j < secondLevel.length; j++) { |
| | | const secondLevelItem = secondLevel[j]; |
| | | var thirdLevel = secondLevelItem.subList; |
| | | if (thirdLevel) { |
| | | for (let q = 0; q < thirdLevel.length; q++) { |
| | | const thirdLevelItem = thirdLevel[q]; |
| | | var item = {}; |
| | | this.deepCopyWithPrefix(firstLevelItem, item, 'one_'); |
| | | this.deepCopyWithPrefix(secondLevelItem, item, 'two_'); |
| | | this.deepCopyWithPrefix(thirdLevelItem, item, 'three_'); |
| | | result.push(item); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | }, |
| | | getList() { |
| | | this.subTaskId = this.$route.params.subTaskId; |
| | | evaluateApi.fetchItemEvaluation(this.subTaskId).then((res) => { |
| | | this.isUpdated = false; |
| | | this.tableData = this.genTableData(res.data.details); |
| | | }); |
| | | }, |
| | | onSearch(page, func) { |
| | | evaluateApi.fetchItemEvaluation(this.$route.params.subTaskId).then((res) => { |
| | | if (typeof func === 'function') { |
| | | // å¤çæ°æ® |
| | | var data = this.genTableData(res.data); |
| | | |
| | | func({ data: data }); |
| | | } |
| | | this.tableData = this.genTableData(res.data); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .table-style { |
| | | width: 100%; |
| | | padding-bottom: 30px; |
| | | } |
| | | .btns { |
| | | padding-bottom: 10px; |
| | | padding-right: 30px; |
| | | display: flex; |
| | | flex-direction: row-reverse; |
| | | } |
| | | /* æ¹åè¡¨æ ¼å
åå
æ ¼è¾¹æ¡é¢è² */ |
| | | .el-table { |
| | | --el-table-border-color: #000000; |
| | | } |
| | | .red-cell { |
| | | background-color: red; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FYTable |
| | | @search="onSearch" |
| | | :pagination="false" |
| | | ref="tableRef" |
| | | @cell-click="cellClick" |
| | | :cell-class-name="cellClassName" |
| | | @table-paste="handlePaste" |
| | | @sort-change="handleSortChange" |
| | | > |
| | | <template #options> |
| | | <!-- åºå¿ --> |
| | | <FYOptionLocation |
| | | :allOption="false" |
| | | :level="3" |
| | | :checkStrictly="false" |
| | | v-model:value="formSearch.locations" |
| | | ></FYOptionLocation> |
| | | <!-- åºæ¯ç±»å --> |
| | | <FYOptionScene |
| | | :allOption="false" |
| | | :type="2" |
| | | v-model:value="formSearch.scenetype" |
| | | ></FYOptionScene> |
| | | <!-- æ¶é´ --> |
| | | <FYOptionTime |
| | | :initValue="false" |
| | | type="month" |
| | | v-model:value="formSearch.time" |
| | | ></FYOptionTime> |
| | | </template> |
| | | <template #buttons> |
| | | <!-- <el-button icon="Download" size="default" type="success" @click="download" |
| | | >è§èæ§è¯ä¼°ä¸åææ¥å</el-button |
| | | > --> |
| | | <CompReport |
| | | :locations="formSearch.locations" |
| | | :scenetype="formSearch.scenetype" |
| | | :time="formSearch.time" |
| | | ></CompReport> |
| | | </template> |
| | | |
| | | <template #options-expand> |
| | | <el-form :inline="true"> |
| | | <CompQuickSet @quick-set="setOptions"></CompQuickSet> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <template #table-column="{ size }"> |
| | | <el-table-column |
| | | fixed="left" |
| | | sortable="custom" |
| | | prop="sceneIndex" |
| | | label="ç¼å·" |
| | | width="80" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="sceneName" |
| | | :show-overflow-tooltip="true" |
| | | label="åç§°" |
| | | width="300" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="subTaskTime" |
| | | label="å·¡æ¥æ¥æ" |
| | | width="110" |
| | | sortable="custom" |
| | | :formatter="timeFormat" |
| | | /> |
| | | <el-table-column |
| | | prop="evaluation.resultscorebef" |
| | | label="å¾å" |
| | | width="90" |
| | | sortable="custom" |
| | | /> |
| | | <el-table-column |
| | | prop="evaluation.resultscorebef" |
| | | label="ç¯ä¿¡ç " |
| | | width="100" |
| | | > |
| | | <template #default="{ row }"> |
| | | <span :style="`color: ${toCode(row).color};`">{{ |
| | | toCode(row).name |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="dname" label="åºå¿" width="90" /> |
| | | <el-table-column |
| | | prop="tname" |
| | | label="è¡é" |
| | | width="110" |
| | | :filters="townFilters" |
| | | :filter-method="filterHandler" |
| | | /> |
| | | <el-table-column prop="evaluation.scenseaddress" label="å°å" /> |
| | | <!-- <el-table-column prop="biArea" label="éä¸åº" width="110" /> |
| | | <el-table-column prop="biManagementCompany" label="ç©ä¸" min-width="110"/> --> |
| | | <el-table-column |
| | | v-if="scoreShow" |
| | | fixed="right" |
| | | align="right" |
| | | label="çæµæ°æ®è¶
æ " |
| | | width="160" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-input :size="size" v-model="row.score1" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | v-if="scoreShow" |
| | | fixed="right" |
| | | align="right" |
| | | label="çæµæ°æ®è¶
åºæåå¼" |
| | | width="160" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-input :size="size" v-model="row.score2" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" align="right" label="æä½" width="160"> |
| | | <template #header> |
| | | <el-button |
| | | v-show="!scoreShow" |
| | | icon="ArrowLeft" |
| | | size="small" |
| | | type="success" |
| | | @click="scoreShow = true" |
| | | >çæµæ°æ®å¾å</el-button |
| | | > |
| | | <el-button |
| | | v-show="scoreShow" |
| | | size="small" |
| | | type="primary" |
| | | @click="updateMultipleScore" |
| | | :loading="updateLoading" |
| | | >ä¸ä¼ </el-button |
| | | > |
| | | <el-button |
| | | v-show="scoreShow" |
| | | size="small" |
| | | type="error" |
| | | @click="scoreShow = false" |
| | | >åæ¶</el-button |
| | | > |
| | | </template> |
| | | <template #default="{ row }"> |
| | | <el-button type="primary" size="small" @click="editRow(row)" |
| | | >æ¥ç</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </template> |
| | | </FYTable> |
| | | </template> |
| | | |
| | | <script> |
| | | import dayjs from 'dayjs'; |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | import { envCreditCode } from '@/constants/index'; |
| | | import CompReport from './components/CompReport.vue'; |
| | | import { useTablePaste } from '@/composables/tablePaste'; |
| | | import { useCloned } from '@vueuse/core'; |
| | | import { useMessageBoxTip } from '@/composables/messageBox'; |
| | | |
| | | export default { |
| | | setup() { |
| | | const { |
| | | cellClick, |
| | | cellClassName, |
| | | handlePaste, |
| | | setTableData, |
| | | addRefreshEvent, |
| | | tableData |
| | | } = useTablePaste({ |
| | | score1: 8, |
| | | score2: 9 |
| | | }); |
| | | return { |
| | | cellClick, |
| | | cellClassName, |
| | | handlePaste, |
| | | setTableData, |
| | | addRefreshEvent, |
| | | tableData |
| | | }; |
| | | }, |
| | | components: { CompReport }, |
| | | data() { |
| | | return { |
| | | formSearch: { |
| | | locations: {}, |
| | | scenetype: {}, |
| | | time: dayjs().add(-1, 'M').date(1).toDate() |
| | | }, |
| | | townFilters: [], |
| | | // åå§æ°æ®ï¼ç¨äºæåºåæ¶å |
| | | orginData: [], |
| | | evaluationRule: undefined, |
| | | evaluationSubRule: undefined, |
| | | //çæµæ°æ®è§ååç§° |
| | | ruleName: { |
| | | score1: { |
| | | id: undefined, |
| | | name: 'çæµæ°æ®åºç°åæ¥å以䏿æè¶
æ ' |
| | | }, |
| | | score2: { |
| | | id: undefined, |
| | | name: 'çæµæ°æ®æåå¼è¶
åºåæåå¼20%ä»¥ä¸ææ°æ®ææ¾å¼å¸¸' |
| | | } |
| | | }, |
| | | scoreShow: false, |
| | | updateLoading: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | area() { |
| | | const { locations, scenetype, time } = this.formSearch; |
| | | return { |
| | | provincecode: locations.pCode, |
| | | provincename: locations.pName, |
| | | citycode: locations.cCode, |
| | | cityname: locations.cName, |
| | | districtcode: locations.dCode, |
| | | districtname: locations.dName, |
| | | starttime: dayjs(time).format('YYYY-MM-DD HH:mm:ss'), |
| | | scensetypeid: scenetype.value |
| | | }; |
| | | } |
| | | }, |
| | | methods: { |
| | | // _getParam() { |
| | | // const { locations, scenetype, time } = this.formSearch; |
| | | // return { |
| | | // provincecode: locations.pCode, |
| | | // provincename: locations.pName, |
| | | // citycode: locations.cCode, |
| | | // cityname: locations.cName, |
| | | // districtcode: locations.dCode, |
| | | // districtname: locations.dName, |
| | | // starttime: dayjs(time).format('YYYY-MM-DD HH:mm:ss'), |
| | | // scensetypeid: scenetype.value |
| | | // }; |
| | | // }, |
| | | editRow(row) { |
| | | this.$router.push(`evalutationEdit/${row.subTaskId}`); |
| | | }, |
| | | setOptions(param) { |
| | | this.formSearch.locations = param.locations; |
| | | this.formSearch.scenetype = param.scenetype; |
| | | this.formSearch.sourceType = param.sourceType; |
| | | this.$refs.tableRef.onSearch(); |
| | | }, |
| | | onSearch(page, func) { |
| | | this.$refs.tableRef.clearSort(); |
| | | this.fetchEvaluationRule(this.area).then(() => { |
| | | evaluateApi.fetchAutoEvaluation(this.area).then((res) => { |
| | | if (res.data) { |
| | | this.tableData = res.data; |
| | | this.tableData.forEach((v) => { |
| | | // å°åå§çå¾åå±ç¤ºå°è¡¨æ ¼ä¸ |
| | | if (v.itemEvaluations) { |
| | | for (const key in this.ruleName) { |
| | | const value = this.ruleName[key]; |
| | | const itemEva = v.itemEvaluations.find((ie) => { |
| | | return ie.esrguid == value.id && ie.extension1 == 'true'; |
| | | }); |
| | | if (itemEva) { |
| | | v[key] = itemEva.value; |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | this.orginData = useCloned(this.tableData).cloned; |
| | | this.getFilters(res.data); |
| | | if (typeof func === 'function') { |
| | | func({ data: this.tableData }); |
| | | } |
| | | } else { |
| | | this.tableData = []; |
| | | this.orginData = []; |
| | | if (typeof func === 'function') { |
| | | func({ data: this.tableData }); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | fetchEvaluationRule() { |
| | | const param = { |
| | | // èªå¨è¯ä¼°ç±»å |
| | | taskTypeId: 99, |
| | | ...this.area |
| | | }; |
| | | // è·åè¯ä¼°æ»è§å |
| | | return evaluateApi.fetchEvaluationRule(param).then((res) => { |
| | | if (res.data.length > 0) { |
| | | this.evaluationRule = res.data[0]; |
| | | // è·åå
·ä½åè§å |
| | | return evaluateApi |
| | | .getSubRules(this.evaluationRule.guid) |
| | | .then((res) => { |
| | | this.evaluationSubRule = res.data; |
| | | // æ¥æ¾å¯å¯¼å
¥å¾åçè§åid |
| | | for (const key in this.ruleName) { |
| | | const value = this.ruleName[key]; |
| | | const subrule = this.evaluationSubRule.find((v) => { |
| | | return v.itemname == value.name; |
| | | }); |
| | | if (subrule) { |
| | | value.id = subrule.guid; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // æ¹éæ´æ°çæµæ°æ®å¾å |
| | | updateMultipleScore() { |
| | | this.updateLoading = true; |
| | | useMessageBoxTip({ |
| | | confirmMsg: 'æ¯å¦ä¸ä¼ çæµæ°æ®å¾å', |
| | | confirmTitle: 'ä¸ä¼ çæµæ°æ®å¾å', |
| | | onConfirm: async () => { |
| | | if (this.evaluationRule) { |
| | | const subTaskEvaList = this.tableData.map((v) => { |
| | | const subRule = []; |
| | | for (const key in this.ruleName) { |
| | | const value = this.ruleName[key]; |
| | | subRule.push({ |
| | | id: value.id, |
| | | selected: v[key] && (v[key] + '').trim() != '' |
| | | }); |
| | | } |
| | | return { |
| | | subTaskId: v.subTaskId, |
| | | ruleId: this.evaluationRule.guid, |
| | | subRule |
| | | }; |
| | | }); |
| | | const param = { |
| | | ...this.area, |
| | | subTaskEvaList |
| | | }; |
| | | |
| | | return await evaluateApi |
| | | .updateMultipleScore(param) |
| | | .finally(() => (this.updateLoading = false)); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | // è§èæ§è¯ä¼°ä¸åææ¥ååå°çæä»»å¡ |
| | | download() { |
| | | evaluateApi.downloadAutoEvaluation(this.area).then((res) => { |
| | | if (res == false) { |
| | | // æªä¸è½½ææ¡£ï¼èæ¯å¼å¯äºææ¡£çæåå°ä»»å¡ |
| | | this.$parent; |
| | | } |
| | | }); |
| | | }, |
| | | // 导åºè¡¨æ ¼ä¸ºexcelæ ¼å¼ |
| | | exportExcel() {}, |
| | | getFilters(data) { |
| | | const townList = []; |
| | | data.forEach((e) => { |
| | | if (townList.indexOf(e.tname) == -1) { |
| | | townList.push(e.tname); |
| | | } |
| | | }); |
| | | this.townFilters = townList.map((v) => { |
| | | return { text: v, value: v }; |
| | | }); |
| | | }, |
| | | toCode(row, column) { |
| | | if (row.evaluation) { |
| | | return envCreditCode(row.evaluation.resultscorebef); |
| | | } else { |
| | | return ''; |
| | | } |
| | | }, |
| | | timeFormat(row, column) { |
| | | const time = row.subTaskTime; |
| | | if (time) { |
| | | return dayjs(time).format('MM-DD'); |
| | | } else { |
| | | return ''; |
| | | } |
| | | }, |
| | | filterHandler(value, row, column) { |
| | | const property = column['property']; |
| | | return row[property] === value; |
| | | }, |
| | | sortScore(a, b) { |
| | | const s1 = a.evaluation ? parseInt(a.evaluation.resultscorebef) : 0; |
| | | const s2 = b.evaluation ? parseInt(b.evaluation.resultscorebef) : 0; |
| | | return s1 - s2; |
| | | }, |
| | | handleSortChange({ column, prop, order }) { |
| | | console.log(column, prop, order); |
| | | if (order == null) { |
| | | this.orginData.forEach((e, i) => { |
| | | this.tableData[i] = e; |
| | | }); |
| | | } else if (prop == 'evaluation.resultscorebef') { |
| | | this.tableData.sort((a, b) => { |
| | | const s1 = a.evaluation ? parseInt(a.evaluation.resultscorebef) : 0; |
| | | const s2 = b.evaluation ? parseInt(b.evaluation.resultscorebef) : 0; |
| | | if (order == 'ascending') { |
| | | return s1 - s2; |
| | | } else if (order == 'descending') { |
| | | return s2 - s1; |
| | | } |
| | | }); |
| | | } else if (prop == 'sceneIndex') { |
| | | this.tableData.sort((a, b) => { |
| | | if (order == 'ascending') { |
| | | if (a.sceneIndex === b.sceneIndex) { |
| | | return a.subTaskTime > b.subTaskTime ? 1 : -1; |
| | | } else { |
| | | return a.sceneIndex - b.sceneIndex; |
| | | } |
| | | } else if (order == 'descending') { |
| | | if (a.sceneIndex === b.sceneIndex) { |
| | | return b.subTaskTime > a.subTaskTime ? 1 : -1; |
| | | } else { |
| | | return b.sceneIndex - a.sceneIndex; |
| | | } |
| | | } |
| | | }); |
| | | } else if (prop == 'subTaskTime') { |
| | | this.tableData.sort((a, b) => { |
| | | if (order == 'ascending') { |
| | | return a[prop] > b[prop] ? 1 : -1; |
| | | // return dayjs(a).isAfter(dayjs(b)) ? 1 : -1; |
| | | } else if (order == 'descending') { |
| | | return b[prop] > a[prop] ? 1 : -1; |
| | | // return dayjs(b).isAfter(dayjs(a)) ? 1 : -1; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.addRefreshEvent(this.$refs.tableRef.doLayout); |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="16"> |
| | | <CompPreCheck @start-task="refreshTask"></CompPreCheck> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <CompEvaTask ref="refEvaTask"></CompEvaTask> |
| | | </el-col> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <script> |
| | | import CompEvaTask from './components/CompEvaTask.vue'; |
| | | import CompPreCheck from './components/precheck/CompPreCheck.vue'; |
| | | export default { |
| | | name: 'EvalutationTask', |
| | | components: { CompPreCheck, CompEvaTask }, |
| | | data() { |
| | | return {}; |
| | | }, |
| | | methods:{ |
| | | refreshTask(){ |
| | | this.$refs.refEvaTask.fetchTask() |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .radius { |
| | | height: 80vh; |
| | | /* border: 1px solid var(--el-border-color); */ |
| | | /* border-radius: var(--el-border-radius-base); */ |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <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 |
| | | > |
| | | </el-row> |
| | | <el-table |
| | | ref="tableRef" |
| | | :data="data" |
| | | v-loading="tableLoading" |
| | | table-layout="fixed" |
| | | 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="åºæ¯åç§°" |
| | | > |
| | | <template #default="{ row }"> |
| | | <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 |
| | | 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, 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() { |
| | | monitordataApi.fetchDustDataResult(props.areaInfo).then((res) => { |
| | | data.value = res.data; |
| | | }); |
| | | } |
| | | |
| | | function handleExceed(files, uploadFiles) { |
| | | upload.value.clearFiles(); |
| | | const file = files[0]; |
| | | file.uid = genFileId(); |
| | | upload.value.handleStart(file); |
| | | } |
| | | |
| | | /** |
| | | * å¤çä¸ä¼ æä»¶è§£æ |
| | | * @param uploadFile |
| | | * @param uploadFiles |
| | | */ |
| | | function handleChange(uploadFile, uploadFiles) { |
| | | expandRowKeys.value = []; |
| | | tableLoading.value = true; |
| | | loadTxt.value = 'æä»¶è§£æä¸...'; |
| | | // console.log(uploadFile, uploadFiles); |
| | | const fileReader = new FileReader(); |
| | | fileReader.onload = (file) => { |
| | | const fileData = file.target.result; |
| | | workbook = XLSX.read(fileData, { type: 'array' }); |
| | | console.log(workbook.SheetNames); |
| | | if (workbook.SheetNames.length == 0) { |
| | | tips.value = 'excelæä»¶éè¯¯ï¼æ²¡æsheet表å'; |
| | | 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() { |
| | | 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(); |
| | | }); |
| | | </script> |
| | | <style scoped> |
| | | .upload-file { |
| | | /* background-color: aliceblue; */ |
| | | width: 300px; |
| | | min-height: 60px; |
| | | } |
| | | |
| | | :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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-card shadow="never" :body-style="{ padding: 0 }"> |
| | | <template #header> |
| | | <el-row justify="space-between"> |
| | | <div> |
| | | <div><el-text tag="b" size="large">èªå¨è¯ä¼°ä»»å¡</el-text></div> |
| | | <el-text size="small" type="info">æ¾ç¤ºå½åæ£å¨è¿è¡çèªå¨è¯ä¼°ä»»å¡ç¶æ</el-text> |
| | | </div> |
| | | <el-button |
| | | icon="Refresh" |
| | | type="primary" |
| | | size="default" |
| | | :loading="loading" |
| | | @click="fetchTask" |
| | | >å·æ°ä»»å¡</el-button |
| | | > |
| | | </el-row> |
| | | <!-- <el-row> |
| | | <el-button type="default" size="default" @click="newTestTask">æ°å¢æµè¯ä»»å¡</el-button> |
| | | <el-button type="default" size="default" @click="startNewTestTask" |
| | | >æ°å»ºå¹¶è¿è¡ä¸ä¸ªæµè¯ä»»å¡</el-button |
| | | > |
| | | <el-button type="default" size="default" @click="shutDownTask" |
| | | >强å¶å
³éæææµè¯ä»»å¡</el-button |
| | | > |
| | | </el-row> --> |
| | | </template> |
| | | <el-scrollbar height="70vh" class="scrollbar"> |
| | | <template v-for="(v, i) in taskList" :key="i"> |
| | | <FYBgTaskItem |
| | | :model="v" |
| | | :index="i" |
| | | @start="startTask" |
| | | @shutDown="shutDownTask" |
| | | @remove="removeTask" |
| | | @gotoResult="gotoResult" |
| | | ></FYBgTaskItem> |
| | | </template> |
| | | </el-scrollbar> |
| | | </el-card> |
| | | </template> |
| | | <script> |
| | | /** |
| | | * èªå¨è¯ä¼°ä»»å¡ç®¡ç |
| | | */ |
| | | import { useFetchData } from '@/composables/fetchData'; |
| | | import bgtaskApi from '@/api/fysp/bgtaskApi'; |
| | | import { enumBgTask, BG_TASK_TYPE } from '@/enum/bgTask'; |
| | | |
| | | export default { |
| | | setup() { |
| | | const { loading, fetchData } = useFetchData(); |
| | | return { loading, fetchData }; |
| | | }, |
| | | data() { |
| | | return { |
| | | taskList: [], |
| | | taskIndex: 0 |
| | | }; |
| | | }, |
| | | methods: { |
| | | addTask(){ |
| | | |
| | | }, |
| | | newTestTask() { |
| | | this.fetchData((page, pageSize) => { |
| | | return bgtaskApi.newTestTask(`Test-Task-${++this.taskIndex}`).then((res) => { |
| | | this.taskList.push(res.data); |
| | | }); |
| | | }); |
| | | }, |
| | | startNewTestTask() { |
| | | this.fetchData((page, pageSize) => { |
| | | return bgtaskApi.startNewTestTask(`Test-Task-${++this.taskIndex}`).then((res) => { |
| | | this.taskList.push(res.data); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | _getParam(taskStatus) { |
| | | return { |
| | | type: taskStatus.type, |
| | | id: taskStatus.id |
| | | }; |
| | | }, |
| | | fetchTask() { |
| | | this.fetchData((page, pageSize) => { |
| | | return bgtaskApi |
| | | .fetchTaskStatus({ |
| | | type: BG_TASK_TYPE.AUTO_SCORE.name |
| | | }) |
| | | .then((res) => { |
| | | this.taskList = res.data; |
| | | }); |
| | | }); |
| | | }, |
| | | startTask(index, callback) { |
| | | this.fetchData((page, pageSize) => { |
| | | const param = this._getParam(this.taskList[index]); |
| | | return bgtaskApi.startTask(param).then((res) => { |
| | | this.taskList[index] = res.data; |
| | | callback(true); |
| | | }); |
| | | }); |
| | | }, |
| | | shutDownTask(index, callback) { |
| | | this.fetchData((page, pageSize) => { |
| | | const param = this._getParam(this.taskList[index]); |
| | | return bgtaskApi.shutDownTask(param).then((res) => { |
| | | if (index && res.data && res.data.length == 1) { |
| | | this.taskList[index] = res.data[0]; |
| | | } else { |
| | | res.data.forEach((e) => { |
| | | let v = this.taskList.find((value) => { |
| | | return value.id == e.id; |
| | | }); |
| | | const i = this.taskList.indexOf(v); |
| | | this.taskList[i] = e; |
| | | }); |
| | | } |
| | | callback(true); |
| | | }); |
| | | }); |
| | | }, |
| | | removeTask(index, callback) { |
| | | this.fetchData((page, pageSize) => { |
| | | const param = this._getParam(this.taskList[index]); |
| | | return bgtaskApi.removeTask(param).then((res) => { |
| | | if (res.data) { |
| | | this.taskList.splice(index, 1); |
| | | callback(true); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | gotoResult(index) {} |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .scrollbar { |
| | | padding: 8px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-button icon="Download" type="success" @click="dialogVisible = true" |
| | | >è§èæ§è¯ä¼°ä¸åææ¥å</el-button |
| | | > |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | title="è§èæ§è¯ä¼°ä¸åææ¥åçæ" |
| | | width="500" |
| | | > |
| | | <el-text tag="b" size="large">æ°æ®èå´ç¡®è®¤</el-text> |
| | | <el-text tag="div">åºåï¼{{ locationText }}</el-text> |
| | | <el-text tag="div">ç±»åï¼{{ scenetype.label }}</el-text> |
| | | <el-text tag="div">æ¶é´ï¼{{ timeText }}</el-text> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-row align="middle"> |
| | | <el-checkbox v-model="forceUpdate" label="强å¶çææ°æ¥å" /> |
| | | <el-tooltip placement="bottom-start" effect="light"> |
| | | <template #content> |
| | | <el-text tag="b" size="small">ä¸å¾éï¼</el-text><br /> |
| | | <el-text size="small" |
| | | >ä¸å¾éæ¶ï¼å¦æå·²çæè¿ç¸ååºåçæ¥åï¼åç´æ¥è·å该份æ¥åè®°å½</el-text |
| | | ><br /> |
| | | <el-text tag="b" size="small">å¾éï¼</el-text><br /> |
| | | <el-text size="small" |
| | | >å¾éæ¶ï¼æ 论æ¯å¦æåå²è®°å½ï¼é½ä¼å¯å¨æ¥åçæä»»å¡è¦çæ§è®°å½ï¼å¯å¨åå°ä»»å¡ç颿¥çä»»å¡è¿åº¦</el-text |
| | | ><br /> |
| | | </template> |
| | | <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)" |
| | | ><QuestionFilled |
| | | /></el-icon> |
| | | </el-tooltip> |
| | | </el-row> |
| | | <div> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="download">ç¡®å®</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import dayjs from 'dayjs'; |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | |
| | | export default { |
| | | props: ['locations', 'time', 'scenetype'], |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | forceUpdate: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | locationText() { |
| | | const loc = this.locations; |
| | | let text = ''; |
| | | text = loc.pName == loc.cName ? loc.pName : loc.pName + loc.cName; |
| | | text += loc.dName; |
| | | return text; |
| | | }, |
| | | timeText() { |
| | | return dayjs(this.time).format('YYYYå¹´MMæ'); |
| | | } |
| | | }, |
| | | methods: { |
| | | // è§èæ§è¯ä¼°ä¸åææ¥ååå°çæä»»å¡ |
| | | download() { |
| | | const locations = this.locations; |
| | | const time = this.time; |
| | | const scenetype = this.scenetype; |
| | | const area = { |
| | | provincecode: locations.pCode, |
| | | provincename: locations.pName, |
| | | citycode: locations.cCode, |
| | | cityname: locations.cName, |
| | | districtcode: locations.dCode, |
| | | districtname: locations.dName, |
| | | starttime: dayjs(this.time).format('YYYY-MM-DD HH:mm:ss'), |
| | | scensetypeid: scenetype.value |
| | | }; |
| | | evaluateApi.downloadAutoEvaluation(area, this.forceUpdate).then((res) => { |
| | | if (res == false) { |
| | | // æªä¸è½½ææ¡£ï¼èæ¯å¼å¯äºææ¡£çæåå°ä»»å¡ |
| | | this.$parent; |
| | | } |
| | | this.dialogVisible = false; |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | gap: 2px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-steps :active="stepIndex" finish-status="success" style="" align-center> |
| | | <el-step title="è¯ä¼°èå´" /> |
| | | <el-step title="æ°æ®æºæ£æ¥" /> |
| | | <el-step title="æ¡ç®è±å
" /> |
| | | <el-step title="èªå¨è¯ä¼°" /> |
| | | </el-steps> |
| | | <CompCheckArea v-show="stepIndex == 0" v-model="stepIndex" @change="onAreaChange"></CompCheckArea> |
| | | <CompCheckSource |
| | | v-show="stepIndex == 1" |
| | | v-model="stepIndex" |
| | | ref="refSource" |
| | | @change="onDataSourceChange" |
| | | ></CompCheckSource> |
| | | <CompCheckExemption |
| | | v-show="stepIndex == 2" |
| | | v-model="stepIndex" |
| | | @change="onExemptionChange" |
| | | ></CompCheckExemption> |
| | | <CompCheckConfirm |
| | | v-show="stepIndex == 3" |
| | | v-model="stepIndex" |
| | | :area-info="area" |
| | | :data-source="dataSource" |
| | | :exemption-items="exemptionItems" |
| | | @start="onNewTask" |
| | | ></CompCheckConfirm> |
| | | </template> |
| | | |
| | | <script> |
| | | import dayjs from 'dayjs'; |
| | | import CompCheckArea from './components/CompCheckArea.vue'; |
| | | import CompCheckSource from './components/CompCheckSource.vue'; |
| | | import CompCheckExemption from './components/CompCheckExemption.vue'; |
| | | import CompCheckConfirm from './components/CompCheckConfirm.vue'; |
| | | |
| | | /** |
| | | * èªå¨è¯ä¼°æ¡ä»¶åè§æ§æ£æ¥ |
| | | */ |
| | | export default { |
| | | name: 'CompPreCheck', |
| | | components: { CompCheckArea, CompCheckSource, CompCheckExemption, CompCheckConfirm }, |
| | | props: {}, |
| | | emits: ['startTask'], |
| | | data() { |
| | | return { |
| | | // æä½æ¥éª¤ä¸æ |
| | | stepIndex: 0, |
| | | area: { |
| | | _locations: {}, |
| | | _scenetype: {} |
| | | }, |
| | | dataSource: {}, |
| | | // è±å
æ¡ç® |
| | | exemptionItems: {} |
| | | }; |
| | | }, |
| | | methods: { |
| | | /** |
| | | * çå¬è¯ä¼°èå´åæ´ |
| | | */ |
| | | onAreaChange(val) { |
| | | const v = val.value; |
| | | this.area = v; |
| | | const a = { |
| | | provincecode: v._locations.pCode, |
| | | provincename: v._locations.pName, |
| | | citycode: v._locations.cCode, |
| | | cityname: v._locations.cName, |
| | | districtcode: v._locations.dCode, |
| | | districtname: v._locations.dName, |
| | | towncode: v._locations.tCode, |
| | | townname: v._locations.tName, |
| | | starttime: this.$fm.formatYMDHMS(v.time), |
| | | endtime: this.$fm.formatYMDHMS(v.time), |
| | | scensetypeid: v._scenetype.value, |
| | | online: true, |
| | | sourceType: v.sourceType |
| | | }; |
| | | this.$refs.refSource.startCheck(a); |
| | | }, |
| | | onDataSourceChange(val) { |
| | | this.dataSource = val; |
| | | }, |
| | | onExemptionChange(val) { |
| | | this.exemptionItems = val; |
| | | }, |
| | | /** |
| | | * èªå¨è¯ä¼°åç½®åè§æ§æ£æ¥ |
| | | * æ£æ¥æéèå´å
å项è¯ä¼°æ°æ®æºæ¯å¦å®æ´ |
| | | */ |
| | | onNewTask() { |
| | | this.$emit('startTask'); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <div><el-text tag="b" size="large">éæ©è¯ä¼°èå´</el-text></div> |
| | | <el-text size="small" type="info">å
æ¬åºå¿ãåºæ¯ç±»å以åæä»½</el-text> |
| | | </template> |
| | | <FormCol> |
| | | <FYForm ref="formRef" :rules="evaConditionRules" :showButtons="false" @submit="nextStep"> |
| | | <template #form-item="{ formObj }"> |
| | | <CompQuickSet @quick-set="setOptions"></CompQuickSet> |
| | | <el-form-item label="ä¸»æ°æ®æº" prop="sourceType"> |
| | | <el-radio-group |
| | | v-model="formObj.sourceType" |
| | | size="small" |
| | | @change="sceneOptionSourceInit = true" |
| | | > |
| | | <el-radio-button :value="1">宿³æå¡è®°å½</el-radio-button> |
| | | <el-radio-button :value="2">ç°åºå·¡æ¥è®°å½</el-radio-button> |
| | | </el-radio-group> |
| | | <el-tooltip placement="bottom-start" effect="light"> |
| | | <template #content> |
| | | <el-text tag="i" size="default" type="warning" |
| | | >该é项æ¯ç¨äºå³å®è¯ä¼°ä¸»ä½å¯¹è±¡çè·åæ¹å¼</el-text |
| | | ><br /> |
| | | <el-text tag="b" size="small">宿³æå¡è®°å½ï¼</el-text><br /> |
| | | <el-text size="small" |
| | | >表示å¨è¯ä¼°æ¶ï¼è¯ä¼°å¯¹è±¡æ¯ä»å®æ³æå¡å°ç¨åºç³»ç»ä¸è·åçå½åå¯ç¨çç¨æ·ï¼<br /> |
| | | ä¸è¬æ
åµä¸ï¼å½è¯ä¼°å¯¹è±¡æ²¡æè¿è¡ç°åºå·¡æ¥ï¼åªæå®æ³æå¡ç¸å
³è®°å½æ¶ï¼éç¨æ¤é项ï¼</el-text |
| | | ><br /> |
| | | <el-text tag="b" size="small">ç°åºå·¡æ¥è®°å½ï¼</el-text><br /> |
| | | <el-text size="small" |
| | | >表示å¨è¯ä¼°æ¶ï¼è¯ä¼°å¯¹è±¡æ¯ä»ç°åºå·¡æ¥ç管系ç»ä¸è·åçæ»ä»»å¡ä¸çææçç®¡åºæ¯ï¼<br /> |
| | | ä¸è¬æ
åµä¸ï¼å½è¯ä¼°å¯¹è±¡æè¿è¡ç°åºå·¡æ¥ï¼éç¨æ¤éé¡¹ï¼ </el-text |
| | | ><br /> |
| | | </template> |
| | | <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)" |
| | | ><QuestionFilled |
| | | /></el-icon> |
| | | </el-tooltip> |
| | | </el-form-item> |
| | | <!-- åºå¿ --> |
| | | <FYOptionLocation |
| | | :allOption="false" |
| | | :level="3" |
| | | :initValue="false" |
| | | :checkStrictly="false" |
| | | v-model:value="formObj._locations" |
| | | ></FYOptionLocation> |
| | | <!-- åºæ¯ç±»å --> |
| | | <FYOptionScene |
| | | :allOption="false" |
| | | :initValue="false" |
| | | :sourceInit="sceneOptionSourceInit" |
| | | :type="formObj.sourceType" |
| | | v-model:value="formObj._scenetype" |
| | | ></FYOptionScene> |
| | | <!-- æ¶é´ --> |
| | | <FYOptionTime |
| | | prop="time" |
| | | :initValue="true" |
| | | type="month" |
| | | v-model:value="formObj.time" |
| | | ></FYOptionTime> |
| | | </template> |
| | | </FYForm> |
| | | </FormCol> |
| | | <template #footer> |
| | | <el-row justify="space-around"> |
| | | <el-button type="primary" size="default" :loading="loading" @click="submit" |
| | | >ä¸ä¸æ¥</el-button |
| | | > |
| | | </el-row> |
| | | </template> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | /** |
| | | * è¯ä¼°èå´åè§æ§æ£æ¥ |
| | | */ |
| | | export default { |
| | | props: { |
| | | // æ¥éª¤ä¸æ |
| | | modelValue: Number |
| | | }, |
| | | emits: ['update:modelValue', 'change'], |
| | | data() { |
| | | return { |
| | | loading: false, |
| | | evaConditionRules: { |
| | | time: [ |
| | | { |
| | | required: true, |
| | | message: 'æ¶é´ä¸è½ä¸ºç©º', |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | sourceType: [ |
| | | { |
| | | required: true, |
| | | message: 'ä¸»æ°æ®æºå¿
须鿩', |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | }, |
| | | // å½åºæ¯éé¡¹åæ¢æ°æ®æºæ¶ï¼æ¯å¦æ¸
空å½åéé¡¹å¼ |
| | | sceneOptionSourceInit: true |
| | | }; |
| | | }, |
| | | methods: { |
| | | setOptions(param) { |
| | | this.sceneOptionSourceInit = false; |
| | | this.$refs.formRef.formObj._locations = param.locations; |
| | | this.$refs.formRef.formObj._scenetype = param.scenetype; |
| | | this.$refs.formRef.formObj.sourceType = param.sourceType; |
| | | }, |
| | | submit() { |
| | | this.$refs.formRef.onSubmit(false); |
| | | }, |
| | | // 跳转ä¸ä¸æ¥ |
| | | nextStep(formObj, success, fail) { |
| | | // todo: æ£æ¥æ¯å¦å·²æè¯ä¼°è®°å½ï¼æç¤ºç¨æ·å¯ç´æ¥è·³è½¬æ¥çæç»§ç»ä¸ä¸æ¥ |
| | | |
| | | this.loading = true; |
| | | return new Promise((reslove, reject) => { |
| | | setTimeout(() => { |
| | | this.$emit('change', formObj); |
| | | this.$emit('update:modelValue', this.modelValue + 1); |
| | | this.loading = false; |
| | | success(); |
| | | reslove(); |
| | | }, 1000); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <div><el-text tag="b" size="large">èªå¨è¯ä¼°ç¡®è®¤</el-text></div> |
| | | <el-text size="small" type="info">æç»ç¡®è®¤èªå¨è¯ä¼°åé
置项ï¼å¹¶å¼å§èªå¨è¯ä¼°</el-text> |
| | | </template> |
| | | <el-form label-width="160px" label-position="left"> |
| | | <div class="m-b-16"><el-text tag="b" size="large">è¯ä¼°èå´</el-text></div> |
| | | <el-form-item label="åºå"> |
| | | <el-text size="default">{{ areaInfo._locations.pName }}</el-text> |
| | | <el-text size="default">{{ areaInfo._locations.cName }}</el-text> |
| | | <el-text size="default">{{ areaInfo._locations.dName }}</el-text> |
| | | <el-text size="default">{{ areaInfo.starttime }}</el-text> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶é´"> |
| | | <el-text size="default">{{ $fm.formatYM(areaInfo.time) }}</el-text> |
| | | </el-form-item> |
| | | <el-form-item label="åºæ¯"> |
| | | <el-text size="default">{{ areaInfo._scenetype.label }}</el-text> |
| | | </el-form-item> |
| | | <el-divider /> |
| | | <div class="m-b-16"><el-text tag="b" size="large">è¯ä¼°æ°æ®æºå®æ´åº¦</el-text></div> |
| | | <el-form-item :label="v.name" v-for="v in dataSource" :key="v.name"> |
| | | <template v-if="v.pass == true"> |
| | | <el-icon color="var(--el-color-success)"><Check /></el-icon> |
| | | <el-text size="default" type="success">éè¿</el-text> |
| | | </template> |
| | | <template v-else-if="v.pass == false"> |
| | | <el-icon color="var(--el-color-danger)"><Close /></el-icon> |
| | | <el-text size="default" type="danger">缺失</el-text> |
| | | </template> |
| | | <template v-else> |
| | | <el-icon color="var(--el-color-warning)"><Warning /></el-icon> |
| | | <el-text size="default" type="warning">æç¥è¿</el-text> |
| | | </template> |
| | | </el-form-item> |
| | | <el-divider /> |
| | | <div class="m-b-16"><el-text tag="b" size="large">è±å
æ¡ç®</el-text></div> |
| | | <div class="m-b-16"><el-text size="default">æ è±å
æ¡ç®</el-text></div> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <el-row justify="space-around"> |
| | | <el-button type="primary" size="default" @click="lastStep">ä¸ä¸æ¥</el-button> |
| | | <el-button type="primary" size="default" @click="startEvaluate">å¼å§è¯ä¼°</el-button> |
| | | </el-row> |
| | | </template> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | |
| | | /** |
| | | * è¯ä¼°ä»»å¡æç»å¼å¯ç¡®è®¤ |
| | | */ |
| | | export default { |
| | | props: { |
| | | // æ¥éª¤ä¸æ |
| | | modelValue: Number, |
| | | // åºåä¿¡æ¯ |
| | | areaInfo: { |
| | | type: Object, |
| | | default: () => { |
| | | return { |
| | | _locations: {}, |
| | | _scenetype: {} |
| | | }; |
| | | } |
| | | }, |
| | | // æ°æ®æºå®æ´åº¦æ
åµ |
| | | dataSource: Array, |
| | | // æ¡ç®è±å
æ
åµ |
| | | exemptionItems: Array |
| | | }, |
| | | emits: ['update:modelValue', 'start'], |
| | | data() { |
| | | return {}; |
| | | }, |
| | | methods: { |
| | | // å¼å¯èªå¨è¯ä¼°ä»»å¡ |
| | | startEvaluate() { |
| | | const v = this.areaInfo |
| | | const a = { |
| | | provincecode: v._locations.pCode, |
| | | provincename: v._locations.pName, |
| | | citycode: v._locations.cCode, |
| | | cityname: v._locations.cName, |
| | | districtcode: v._locations.dCode, |
| | | districtname: v._locations.dName, |
| | | towncode: v._locations.tCode, |
| | | townname: v._locations.tName, |
| | | starttime: this.$fm.formatYMDHMS(v.time), |
| | | scensetypeid: v._scenetype.value, |
| | | online: true, |
| | | sourceType: v.sourceType |
| | | }; |
| | | evaluateApi.autoEvaluate(a).then((res) => { |
| | | this.$emit('start', res.data); |
| | | }); |
| | | }, |
| | | // 跳转ä¸ä¸æ¥ |
| | | lastStep() { |
| | | this.$emit('update:modelValue', this.modelValue - 1); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <div><el-text tag="b" size="large">æ¡ç®è±å
</el-text></div> |
| | | <el-text size="small" type="info">èªå®ä¹è®¾ç½®æ¤æ¬¡è¯ä¼°ä¸åä¸è®¡ç®çæ¡ç®</el-text> |
| | | </template> |
| | | è±å
æ¡ç®åè½ææªå®æï¼è¯·ç´æ¥ç¹å»ä¸ä¸æ¥ |
| | | <template #footer> |
| | | <el-row justify="space-around"> |
| | | <el-button type="primary" size="default" @click="lastStep">ä¸ä¸æ¥</el-button> |
| | | <el-button type="primary" size="default" @click="nextStep">ä¸ä¸æ¥</el-button> |
| | | </el-row> |
| | | </template> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * è¯ä¼°æ¡ç®è±å
è®¾å® |
| | | */ |
| | | export default { |
| | | props: { |
| | | // æ¥éª¤ä¸æ |
| | | modelValue: Number |
| | | }, |
| | | emits: ['update:modelValue', 'change'], |
| | | data() { |
| | | return { |
| | | // è±å
æ¡ç® |
| | | exemptionItems: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | // 跳转ä¸ä¸æ¥ |
| | | nextStep() { |
| | | this.$emit('change', this.exemptionItems); |
| | | this.$emit('update:modelValue', this.modelValue + 1); |
| | | }, |
| | | // 跳转ä¸ä¸æ¥ |
| | | lastStep() { |
| | | this.$emit('update:modelValue', this.modelValue - 1); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <div><el-text tag="b" size="large">æ°æ®æºæ£æ¥</el-text></div> |
| | | <el-text size="small" type="info">æ£æ¥è¯ä¼°æéæ°æ®æºæ¯å¦å®æ´</el-text> |
| | | </template> |
| | | <FormCol> |
| | | <template v-for="(v, i) in checkResults" :key="i"> |
| | | <el-row class="h-small" align="middle"> |
| | | <el-col :span="14"> |
| | | <el-row align="middle"> |
| | | <el-text |
| | | size="default" |
| | | :class="v.required ? 'required' : 'not-required'" |
| | | >*</el-text |
| | | > |
| | | <el-text size="default" class="m-l-4">{{ v.name }}</el-text> |
| | | </el-row> |
| | | </el-col> |
| | | <el-col :span="5"> |
| | | <el-row align="middle"> |
| | | <el-space> |
| | | <template v-if="v.loading"> |
| | | <el-icon class="is-loading"><Loading /></el-icon> |
| | | <el-text size="default" type="default">æ£æ¥ä¸...</el-text> |
| | | </template> |
| | | <template v-else-if="v.pass == true"> |
| | | <el-icon color="var(--el-color-success)"><Check /></el-icon> |
| | | <el-text size="default" type="success">éè¿</el-text> |
| | | </template> |
| | | <template v-else-if="v.pass == false"> |
| | | <el-icon color="var(--el-color-danger)"><Close /></el-icon> |
| | | <el-text size="default" type="danger">缺失</el-text> |
| | | </template> |
| | | <template v-else> |
| | | <el-icon color="var(--el-color-warning)" |
| | | ><Warning |
| | | /></el-icon> |
| | | <el-text size="default" type="warning">æç¥è¿</el-text> |
| | | </template> |
| | | </el-space> |
| | | </el-row> |
| | | </el-col> |
| | | <el-col :span="5"> |
| | | <el-button |
| | | v-show="!v.loading" |
| | | :type="v.pass ? '' : 'danger'" |
| | | size="small" |
| | | @click="goto(v.path)" |
| | | :disabled="v.path == ''" |
| | | > |
| | | {{ v.pass ? 'å»ä¿®æ¹' : 'å»å®å' }} |
| | | <el-icon class="m-l-4"><Right /></el-icon> |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row align="middle" class="m-b-16"> |
| | | <el-text size="small" class="not-required">*</el-text> |
| | | <el-text size="small" class="m-l-4 color-i">{{ v.des }}</el-text> |
| | | </el-row> |
| | | </template> |
| | | </FormCol> |
| | | <template #footer> |
| | | <el-row justify="space-around"> |
| | | <el-button type="primary" size="default" @click="lastStep" |
| | | >ä¸ä¸æ¥</el-button |
| | | > |
| | | <el-button |
| | | :disabled="!checkPass" |
| | | type="primary" |
| | | size="default" |
| | | @click="nextStep" |
| | | >ä¸ä¸æ¥</el-button |
| | | > |
| | | </el-row> |
| | | </template> |
| | | </el-card> |
| | | <el-dialog |
| | | title="æ¬å°çæµæ°æ®æåº¦ç»è®¡ç®¡ç" |
| | | v-model="dialog1" |
| | | destroy-on-close |
| | | width="90%" |
| | | > |
| | | <CompDataResultEdit :areaInfo="areaInfo"></CompDataResultEdit> |
| | | <template #footer> </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | import taskApi from '@/api/fysp/taskApi'; |
| | | import userMapApi from '@/api/fysp/userMapApi'; |
| | | import problemApi from '@/api/fysp/problemApi'; |
| | | import monitordataApi from '@/api/fysp/monitordataApi'; |
| | | import complaintApi from '@/api/fytz/complaintApi'; |
| | | import CompDataResultEdit from '../../CompDataResultEdit.vue'; |
| | | |
| | | /** |
| | | * çæä¸é¡¹æ°æ®æºæ£æ¥æ¡ç® |
| | | * @param {*} _name æ¡ç®åç§° |
| | | * @param {*} _path 跳转页é¢URL |
| | | * @param {*} _fetch æ¡ç®çç½ç»è¯·æ±å½æ° |
| | | * @param {*} _required æ¯å¦å¿
é |
| | | */ |
| | | function baseCheckItem(_name, _path, _fetch, _required) { |
| | | return { |
| | | required: _required, |
| | | name: _name, |
| | | loading: true, |
| | | pass: false, |
| | | path: _path, |
| | | des: '', |
| | | async fetch() { |
| | | this.loading = true; |
| | | setTimeout(async () => { |
| | | if (typeof _fetch === 'function') { |
| | | _fetch() |
| | | .then((res) => { |
| | | this.pass = res ? res.pass : undefined; |
| | | this.des = res ? res.des : undefined; |
| | | }) |
| | | .catch(() => { |
| | | this.pass = false; |
| | | this.des = 'ç½ç»é¾æ¥é误'; |
| | | }) |
| | | .finally(() => { |
| | | this.loading = false; |
| | | }); |
| | | } else { |
| | | this.pass = undefined; |
| | | this.des = undefined; |
| | | this.loading = false; |
| | | } |
| | | }, 1000); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * è¯ä¼°æ°æ®æºå®æ´æ§æ£æ¥ |
| | | */ |
| | | export default { |
| | | components: { |
| | | CompDataResultEdit |
| | | }, |
| | | props: { |
| | | // æ¥éª¤ä¸æ |
| | | modelValue: Number |
| | | }, |
| | | emits: ['update:modelValue', 'change'], |
| | | data() { |
| | | return { |
| | | areaInfo: {}, |
| | | // æ°æ®æºæ£æ¥è®°å½ |
| | | checkResults: [ |
| | | // åºåèå´å
çèªå¨è¯ä¼°è§å表æ¯å¦åå¨ |
| | | baseCheckItem( |
| | | 'èªå¨è¯ä¼°è§å表', |
| | | '', |
| | | () => { |
| | | const param = { |
| | | taskTypeId: 99, |
| | | ...this.areaInfo |
| | | }; |
| | | return evaluateApi.fetchEvaluationRule(param).then((res) => { |
| | | const pass = res.data.length > 0; |
| | | let des = ''; |
| | | if (pass) { |
| | | res.data.forEach((e) => { |
| | | if (des != '') { |
| | | des += 'ã'; |
| | | } |
| | | des += `ã${e.rulename}ã`; |
| | | }); |
| | | } else { |
| | | des = 'æªæ¾å°ç¸å
³è¯ä¼°è§å表'; |
| | | } |
| | | return { pass, des }; |
| | | }); |
| | | }, |
| | | true |
| | | ), |
| | | // åºåèå´å
ççç®¡ä»»å¡æ¯å¦åå¨ |
| | | baseCheckItem('ç°åºçç®¡å·¡æ¥æ»ä»»å¡', '', () => { |
| | | return taskApi.fetchTopTasks(this.areaInfo).then((res) => { |
| | | const pass = res.data.length > 0; |
| | | let des = ''; |
| | | if (pass) { |
| | | res.data.forEach((e) => { |
| | | if (des != '') { |
| | | des += 'ã'; |
| | | } |
| | | des += e.name; |
| | | }); |
| | | } else { |
| | | des = 'æªæ¾å°ç¸å
³å·¡æ¥æ»ä»»å¡'; |
| | | } |
| | | return { pass, des }; |
| | | }); |
| | | }), |
| | | // åºåèå´å
ççæµæ°æ®æ¯å¦åå¨ãæ°æ®æ¶é´è·¨åº¦æ¯å¦å®æ´ãæ°æ®ç忥忿¯å¦å®æ |
| | | baseCheckItem( |
| | | 'ç°åºçæµæ°æ®', |
| | | () => { |
| | | this.dialog1 = true; |
| | | }, |
| | | () => { |
| | | return monitordataApi |
| | | .fetchDustDataResult(this.areaInfo) |
| | | .then((res) => { |
| | | const pass = res.data.length > 0; |
| | | let des = ''; |
| | | if (pass) { |
| | | des = `æ¾å°æåº¦ç»è®¡å
±${res.data.length}æ¡`; |
| | | } else { |
| | | des = 'æªæ¾å°ç¸å
³è®°å½'; |
| | | } |
| | | return { pass, des }; |
| | | }); |
| | | } |
| | | ), |
| | | // åºåèå´å
çæ¯ä¸ªç管ç¹ä½ä¸çæµä»ªå¨çå¹é
è®°å½æ¯å¦åå¨ï¼ç¼ºå¤±æ
åµç |
| | | baseCheckItem('ç管ç¹ä½ä¸çæµç¹å¹é
', '', () => { |
| | | return userMapApi.fetchDeviceMap(this.areaInfo).then((res) => { |
| | | const pass = res.data.length > 0; |
| | | let des = ''; |
| | | if (pass) { |
| | | des = `æ¾å°å¹é
è®°å½å
±${res.data.length}æ¡`; |
| | | } else { |
| | | des = 'æªæ¾å°ç¸å
³å¹é
è®°å½'; |
| | | } |
| | | return { pass, des }; |
| | | }); |
| | | }), |
| | | // åºåèå´å
çç管é®é¢é
置表æ¯å¦åå¨ |
| | | baseCheckItem('ç°åºç管é®é¢ç±»å', '', () => { |
| | | const param = { |
| | | cityCode: this.areaInfo.citycode, |
| | | districtCode: this.areaInfo.districtcode, |
| | | sceneTypeId: this.areaInfo.scensetypeid |
| | | }; |
| | | return problemApi.fetchProblemType(param).then((res) => { |
| | | const pass = res.length > 0; |
| | | let des = ''; |
| | | if (pass) { |
| | | des = `æ¾å°é®é¢ç±»åå
±${res.length}æ¡`; |
| | | } else { |
| | | des = 'æªæ¾å°ç¸å
³é®é¢ç±»å'; |
| | | } |
| | | return { pass, des }; |
| | | }); |
| | | }), |
| | | // complaintApi.fetchComplaints(); |
| | | // åºåèå´å
ç信访æè¯è®°å½æ¯å¦åå¨ï¼å¯éæ¶è¡¥å
|
| | | baseCheckItem('信访æè¯', ''), |
| | | // complaintApi.fetchPunishment(); |
| | | // åºåèå´å
çè¡æ¿å¤ç½è®°å½æ¯å¦åå¨ï¼å¯éæ¶è¡¥å
|
| | | baseCheckItem('è¡æ¿å¤ç½', '') |
| | | ], |
| | | dialog1: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | /** |
| | | * å¤ææ°æ®æºæ£æ¥æ¯å¦éè¿ |
| | | * å
¨é¨å è½½å®æåï¼å¿
è¦é¡¹å¿
é¡»éè¿ï¼å¯é项éå¿
é¡»éè¿ |
| | | */ |
| | | checkPass() { |
| | | let res = true; |
| | | this.checkResults.forEach((e) => { |
| | | if (e.loading) { |
| | | res = res && false; |
| | | } else if (e.required) { |
| | | res = res && e.pass; |
| | | } |
| | | }); |
| | | return res; |
| | | } |
| | | }, |
| | | methods: { |
| | | // 跳转ä¸ä¸æ¥ |
| | | nextStep() { |
| | | this.$emit('change', this.checkResults); |
| | | this.$emit('update:modelValue', this.modelValue + 1); |
| | | }, |
| | | // 跳转ä¸ä¸æ¥ |
| | | lastStep() { |
| | | this.$emit('update:modelValue', this.modelValue - 1); |
| | | }, |
| | | // è·³è½¬æ£æ¥é¡¹ç龿¥ |
| | | goto(path) { |
| | | if (typeof path === 'string' && path != '') { |
| | | this.$router.push(path); |
| | | } else if (typeof path === 'function') { |
| | | path(); |
| | | } |
| | | }, |
| | | // å¼å§æ£æ¥ä»»å¡ |
| | | startCheck(value) { |
| | | // const v = value.value; |
| | | // this.areaInfo = { |
| | | // provincecode: v._locations.pCode, |
| | | // provincename: v._locations.pName, |
| | | // citycode: v._locations.cCode, |
| | | // cityname: v._locations.cName, |
| | | // districtcode: v._locations.dCode, |
| | | // districtname: v._locations.dName, |
| | | // towncode: v._locations.tCode, |
| | | // townname: v._locations.tName, |
| | | // starttime: this.$fm.formatYMDHMS(v.time), |
| | | // scensetypeid: v._scenetype.value, |
| | | // online: true, |
| | | // sourceType: v.sourceType |
| | | // }; |
| | | this.areaInfo = value; |
| | | |
| | | this.checkResults.forEach((e) => { |
| | | e.fetch(); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .required { |
| | | color: var(--el-color-danger); |
| | | } |
| | | |
| | | .not-required { |
| | | color: transparent; |
| | | } |
| | | </style> |
| | |
| | | <!-- e:\VSprojects\fume-supervision-vue\src\views\monitor\DataDashboard.vue --> |
| | | <template> |
| | | <el-container class="data-dashboard"> |
| | | <el-main> |
| | | <!-- 设å¤å¨çº¿æ
åµåºå --> |
| | | <DeviceStatus |
| | | :online-count="onlineCount" |
| | | :offline-count="offlineCount" |
| | | :normal-count="normalCount" |
| | | :fault-count="faultCount" |
| | | /> |
| | | |
| | | <!-- 设å¤å®æ¶æ°æ®åºå --> |
| | | <RealTimeData :current-device="currentDevice" :hourly-data="hourlyData" /> |
| | | |
| | | <!-- ååºæ°æ®æååºå --> |
| | | <DistrictRanking |
| | | :selected-month="selectedMonth" |
| | | :ranking-type="rankingType" |
| | | :ranking-data="rankingData" |
| | | :sorted-ranking-data="sortedRankingData" |
| | | @month-change="handleMonthChange" |
| | | @type-change="handleTypeChange" |
| | | /> |
| | | <div class="grid-container"> |
| | | <div class="left-section"> |
| | | <!-- 设å¤å¨çº¿æ
åµåºå --> |
| | | <DeviceStatus |
| | | :online-count="onlineCount" |
| | | :offline-count="offlineCount" |
| | | :normal-count="normalCount" |
| | | :fault-count="faultCount" |
| | | /> |
| | | <!-- ååºæ°æ®æååºå --> |
| | | <DistrictRanking |
| | | style="flex: 1" |
| | | :selected-month="selectedMonth" |
| | | :ranking-type="rankingType" |
| | | :ranking-data="rankingData" |
| | | :sorted-ranking-data="sortedRankingData" |
| | | @month-change="handleMonthChange" |
| | | @type-change="handleTypeChange" |
| | | /> |
| | | </div> |
| | | <div class="right-section"> |
| | | <!-- 设å¤å®æ¶æ°æ®åºå --> |
| | | <RealTimeData style="flex: 1" :devices="devices" /> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¨çº¿è®¾å¤ååºéºæ¸
ååºå --> |
| | | <ShopList |
| | |
| | | faultCount: 0, |
| | | |
| | | // 设å¤å®æ¶æ°æ® |
| | | currentDevice: null, |
| | | hourlyData: [], |
| | | devices: [], |
| | | |
| | | // ååºæ°æ®æå |
| | | selectedMonth: '2023-12', |
| | |
| | | |
| | | updateRealTimeData() { |
| | | // æ¨¡ææ°æ® - å®é
åºä»APIè·å |
| | | const devices = [ |
| | | this.devices = [ |
| | | { |
| | | deviceId: 'DEV-001', |
| | | supplier: 'ä¾åºåA', |
| | | æ²¹çæµåº¦: (Math.random() * 2).toFixed(2), |
| | | 飿ºçµæµ: (Math.random() * 5 + 1).toFixed(2), |
| | | ååå¨çµæµ: (Math.random() * 3 + 0.5).toFixed(2), |
| | | status: 'æ£å¸¸', |
| | | monitorTime: new Date().toLocaleString(), |
| | | smokeDensity: (Math.random() * 2).toFixed(2), |
| | | fanCurrent: (Math.random() * 5 + 1).toFixed(2), |
| | | purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2), |
| | | hourlyData: this.generateHourlyData(), |
| | | }, |
| | | { |
| | | deviceId: 'DEV-002', |
| | | supplier: 'ä¾åºåB', |
| | | status: 'æ£å¸¸', |
| | | monitorTime: new Date().toLocaleString(), |
| | | smokeDensity: (Math.random() * 2).toFixed(2), |
| | | fanCurrent: (Math.random() * 5 + 1).toFixed(2), |
| | | purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2), |
| | | hourlyData: this.generateHourlyData(), |
| | | }, |
| | | { |
| | | deviceId: 'DEV-003', |
| | | supplier: 'ä¾åºåC', |
| | | status: 'å¼å¸¸', |
| | | monitorTime: new Date().toLocaleString(), |
| | | smokeDensity: (Math.random() * 15 + 5).toFixed(2), |
| | | fanCurrent: (Math.random() * 3 + 4).toFixed(2), |
| | | purifierCurrent: (Math.random() * 2 + 2).toFixed(2), |
| | | hourlyData: this.generateHourlyData(), |
| | | }, |
| | | { |
| | | deviceId: 'DEV-004', |
| | | supplier: 'ä¾åºåD', |
| | | status: 'å¼å¸¸', |
| | | monitorTime: new Date().toLocaleString(), |
| | | smokeDensity: (Math.random() * 15 + 5).toFixed(2), |
| | | fanCurrent: (Math.random() * 3 + 4).toFixed(2), |
| | | purifierCurrent: (Math.random() * 2 + 2).toFixed(2), |
| | | hourlyData: this.generateHourlyData(), |
| | | }, |
| | | ] |
| | | }, |
| | | |
| | | this.currentDevice = devices[0] |
| | | |
| | | generateHourlyData() { |
| | | // çææ¨¡æçè¿ä¸å°æ¶æ°æ® |
| | | this.hourlyData = [] |
| | | const hourlyData = [] |
| | | for (let i = 59; i >= 0; i--) { |
| | | const time = new Date() |
| | | time.setMinutes(time.getMinutes() - i) |
| | | this.hourlyData.push({ |
| | | hourlyData.push({ |
| | | time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }), |
| | | æ²¹çæµåº¦: (Math.random() * 2).toFixed(2), |
| | | 飿ºçµæµ: (Math.random() * 5 + 1).toFixed(2), |
| | | ååå¨çµæµ: (Math.random() * 3 + 0.5).toFixed(2), |
| | | smokeDensity: (Math.random() * 2).toFixed(2), |
| | | fanCurrent: (Math.random() * 5 + 1).toFixed(2), |
| | | purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2), |
| | | }) |
| | | } |
| | | return hourlyData |
| | | }, |
| | | |
| | | updateRankingData() { |
| | | // æ¨¡ææ°æ® - å®é
åºä»APIè·å |
| | | this.rankingData = [ |
| | | { name: 'ä¸ååº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '西ååº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 }, |
| | | { name: 'æé³åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 }, |
| | | { name: 'æµ·æ·åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '丰å°åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -2 }, |
| | | { name: 'ç³æ¯å±±åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 2 }, |
| | | { name: 'éå·åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '顺ä¹åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 }, |
| | | { name: 'æå¹³åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 }, |
| | | { name: '大å
´åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: 'çæ¦åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '秦淮åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 }, |
| | | { name: '建éºåº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 }, |
| | | { name: '鼿¥¼åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '浦å£åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -2 }, |
| | | { name: 'æ éåº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 2 }, |
| | | { name: 'é¨è±å°åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: 'æ±å®åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 }, |
| | | { name: 'å
ååº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: -1 }, |
| | | { name: '溧水åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 0 }, |
| | | { name: '髿·³åº', value: (Math.random() * 1.5 + 0.5).toFixed(2), rankChange: 1 }, |
| | | ] |
| | | |
| | | // æåº |
| | |
| | | padding: 20px; |
| | | } |
| | | |
| | | .grid-container { |
| | | display: flex; |
| | | /* display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | grid-template-rows: min-content; */ |
| | | gap: 20px; |
| | | } |
| | | |
| | | .left-section { |
| | | flex: 2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .right-section { |
| | | width: 670px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .el-row { |
| | | flex-direction: column; |
| | | .grid-container { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | |
| | | .el-col { |
| | | width: 100% !important; |
| | | .left-section, |
| | | .right-section { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |