| components.d.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/debug/debugdata.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/utils/map/marks.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/inspection/MonitorControl.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/monitor/DataDashboard.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
components.d.ts
@@ -27,6 +27,7 @@ ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] ElButton: typeof import('element-plus/es')['ElButton'] ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCalendar: typeof import('element-plus/es')['ElCalendar'] ElCard: typeof import('element-plus/es')['ElCard'] ElCascader: typeof import('element-plus/es')['ElCascader'] @@ -43,10 +44,12 @@ ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFrom: typeof import('element-plus/es')['ElFrom'] ElHeader: typeof import('element-plus/es')['ElHeader'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElImage: typeof import('element-plus/es')['ElImage'] @@ -59,6 +62,7 @@ ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] ElOption: typeof import('element-plus/es')['ElOption'] ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElProgress: typeof import('element-plus/es')['ElProgress'] @@ -109,9 +113,9 @@ 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'] IEpArrowLeft: typeof import('~icons/ep/arrow-left')['default'] IEpArrowRight: typeof import('~icons/ep/arrow-right')['default'] IEpDataLine: typeof import('~icons/ep/data-line')['default'] IEpDownload: typeof import('~icons/ep/download')['default'] IEpGrid: typeof import('~icons/ep/grid')['default'] IEpInfoFilled: typeof import('~icons/ep/info-filled')['default'] ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default'] ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default'] @@ -150,6 +154,7 @@ const ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] const ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] const ElButton: typeof import('element-plus/es')['ElButton'] const ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] const ElCalendar: typeof import('element-plus/es')['ElCalendar'] const ElCard: typeof import('element-plus/es')['ElCard'] const ElCascader: typeof import('element-plus/es')['ElCascader'] @@ -166,10 +171,12 @@ const ElDialog: typeof import('element-plus/es')['ElDialog'] const ElDivider: typeof import('element-plus/es')['ElDivider'] const ElDrawer: typeof import('element-plus/es')['ElDrawer'] const ElDropdown: typeof import('element-plus/es')['ElDropdown'] const ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] const ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] const ElEmpty: typeof import('element-plus/es')['ElEmpty'] const ElForm: typeof import('element-plus/es')['ElForm'] const ElFormItem: typeof import('element-plus/es')['ElFormItem'] const ElFrom: typeof import('element-plus/es')['ElFrom'] const ElHeader: typeof import('element-plus/es')['ElHeader'] const ElIcon: typeof import('element-plus/es')['ElIcon'] const ElImage: typeof import('element-plus/es')['ElImage'] @@ -182,6 +189,7 @@ const ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] const ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] const ElOption: typeof import('element-plus/es')['ElOption'] const ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] const ElPagination: typeof import('element-plus/es')['ElPagination'] const ElPopover: typeof import('element-plus/es')['ElPopover'] const ElProgress: typeof import('element-plus/es')['ElProgress'] @@ -232,9 +240,9 @@ 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'] const IEpArrowLeft: typeof import('~icons/ep/arrow-left')['default'] const IEpArrowRight: typeof import('~icons/ep/arrow-right')['default'] const IEpDataLine: typeof import('~icons/ep/data-line')['default'] const IEpDownload: typeof import('~icons/ep/download')['default'] const IEpGrid: typeof import('~icons/ep/grid')['default'] const IEpInfoFilled: typeof import('~icons/ep/info-filled')['default'] const ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default'] const ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default'] src/debug/debugdata.js
@@ -129,7 +129,7 @@ const time = new Date(now.getTime() - i * 10 * 60 * 1000) data.push({ sampleTime: time.toISOString().slice(0, 19).replace('T', ' '), oilSmokeConcentration: (Math.random() * 5).toFixed(2), oilSmokeConcentration: (Math.random() * 2).toFixed(2), purifierCurrent: (Math.random() * 10).toFixed(2), fanCurrent: (Math.random() * 15).toFixed(2), }) src/utils/map/marks.js
@@ -383,10 +383,14 @@ <h3 style="margin: 0 0 10px 0; color: #333;">${shop.shop.name}</h3> <div style="font-size: 14px; line-height: 1.5;"> <p><strong>地址:</strong>${shop.shop.address}</p> <p><strong>在线状态:</strong><span style="color: ${shop.shop.isOnline ? '#52c41a' : '#8c8c8c'}">${onlineStatusText}</span> </p> <p><strong>异常状态:</strong><span style="color: ${exceptionStatusColor}">${exceptionStatusText}</span></p> <p><strong>环信码等级:</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${getRingCodeLevelText(shop.shop.ringCodeLevel)}</span></p> <p><strong>环信码发布时间:</strong>${shop.shop.ringCodePublishTime}</p> <div style="display: flex; flex-direction: row;"> <span style="flex:1"><strong>在线状态:</strong><span style="color: ${shop.shop.isOnline ? '#52c41a' : '#8c8c8c'}">${onlineStatusText}</span> </span> <span style="flex:1"><strong>异常状态:</strong><span style="color: ${exceptionStatusColor}">${exceptionStatusText}</span></span> </div> <div style="display: flex; flex-direction: row;"> <span style="flex:1"><strong>环信码等级:</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${getRingCodeLevelText(shop.shop.ringCodeLevel)}</span></span> <span style="flex:1"><strong>发布时间:</strong>${shop.shop.ringCodePublishTime}</span> </div> <h4 style="margin: 10px 0 5px 0; color: #666;">近1小时监测数据</h4> <div id="infowindowChartContainer" style="width: 100%; height: 250px;"></div> </div> src/views/inspection/MonitorControl.vue
@@ -30,44 +30,50 @@ <!-- 左侧:已巡查店铺率、巡查点次、复查点次 --> <div class="stats-section left-section"> <h3>巡查概况</h3> <div class="chart-item"> <div class="progress-container"> <el-progress type="dashboard" :percentage="parseFloat(inspectionStats.inspectedRate)" :color="['#409EFF', '#67C23A']" :width="120" /> <div class="progress-label">已巡查店铺率</div> <div class="progress-value"> {{ `${inspectionStats.inspectedShops}/${inspectionStats.totalShops}` }} <el-row justify="space-between"> <div class="chart-item"> <div class="progress-container"> <el-progress type="dashboard" :percentage="parseFloat(inspectionStats.inspectedRate)" :color="['#409EFF', '#67C23A']" :width="120" /> <div class="progress-label">已巡查店铺率</div> <div class="progress-value"> {{ `${inspectionStats.inspectedShops}/${inspectionStats.totalShops}` }} </div> </div> </div> </div> <div class="stats-grid m-t-16"> <el-statistic class="stat-item" :value="inspectionStats.inspectionPoints" title="巡查点次" /> <el-statistic class="stat-item" :value="inspectionStats.reviewPoints" title="复查点次" /> </div> <div class="stats-grid m-l-16"> <el-statistic class="stat-item" :value="inspectionStats.inspectionPoints" title="巡查点次" /> <el-statistic class="stat-item" :value="inspectionStats.reviewPoints" title="复查点次" /> </div> </el-row> </div> <!-- 右侧:问题数、问题整改数、问题整改率统计图 --> <div class="stats-section right-section"> <h3>问题整改概况</h3> <div class="stats-grid"> <el-statistic class="stat-item" :value="inspectionStats.problemCount" title="问题数" /> <el-row justify="space-around"> <el-text>问题数:{{ inspectionStats.problemCount }}</el-text> <el-text>整改数:{{ inspectionStats.rectifiedProblems }}</el-text> </el-row> <!-- <el-statistic class="stat-item" :value="inspectionStats.problemCount" title="问题数" /> <el-statistic class="stat-item" :value="inspectionStats.rectifiedProblems" title="问题整改数" /> /> --> </div> <!-- <div class="chart-item"> --> <div ref="rectificationRateChart" class="chart"></div> @@ -320,7 +326,12 @@ chart.setOption({ xAxis: { type: 'category', data: ['当日整改率', '48小时内整改率', '综合整改率', '审核通过率'], data: [ '当日整改率', // '48小时内整改率', '综合整改率', '审核通过率', ], }, yAxis: { type: 'value', @@ -332,7 +343,7 @@ { data: [ parseFloat(inspectionStats.value.sameDayRectificationRate), parseFloat(inspectionStats.value.effectiveRectificationRate), // parseFloat(inspectionStats.value.effectiveRectificationRate), parseFloat(inspectionStats.value.comprehensiveRectificationRate), parseFloat(inspectionStats.value.auditPassRate), ], @@ -391,6 +402,9 @@ </script> <style scoped> :deep() .el-card__body { padding: 8px; } .mb-4 { /* width: 600px; */ } @@ -418,7 +432,6 @@ display: flex; flex-direction: column; gap: 20px; margin-bottom: 30px; } .stats-section { @@ -436,13 +449,13 @@ } .stats-grid { display: grid; grid-template-columns: 1fr 1fr; display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; } .stat-item { flex: 1; background-color: #fff; padding: 20px; border-radius: 8px; @@ -479,6 +492,7 @@ } .chart-item { flex: 1; background-color: #fff; padding: 20px; border-radius: 8px; src/views/monitor/DataDashboard.vue
@@ -57,48 +57,6 @@ </div> </div> <div class="cards-container"> <!-- 浓度预警 --> <div class="metric-card"> <div class="card-header"> <div class="card-title">{{ getPeriodLabel() }}浓度预警</div> <div class="card-icon warning-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M12 9V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> <path d="M12 17.5V17" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> </div> <div class="card-value">{{ metrics.overStandardCount }}<el-text>次</el-text></div> <div class="card-trend"> <span class="trend-arrow" :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }" > {{ metrics.overStandardTrend > 0 ? '↑' : '↓' }} </span> <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span> <span class="trend-label">{{ getCompareLabel() }}</span> </div> </div> <!-- 设备在线率 --> <el-popover placement="right-start" title="设备监控" width="400" trigger="click"> <div class="popover-content"> @@ -153,7 +111,7 @@ </svg> </div> </div> <div class="card-value">{{ metrics.onlineRate }}%</div> <div class="card-value">{{ metrics.onlineRate }}<el-text>%</el-text></div> <div class="card-trend"> <span class="trend-arrow" @@ -186,11 +144,11 @@ </template> </el-popover> <!-- 环信码绿码率 --> <!-- 浓度预警 --> <div class="metric-card"> <div class="card-header"> <div class="card-title">环信码绿码率</div> <div class="card-icon efficiency-icon"> <div class="card-title">{{ getPeriodLabel() }}浓度预警</div> <div class="card-icon warning-icon"> <svg width="20" height="20" @@ -198,15 +156,15 @@ fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M12 9V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" /> <path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z" d="M12 17.5V17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12 6V12L16 14" d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" @@ -215,23 +173,20 @@ </svg> </div> </div> <div class="card-value">{{ metrics.purifierEfficiency }}%</div> <div class="card-value">{{ metrics.overStandardCount }}<el-text>次</el-text></div> <div class="card-trend"> <span class="trend-arrow" :class="{ up: metrics.purifierEfficiencyTrend > 0, down: metrics.purifierEfficiencyTrend < 0, }" :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }" > {{ metrics.purifierEfficiencyTrend > 0 ? '↑' : '↓' }} {{ metrics.overStandardTrend > 0 ? '↑' : '↓' }} </span> <span class="trend-text">{{ Math.abs(metrics.purifierEfficiencyTrend) }}%</span> <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span> <span class="trend-label">{{ getCompareLabel() }}</span> </div> </div> <!-- 巡查点次 --> <!-- 现场巡查 --> <el-popover placement="right-start" title="现场巡查统计" width="350" trigger="click"> <div class="inspection-popover-content"> <!-- 巡查量统计 --> @@ -318,7 +273,7 @@ <template #reference> <div class="metric-card"> <div class="card-header"> <div class="card-title">巡查点次</div> <div class="card-title">现场巡查</div> <div class="card-icon task-icon"> <svg width="20" @@ -344,7 +299,7 @@ </svg> </div> </div> <div class="card-value">{{ metrics.inspectionPoints }}</div> <div class="card-value">{{ metrics.inspectionPoints }}<el-text>点次</el-text></div> <div class="card-trend"> <span class="trend-arrow" @@ -379,6 +334,177 @@ </div> </template> </el-popover> <!-- 信访投诉 --> <div class="metric-card"> <div class="card-header"> <div class="card-title">信访投诉</div> <div class="card-icon warning-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M21 6H3C2.46957 6 1.96086 6.21071 1.58579 6.58579C1.21071 6.96086 1 7.46957 1 8V18C1 19.1046 1.89543 20 3 20H21C22.1046 20 23 19.1046 23 18V8C23 7.46957 22.7893 6.96086 22.4142 6.58579C22.0391 6.21071 21.5304 6 21 6Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M8 12H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M8 16H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M8 8H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> </div> <div class="card-value">{{ metrics.overStandardCount }}<el-text>件</el-text></div> <div class="card-trend"> <span class="trend-arrow" :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }" > {{ metrics.overStandardTrend > 0 ? '↑' : '↓' }} </span> <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span> <span class="trend-label">{{ getCompareLabel() }}</span> </div> </div> <!-- 环信码 --> <div class="metric-card"> <div class="card-header"> <div class="card-title">环信码</div> <div class="card-icon efficiency-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12 8V16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M8 12H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> </div> <div class="card-value" style="color: #52c41a"> <div>{{ metrics.purifierEfficiency }}<el-text>%</el-text></div> <div class="card-subvalues"> <span style="color: #faad14; font-size: 14px">黄码:3%</span> <span style="color: #f5222d; font-size: 14px; margin-left: 12px">红码:2%</span> </div> </div> <div class="card-trend"> <span class="trend-arrow" :class="{ up: metrics.purifierEfficiencyTrend > 0, down: metrics.purifierEfficiencyTrend < 0, }" > {{ metrics.purifierEfficiencyTrend > 0 ? '↑' : '↓' }} </span> <span class="trend-text">{{ Math.abs(metrics.purifierEfficiencyTrend) }}%</span> <span class="trend-label">{{ getCompareLabel() }}</span> </div> </div> <!-- 行政处罚 --> <div class="metric-card"> <div class="card-header"> <div class="card-title">行政处罚</div> <div class="card-icon warning-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M12 15C15.866 15 19 11.866 19 8C19 4.13401 15.866 1 12 1C8.13401 1 5 4.13401 5 8C5 11.866 8.13401 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12 15C12 15 15 21 15 21H9C9 21 12 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M11 8H13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> <path d="M11 11H13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> </div> </div> <div class="card-value">{{ metrics.overStandardCount }}<el-text>次</el-text></div> <div class="card-trend"> <span class="trend-arrow" :class="{ up: metrics.overStandardTrend > 0, down: metrics.overStandardTrend < 0 }" > {{ metrics.overStandardTrend > 0 ? '↑' : '↓' }} </span> <span class="trend-text">{{ Math.abs(metrics.overStandardTrend) }}%</span> <span class="trend-label">{{ getCompareLabel() }}</span> </div> </div> </div> </div> @@ -387,10 +513,12 @@ <!-- 中部GIS地图区 --> <div class="map-section"> <div id="map" class="map-container"> <BaseMap :showSatellite="true"></BaseMap> <BaseMap :showSatellite="false"></BaseMap> </div> </div> </div> <!-- --> <div class="monitor-control-container"> <el-button size="large" @click="toggleMonitorControl" class="push-btn"> <div style="display: flex; flex-direction: column"> @@ -398,10 +526,10 @@ <ArrowRight v-if="isMonitorControlExpanded" /> <ArrowLeft v-else /> </el-icon> <div>现</div> <!-- <div>现</div> <div>场</div> <div>巡</div> <div>查</div> <div>查</div> --> </div> </el-button> <MonitorControl @@ -877,7 +1005,7 @@ /* 监控控制卡片 */ .monitor-control { /* position: absolute; */ width: 500px; width: 400px; transition: all 0.3s ease; /* top: 0px; */ /* right: 0px; */ @@ -887,7 +1015,7 @@ .push-btn { z-index: 1; width: 2.5rem; height: initial; height: 40px; margin: initial; display: flex; flex-direction: column; @@ -1060,6 +1188,16 @@ margin: 12px 0; color: #262626; line-height: 1.2; /* display: flex; justify-content: space-between; align-items: flex-end; */ } .card-subvalues { display: flex; align-items: center; margin: 8px 0; font-weight: 500; } .card-trend { @@ -1391,8 +1529,11 @@ /* 地图图例样式 */ .map-legend { position: absolute; display: flex; align-items: center; bottom: 4px; left: 4px; left: 50%; transform: translateX(-50%); /* width: 200px; */ background-color: rgba(255, 255, 255, 0.9); border-radius: 8px; @@ -1402,7 +1543,7 @@ } .legend-header { margin-bottom: 12px; margin-right: 12px; } .legend-header h4 { @@ -1415,7 +1556,7 @@ .legend-items { display: flex; flex-direction: column; flex-direction: row; gap: 8px; }