From 723be8e0896fbf7e9456a5defb44911a3d0cbc27 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 12 三月 2026 17:34:55 +0800
Subject: [PATCH] 2026.3.12
---
src/views/monitor/DataException_old.vue | 1690 ++++++++++++++
src/views/inspection/scenenew/components/CompUserInfo.vue | 250 ++
src/views/inspection/scenenew/components/CompHazardousWasteFile.vue | 1
src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue | 54
src/constants/menu.js | 82
src/style/base.scss | 99
src/sfc/TimeSelect.vue | 177 +
src/views/monitor/DataHistory.vue | 56
src/views/inspection/scenenew/components/CompSceneInfo.vue | 132 +
index.html | 5
src/utils/map/index.js | 98
src/views/inspection/scenenew/components/CompCompanyInfo.vue | 205 +
src/views/monitor/DataDashboard_old3.vue | 730 ++++++
components.d.ts | 20
src/views/inspection/scenenew/UserEdit.vue | 191 +
src/views/monitor/DataDashboard_old2.vue | 313 ++
src/sfc/ExceptionTypeLineChart.vue | 74
src/router/index.js | 8
src/components/layout/FormCol.vue | 18
src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue | 1
src/views/monitor/DataDashboard.vue | 1064 +++++++--
src/views/inspection/scenenew/UserInfo.vue | 226 +
src/style/layout.js | 70
src/views/inspection/scenenew/components/CompDeviceInfo.vue | 159 +
src/views/monitor/DataException.vue | 1058 +++++---
src/utils/map/districtsearch.js | 80
26 files changed, 5,938 insertions(+), 923 deletions(-)
diff --git a/components.d.ts b/components.d.ts
index dac87af..3884445 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -27,10 +27,12 @@
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']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+ ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
@@ -43,6 +45,9 @@
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']
@@ -58,6 +63,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']
ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -81,6 +87,7 @@
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree']
ElUpload: typeof import('element-plus/es')['ElUpload']
+ FormCol: typeof import('./src/components/layout/FormCol.vue')['default']
FYDownloadTableButton: typeof import('./src/components/button/FYDownloadTableButton.vue')['default']
FYForm: typeof import('./src/components/form/FYForm.vue')['default']
FYImageSelectDialog: typeof import('./src/components/FYImageSelectDialog.vue')['default']
@@ -103,8 +110,11 @@
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']
+ 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']
+ IEpWarning: typeof import('~icons/ep/warning')['default']
ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
@@ -142,10 +152,12 @@
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']
const ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+ const ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
const ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
const ElCol: typeof import('element-plus/es')['ElCol']
const ElCollapse: typeof import('element-plus/es')['ElCollapse']
@@ -158,6 +170,9 @@
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']
@@ -173,6 +188,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 ElRadio: typeof import('element-plus/es')['ElRadio']
@@ -196,6 +212,7 @@
const ElTooltip: typeof import('element-plus/es')['ElTooltip']
const ElTree: typeof import('element-plus/es')['ElTree']
const ElUpload: typeof import('element-plus/es')['ElUpload']
+ const FormCol: typeof import('./src/components/layout/FormCol.vue')['default']
const FYDownloadTableButton: typeof import('./src/components/button/FYDownloadTableButton.vue')['default']
const FYForm: typeof import('./src/components/form/FYForm.vue')['default']
const FYImageSelectDialog: typeof import('./src/components/FYImageSelectDialog.vue')['default']
@@ -218,8 +235,11 @@
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 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 IEpWarning: typeof import('~icons/ep/warning')['default']
const ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
const ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
const ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
diff --git a/index.html b/index.html
index 5022eff..3799af3 100644
--- a/index.html
+++ b/index.html
@@ -8,6 +8,11 @@
</head>
<body>
<div id="app"></div>
+ <script type="text/javascript">
+ window._AMapSecurityConfig = {
+ serviceHost: 'https://fyami.com.cn:449/_AMapService',
+ }
+ </script>
<script type="module" src="/src/main.js"></script>
</body>
</html>
diff --git a/src/components/layout/FormCol.vue b/src/components/layout/FormCol.vue
new file mode 100644
index 0000000..b17f57d
--- /dev/null
+++ b/src/components/layout/FormCol.vue
@@ -0,0 +1,18 @@
+<template>
+ <el-col :xs="cols.xs" :sm="cols.sm" :md="cols.md" :lg="cols.lg" :xl="cols.xl">
+ <slot></slot>
+ </el-col>
+</template>
+
+<script>
+import { formResponsiveCols } from '@/style/layout'
+
+export default {
+ data() {
+ return {
+ cols: formResponsiveCols(),
+ }
+ },
+}
+</script>
+<style scoped></style>
diff --git a/src/constants/menu.js b/src/constants/menu.js
index b244501..ce7a257 100644
--- a/src/constants/menu.js
+++ b/src/constants/menu.js
@@ -6,49 +6,59 @@
{
path: '/index/monitor/data-dashboard',
icon: 'solar:window-frame-line-duotone',
- name: '鏁版嵁鐪嬫澘',
+ name: '姹℃煋鎬佸娍',
},
{
path: '/index/monitor/data-exception',
icon: 'solar:siren-line-duotone',
- name: '寮傚父鍒嗘瀽',
+ name: '鐩戞祴棰勮',
},
{
+ path: '/index/monitor/data-analysis-all',
icon: 'solar:presentation-graph-line-duotone',
- name: '瑕佺礌鍒嗘瀽',
- children: [
- {
- path: '/index/monitor/data-analysis-all',
- icon: 'solar:structure-line-duotone',
- name: '鍏ㄨ绱犲垎鏋�',
- },
- {
- icon: 'solar:round-graph-line-duotone',
- name: '鍒嗚绱犲垎鏋�',
- children: [
- {
- path: '/index/monitor/data-analysis-concentration',
- icon: 'solar:graph-new-line-duotone',
- name: '娌圭儫娴撳害',
- },
- {
- path: '/index/monitor/data-analysis-online-rate',
- icon: 'solar:graph-new-line-duotone',
- name: '鍦ㄧ嚎鐜�',
- },
- {
- path: '/index/monitor/data-analysis-open-rate',
- icon: 'solar:graph-new-line-duotone',
- name: '寮�鍚巼',
- },
- {
- path: '/index/monitor/data-analysis-over-standard-rate',
- icon: 'solar:graph-new-line-duotone',
- name: '瓒呮爣鐜�',
- },
- ],
- },
- ],
+ name: '鏁版嵁鍒嗘瀽',
+ },
+ // {
+ // icon: 'solar:presentation-graph-line-duotone',
+ // name: '鏁版嵁鍒嗘瀽',
+ // children: [
+ // {
+ // path: '/index/monitor/data-analysis-all',
+ // icon: 'solar:structure-line-duotone',
+ // name: '鍏ㄨ绱犲垎鏋�',
+ // },
+ // {
+ // icon: 'solar:round-graph-line-duotone',
+ // name: '鍒嗚绱犲垎鏋�',
+ // children: [
+ // {
+ // path: '/index/monitor/data-analysis-concentration',
+ // icon: 'solar:graph-new-line-duotone',
+ // name: '娌圭儫娴撳害',
+ // },
+ // {
+ // path: '/index/monitor/data-analysis-online-rate',
+ // icon: 'solar:graph-new-line-duotone',
+ // name: '鍦ㄧ嚎鐜�',
+ // },
+ // {
+ // path: '/index/monitor/data-analysis-open-rate',
+ // icon: 'solar:graph-new-line-duotone',
+ // name: '寮�鍚巼',
+ // },
+ // {
+ // path: '/index/monitor/data-analysis-over-standard-rate',
+ // icon: 'solar:graph-new-line-duotone',
+ // name: '瓒呮爣鐜�',
+ // },
+ // ],
+ // },
+ // ],
+ // },
+ {
+ path: '/index/monitor/data-history',
+ icon: 'solar:graph-new-line-duotone',
+ name: '鍘嗗彶鏁版嵁',
},
],
},
diff --git a/src/router/index.js b/src/router/index.js
index 4f042be..058233e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -77,7 +77,13 @@
{
name: 'scene-info',
path: 'scene-info',
- component: () => import('@/views/inspection/scene/SceneInfo.vue'),
+ component: () => import('@/views/inspection/scenenew/UserInfo.vue'),
+ },
+ {
+ //璐︽埛缂栬緫
+ name: 'scene-info-edit',
+ path: 'scene-info-edit/:userId',
+ component: () => import('@/views/inspection/scenenew/UserEdit.vue'),
},
{
name: 'pro-check',
diff --git a/src/sfc/ExceptionTypeLineChart.vue b/src/sfc/ExceptionTypeLineChart.vue
index 75576f2..ae457c4 100644
--- a/src/sfc/ExceptionTypeLineChart.vue
+++ b/src/sfc/ExceptionTypeLineChart.vue
@@ -1,5 +1,5 @@
<!-- 寮傚父鎯呭喌鐨� 鎶樼嚎鍥剧粍浠�
-瀛愮粍浠舵湁鍩烘湰鐨勬牱寮�
+瀛愮粍浠舵湁鍩烘湰鐨勬牱寮�
浣跨敤鍚屼竴涓浘褰㈠疄渚嬶紝鎺ュ彈鐖剁粍浠朵紶鍏ョ殑鎶樼嚎鍥緊ption
**鐖剁粍浠�
<ExceptionTypeLineChart
@@ -9,66 +9,65 @@
></ExceptionTypeLineChart>
-->
<template>
- <div id="main" class="line-chart"></div>
+ <div id="main" class="line-chart"></div>
</template>
<script>
-import * as echarts from 'echarts';
+import * as echarts from 'echarts'
export default {
props: {
- option:{
- type:Object,
- default(){
+ option: {
+ type: Object,
+ default() {
return {}
- }
+ },
},
- isOpenDialog:{
- type:Boolean
+ isOpenDialog: {
+ type: Boolean,
},
-
},
data() {
return {
- chart: null
- };
+ chart: null,
+ }
},
mounted() {
- // 鑾峰彇椤甸潰瀹藉害鐨勪竴鍗�
-
- this.initChart();
+ // 鑾峰彇椤甸潰瀹藉害鐨勪竴鍗�
+
+ this.initChart()
this.chart.clear
- this.chart.setOption(this.option,true)
- window.addEventListener('resize', this.resizeChart);
+ this.chart.setOption(this.option, true)
+ window.addEventListener('resize', this.resizeChart)
},
watch: {
- option(){
+ option() {
// this.chart.dispose;
// this.initChart();
// this.chart.clear
// 涓嶄笌涔嬪墠鐨刼ption杩涜鍚堝苟
- this.chart.setOption(this.option,true)
+ this.chart.setOption(this.option, true)
},
- isOpenDialog(){
- window.addEventListener('resize', this.resizeChart);
+ isOpenDialog() {
+ window.addEventListener('resize', this.resizeChart)
},
},
beforeUnmount() {
if (this.chart) {
- this.chart.dispose;
+ this.chart.dispose
}
},
methods: {
initChart() {
// 鍒涘缓echarts瀹炰緥
- this.chart = echarts.init(document.getElementById('main'));
+ this.chart = echarts.init(document.getElementById('main'))
// 瀹氫箟鍥捐〃鐨勯厤缃」鍜屾暟鎹�
const option = {
grid: {
left: '3%',
right: '4%',
bottom: '3%',
- containLabel: true
+ containLabel: true,
},
tooltip: {},
toolbox: {
@@ -79,8 +78,8 @@
// yAxisIndex: 'none'
// },
// 淇濆瓨涓哄浘鐗�
- saveAsImage: {}
- }
+ saveAsImage: {},
+ },
},
xAxis: {
type: 'time',
@@ -93,31 +92,30 @@
{
name: '娌圭儫娴撳害',
type: 'line',
- data: []
- }
- ]
- };
+ data: [],
+ },
+ ],
+ }
// 浣跨敤鍒氭寚瀹氱殑閰嶇疆椤瑰拰鏁版嵁鏄剧ず鍥捐〃
- this.chart.setOption(option, true);
+ this.chart.setOption(option, true)
},
// 璺熼〉闈㈠搷搴斿紡鍙樺寲
resizeChart() {
this.$nextTick(() => {
if (this.chart) {
- this.chart.resize();
+ this.chart.resize()
}
- });
+ })
// this.chart.resize();
- }
- }
-};
+ },
+ },
+}
</script>
-
<style>
.line-chart {
- width:920px;
+ width: 100%;
height: 300px;
margin-bottom: 20px;
/* margin-left: 10px; */
diff --git a/src/sfc/TimeSelect.vue b/src/sfc/TimeSelect.vue
index c2834ac..c6783a8 100644
--- a/src/sfc/TimeSelect.vue
+++ b/src/sfc/TimeSelect.vue
@@ -1,8 +1,8 @@
-<!-- 鏃ユ湡鏃堕棿閫夋嫨鍣ㄧ粍浠�
+<!-- 鏃ユ湡鏃堕棿閫夋嫨鍣ㄧ粍浠�
浼氬皢鍒濆榛樿鏃堕棿锛堜竴鍛ㄥ墠锛夊拰鏀瑰彉鐨勬椂闂撮�氳繃浜嬩欢鈥榮ubmitTime鈥欎紶閫掔粰鐖剁粍浠�
-
+
鍒濆娓叉煋鏃跺氨灏嗘椂闂翠紶閫掔粰鐖剁粍浠讹細
- **
+ **
鍦ㄧ埗缁勪欢涓缃�
<TimeSelect @submit-time="giveTime"></TimeSelect>
giveTime(val) {
@@ -16,63 +16,192 @@
import dayjs from 'dayjs'
export default {
emits: ['submitTime'],
+ props: {
+ // 鎺у埗鏄惁鍚敤鏂扮殑鏁堟灉锛堝揩鎹锋寜閽� + 璇︽儏鎸夐挳锛�
+ useNewStyle: {
+ type: Boolean,
+ default: false,
+ },
+ },
data() {
return {
//淇濆瓨寮�濮嬪拰缁撴潫鏃堕棿
// 闅忎究璁剧疆鍒濆鍊� 锛宮ounted鏃跺啀璁炬纭殑锛岀洰鐨勬槸鏀瑰彉鏃堕棿浜嗚Е鍙慶hange
- time: ['2023-06-01 12:00:00', '2023-06-20 16:00:00']
- };
+ time: ['2023-06-01 12:00:00', '2023-06-20 16:00:00'],
+ // 鎺у埗鏃堕棿閫夋嫨鍣ㄧ殑鏄剧ず/闅愯棌锛堜粎鍦ㄦ柊鏍峰紡涓嬩娇鐢級
+ showTimePicker: false,
+ // 鏃堕棿鑼冨洿閫夐」
+ timeRanges: [
+ { value: 'today', label: '浠婃棩' },
+ { value: 'yesterday', label: '鏄ㄦ棩' },
+ { value: 'thisWeek', label: '鏈懆' },
+ { value: 'lastWeek', label: '涓婂懆' },
+ { value: 'thisMonth', label: '鏈湀' },
+ { value: 'lastMonth', label: '涓婃湀' },
+ ],
+ // 閫変腑鐨勬椂闂磋寖鍥�
+ selectedRange: '',
+ }
},
// 灏嗗垵濮嬮粯璁ゅ紑濮嬪拰缁撴潫鏃堕棿浼犻�掔粰鐖剁粍浠�
mounted() {
- this,this.initOneWeekAgoTime()
- this.$emit('submitTime', this.time);
+ if (this.useNewStyle) {
+ // 鏂版牱寮忎笅榛樿閫変腑浠婃棩
+ this.selectedRange = 'today'
+ this.selectTimeRange('today')
+ } else {
+ // 鍘熸湁鏍峰紡涓嬩娇鐢ㄤ竴鍛ㄥ墠鐨勯粯璁ゆ椂闂�
+ this.initOneWeekAgoTime()
+ this.$emit('submitTime', this.time)
+ }
},
- methods:{
- initOneWeekAgoTime(){
+ methods: {
+ initOneWeekAgoTime() {
// 缁欐椂闂撮�夋嫨鍣ㄨ缃粯璁ゆ椂闂翠负涓�鍛ㄥ墠
- this.time[0] = dayjs().subtract(4, 'week').format('YYYY-MM-DD HH:mm:ss');
- this.time[1] = dayjs().format('YYYY-MM-DD HH:mm:ss');
- }
- }
-};
+ this.time[0] = dayjs().subtract(4, 'week').format('YYYY-MM-DD HH:mm:ss')
+ this.time[1] = dayjs().format('YYYY-MM-DD HH:mm:ss')
+ },
+
+ // 蹇嵎鏃舵閫夋嫨
+ selectTimeRange(range) {
+ let now = dayjs()
+ let start, end
+
+ switch (range) {
+ case 'today':
+ start = now.startOf('day').format('YYYY-MM-DD HH:mm:ss')
+ end = now.endOf('day').format('YYYY-MM-DD HH:mm:ss')
+ break
+ case 'yesterday':
+ start = now.subtract(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
+ end = now.subtract(1, 'day').endOf('day').format('YYYY-MM-DD HH:mm:ss')
+ break
+ case 'thisWeek':
+ start = now.startOf('week').format('YYYY-MM-DD HH:mm:ss')
+ end = now.endOf('week').format('YYYY-MM-DD HH:mm:ss')
+ break
+ case 'lastWeek':
+ start = now.subtract(1, 'week').startOf('week').format('YYYY-MM-DD HH:mm:ss')
+ end = now.subtract(1, 'week').endOf('week').format('YYYY-MM-DD HH:mm:ss')
+ break
+ case 'thisMonth':
+ start = now.startOf('month').format('YYYY-MM-DD HH:mm:ss')
+ end = now.endOf('month').format('YYYY-MM-DD HH:mm:ss')
+ break
+ case 'lastMonth':
+ start = now.subtract(1, 'month').startOf('month').format('YYYY-MM-DD HH:mm:ss')
+ end = now.subtract(1, 'month').endOf('month').format('YYYY-MM-DD HH:mm:ss')
+ break
+ }
+
+ this.time = [start, end]
+ this.$emit('submitTime', this.time)
+ },
+
+ // 澶勭悊鏃堕棿鑼冨洿閫夋嫨鍙樺寲
+ handleRangeChange(val) {
+ if (val) {
+ this.selectTimeRange(val)
+ }
+ },
+
+ // 鍒囨崲鏃堕棿閫夋嫨鍣ㄧ殑鏄剧ず/闅愯棌
+ toggleTimePicker() {
+ this.showTimePicker = !this.showTimePicker
+ },
+ },
+}
</script>
<template>
- <!-- 鏃ユ湡鏃堕棿閫夋嫨鍣� -->
- <div class="block">
- <span class="demonstration">璧锋鏃堕棿锛�</span>
+ <!-- 鏃堕棿閫夋嫨缁勪欢 -->
+ <div v-if="useNewStyle" class="time-select-container">
+ <el-row align="middle" class="m-b-8">
+ <span class="demonstration">鏃堕棿锛�</span>
+ <!-- 蹇嵎鏃舵閫夋嫨鎸夐挳 -->
+ <div class="quick-time-buttons">
+ <el-radio-group v-model="selectedRange" @change="handleRangeChange">
+ <el-radio-button v-for="range in timeRanges" :key="range.value" :label="range.value">
+ {{ range.label }}
+ </el-radio-button>
+ </el-radio-group>
+ <el-button size="small" type="primary" @click="toggleTimePicker">鏃堕棿璇︽儏</el-button>
+ </div>
+ </el-row>
+
+ <!-- 鏃堕棿閫夋嫨鍣紙榛樿闅愯棌锛� -->
+ <div v-show="showTimePicker" class="time-picker-container">
+ <el-date-picker
+ v-model="time"
+ type="daterange"
+ range-separator="~"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ @change="$emit('submitTime', time)"
+ class="pick-date"
+ />
+ </div>
+ </div>
+
+ <!-- 鍘熸湁鏍峰紡 -->
+ <div v-else class="block">
+ <span class="demonstration">鏃堕棿锛�</span>
<el-date-picker
v-model="time"
- type="datetimerange"
+ type="daterange"
range-separator="~"
start-placeholder="Start date"
end-placeholder="End date"
@change="$emit('submitTime', time)"
class="pick-date"
-
/>
</div>
</template>
<style>
+.time-select-container {
+ /* width: 100%; */
+}
+
+.time-label {
+ margin-bottom: 8px;
+}
+
+.quick-time-buttons {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+}
+
+.time-picker-container {
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+}
+
.demonstration {
- margin-left: 30px;
- margin-top: 5px;
+ margin-right: 10px;
font-weight: bold;
white-space: nowrap;
}
+
+.pick-date {
+ width: 100%;
+}
+
.block {
display: flex;
justify-content: center;
/* width: 50%; */
white-space: nowrap;
}
-.pick-date {
- width: 100%;
-}
+.block .demonstration {
+ margin-left: 30px;
+ margin-top: 5px;
+}
</style>
diff --git a/src/style/base.scss b/src/style/base.scss
index 93f05ed..b151ce8 100644
--- a/src/style/base.scss
+++ b/src/style/base.scss
@@ -5,3 +5,102 @@
body {
margin: 0;
}
+
+/************************************** font size **************************************/
+$fontsize: (
+ s: var(--el-font-size-small),
+ b: var(--el-font-size-base),
+ m: var(--el-font-size-medium),
+ l: var(--el-font-size-large),
+);
+
+@each $dName, $dValue in $fontsize {
+ .f-#{$dName} {
+ font-size: #{$dValue};
+ }
+}
+
+/************************************** color **************************************/
+$colors: (
+ p: var(--el-color-primary),
+ s: var(--el-color-success),
+ w: var(--el-color-warning),
+ d: var(--el-color-danger),
+ e: var(--el-color-error),
+ i: var(--el-color-info),
+);
+
+@each $dName, $dValue in $colors {
+ .color-#{$dName} {
+ color: #{$dValue};
+ }
+ .b-color-#{$dName} {
+ background-color: #{$dValue};
+ }
+}
+
+/************************************** 鍐呭杈硅窛 **************************************/
+$direction: (
+ l: 'left',
+ t: 'top',
+ r: 'right',
+ b: 'bottom',
+);
+$size: (4, 8, 10, 16);
+@each $dName, $dValue in $direction {
+ @each $i in $size {
+ .p-#{$dName}-#{$i} {
+ padding-#{$dValue}: #{$i}px;
+ }
+ .m-#{$dName}-#{$i} {
+ margin-#{$dValue}: #{$i}px;
+ }
+ }
+}
+
+@each $i in $size {
+ .p-#{$i} {
+ padding: #{$i}px;
+ }
+ .p-v-#{$i} {
+ padding: #{$i}px 0;
+ }
+ .p-h-#{$i} {
+ padding: 0 #{$i}px;
+ }
+ .m-v-#{$i} {
+ margin: #{$i}px 0;
+ }
+ .m-h-#{$i} {
+ margin: 0 #{$i}px;
+ }
+}
+
+/************************************** 瀹介珮 **************************************/
+$csize: (
+ small: var(--el-component-size-small),
+ default: var(--el-component-size-default),
+ large: var(--el-component-size-large),
+);
+$ws: (20px, 40px, 60px, 100px, 150px, 250px, 300px);
+@each $name, $value in $csize {
+ .w-#{$name} {
+ width: #{$value};
+ }
+ .h-#{$name} {
+ height: #{$value};
+ }
+}
+@each $i in $ws {
+ .w-#{$i} {
+ width: #{$i};
+ }
+ .h-#{$i} {
+ height: #{$i};
+ }
+}
+
+//
+.cursor-p {
+ cursor: pointer;
+}
diff --git a/src/style/layout.js b/src/style/layout.js
new file mode 100644
index 0000000..f315ca1
--- /dev/null
+++ b/src/style/layout.js
@@ -0,0 +1,70 @@
+// 琛ㄥ崟鐨勫搷搴斿紡鏍呮牸甯冨眬
+function formResponsiveCols() {
+ return {
+ xs: {
+ span: 24,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ sm: {
+ span: 24,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ md: {
+ span: 20,
+ offset: 2,
+ push: 0,
+ pull: 0
+ },
+ lg: {
+ span: 18,
+ offset: 3,
+ push: 0,
+ pull: 0
+ },
+ xl: {
+ span: 14,
+ offset: 5,
+ push: 0,
+ pull: 0
+ }
+ };
+}
+
+const cardResponsiveCols = {
+ xs: {
+ span: 24,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ sm: {
+ span: 24,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ md: {
+ span: 24,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ lg: {
+ span: 12,
+ offset: 0,
+ push: 0,
+ pull: 0
+ },
+ xl: {
+ span: 8,
+ offset: 0,
+ push: 0,
+ pull: 0
+ }
+};
+
+export { formResponsiveCols, cardResponsiveCols };
diff --git a/src/utils/map/districtsearch.js b/src/utils/map/districtsearch.js
index dcba0a1..a145b87 100644
--- a/src/utils/map/districtsearch.js
+++ b/src/utils/map/districtsearch.js
@@ -1,53 +1,83 @@
-import { map, AMap, onMapMounted } from './index';
+import { map, AMap, onMapMounted } from './index'
// 琛屾斂鍖哄垝缂撳瓨
-var districtPolygonMap = new Map();
+var districtPolygonMap = new Map()
// 褰撳墠鏄剧ず鐨勫尯鍘�
-var activeDistrict = undefined;
+var activeDistrict = undefined
export default {
// 缁樺埗鍖哄幙杈圭晫
drawDistrict(districtName, isNew) {
- if(!districtName) return;
+ if (!districtName) return
onMapMounted(() => {
if (!isNew && districtPolygonMap.has(districtName)) {
- const districtPolygon = districtPolygonMap.get(districtName);
- map.add(districtPolygon);
- map.setFitView(districtPolygon);
- activeDistrict = districtPolygon;
+ const { polygon, mask } = districtPolygonMap.get(districtName)
+ map.add(polygon)
+ map.setFitView(polygon)
+ map.setMask(mask)
+ activeDistrict = polygon
} else {
var district = new AMap.DistrictSearch({
extensions: 'all', //杩斿洖琛屾斂鍖鸿竟鐣屽潗鏍囩瓑鍏蜂綋淇℃伅
- level: 'district' //璁剧疆鏌ヨ琛屾斂鍖虹骇鍒负鍖�
- });
+ level: 'district', //璁剧疆鏌ヨ琛屾斂鍖虹骇鍒负鍖�
+ })
district.search(districtName, function (status, result) {
- var bounds = result.districtList[0].boundaries; //鑾峰彇杈圭晫淇℃伅
- if (bounds) {
+ if (status === 'complete') {
+ var bounds = result.districtList[0].boundaries //鑾峰彇杈圭晫淇℃伅
+ var mask = []
+ var polygon = []
for (var i = 0; i < bounds.length; i++) {
+ mask.push([bounds[i]])
+
//鐢熸垚琛屾斂鍖哄垝 polygon
const districtPolygon = new AMap.Polygon({
map: map, //鏄剧ず璇ヨ鐩栫墿鐨勫湴鍥惧璞�
- strokeWeight: 1, //杞粨绾垮搴�
+ strokeWeight: 2, //杞粨绾垮搴�
path: bounds[i], //澶氳竟褰㈣疆寤撶嚎鐨勮妭鐐瑰潗鏍囨暟缁�
- fillOpacity: 0.4, //澶氳竟褰㈠~鍏呴�忔槑搴�
+ fillOpacity: 0, //澶氳竟褰㈠~鍏呴�忔槑搴�
fillColor: '#0077ff',
- strokeColor: '#CC66CC' //绾挎潯棰滆壊
- });
+ strokeColor: '#99ffff', //绾挎潯棰滆壊
+ })
- districtPolygonMap.set(districtName, districtPolygon);
- activeDistrict = districtPolygon;
- map.setFitView(districtPolygon, true);
+ polygon.push(districtPolygon)
}
+ activeDistrict = polygon
+ districtPolygonMap.set(districtName, { polygon, mask })
+ map.setFitView(polygon, true)
+ map.setMask(mask)
}
- });
+ })
}
- });
+ })
},
removeDistrict() {
onMapMounted(() => {
if (activeDistrict) {
- map.remove(activeDistrict);
- activeDistrict = undefined;
+ map.remove(activeDistrict)
+ activeDistrict = undefined
}
})
- }
-};
+ },
+ districtLayer(districtName) {
+ onMapMounted(() => {
+ //2銆佸垱寤虹渷甯傜畝鏄撹鏀垮尯鍥惧眰
+ var distProvince = new AMap.DistrictLayer.Province({
+ zIndex: 10, //璁剧疆鍥惧眰灞傜骇
+ zooms: [2, 15], //璁剧疆鍥惧眰鏄剧ず鑼冨洿
+ adcode: districtName, //璁剧疆琛屾斂鍖� adcode
+ depth: 2, //璁剧疆鏁版嵁鏄剧ず灞傜骇锛�0锛氭樉绀哄浗瀹堕潰锛�1锛氭樉绀虹渷绾э紝褰撳浗瀹朵负涓浗鏃惰缃甦epth涓�2鐨勫彲浠ユ樉绀哄競涓�绾�
+ })
+ // 3銆佽缃鏀垮尯鍥惧眰鏍峰紡
+ distProvince.setStyles({
+ 'stroke-width': 2, //鎻忚竟绾垮
+ fill: function (data) {
+ //璁剧疆鍖哄煙濉厖棰滆壊锛屽彲鏍规嵁鍥炶皟淇℃伅杩斿洖鍖哄煙淇℃伅璁剧疆涓嶅悓濉厖鑹�
+ //鍥炶皟杩斿洖鍖哄煙淇℃伅鏁版嵁锛屽瓧娈靛寘鎷� SOC(鍥藉浠g爜)銆丯AME_ENG(鑻辨枃鍚嶇О)銆丯AME_CHN(涓枃鍚嶇О)绛�
+ //鍥藉浠g爜鍚嶇О璇存槑鍙傝�� https://a.amap.com/jsapi_demos/static/demo-center/js/soc-list.json
+ return '#ffffffe7'
+ },
+ })
+ //4銆佸皢绠�鏄撹鏀垮尯鍥惧眰娣诲姞鍒板湴鍥�
+ map.add(distProvince)
+ })
+ },
+}
diff --git a/src/utils/map/index.js b/src/utils/map/index.js
index 76a1e7b..80a18f1 100644
--- a/src/utils/map/index.js
+++ b/src/utils/map/index.js
@@ -1,28 +1,28 @@
-import AMapLoader from '@amap/amap-jsapi-loader';
+import AMapLoader from '@amap/amap-jsapi-loader'
-var mapInitDone = false;
-var onMapMountedEvents = [];
+var mapInitDone = false
+var onMapMountedEvents = []
-var AMap;
+var AMap
// 鍦板浘瀵硅薄
-var map;
+var map
// 鍗槦鍥惧眰
-var satellite;
+var satellite
// 榧犳爣缁樺浘
-var mouseTool;
+var mouseTool
// 3D鍥惧眰
-var object3Dlayer;
+var object3Dlayer
// 鍦板浘鎷栧姩鐘舵��
-var isDragging = false;
+var isDragging = false
// 鍦板浘鍔犺浇瀹屾垚瑙﹀彂
function onMapMounted(...events) {
if (mapInitDone) {
events.forEach((e) => {
- e();
- });
+ e()
+ })
} else {
- onMapMountedEvents = onMapMountedEvents.concat(events);
+ onMapMountedEvents = onMapMountedEvents.concat(events)
}
}
@@ -36,50 +36,51 @@
'AMap.ControlBar',
'AMap.ToolBar',
'AMap.Scale',
- 'AMap.DistrictSearch'
+ 'AMap.DistrictSearch',
// 'AMap.DragRoute',
// 'AMap.MouseTool',
// 'AMap.PolygonEditor'
- ]
+ ],
})
.then((_AMap) => {
- AMap = _AMap;
- _initMap(id);
- mapInitDone = true;
+ AMap = _AMap
+ _initMap(id)
+ mapInitDone = true
onMapMountedEvents.forEach((e) => {
- e();
- });
- onMapMountedEvents = [];
- console.log('-------------------map init done');
+ e()
+ })
+ onMapMountedEvents = []
+ console.log('-------------------map init done')
})
.catch((e) => {
- console.log(e);
- });
+ console.log(e)
+ })
}
function destroyMap() {
- map?.destroy();
- map = null;
- mapInitDone = false;
+ map?.destroy()
+ map = null
+ mapInitDone = false
}
function _initMap(elementId) {
map = new AMap.Map(elementId, {
// mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
features: ['bg', 'road'],
- pitch: 45, // 鍦板浘淇话瑙掑害锛屾湁鏁堣寖鍥� 0 搴�- 83 搴�
- viewMode: '2D', // 鍦板浘妯″紡
+ pitch: 30, // 鍦板浘淇话瑙掑害锛屾湁鏁堣寖鍥� 0 搴�- 83 搴�
+ viewMode: '3D', // 鍦板浘妯″紡
resizeEnable: true,
center: [121.6039283, 31.25295567],
zooms: [2, 26],
- zoom: 14
- });
+ zoom: 14,
+ })
// map = new AMap.Map(elementId);
// 娣诲姞鍗槦鍦板浘
- satellite = new AMap.TileLayer.Satellite();
- satellite.hide();
- map.add([satellite]);
+ satellite = new AMap.TileLayer.Satellite()
+ const roadNet = new AMap.TileLayer.RoadNet()
+ // satellite.hide()
+ map.add([satellite, roadNet])
// _initMouseTool();
// _init3DLayer();
@@ -88,36 +89,27 @@
// 榧犳爣缁樺浘鍒濆鍖�
function _initMouseTool() {
- mouseTool = new AMap.MouseTool(map);
+ mouseTool = new AMap.MouseTool(map)
}
// 3D鍥惧眰鍒濆鍖�
function _init3DLayer() {
- object3Dlayer = new AMap.Object3DLayer();
- map.add(object3Dlayer);
+ object3Dlayer = new AMap.Object3DLayer()
+ map.add(object3Dlayer)
}
// 璁剧疆鍦板浘鎷栨嫿鐩戝惉浜嬩欢
function _initDragEvent() {
- let dragEndEvent;
+ let dragEndEvent
map.on('dragstart', () => {
- clearTimeout(dragEndEvent);
- isDragging = true;
- });
+ clearTimeout(dragEndEvent)
+ isDragging = true
+ })
map.on('dragend', function () {
dragEndEvent = setTimeout(() => {
- isDragging = false;
- }, 8000);
- });
+ isDragging = false
+ }, 8000)
+ })
}
-export {
- createMap,
- destroyMap,
- onMapMounted,
- map,
- AMap,
- mouseTool,
- object3Dlayer,
- isDragging
-};
+export { createMap, destroyMap, onMapMounted, map, AMap, mouseTool, object3Dlayer, isDragging }
diff --git a/src/views/inspection/scenenew/UserEdit.vue b/src/views/inspection/scenenew/UserEdit.vue
new file mode 100644
index 0000000..1db19c5
--- /dev/null
+++ b/src/views/inspection/scenenew/UserEdit.vue
@@ -0,0 +1,191 @@
+<template>
+ <el-page-header @back="onBack">
+ <template #content>
+ <span> 璐︽埛淇℃伅缂栬緫 </span>
+ </template>
+ </el-page-header>
+ <el-divider />
+ <el-tabs v-model="activeName" class="p-h-8" @tab-click="handleClick">
+ <el-tab-pane label="鍩烘湰淇℃伅" name="first">
+ <FormCol>
+ <div class="sub-title">璐︽埛淇℃伅</div>
+ <CompUserInfo :model="formUser" />
+ </FormCol>
+ <el-divider />
+ <FormCol>
+ <div class="sub-title">搴楅摵淇℃伅</div>
+ <CompSceneInfo :form-info="formSceneInfo" />
+ </FormCol>
+ <el-divider />
+ <FormCol>
+ <div class="sub-title">浼佷笟淇℃伅</div>
+ <CompCompanyInfo :form-info="formCompanyInfo" />
+ </FormCol>
+ </el-tab-pane>
+ <el-tab-pane label="璁惧绠$悊" name="second">
+ <FormCol>
+ <el-row class="sub-title" justify="space-between">
+ <div>鐩戞祴璁惧淇℃伅</div>
+ <el-button type="success" @click="addDevice">鏂板璁惧</el-button>
+ </el-row>
+ <!-- 鏂板璁惧琛ㄥ崟 -->
+ <CompDeviceInfo
+ v-if="showAddDevice"
+ :form-info="newDeviceForm"
+ :create="true"
+ @onSubmit="handleDeviceSubmit"
+ @onCancel="handleDeviceCancel"
+ />
+ <!-- 璁惧鍒楄〃 -->
+ <div v-if="formDeviceList.length === 0 && !showAddDevice" class="empty-device">
+ <el-empty description="鏆傛棤璁惧淇℃伅" />
+ </div>
+ <CompDeviceInfo
+ v-else-if="formDeviceList.length > 0"
+ v-for="(item, index) in formDeviceList"
+ :key="index"
+ :form-info="item"
+ />
+ </FormCol>
+ </el-tab-pane>
+
+ <el-tab-pane label="鍗卞簾鎺掓薄" name="third">
+ <FormCol>
+ <div class="sub-title">鍗卞簾鎺掓薄娓呭崟</div>
+ <CompHazardousWasteFile :form-info="formHazardousWasteFile" />
+ </FormCol>
+ <FormCol>
+ <div class="sub-title">鍗卞簾鎺掓薄璁板綍</div>
+ <CompHazardousWasteRecord :form-info="formHazardousWasteRecord" />
+ </FormCol>
+ </el-tab-pane>
+
+ <el-tab-pane label="琛屾斂澶勭綒" name="fourth">
+ <FormCol>
+ <div class="sub-title">琛屾斂澶勭綒琛�</div>
+ <!-- <CompPunishment :form-info="formProblem" /> -->
+ </FormCol>
+ </el-tab-pane>
+
+ <el-tab-pane label="淇¤鎶曡瘔" name="fifth">
+ <FormCol>
+ <div class="sub-title">淇¤鎶曡瘔</div>
+ <!-- <CompLaint :form-info="formLaint" /> -->
+ </FormCol>
+ </el-tab-pane>
+
+ <el-tab-pane label="宸℃煡闂琛�" name="sixth">
+ <FormCol>
+ <div class="sub-title">宸℃煡闂琛�</div>
+ <!-- <CompProblem :form-info="formProblem" /> -->
+ </FormCol>
+ </el-tab-pane>
+ </el-tabs>
+
+ <!-- <ComBaseInformation v-model="drawer"></ComBaseInformation> -->
+</template>
+
+<script>
+import userApi from '@/api/fytz/userApi'
+import CompUserInfo from './components/CompUserInfo.vue'
+import CompSceneInfo from './components/CompSceneInfo.vue'
+import CompCompanyInfo from './components/CompCompanyInfo.vue'
+import CompDeviceInfo from './components/CompDeviceInfo.vue'
+import CompHazardousWasteFile from './components/CompHazardousWasteFile.vue'
+import CompHazardousWasteRecord from './components/CompHazardousWasteRecord.vue'
+
+export default {
+ components: {
+ // ComBaseInformation,
+ // CompLaint,
+ CompUserInfo,
+ CompSceneInfo,
+ CompCompanyInfo,
+ CompDeviceInfo,
+ CompHazardousWasteFile,
+ CompHazardousWasteRecord,
+ // CompPanyInfo,
+ // CompFumePurifyDevice,
+ // CompHazardousWasteFile,
+ // CompHazardousWasteRecord,
+ // CompProblem,
+ // CompPunishment,
+ // CompRestaurantBaseInfo,
+ // CompVehicleBaseInfo,
+ // CompUserInfos,
+ },
+ data() {
+ return {
+ drawer: false,
+ formUser: {},
+ formSceneInfo: {},
+ formCompanyInfo: {},
+ // formSubScene: {},
+ formLaint: {},
+ formDeviceList: [],
+ formPanyInfo: {},
+ formFumePurifyDevice: {},
+ formHazardousWasteFile: {},
+ formHazardousWasteRecord: {},
+ formProblem: {},
+ formPunishment: {},
+ formRestaurantBaseInfo: {},
+ activeName: 'first',
+ scroll: '',
+ showAddDevice: false,
+ newDeviceForm: {},
+ }
+ },
+ beforeRouteEnter(to, from, next) {
+ userApi.fetchUserBaseInfo(to.params.userId).then((res) => {
+ next((vm) => {
+ if (res.userInfo) {
+ vm.formUser = res.userInfo
+ } else {
+ vm.formUser = {
+ guid: to.params.userId,
+ }
+ }
+ })
+ })
+ },
+ methods: {
+ handleClick(tab) {
+ console.log('tab', tab)
+ },
+ // 鍥為��椤甸潰
+ onBack() {
+ this.$router.back()
+ },
+ // 鏂板璁惧
+ addDevice() {
+ this.showAddDevice = true
+ this.newDeviceForm = {}
+ },
+ // 璁惧鎻愪氦
+ handleDeviceSubmit(formData) {
+ // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+ this.formDeviceList.push(formData.value)
+ this.showAddDevice = false
+ this.newDeviceForm = {}
+ },
+ // 璁惧鍙栨秷
+ handleDeviceCancel() {
+ this.showAddDevice = false
+ this.newDeviceForm = {}
+ },
+ },
+}
+</script>
+<style scoped>
+.sub-title {
+ font-size: var(--el--font--size--large);
+ margin-bottom: 30px;
+ margin-top: 30px;
+ margin-left: 20px;
+}
+.empty-device {
+ padding: 40px 0;
+ text-align: center;
+}
+</style>
diff --git a/src/views/inspection/scenenew/UserInfo.vue b/src/views/inspection/scenenew/UserInfo.vue
new file mode 100644
index 0000000..73dbfb2
--- /dev/null
+++ b/src/views/inspection/scenenew/UserInfo.vue
@@ -0,0 +1,226 @@
+<template>
+ <FYTable @search="onSearch" :row-class-name="tableRowClassName">
+ <template #options>
+ <FYOptionLocation
+ :allOption="true"
+ :level="5"
+ v-model:value="formSearch._locations"
+ ></FYOptionLocation>
+ <FYOptionText
+ label="鍦烘櫙鍚嶇О"
+ placeholder="杈撳叆鍚嶇О鍏抽敭瀛�"
+ v-model:value="formSearch.searchText"
+ ></FYOptionText>
+ <FYOptionScene
+ :allOption="true"
+ :type="1"
+ :initValue="false"
+ v-model:value="formSearch.scensetype"
+ ></FYOptionScene>
+ <FYOptionOnlineStatus
+ :allOption="true"
+ v-model:value="formSearch.online"
+ ></FYOptionOnlineStatus>
+ </template>
+
+ <template #table-column>
+ <el-table-column
+ fixed="left"
+ prop="userInfo.realname"
+ label="鍚嶇О"
+ :show-overflow-tooltip="true"
+ width="400"
+ >
+ </el-table-column>
+ <el-table-column prop="userInfo.acountname" label="璐﹀彿" width="110" />
+ <el-table-column prop="sceneTypeName" label="绫诲瀷" width="100" />
+ <el-table-column prop="biProvinceName" label="鐪�" width="80" />
+ <el-table-column prop="biCityName" label="甯�" width="80" />
+ <!-- <el-table-column prop="districtname" label="鍖哄幙" width="90" /> -->
+ <el-table-column prop="userInfo.extension1" label="鍖哄幙" width="80" />
+ <el-table-column prop="biTownName" label="琛楅亾" width="110" />
+ <el-table-column prop="biArea" label="闆嗕腑鍖�" width="110" />
+ <el-table-column prop="biManagementCompany" label="鐗╀笟" min-width="110" />
+ <el-table-column prop="userInfo.isenable" label="鐘舵��" width="90">
+ <template #default="{ row }">
+ {{ row.userInfo.isenable ? '涓婄嚎涓�' : '宸蹭笅绾�' }}
+ </template>
+ </el-table-column>
+ <el-table-column prop="userInfo.usertype" label="鐢ㄦ埛绫诲瀷" width="90" />
+ <el-table-column fixed="right" align="right" label="鎿嶄綔" width="190">
+ <template #header>
+ <el-button icon="DocumentAdd" size="default" type="success" @click="drawer = true"
+ >鏂板鐢ㄦ埛</el-button
+ >
+ </template>
+ <template #default="{ row }">
+ <el-space>
+ <el-button
+ :loading="row.loading2"
+ :type="row.userInfo.isenable != '0' ? 'danger' : 'primary'"
+ size="small"
+ @click="itemActive(row)"
+ >{{ row.userInfo.isenable != '0' ? '涓嬬嚎' : '涓婄嚎' }}</el-button
+ >
+ <el-button-group>
+ <el-button type="primary" :loading="row.loading1" size="small" @click="editRow(row)"
+ >鏌ョ湅</el-button
+ >
+ <el-dropdown @command="handleCommand" trigger="click">
+ <el-button
+ type="primary"
+ :loading="row.downloadLoading"
+ size="small"
+ :icon="row.downloadLoading ? '' : 'ArrowDown'"
+ ></el-button>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item icon="Download" :command="{ c: 1, p: row }"
+ >涓嬭浇鐜俊鐮�</el-dropdown-item
+ >
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
+ </el-button-group>
+ <!-- <el-dropdown
+ split-button
+ :loading="row.loading1"
+ size="small"
+ type="primary"
+ @click="editRow(row)"
+ @command="handleCommand"
+ trigger="click"
+ >
+ 鏌ョ湅
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item icon="Download" :command="{ c: 1, p: row }"
+ >涓嬭浇鐜俊鐮�</el-dropdown-item
+ >
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown> -->
+ </el-space>
+ </template>
+ </el-table-column>
+ </template>
+ </FYTable>
+ <CompUserInfoAddDrawer v-model="drawer"></CompUserInfoAddDrawer>
+</template>
+
+<script>
+import userApi from '@/api/fytz/userApi'
+import creditApi from '@/api/fytz/creditApi'
+import { useLoadingStore } from '@/stores/loadingStore'
+import { mapStores } from 'pinia'
+import { useMessageBoxTip } from '@/composables/messageBox'
+import CompUserInfoAddDrawer from './components/CompUserInfoAddDrawer.vue'
+
+export default {
+ components: {
+ CompUserInfoAddDrawer,
+ },
+ data() {
+ return {
+ // 鏌ヨ鏉′欢
+ formSearch: {
+ _locations: {},
+ searchText: '',
+ scensetype: {
+ label: '椁愰ギ',
+ value: '1',
+ },
+ online: {},
+ },
+ // 鏂板鐢ㄦ埛寮瑰嚭妗�
+ drawer: false,
+ }
+ },
+ computed: {
+ ...mapStores(useLoadingStore),
+ },
+ methods: {
+ onSearch(page, func) {
+ const f = this.formSearch
+ const area = {}
+ // 琛屾斂鍖哄垝
+ area.provinceCode = f._locations.pCode
+ area.provinceName = f._locations.pName
+ if (area.provinceCode == null) {
+ area.provinceCode = null
+ area.provinceName = null
+ }
+ area.cityCode = f._locations.cCode
+ area.cityName = f._locations.cName
+ area.districtCode = f._locations.dCode
+ area.districtName = f._locations.dName
+ area.townCode = f._locations.tCode
+ area.townName = f._locations.tName
+ // 鍦烘櫙绫诲瀷
+ area.sceneTypes = []
+ f.scensetype.value == null ? (area.sceneTypes = []) : (area.sceneTypes = [f.scensetype.value])
+ // 涓婁笅绾跨姸鎬�
+ area.online = f.online.value
+ // 鍏抽敭瀛�
+ area.searchText = f.searchText
+
+ userApi.fetchUser(page.currentPage, page.pageSize, area).then((res) => {
+ if (res) {
+ func({
+ data: res.data,
+ total: res.head.totalCount,
+ })
+ }
+ })
+ },
+ editRow(row) {
+ row.loading1 = true
+ this.loadingStore.pushLoading(() => (row.loading1 = false))
+ this.$router.push(`scene-info-edit/${row.userInfo.guid}`)
+ },
+ itemActive(row) {
+ const param = {
+ guid: row.userInfo.guid,
+ isenable: !row.userInfo.isenable,
+ }
+ const msg = row.userInfo.isenable ? '涓嬬嚎' : '涓婄嚎'
+ useMessageBoxTip({
+ confirmMsg: `纭${msg}璇ュ満鏅紵`,
+ confirmTitle: msg,
+ onConfirm: async () => {
+ row.loading2 = true
+ return userApi
+ .updateUserInfo(param)
+ .then((res) => {
+ if (res.success) {
+ row.userInfo.isenable = param.isenable
+ }
+ })
+ .finally(() => {
+ row.loading2 = false
+ })
+ },
+ })
+ },
+ tableRowClassName({ row }) {
+ return row.userInfo.isenable ? 'online-row' : 'offline-row'
+ },
+ handleCommand(e) {
+ const userId = e.p.userInfo.guid
+ switch (e.c) {
+ // 涓嬭浇鐜俊鐮�
+ case 1:
+ e.p.downloadLoading = true
+ creditApi.downloadCode(userId).finally(() => {
+ e.p.downloadLoading = false
+ })
+ break
+
+ default:
+ break
+ }
+ },
+ },
+}
+</script>
+<style></style>
diff --git a/src/views/inspection/scenenew/components/CompCompanyInfo.vue b/src/views/inspection/scenenew/components/CompCompanyInfo.vue
new file mode 100644
index 0000000..dc440f1
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompCompanyInfo.vue
@@ -0,0 +1,205 @@
+<template>
+ <el-form
+ :inline="false"
+ :model="formObj"
+ ref="formRef"
+ :rules="rules"
+ label-position="right"
+ label-width="150px"
+ >
+ <el-form-item label="鍗曚綅鍚嶇О" prop="companyName">
+ <el-input clearable v-model="formObj.companyName" placeholder="鍗曚綅鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="涓昏浠庝簨涓氬姟" prop="businessScope">
+ <el-input
+ clearable
+ v-model="formObj.businessScope"
+ placeholder="涓昏浠庝簨涓氬姟"
+ type="textarea"
+ rows="2"
+ />
+ </el-form-item>
+ <el-form-item label="鎵�灞為泦鍥�" prop="group">
+ <el-input clearable v-model="formObj.group" placeholder="鎵�灞為泦鍥�" />
+ </el-form-item>
+ <el-form-item label="鐪佷唤鍚嶇О" prop="province">
+ <el-input clearable v-model="formObj.province" placeholder="鐪佷唤鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="鍦板競鍚嶇О" prop="city">
+ <el-input clearable v-model="formObj.city" placeholder="鍦板競鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="鍖哄幙鍚嶇О" prop="district">
+ <el-input clearable v-model="formObj.district" placeholder="鍖哄幙鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="琛楅晣鍚嶇О" prop="town">
+ <el-input clearable v-model="formObj.town" placeholder="琛楅晣鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="鎵�鍦ㄥ伐涓氬尯" prop="industrialZone">
+ <el-input clearable v-model="formObj.industrialZone" placeholder="鎵�鍦ㄥ伐涓氬尯" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅鍦板潃" prop="address">
+ <el-input
+ clearable
+ v-model="formObj.address"
+ placeholder="鍗曚綅鍦板潃"
+ type="textarea"
+ rows="2"
+ />
+ </el-form-item>
+ <el-form-item label="缁勭粐鏈烘瀯浠g爜" prop="orgCode">
+ <el-input clearable v-model="formObj.orgCode" placeholder="缁勭粐鏈烘瀯浠g爜" />
+ </el-form-item>
+ <el-form-item label="娉曚汉" prop="legalPerson">
+ <el-input clearable v-model="formObj.legalPerson" placeholder="娉曚汉" />
+ </el-form-item>
+ <el-form-item label="琛屼笟绫诲埆" prop="industryCategory">
+ <el-input clearable v-model="formObj.industryCategory" placeholder="琛屼笟绫诲埆" />
+ </el-form-item>
+ <el-form-item label="琛屼笟浠g爜" prop="industryCode">
+ <el-input clearable v-model="formObj.industryCode" placeholder="琛屼笟浠g爜" />
+ </el-form-item>
+ <el-form-item label="鐧昏娉ㄥ唽绫诲瀷" prop="registrationType">
+ <el-input clearable v-model="formObj.registrationType" placeholder="鐧昏娉ㄥ唽绫诲瀷" />
+ </el-form-item>
+ <el-form-item label="娉ㄥ唽璧勬湰锛堜竾鍏冿級" prop="registeredCapital">
+ <el-input
+ clearable
+ type="number"
+ v-model="formObj.registeredCapital"
+ placeholder="娉ㄥ唽璧勬湰锛堜竾鍏冿級"
+ />
+ </el-form-item>
+ <el-form-item label="寤哄巶骞存湀" prop="establishmentDate">
+ <el-input clearable v-model="formObj.establishmentDate" placeholder="寤哄巶骞存湀" />
+ </el-form-item>
+ <el-form-item label="鏈�鏂版敼鎵╁缓骞存湀" prop="latestExpansionDate">
+ <el-input clearable v-model="formObj.latestExpansionDate" placeholder="鏈�鏂版敼鎵╁缓骞存湀" />
+ </el-form-item>
+ <el-form-item label="鑱屽伐浜烘暟" prop="employeeCount">
+ <el-input clearable type="number" v-model="formObj.employeeCount" placeholder="鑱屽伐浜烘暟" />
+ </el-form-item>
+ <el-form-item label="浼佷笟瑙勬ā" prop="companyScale">
+ <el-input clearable v-model="formObj.companyScale" placeholder="浼佷笟瑙勬ā" />
+ </el-form-item>
+ <el-form-item label="鍘嗘鐜瘎瀹℃壒骞存湀" prop="鐜瘎ApprovalDate">
+ <el-input clearable v-model="formObj.鐜瘎ApprovalDate" placeholder="鍘嗘鐜瘎瀹℃壒骞存湀" />
+ </el-form-item>
+ <el-form-item label="鎺掓薄璁稿彲璇佺紪鍙�" prop="pollutantLicenseNumber">
+ <el-input clearable v-model="formObj.pollutantLicenseNumber" placeholder="鎺掓薄璁稿彲璇佺紪鍙�" />
+ </el-form-item>
+ <el-form-item label="鎺掓薄鏉冧氦鏄撴枃浠�" prop="emissionRightFile">
+ <el-input clearable v-model="formObj.emissionRightFile" placeholder="鎺掓薄鏉冧氦鏄撴枃浠�" />
+ </el-form-item>
+ <el-form-item label="閭斂缂栫爜" prop="postalCode">
+ <el-input clearable v-model="formObj.postalCode" placeholder="閭斂缂栫爜" />
+ </el-form-item>
+ <el-form-item label="鑱旂郴浜哄鍚�" prop="contactName">
+ <el-input clearable v-model="formObj.contactName" placeholder="鑱旂郴浜哄鍚�" />
+ </el-form-item>
+ <el-form-item label="鑱旂郴鐢佃瘽" prop="telephone">
+ <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鑱旂郴鐢佃瘽">
+ <template #prepend>
+ <el-icon><Iphone /></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item label="鑱旂郴寰俊鍙�" prop="wechat">
+ <el-input clearable v-model="formObj.wechat" placeholder="鑱旂郴寰俊鍙�" />
+ </el-form-item>
+ <el-form-item label="浼犵湡" prop="fax">
+ <el-input clearable v-model="formObj.fax" placeholder="浼犵湡" />
+ </el-form-item>
+ <el-form-item label="鐢靛瓙閭" prop="email">
+ <el-input clearable type="email" v-model="formObj.email" placeholder="鐢靛瓙閭" />
+ </el-form-item>
+
+ <el-form-item>
+ <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+ >鎻愪氦</el-button
+ >
+ <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+ //浼佷笟淇℃伅
+ formInfo: Object,
+ //鏄垱寤烘垨鑰呮洿鏂�
+ create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+ submit: {
+ do: submit,
+ },
+ cancel: {
+ do: cancel,
+ },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+ companyName: [
+ {
+ required: true,
+ message: '鍗曚綅鍚嶇О涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ address: [
+ {
+ required: true,
+ message: '鍗曚綅鍦板潃涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ contactName: [
+ {
+ required: true,
+ message: '鑱旂郴浜哄鍚嶄笉鑳戒负绌�',
+ trigger: 'blur',
+ },
+ ],
+ telephone: [
+ {
+ required: true,
+ message: '鑱旂郴鐢佃瘽涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+})
+
+// 浼佷笟淇℃伅鏍煎紡鍖�
+function parseCompanyInfo(s) {
+ return s
+}
+
+function updateCompany() {
+ updateLoading.value = true
+ // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+ setTimeout(() => {
+ updateLoading.value = false
+ }, 1000)
+}
+
+watch(
+ () => props.formInfo,
+ (nValue) => {
+ formObj.value = parseCompanyInfo(nValue)
+ },
+)
+
+function submit() {
+ emit('onSubmit', formObj)
+ return updateCompany()
+}
+function cancel() {
+ emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompDeviceInfo.vue b/src/views/inspection/scenenew/components/CompDeviceInfo.vue
new file mode 100644
index 0000000..385f1e2
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompDeviceInfo.vue
@@ -0,0 +1,159 @@
+<template>
+ <el-form
+ :inline="false"
+ :model="formObj"
+ ref="formRef"
+ :rules="rules"
+ label-position="right"
+ label-width="150px"
+ >
+ <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+ <el-input clearable v-model="formObj.deviceName" placeholder="璁惧鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="璁惧鍨嬪彿" prop="deviceModel">
+ <el-input clearable v-model="formObj.deviceModel" placeholder="璁惧鍨嬪彿" />
+ </el-form-item>
+ <el-form-item label="璁惧缂栧彿" prop="deviceCode">
+ <el-input clearable v-model="formObj.deviceCode" placeholder="璁惧缂栧彿" />
+ </el-form-item>
+ <el-form-item label="鐢熶骇鍘傚" prop="manufacturer">
+ <el-input clearable v-model="formObj.manufacturer" placeholder="鐢熶骇鍘傚" />
+ </el-form-item>
+ <el-form-item label="瀹夎鏃ユ湡" prop="installationDate">
+ <el-input clearable v-model="formObj.installationDate" placeholder="瀹夎鏃ユ湡" />
+ </el-form-item>
+ <el-form-item label="璁惧鐘舵��" prop="status">
+ <el-select v-model="formObj.status" placeholder="璁惧鐘舵��">
+ <el-option label="姝e父" value="normal" />
+ <el-option label="寮傚父" value="abnormal" />
+ <el-option label="缁存姢涓�" value="maintenance" />
+ <el-option label="鍋滅敤" value="disabled" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="璁惧浣嶇疆" prop="location">
+ <el-input clearable v-model="formObj.location" placeholder="璁惧浣嶇疆" />
+ </el-form-item>
+ <el-form-item label="缁存姢鍛ㄦ湡" prop="maintenanceCycle">
+ <el-input clearable v-model="formObj.maintenanceCycle" placeholder="缁存姢鍛ㄦ湡" />
+ </el-form-item>
+ <el-form-item label="涓婃缁存姢鏃ユ湡" prop="lastMaintenanceDate">
+ <el-input clearable v-model="formObj.lastMaintenanceDate" placeholder="涓婃缁存姢鏃ユ湡" />
+ </el-form-item>
+ <el-form-item label="璐熻矗浜�" prop="responsiblePerson">
+ <el-input clearable v-model="formObj.responsiblePerson" placeholder="璐熻矗浜�" />
+ </el-form-item>
+ <el-form-item label="鑱旂郴鐢佃瘽" prop="contactPhone">
+ <el-input clearable type="tel" v-model="formObj.contactPhone" placeholder="鑱旂郴鐢佃瘽">
+ <template #prepend>
+ <el-icon><Iphone /></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item label="璁惧鎻忚堪" prop="description">
+ <el-input
+ clearable
+ v-model="formObj.description"
+ placeholder="璁惧鎻忚堪"
+ type="textarea"
+ rows="2"
+ />
+ </el-form-item>
+
+ <el-form-item>
+ <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+ >鎻愪氦</el-button
+ >
+ <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+ <el-button v-if="create" @click="cancel">鍙栨秷</el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+ //璁惧淇℃伅
+ formInfo: Object,
+ //鏄垱寤烘垨鑰呮洿鏂�
+ create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+ submit: {
+ do: submit,
+ },
+ cancel: {
+ do: cancel,
+ },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+ deviceName: [
+ {
+ required: true,
+ message: '璁惧鍚嶇О涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ deviceModel: [
+ {
+ required: true,
+ message: '璁惧鍨嬪彿涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ deviceCode: [
+ {
+ required: true,
+ message: '璁惧缂栧彿涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ manufacturer: [
+ {
+ required: true,
+ message: '鐢熶骇鍘傚涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ status: [
+ {
+ required: true,
+ message: '璁惧鐘舵�佷笉鑳戒负绌�',
+ trigger: 'change',
+ },
+ ],
+})
+
+// 璁惧淇℃伅鏍煎紡鍖�
+function parseDeviceInfo(s) {
+ return s
+}
+
+function updateDevice() {
+ updateLoading.value = true
+ // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+ setTimeout(() => {
+ updateLoading.value = false
+ }, 1000)
+}
+
+watch(
+ () => props.formInfo,
+ (nValue) => {
+ formObj.value = parseDeviceInfo(nValue)
+ },
+)
+
+function submit() {
+ emit('onSubmit', formObj)
+ return updateDevice()
+}
+function cancel() {
+ emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue b/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue
new file mode 100644
index 0000000..50ede86
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompHazardousWasteFile.vue
@@ -0,0 +1 @@
+<template>s</template>
diff --git a/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue b/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue
new file mode 100644
index 0000000..50ede86
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompHazardousWasteRecord.vue
@@ -0,0 +1 @@
+<template>s</template>
diff --git a/src/views/inspection/scenenew/components/CompSceneInfo.vue b/src/views/inspection/scenenew/components/CompSceneInfo.vue
new file mode 100644
index 0000000..874818e
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompSceneInfo.vue
@@ -0,0 +1,132 @@
+<template>
+ <el-form
+ :inline="false"
+ :model="formObj"
+ ref="formRef"
+ :rules="rules"
+ label-position="right"
+ label-width="150px"
+ >
+ <el-form-item label="搴楅摵鍚嶇О" prop="shopName">
+ <el-input clearable v-model="formObj.shopName" placeholder="搴楅摵鍚嶇О" />
+ </el-form-item>
+ <el-form-item label="鎵�灞炲叕鍙�" prop="company">
+ <el-input clearable v-model="formObj.company" placeholder="鎵�灞炲叕鍙�" />
+ </el-form-item>
+ <el-form-item label="闆嗕腑鍖�" prop="centralArea">
+ <el-input clearable v-model="formObj.centralArea" placeholder="闆嗕腑鍖�" />
+ </el-form-item>
+ <el-form-item label="鐗╀笟鍏徃" prop="propertyCompany">
+ <el-input clearable v-model="formObj.propertyCompany" placeholder="鐗╀笟鍏徃" />
+ </el-form-item>
+ <el-form-item label="鑱旂郴浜�" prop="contactName">
+ <el-input clearable v-model="formObj.contactName" placeholder="鑱旂郴浜�" />
+ </el-form-item>
+ <el-form-item label="鑱旂郴鐢佃瘽" prop="telephone">
+ <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鑱旂郴鐢佃瘽">
+ <template #prepend>
+ <el-icon><Iphone /></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item label="鍦板潃" prop="address">
+ <el-input clearable v-model="formObj.address" placeholder="鍦板潃" type="textarea" rows="2" />
+ </el-form-item>
+
+ <el-form-item>
+ <el-button :disabled="!edit" type="primary" @click="onSubmit" :loading="updateLoading"
+ >鎻愪氦</el-button
+ >
+ <el-button :disabled="!edit" @click="onReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch } from 'vue'
+import { Iphone } from '@element-plus/icons-vue'
+import { useFormConfirm } from '@/composables/formConfirm'
+
+const props = defineProps({
+ //鍩烘湰淇℃伅
+ formInfo: Object,
+ //鏄垱寤烘垨鑰呮洿鏂�
+ create: Boolean,
+})
+const emit = defineEmits(['onSubmit', 'onCancel'])
+
+const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({
+ submit: {
+ do: submit,
+ },
+ cancel: {
+ do: cancel,
+ },
+})
+const updateLoading = ref(false)
+const rules = reactive({
+ shopName: [
+ {
+ required: true,
+ message: '搴楅摵鍚嶇О涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ company: [
+ {
+ required: true,
+ message: '鎵�灞炲叕鍙镐笉鑳戒负绌�',
+ trigger: 'blur',
+ },
+ ],
+ contactName: [
+ {
+ required: true,
+ message: '鑱旂郴浜轰笉鑳戒负绌�',
+ trigger: 'blur',
+ },
+ ],
+ telephone: [
+ {
+ required: true,
+ message: '鑱旂郴鐢佃瘽涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+ address: [
+ {
+ required: true,
+ message: '鍦板潃涓嶈兘涓虹┖',
+ trigger: 'blur',
+ },
+ ],
+})
+
+// 鍦烘櫙鍩烘湰淇℃伅鏍煎紡鍖�
+function parseSceneBaseInfo(s) {
+ return s
+}
+
+function updateScene() {
+ updateLoading.value = true
+ // 杩欓噷鍙互娣诲姞瀹為檯鐨凙PI璋冪敤
+ setTimeout(() => {
+ updateLoading.value = false
+ }, 1000)
+}
+
+watch(
+ () => props.formInfo,
+ (nValue) => {
+ formObj.value = parseSceneBaseInfo(nValue)
+ },
+)
+
+function submit() {
+ emit('onSubmit', formObj)
+ return updateScene()
+}
+function cancel() {
+ emit('onCancel')
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompUserInfo.vue b/src/views/inspection/scenenew/components/CompUserInfo.vue
new file mode 100644
index 0000000..aece522
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompUserInfo.vue
@@ -0,0 +1,250 @@
+<template>
+ <FYForm
+ :form-info="formInfo"
+ :rules="rules"
+ :doClear="active"
+ :useCancel="create"
+ :useReset="!create"
+ @update:isEdit="(v) => $emit('updateEdit', v)"
+ @submit="submit"
+ @cancel="$emit('onCancel')"
+ >
+ <template #form-item="{ formObj }">
+ <!-- <el-form-item label="澶村儚url" prop="HeadIconUrl">
+ <el-input
+ clearable
+ v-model="formObj.HeadIconUrl"
+ placeholder="澶村儚url"
+ />
+ </el-form-item> -->
+ <el-form-item label="璐︽埛鍚�" prop="acountname">
+ <el-input clearable v-model="formObj.acountname" placeholder="璐︽埛鍚�" />
+ </el-form-item>
+ <el-form-item label="鐢ㄦ埛鏄电О" prop="realname">
+ <el-input clearable v-model="formObj.realname" placeholder="鐢ㄦ埛鏄电О" />
+ </el-form-item>
+ <el-form-item label="瀵嗙爜" prop="password">
+ <el-col :span="18">
+ <el-input
+ :disabled="true"
+ clearable
+ type="password"
+ v-model="formObj.password"
+ placeholder="榛樿瀵嗙爜123456"
+ />
+ </el-col>
+ <el-col :span="6" v-if="!create">
+ <el-row justify="end">
+ <el-button type="danger" @click="onResetPw" :loading="pwLoading">閲嶇疆瀵嗙爜</el-button>
+ </el-row>
+ </el-col>
+ </el-form-item>
+ <FYOptionUserType
+ prop="_usertype"
+ :allOption="false"
+ :initValue="false"
+ v-model:value="formObj._usertype"
+ ></FYOptionUserType>
+ <!-- <el-form-item label="鎵�灞炰紒涓�" prop="departmentname">
+ <el-input
+ clearable
+ v-model="formObj.departmentname"
+ placeholder="鎵�灞炰紒涓�"
+ disabled
+ />
+ </el-form-item> -->
+ <el-form-item label="鏄惁鍙敤" prop="isenable">
+ <el-switch v-model="formObj.isenable" />
+ <span style="margin-left: 16px">{{ formObj.isenable ? '鍙敤' : '涓嶅彲鐢�' }}</span>
+ </el-form-item>
+ <el-form-item label="宸ュ彿" prop="workno">
+ <el-input clearable v-model="formObj.workno" placeholder="宸ュ彿" />
+ </el-form-item>
+ <el-form-item label="鎵嬫満" prop="telephone">
+ <el-input clearable type="tel" v-model="formObj.telephone" placeholder="鎵嬫満" />
+ </el-form-item>
+ <FYOptionLocation
+ v-if="create"
+ prop="_locations"
+ :allOption="false"
+ :level="5"
+ :checkStrictly="true"
+ :initValue="false"
+ v-model:value="formObj._locations"
+ ></FYOptionLocation>
+ <FYOptionScene
+ prop="_scenetype"
+ :allOption="false"
+ :type="1"
+ :initValue="false"
+ v-model:value="formObj._scenetype"
+ ></FYOptionScene>
+ </template>
+ </FYForm>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, reactive, ref, watch, computed } from 'vue';
+import { getSceneName } from '@/enum/scene';
+import userApi from '@/api/fytz/userApi';
+import { useMessageBoxTip } from '@/composables/messageBox';
+
+const props = defineProps({
+ //鍩烘湰淇℃伅
+ model: {
+ type: Object
+ // default: () => {
+ // return { isenable: true };
+ // }
+ },
+ create: {
+ type: Boolean,
+ default: false
+ },
+ active: {
+ type: Boolean,
+ default: false
+ }
+});
+
+const formInfo = ref({ isenable: true });
+
+watch(
+ () => props.model,
+ (nValue) => {
+ formInfo.value = parseUserInfo(nValue);
+ }
+);
+
+const emit = defineEmits(['onSubmit', 'onCancel', 'updateEdit']);
+
+const rules = reactive({
+ acountname: [
+ {
+ required: true,
+ message: '璐︽埛鍚嶄笉鑳戒负绌�',
+ trigger: 'blur'
+ }
+ ],
+ realname: [
+ {
+ required: true,
+ message: '鐢ㄦ埛鏄电О涓嶈兘涓虹┖',
+ trigger: 'blur'
+ }
+ ]
+ // password: [
+ // {
+ // required: props.create,
+ // message: '瀵嗙爜涓嶈兘涓虹┖',
+ // trigger: 'blur',
+ // },
+ // ],
+});
+
+// 鐢ㄦ埛鍩烘湰淇℃伅鏍煎紡鍖�
+function parseUserInfo(s) {
+ if (s.usertype && s.usertypeid) {
+ s._usertype = {
+ label: s.usertype,
+ value: s.usertypeid + ''
+ };
+ }
+
+ if (s.extension2) {
+ s._scenetype = getSceneName(s.extension2, 1);
+ }
+
+ s._locations = {};
+
+ return s;
+}
+
+function parseUserInfoReverse(v) {
+ // 琛屾斂鍖哄垝淇℃伅濉厖
+ const a = v._locations;
+ v.extension1 = a.dName;
+ // 鐢ㄦ埛绫诲瀷淇℃伅濉厖
+ const b = v._usertype;
+ v.usertypeid = b.value;
+ v.usertype = b.label;
+
+ // 鍦烘櫙绫诲瀷淇℃伅濉厖
+ const c = v._scenetype;
+ v.extension2 = c.value;
+
+ return v;
+}
+
+function createUser(v, success, fail) {
+ const l = v._locations;
+ const params = {
+ userInfo: v,
+ baseInfo: {
+ biProvinceCode: l.pCode,
+ biProvinceName: l.pName,
+ biCityCode: l.cCode,
+ biCityName: l.cName,
+ biDistrictCode: l.dCode,
+ biDistrictName: l.dName,
+ biTownCode: l.tCode,
+ biTownName: l.tName,
+ biAreaCode: l.aCode,
+ biArea: l.aName
+ // biManagementCompanyId:
+ // biManagementCompany:
+ // biContact
+ // biTelephone
+ // biAddress
+ }
+ };
+ return userApi
+ .createUser(params)
+ .then(() => {
+ emit('onSubmit', params);
+ success();
+ })
+ .catch((err) => {
+ fail(err);
+ });
+}
+
+function updateUser(v, success, fail) {
+ return userApi
+ .updateUserInfo(v)
+ .then(() => {
+ emit('onSubmit', v);
+ if (success) success();
+ })
+ .catch((err) => {
+ if (fail) fail(err);
+ });
+}
+
+function submit(v, success, fail) {
+ parseUserInfoReverse(v.value);
+
+ return props.create ? createUser(v.value, success, fail) : updateUser(v.value, success, fail);
+ // parseUserInfoReverse(props.formInfo);
+
+ // return props.create
+ // ? createUser(props.formInfo, success, fail)
+ // : updateUser(props.formInfo, success, fail);
+}
+
+// 閲嶇疆瀵嗙爜
+const pwLoading = ref(false);
+
+function onResetPw() {
+ useMessageBoxTip({
+ confirmMsg: '鏄惁閲嶇疆璇ュ満鏅瘑鐮侊紵',
+ confirmTitle: '閲嶇疆瀵嗙爜',
+ onConfirm: async () => {
+ pwLoading.value = true;
+ return userApi.resetPassword(formInfo.value.guid).finally(() => {
+ pwLoading.value = false;
+ });
+ }
+ });
+}
+</script>
diff --git a/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue b/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue
new file mode 100644
index 0000000..720a1a5
--- /dev/null
+++ b/src/views/inspection/scenenew/components/CompUserInfoAddDrawer.vue
@@ -0,0 +1,54 @@
+<template>
+ <el-drawer
+ title="鏂板鐢ㄦ埛"
+ direction="rtl"
+ :model-value="modelValue"
+ @open="updateDrawer(true)"
+ @close="updateDrawer(false)"
+ :before-close="onDrawerClose"
+ >
+ <CompUserInfo
+ :create="true"
+ :active="modelValue"
+ @updateEdit="(v) => (drawerEdit = v)"
+ @on-submit="updateDrawer(false)"
+ @on-cancel="updateDrawer(false)"
+ ></CompUserInfo>
+ </el-drawer>
+</template>
+
+<script>
+import CompUserInfo from './CompUserInfo.vue';
+import { useMessageBox } from '@/composables/messageBox';
+
+export default {
+ components: { CompUserInfo },
+ props: ['modelValue'],
+ emits: ['update:modelValue'],
+ data() {
+ return {
+ drawerEdit: false
+ };
+ },
+ methods: {
+ updateDrawer(status) {
+ this.$emit('update:modelValue', status);
+ },
+ onDrawerClose(done) {
+ if (this.drawerEdit) {
+ // 寮瑰嚭纭妗�
+ useMessageBox({
+ confirmMsg: '鏄惁鏀惧純宸茬紪杈戠殑鍐呭锛�',
+ confirmTitle: '鍏抽棴寮瑰嚭妗�',
+ onConfirm: () => {
+ done();
+ }
+ });
+ } else {
+ // 鐩存帴鍏抽棴
+ done();
+ }
+ },
+ }
+};
+</script>
diff --git a/src/views/monitor/DataDashboard.vue b/src/views/monitor/DataDashboard.vue
index 3292858..4d366dd 100644
--- a/src/views/monitor/DataDashboard.vue
+++ b/src/views/monitor/DataDashboard.vue
@@ -1,313 +1,865 @@
<template>
- <el-container class="data-dashboard">
- <el-main>
- <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 class="data-dashboard">
+ <!-- 椤堕儴鎸囨爣鍗$墖鍖� -->
+ <div class="top-cards">
+ <div class="cards-container">
+ <!-- 鏃堕棿鍛ㄦ湡閫夐」鍗$墖 -->
+ <div class="time-period-card">
+ <div class="card-title">鏃堕棿鍛ㄦ湡</div>
+ <div class="time-tab-container">
+ <div
+ v-for="tab in timeTabs"
+ :key="tab.value"
+ class="time-tab"
+ :class="{ active: activeTime === tab.value }"
+ @click="handleTimeChange(tab)"
+ >
+ {{ tab.label }}
+ </div>
+ </div>
</div>
- <div class="right-section">
- <!-- 璁惧瀹炴椂鏁版嵁鍖哄煙 -->
- <RealTimeData style="flex: 1" :devices="devices" />
+
+ <!-- 瓒呮爣鏁� -->
+ <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 }}</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 online-icon">
+ <svg
+ width="20"
+ height="20"
+ viewBox="0 0 24 24"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M9 12L11 14L15 10"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </svg>
+ </div>
+ </div>
+ <div class="card-value">{{ metrics.onlineRate }}%</div>
+ <div class="card-trend">
+ <span
+ class="trend-arrow"
+ :class="{ up: metrics.onlineRateTrend > 0, down: metrics.onlineRateTrend < 0 }"
+ >
+ {{ metrics.onlineRateTrend > 0 ? '鈫�' : '鈫�' }}
+ </span>
+ <span class="trend-text">{{ Math.abs(metrics.onlineRateTrend) }}%</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 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"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M12 6V12L16 14"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </svg>
+ </div>
+ </div>
+ <div class="card-value">{{ metrics.purifierEfficiency }}%</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 task-icon">
+ <svg
+ width="20"
+ height="20"
+ viewBox="0 0 24 24"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M22 11.08V12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C15.7376 2 19.0503 4.16113 20.7748 7.33007"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M22 4L12 14.01L9 11.01"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </svg>
+ </div>
+ </div>
+ <div class="card-value">{{ metrics.taskCompletionRate }}%</div>
+ <div class="card-trend">
+ <span
+ class="trend-arrow"
+ :class="{
+ up: metrics.taskCompletionRateTrend > 0,
+ down: metrics.taskCompletionRateTrend < 0,
+ }"
+ >
+ {{ metrics.taskCompletionRateTrend > 0 ? '鈫�' : '鈫�' }}
+ </span>
+ <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span>
+ <span class="trend-label">{{ getCompareLabel() }}</span>
+ </div>
</div>
</div>
+ </div>
- <!-- 鍦ㄧ嚎璁惧鍜屽簵閾烘竻鍗曞尯鍩� -->
- <ShopList
- :shops="shops"
- :shop-types="shopTypes"
- :districts="districts"
- :filter="filter"
- @filter-change="handleFilterChange"
- />
- </el-main>
- </el-container>
+ <!-- 涓昏鍐呭鍖� -->
+ <div class="main-content">
+ <!-- 涓儴GIS鍦板浘鍖� -->
+ <div class="map-section">
+ <div id="map" class="map-container">
+ <BaseMap></BaseMap>
+ </div>
+
+ <!-- 鍦板浘鐐逛綅寮圭獥 -->
+ <el-dialog v-model="dialogVisible" title="浼佷笟瀹炴椂鏁版嵁" width="400px">
+ <div class="dialog-content">
+ <el-descriptions :column="1" border>
+ <el-descriptions-item label="浼佷笟鍚嶇О">{{
+ selectedPoint.enterpriseName
+ }}</el-descriptions-item>
+ <el-descriptions-item label="璁惧缂栧彿">{{
+ selectedPoint.deviceId
+ }}</el-descriptions-item>
+ <el-descriptions-item label="娌圭儫娴撳害"
+ >{{ selectedPoint.oilSmokeConcentration }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="棰楃矑鐗�"
+ >{{ selectedPoint.particulateMatter }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="闈炵敳鐑锋�荤儍"
+ >{{ selectedPoint.nonMethaneHydrocarbon }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="鐩戞祴鏃堕棿">{{
+ selectedPoint.monitoringTime
+ }}</el-descriptions-item>
+ <el-descriptions-item label="瓒呮爣鎯呭喌">
+ <el-tag :type="selectedPoint.isOverStandard ? 'danger' : 'success'">
+ {{ selectedPoint.isOverStandard ? '瓒呮爣' : '姝e父' }}
+ </el-tag>
+ </el-descriptions-item>
+ </el-descriptions>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍏抽棴</el-button>
+ <el-button type="primary" @click="viewDetails">鏌ョ湅璇︽儏</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+
+ <!-- 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� -->
+ <div class="overview-section">
+ <div class="section-header">
+ <h3>瀹炴椂鐩戞祴鎬昏</h3>
+ <span class="view-more">鏌ョ湅鏇村</span>
+ </div>
+
+ <div class="overview-items-container">
+ <div class="overview-item">
+ <div class="overview-label">椁愰ギ搴楅摵鎬绘暟</div>
+ <div class="overview-value">{{ overview.totalShops }}</div>
+ </div>
+
+ <div class="overview-item">
+ <div class="overview-label">鍦ㄧ嚎璁惧鏁�</div>
+ <div class="overview-value">{{ overview.onlineDevices }}</div>
+ </div>
+
+ <div class="overview-item">
+ <div class="overview-label">绂荤嚎璁惧鏁�</div>
+ <div class="overview-value">{{ overview.offlineDevices }}</div>
+ </div>
+ </div>
+
+ <!-- 璁惧鐘舵�侀ゼ鍥� -->
+ <div class="device-status-chart">
+ <canvas id="deviceStatusChart"></canvas>
+ </div>
+ </div>
+ </div>
+ </div>
</template>
<script>
-import DeviceStatus from '@/components/monitor/DeviceStatus.vue'
-import RealTimeData from '@/components/monitor/RealTimeData.vue'
-import DistrictRanking from '@/components/monitor/DistrictRanking.vue'
-import ShopList from '@/components/monitor/ShopList.vue'
+import * as echarts from 'echarts'
+import { onMapMounted, map, AMap } from '@/utils/map/index'
+import districtSearch from '@/utils/map/districtsearch.js'
export default {
name: 'DataDashboard',
- components: {
- DeviceStatus,
- RealTimeData,
- DistrictRanking,
- ShopList,
- },
data() {
return {
- // 璁惧鍦ㄧ嚎鎯呭喌鏁版嵁
- onlineCount: 0,
- offlineCount: 0,
- normalCount: 0,
- faultCount: 0,
-
- // 璁惧瀹炴椂鏁版嵁
- devices: [],
-
- // 鍒嗗尯鏁版嵁鎺掑悕
- selectedMonth: '2023-12',
- rankingType: 'hourly',
- rankingData: [],
- sortedRankingData: [],
-
- // 绛涢�夋潯浠�
- filter: {
- district: '',
- shopType: '',
- status: '',
- },
- shopTypes: ['涓', '瑗块', '蹇', '鐏攨', '鐑х儰'],
- districts: ['涓滃煄鍖�', '瑗垮煄鍖�', '鏈濋槼鍖�', '娴锋穩鍖�', '涓板彴鍖�'],
-
- // 搴楅摵鏁版嵁
- shops: [
- {
- id: 1,
- name: '寮犱笁椁愬巺',
- deviceCount: 2,
- status: '鍦ㄧ嚎',
- district: '涓滃煄鍖�',
- type: '涓',
- },
- {
- id: 2,
- name: '鏉庡洓楗簵',
- deviceCount: 1,
- status: '绂荤嚎',
- district: '瑗垮煄鍖�',
- type: '瑗块',
- },
- {
- id: 3,
- name: '鐜嬩簲灏忓悆',
- deviceCount: 3,
- status: '鍦ㄧ嚎',
- district: '鏈濋槼鍖�',
- type: '蹇',
- },
- {
- id: 4,
- name: '璧靛叚鐏攨',
- deviceCount: 2,
- status: '鍦ㄧ嚎',
- district: '娴锋穩鍖�',
- type: '鐏攨',
- },
- {
- id: 5,
- name: '閽变竷鐑х儰',
- deviceCount: 1,
- status: '绂荤嚎',
- district: '涓板彴鍖�',
- type: '鐑х儰',
- },
+ activeTime: 'day',
+ timeTabs: [
+ { label: '鏃�', value: 'day' },
+ { label: '鍛�', value: 'week' },
+ { label: '鏈�', value: 'month' },
],
+ dialogVisible: false,
+ selectedPoint: {
+ enterpriseName: '',
+ deviceId: '',
+ oilSmokeConcentration: 0,
+ particulateMatter: 0,
+ nonMethaneHydrocarbon: 0,
+ monitoringTime: '',
+ isOverStandard: false,
+ },
+ metrics: {
+ overStandardCount: 12,
+ overStandardTrend: 5,
+ onlineRate: 92,
+ onlineRateTrend: 2,
+ purifierEfficiency: 85,
+ purifierEfficiencyTrend: -3,
+ taskCompletionRate: 78,
+ taskCompletionRateTrend: 10,
+ },
+ overview: {
+ totalShops: 245,
+ onlineDevices: 220,
+ offlineDevices: 25,
+ },
+ map: null,
+ refreshTimer: null,
}
},
mounted() {
- this.initData()
- this.startRealTimeUpdate()
+ this.initMap()
+ this.initDeviceStatusChart()
+ this.startAutoRefresh()
+ },
+ beforeUnmount() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
},
methods: {
- initData() {
- // 鍒濆鍖栬澶囧湪绾挎儏鍐垫暟鎹�
- this.updateDeviceStatus()
-
- // 鍒濆鍖栧疄鏃舵暟鎹�
- this.updateRealTimeData()
-
- // 鍒濆鍖栧垎鍖烘暟鎹帓鍚�
- this.updateRankingData()
+ handleTimeChange(tab) {
+ this.activeTime = tab.value
+ // 妯℃嫙鍒囨崲鏃堕棿鍛ㄦ湡鍚庣殑鏁版嵁鏇存柊
+ this.updateMetrics()
},
-
- updateDeviceStatus() {
- // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
- this.onlineCount = Math.floor(Math.random() * 50) + 50
- this.offlineCount = Math.floor(Math.random() * 20)
- this.normalCount = this.onlineCount
- this.faultCount = this.offlineCount
+ getPeriodLabel() {
+ switch (this.activeTime) {
+ case 'day':
+ return '浠婃棩'
+ case 'week':
+ return '鏈懆'
+ case 'month':
+ return '鏈湀'
+ default:
+ return '浠婃棩'
+ }
},
-
- updateRealTimeData() {
- // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
- this.devices = [
- {
- deviceId: 'DEV-001',
- supplier: '渚涘簲鍟咥',
- status: '姝e父',
- 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: '渚涘簲鍟咮',
- status: '姝e父',
- 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: '渚涘簲鍟咰',
- 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: '渚涘簲鍟咲',
- 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(),
- },
- ]
+ getCompareLabel() {
+ switch (this.activeTime) {
+ case 'day':
+ return '杈冩槰鏃�'
+ case 'week':
+ return '杈冧笂鍛�'
+ case 'month':
+ return '杈冧笂鏈�'
+ default:
+ return '杈冩槰鏃�'
+ }
},
+ updateMetrics() {
+ // 杩欓噷搴旇鏍规嵁閫夋嫨鐨勬椂闂村懆鏈熶粠鎺ュ彛鑾峰彇鏁版嵁
+ // 妯℃嫙鏁版嵁鏇存柊
+ setTimeout(() => {
+ this.metrics = {
+ overStandardCount: Math.floor(Math.random() * 30),
+ overStandardTrend: Math.floor(Math.random() * 20) - 10,
+ onlineRate: Math.floor(Math.random() * 20) + 80,
+ onlineRateTrend: Math.floor(Math.random() * 10) - 5,
+ purifierEfficiency: Math.floor(Math.random() * 30) + 70,
+ purifierEfficiencyTrend: Math.floor(Math.random() * 10) - 5,
+ taskCompletionRate: Math.floor(Math.random() * 40) + 60,
+ taskCompletionRateTrend: Math.floor(Math.random() * 15) - 7,
+ }
+ }, 300)
+ },
+ initMap() {
+ // setTimeout(() => {
+ districtSearch.removeDistrict()
+ districtSearch.drawDistrict('涓婃捣甯�')
+ // districtSearch.districtLayer('310106')
+ // }, 2000)
+ },
+ initDeviceStatusChart() {
+ const chartDom = document.getElementById('deviceStatusChart')
+ if (chartDom) {
+ const chart = echarts.init(chartDom)
+ const option = {
+ tooltip: {
+ trigger: 'item',
+ formatter: '{b}: {c} ({d}%)',
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
+ borderColor: '#e8e8e8',
+ borderWidth: 1,
+ textStyle: {
+ color: '#333',
+ },
+ },
+ legend: {
+ bottom: '0%',
+ left: 'center',
+ textStyle: {
+ color: '#86909c',
+ fontSize: 12,
+ },
+ },
+ series: [
+ {
+ name: '璁惧鐘舵��',
+ type: 'pie',
+ radius: ['50%', '75%'],
+ center: ['50%', '45%'],
+ avoidLabelOverlap: false,
+ itemStyle: {
+ borderRadius: 8,
+ borderColor: '#ffffff',
+ borderWidth: 2,
+ shadowBlur: 5,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.1)',
+ },
+ label: {
+ show: true,
+ position: 'center',
+ formatter: '{d}%',
+ fontSize: 18,
+ fontWeight: 'bold',
+ color: '#262626',
+ },
+ labelLine: {
+ show: false,
+ },
+ data: [
+ {
+ value: this.overview.onlineDevices,
+ name: '鍦ㄧ嚎',
+ itemStyle: {
+ color: '#1890ff',
+ },
+ },
+ {
+ value: this.overview.offlineDevices,
+ name: '绂荤嚎',
+ itemStyle: {
+ color: '#f5222d',
+ },
+ },
+ ],
+ },
+ ],
+ }
+ chart.setOption(option)
- generateHourlyData() {
- // 鐢熸垚妯℃嫙鐨勮繎涓�灏忔椂鏁版嵁
- const hourlyData = []
- for (let i = 59; i >= 0; i--) {
- const time = new Date()
- time.setMinutes(time.getMinutes() - i)
- hourlyData.push({
- time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
- smokeDensity: (Math.random() * 2).toFixed(2),
- fanCurrent: (Math.random() * 5 + 1).toFixed(2),
- purifierCurrent: (Math.random() * 3 + 0.5).toFixed(2),
+ // 鍝嶅簲寮忚皟鏁�
+ window.addEventListener('resize', () => {
+ chart.resize()
})
}
- 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: 1 },
- ]
-
- // 鎺掑簭
- this.sortedRankingData = [...this.rankingData].sort(
- (a, b) => parseFloat(b.value) - parseFloat(a.value),
- )
- },
-
- startRealTimeUpdate() {
- // 姣�30绉掓洿鏂颁竴娆℃暟鎹�
- this.realTimeInterval = setInterval(() => {
- this.updateDeviceStatus()
- this.updateRealTimeData()
+ startAutoRefresh() {
+ // 姣�30绉掕嚜鍔ㄥ埛鏂版暟鎹�
+ this.refreshTimer = setInterval(() => {
+ this.updateMetrics()
+ // 杩欓噷搴旇鍚屾椂鏇存柊鍦板浘鐐逛綅鏁版嵁
}, 30000)
},
-
- handleMonthChange(val) {
- this.selectedMonth = val
- this.updateRankingData()
- },
-
- handleTypeChange(val) {
- this.rankingType = val
- this.updateRankingData()
- },
-
- handleFilterChange(val) {
- this.filter = { ...val }
+ viewDetails() {
+ // 璺宠浆鍒颁紒涓氱洃鎺ц鎯呴〉
+ this.$router.push('/monitor/enterprise-detail')
},
},
}
</script>
<style scoped>
+/* 鍏ㄥ眬鏍峰紡 */
.data-dashboard {
- min-height: 100vh;
+ width: 100%;
+ height: calc(100vh - 60px);
background-color: #f5f7fa;
+ color: #333;
+ box-sizing: border-box;
+ font-family:
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+ position: relative;
}
-.el-header {
+/* 椤堕儴鎸囨爣鍗$墖鍖� */
+.top-cards {
+ position: absolute;
+ top: 24px;
+ left: 24px;
+ z-index: 10;
+ margin-bottom: 24px;
+}
+
+.cards-container {
+ display: grid;
+ grid-template-columns: 280px;
+ grid-template-rows: auto repeat(4, auto);
+ gap: 16px;
+ background-color: rgba(255, 255, 255, 0.9);
+ padding: 16px;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* 鏃堕棿鍛ㄦ湡鍗$墖 */
+.time-period-card {
+ background-color: #ffffff;
+ border-radius: 8px;
padding: 20px;
- background-color: #f5f7fa;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
}
-.el-header h1 {
- font-size: 24px;
+.time-period-card .card-title {
+ font-size: 14px;
+ color: #86909c;
+ font-weight: 500;
+ margin-bottom: 16px;
+ text-align: center;
+}
+
+.time-tab-container {
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ width: 100%;
+ justify-content: center;
+}
+
+.time-tab {
+ padding: 2px 4px;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 500;
+ transition: all 0.3s ease;
+ color: #4e5969;
+ text-align: center;
+ border: 1px solid #e8e8e8;
+ background-color: #fafafa;
+}
+
+.time-tab.active {
+ background-color: #1890ff;
+ color: #ffffff;
+ border-color: #1890ff;
+ box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
+}
+
+.time-tab:hover:not(.active) {
+ color: #1890ff;
+ border-color: #e6f7ff;
+ background-color: #e6f7ff;
+}
+
+/* 鎸囨爣鍗$墖 */
+.metric-card {
+ background-color: #ffffff;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+ transition: all 0.3s ease;
+ position: relative;
+ overflow: hidden;
+}
+
+.metric-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+}
+
+.card-title {
+ font-size: 14px;
+ color: #86909c;
+ font-weight: 500;
+}
+
+.card-icon {
+ color: #1890ff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.warning-icon {
+ color: #fa8c16;
+}
+
+.online-icon {
+ color: #52c41a;
+}
+
+.efficiency-icon {
+ color: #722ed1;
+}
+
+.task-icon {
+ color: #1890ff;
+}
+
+.card-value {
+ font-size: 32px;
+ font-weight: bold;
+ margin: 12px 0;
+ color: #262626;
+ line-height: 1.2;
+}
+
+.card-trend {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 12px;
+ padding-top: 12px;
+ border-top: 1px solid #f0f0f0;
+}
+
+.trend-arrow {
+ font-size: 14px;
+ font-weight: bold;
+}
+
+.trend-arrow.up {
+ color: #52c41a;
+}
+
+.trend-arrow.down {
+ color: #f5222d;
+}
+
+.trend-text {
+ color: #262626;
+ font-weight: 500;
+}
+
+.trend-label {
+ color: #86909c;
+ font-size: 12px;
+}
+
+/* 涓昏鍐呭鍖� */
+.main-content {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+
+/* 涓儴GIS鍦板浘鍖� */
+.map-section {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+ color: #262626;
+}
+
+.section-header h3 {
+ font-size: 16px;
+ font-weight: 600;
+ color: #262626;
margin: 0;
+}
+
+.view-more {
+ font-size: 12px;
+ color: #1890ff;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+}
+
+.view-more:hover {
+ text-decoration: underline;
+}
+
+.map-container {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+ background-color: #fafafa;
+}
+
+.map-placeholder {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #86909c;
+ font-size: 16px;
+}
+
+/* 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� */
+.overview-section {
+ position: absolute;
+ top: 200px;
+ right: 24px;
+ width: 320px;
+ background-color: rgba(255, 255, 255, 0.9);
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ z-index: 10;
+ max-height: calc(100vh - 220px);
+}
+
+.overview-items-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.overview-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+ text-align: center;
+}
+
+.overview-label {
+ font-size: 12px;
+ color: #86909c;
+ font-weight: 500;
+ margin-bottom: 8px;
+}
+
+.overview-value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #262626;
+}
+
+.device-status-chart {
+ flex: 1;
+ margin-top: 16px;
+ min-height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 寮圭獥鏍峰紡 */
+.dialog-content {
color: #333;
}
-.el-main {
- padding: 20px;
+.dialog-footer {
+ text-align: right;
}
-.grid-container {
- display: flex;
- /* display: grid;
- grid-template-columns: 1fr 1fr;
- grid-template-rows: min-content; */
- gap: 20px;
+/* 闂儊鏁堟灉 */
+@keyframes blink {
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
}
-.left-section {
- flex: 2;
- display: flex;
- flex-direction: column;
- gap: 20px;
-}
-
-.right-section {
- width: 670px;
- display: flex;
- flex-direction: column;
+.blink {
+ animation: blink 1s infinite;
}
/* 鍝嶅簲寮忚璁� */
-@media (max-width: 768px) {
- .grid-container {
- grid-template-columns: 1fr;
+@media (max-width: 1200px) {
+ .top-cards {
+ position: relative;
+ margin-bottom: 24px;
}
- .left-section,
- .right-section {
- margin-bottom: 10px;
+ .cards-container {
+ grid-template-columns: repeat(2, 1fr);
+ grid-template-rows: auto auto;
+ background-color: #ffffff;
+ }
+
+ .main-content {
+ height: calc(100vh - 300px);
+ }
+
+ .overview-section {
+ position: relative;
+ top: 0;
+ right: 0;
+ width: 100%;
+ max-height: none;
+ height: 300px;
+ margin-top: 16px;
+ background-color: #ffffff;
+ }
+}
+
+@media (max-width: 768px) {
+ .data-dashboard {
+ padding: 16px;
+ }
+
+ .top-cards {
+ left: 16px;
+ }
+
+ .cards-container {
+ grid-template-columns: 1fr;
+ grid-template-rows: auto repeat(4, auto);
+ }
+
+ .time-period-card {
+ order: -1;
+ }
+
+ .time-tab-container {
+ flex-direction: row;
+ }
+
+ .time-tab {
+ flex: 1;
+ padding: 8px 0;
+ }
+
+ .overview-section {
+ right: 16px;
+ }
+
+ .overview-items-container {
+ flex-direction: column;
+ gap: 16px;
+ }
+
+ .overview-item {
+ flex-direction: row;
+ justify-content: space-between;
+ width: 100%;
+ text-align: left;
}
}
</style>
diff --git a/src/views/monitor/DataDashboard_old2.vue b/src/views/monitor/DataDashboard_old2.vue
new file mode 100644
index 0000000..3292858
--- /dev/null
+++ b/src/views/monitor/DataDashboard_old2.vue
@@ -0,0 +1,313 @@
+<template>
+ <el-container class="data-dashboard">
+ <el-main>
+ <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
+ :shops="shops"
+ :shop-types="shopTypes"
+ :districts="districts"
+ :filter="filter"
+ @filter-change="handleFilterChange"
+ />
+ </el-main>
+ </el-container>
+</template>
+
+<script>
+import DeviceStatus from '@/components/monitor/DeviceStatus.vue'
+import RealTimeData from '@/components/monitor/RealTimeData.vue'
+import DistrictRanking from '@/components/monitor/DistrictRanking.vue'
+import ShopList from '@/components/monitor/ShopList.vue'
+
+export default {
+ name: 'DataDashboard',
+ components: {
+ DeviceStatus,
+ RealTimeData,
+ DistrictRanking,
+ ShopList,
+ },
+ data() {
+ return {
+ // 璁惧鍦ㄧ嚎鎯呭喌鏁版嵁
+ onlineCount: 0,
+ offlineCount: 0,
+ normalCount: 0,
+ faultCount: 0,
+
+ // 璁惧瀹炴椂鏁版嵁
+ devices: [],
+
+ // 鍒嗗尯鏁版嵁鎺掑悕
+ selectedMonth: '2023-12',
+ rankingType: 'hourly',
+ rankingData: [],
+ sortedRankingData: [],
+
+ // 绛涢�夋潯浠�
+ filter: {
+ district: '',
+ shopType: '',
+ status: '',
+ },
+ shopTypes: ['涓', '瑗块', '蹇', '鐏攨', '鐑х儰'],
+ districts: ['涓滃煄鍖�', '瑗垮煄鍖�', '鏈濋槼鍖�', '娴锋穩鍖�', '涓板彴鍖�'],
+
+ // 搴楅摵鏁版嵁
+ shops: [
+ {
+ id: 1,
+ name: '寮犱笁椁愬巺',
+ deviceCount: 2,
+ status: '鍦ㄧ嚎',
+ district: '涓滃煄鍖�',
+ type: '涓',
+ },
+ {
+ id: 2,
+ name: '鏉庡洓楗簵',
+ deviceCount: 1,
+ status: '绂荤嚎',
+ district: '瑗垮煄鍖�',
+ type: '瑗块',
+ },
+ {
+ id: 3,
+ name: '鐜嬩簲灏忓悆',
+ deviceCount: 3,
+ status: '鍦ㄧ嚎',
+ district: '鏈濋槼鍖�',
+ type: '蹇',
+ },
+ {
+ id: 4,
+ name: '璧靛叚鐏攨',
+ deviceCount: 2,
+ status: '鍦ㄧ嚎',
+ district: '娴锋穩鍖�',
+ type: '鐏攨',
+ },
+ {
+ id: 5,
+ name: '閽变竷鐑х儰',
+ deviceCount: 1,
+ status: '绂荤嚎',
+ district: '涓板彴鍖�',
+ type: '鐑х儰',
+ },
+ ],
+ }
+ },
+ mounted() {
+ this.initData()
+ this.startRealTimeUpdate()
+ },
+ methods: {
+ initData() {
+ // 鍒濆鍖栬澶囧湪绾挎儏鍐垫暟鎹�
+ this.updateDeviceStatus()
+
+ // 鍒濆鍖栧疄鏃舵暟鎹�
+ this.updateRealTimeData()
+
+ // 鍒濆鍖栧垎鍖烘暟鎹帓鍚�
+ this.updateRankingData()
+ },
+
+ updateDeviceStatus() {
+ // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
+ this.onlineCount = Math.floor(Math.random() * 50) + 50
+ this.offlineCount = Math.floor(Math.random() * 20)
+ this.normalCount = this.onlineCount
+ this.faultCount = this.offlineCount
+ },
+
+ updateRealTimeData() {
+ // 妯℃嫙鏁版嵁 - 瀹為檯搴斾粠API鑾峰彇
+ this.devices = [
+ {
+ deviceId: 'DEV-001',
+ supplier: '渚涘簲鍟咥',
+ status: '姝e父',
+ 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: '渚涘簲鍟咮',
+ status: '姝e父',
+ 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: '渚涘簲鍟咰',
+ 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: '渚涘簲鍟咲',
+ 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(),
+ },
+ ]
+ },
+
+ generateHourlyData() {
+ // 鐢熸垚妯℃嫙鐨勮繎涓�灏忔椂鏁版嵁
+ const hourlyData = []
+ for (let i = 59; i >= 0; i--) {
+ const time = new Date()
+ time.setMinutes(time.getMinutes() - i)
+ hourlyData.push({
+ time: time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
+ 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: 1 },
+ ]
+
+ // 鎺掑簭
+ this.sortedRankingData = [...this.rankingData].sort(
+ (a, b) => parseFloat(b.value) - parseFloat(a.value),
+ )
+ },
+
+ startRealTimeUpdate() {
+ // 姣�30绉掓洿鏂颁竴娆℃暟鎹�
+ this.realTimeInterval = setInterval(() => {
+ this.updateDeviceStatus()
+ this.updateRealTimeData()
+ }, 30000)
+ },
+
+ handleMonthChange(val) {
+ this.selectedMonth = val
+ this.updateRankingData()
+ },
+
+ handleTypeChange(val) {
+ this.rankingType = val
+ this.updateRankingData()
+ },
+
+ handleFilterChange(val) {
+ this.filter = { ...val }
+ },
+ },
+}
+</script>
+
+<style scoped>
+.data-dashboard {
+ min-height: 100vh;
+ background-color: #f5f7fa;
+}
+
+.el-header {
+ padding: 20px;
+ background-color: #f5f7fa;
+}
+
+.el-header h1 {
+ font-size: 24px;
+ margin: 0;
+ color: #333;
+}
+
+.el-main {
+ 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) {
+ .grid-container {
+ grid-template-columns: 1fr;
+ }
+
+ .left-section,
+ .right-section {
+ margin-bottom: 10px;
+ }
+}
+</style>
diff --git a/src/views/monitor/DataDashboard_old3.vue b/src/views/monitor/DataDashboard_old3.vue
new file mode 100644
index 0000000..2a70319
--- /dev/null
+++ b/src/views/monitor/DataDashboard_old3.vue
@@ -0,0 +1,730 @@
+<template>
+ <div class="data-dashboard">
+ <!-- 椤堕儴鎸囨爣鍗$墖鍖� -->
+ <div class="top-cards">
+ <div class="cards-container">
+ <!-- 鏃堕棿鍛ㄦ湡閫夐」鍗$墖 -->
+ <div class="time-period-card">
+ <div class="card-title">鏃堕棿鍛ㄦ湡</div>
+ <div class="time-tab-container">
+ <div
+ v-for="tab in timeTabs"
+ :key="tab.value"
+ class="time-tab"
+ :class="{ active: activeTime === tab.value }"
+ @click="handleTimeChange(tab)"
+ >
+ {{ tab.label }}
+ </div>
+ </div>
+ </div>
+
+ <!-- 瓒呮爣鏁� -->
+ <div class="metric-card">
+ <div class="card-header">
+ <div class="card-title">{{ getPeriodLabel() }}瓒呮爣鏁�</div>
+ <div class="card-icon warning-icon">鈿�</div>
+ </div>
+ <div class="card-value">{{ metrics.overStandardCount }}</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">{{ getPeriodLabel() }}鍦ㄧ嚎鐜�</div>
+ <div class="card-icon online-icon">馃煝</div>
+ </div>
+ <div class="card-value">{{ metrics.onlineRate }}%</div>
+ <div class="card-trend">
+ <span
+ class="trend-arrow"
+ :class="{ up: metrics.onlineRateTrend > 0, down: metrics.onlineRateTrend < 0 }"
+ >
+ {{ metrics.onlineRateTrend > 0 ? '鈫�' : '鈫�' }}
+ </span>
+ <span class="trend-text">{{ Math.abs(metrics.onlineRateTrend) }}%</span>
+ <span class="trend-label">{{ getCompareLabel() }}</span>
+ </div>
+ </div>
+
+ <!-- 鍑�鍖栧櫒杩愯鏁堢巼 -->
+ <div class="metric-card">
+ <div class="card-header">
+ <div class="card-title">{{ getPeriodLabel() }}鍑�鍖栧櫒杩愯鏁堢巼</div>
+ <div class="card-icon efficiency-icon">鈿�</div>
+ </div>
+ <div class="card-value">{{ metrics.purifierEfficiency }}%</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">{{ getPeriodLabel() }}浠诲姟瀹屾垚鐜�</div>
+ <div class="card-icon task-icon">鉁�</div>
+ </div>
+ <div class="card-value">{{ metrics.taskCompletionRate }}%</div>
+ <div class="card-trend">
+ <span
+ class="trend-arrow"
+ :class="{
+ up: metrics.taskCompletionRateTrend > 0,
+ down: metrics.taskCompletionRateTrend < 0,
+ }"
+ >
+ {{ metrics.taskCompletionRateTrend > 0 ? '鈫�' : '鈫�' }}
+ </span>
+ <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span>
+ <span class="trend-label">{{ getCompareLabel() }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 涓儴GIS鍦板浘鍖� -->
+ <div class="map-section">
+ <div id="map" class="map-container"></div>
+
+ <!-- 鍦板浘鐐逛綅寮圭獥 -->
+ <el-dialog v-model="dialogVisible" title="浼佷笟瀹炴椂鏁版嵁" width="400px">
+ <div class="dialog-content">
+ <el-descriptions :column="1" border>
+ <el-descriptions-item label="浼佷笟鍚嶇О">{{
+ selectedPoint.enterpriseName
+ }}</el-descriptions-item>
+ <el-descriptions-item label="璁惧缂栧彿">{{
+ selectedPoint.deviceId
+ }}</el-descriptions-item>
+ <el-descriptions-item label="娌圭儫娴撳害"
+ >{{ selectedPoint.oilSmokeConcentration }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="棰楃矑鐗�"
+ >{{ selectedPoint.particulateMatter }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="闈炵敳鐑锋�荤儍"
+ >{{ selectedPoint.nonMethaneHydrocarbon }} mg/m鲁</el-descriptions-item
+ >
+ <el-descriptions-item label="鐩戞祴鏃堕棿">{{
+ selectedPoint.monitoringTime
+ }}</el-descriptions-item>
+ <el-descriptions-item label="瓒呮爣鎯呭喌">
+ <el-tag :type="selectedPoint.isOverStandard ? 'danger' : 'success'">
+ {{ selectedPoint.isOverStandard ? '瓒呮爣' : '姝e父' }}
+ </el-tag>
+ </el-descriptions-item>
+ </el-descriptions>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍏抽棴</el-button>
+ <el-button type="primary" @click="viewDetails">鏌ョ湅璇︽儏</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+
+ <!-- 鍙充晶瀹炴椂鐩戞祴鎬昏鍖� -->
+ <div class="overview-section">
+ <div class="overview-card">
+ <div class="overview-title">瀹炴椂鐩戞祴鎬昏</div>
+
+ <div class="overview-items-container">
+ <div class="overview-item">
+ <div class="overview-label">椁愰ギ搴楅摵鎬绘暟</div>
+ <div class="overview-value">{{ overview.totalShops }}</div>
+ </div>
+
+ <div class="overview-item">
+ <div class="overview-label">鍦ㄧ嚎璁惧鏁�</div>
+ <div class="overview-value">{{ overview.onlineDevices }}</div>
+ </div>
+
+ <div class="overview-item">
+ <div class="overview-label">绂荤嚎璁惧鏁�</div>
+ <div class="overview-value">{{ overview.offlineDevices }}</div>
+ </div>
+ </div>
+
+ <!-- 璁惧鐘舵�侀ゼ鍥� -->
+ <div class="device-status-chart">
+ <canvas id="deviceStatusChart"></canvas>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+
+export default {
+ name: 'DataDashboard',
+ data() {
+ return {
+ activeTime: 'day',
+ timeTabs: [
+ { label: '鏃�', value: 'day' },
+ { label: '鍛�', value: 'week' },
+ { label: '鏈�', value: 'month' },
+ ],
+ dialogVisible: false,
+ selectedPoint: {
+ enterpriseName: '',
+ deviceId: '',
+ oilSmokeConcentration: 0,
+ particulateMatter: 0,
+ nonMethaneHydrocarbon: 0,
+ monitoringTime: '',
+ isOverStandard: false,
+ },
+ metrics: {
+ overStandardCount: 12,
+ overStandardTrend: 5,
+ onlineRate: 92,
+ onlineRateTrend: 2,
+ purifierEfficiency: 85,
+ purifierEfficiencyTrend: -3,
+ taskCompletionRate: 78,
+ taskCompletionRateTrend: 10,
+ },
+ overview: {
+ totalShops: 245,
+ onlineDevices: 220,
+ offlineDevices: 25,
+ },
+ map: null,
+ refreshTimer: null,
+ }
+ },
+ mounted() {
+ this.initMap()
+ this.initDeviceStatusChart()
+ this.startAutoRefresh()
+ },
+ beforeUnmount() {
+ if (this.refreshTimer) {
+ clearInterval(this.refreshTimer)
+ }
+ },
+ methods: {
+ handleTimeChange(tab) {
+ this.activeTime = tab.value
+ // 妯℃嫙鍒囨崲鏃堕棿鍛ㄦ湡鍚庣殑鏁版嵁鏇存柊
+ this.updateMetrics()
+ },
+ getPeriodLabel() {
+ switch (this.activeTime) {
+ case 'day':
+ return '浠婃棩'
+ case 'week':
+ return '鏈懆'
+ case 'month':
+ return '鏈湀'
+ default:
+ return '浠婃棩'
+ }
+ },
+ getCompareLabel() {
+ switch (this.activeTime) {
+ case 'day':
+ return '杈冩槰鏃�'
+ case 'week':
+ return '杈冧笂鍛�'
+ case 'month':
+ return '杈冧笂鏈�'
+ default:
+ return '杈冩槰鏃�'
+ }
+ },
+ updateMetrics() {
+ // 杩欓噷搴旇鏍规嵁閫夋嫨鐨勬椂闂村懆鏈熶粠鎺ュ彛鑾峰彇鏁版嵁
+ // 妯℃嫙鏁版嵁鏇存柊
+ setTimeout(() => {
+ this.metrics = {
+ overStandardCount: Math.floor(Math.random() * 30),
+ overStandardTrend: Math.floor(Math.random() * 20) - 10,
+ onlineRate: Math.floor(Math.random() * 20) + 80,
+ onlineRateTrend: Math.floor(Math.random() * 10) - 5,
+ purifierEfficiency: Math.floor(Math.random() * 30) + 70,
+ purifierEfficiencyTrend: Math.floor(Math.random() * 10) - 5,
+ taskCompletionRate: Math.floor(Math.random() * 40) + 60,
+ taskCompletionRateTrend: Math.floor(Math.random() * 15) - 7,
+ }
+ }, 300)
+ },
+ initMap() {
+ // 杩欓噷搴旇鍒濆鍖栫湡瀹炵殑GIS鍦板浘
+ // 妯℃嫙鍦板浘鍒濆鍖�
+ const mapElement = document.getElementById('map')
+ if (mapElement) {
+ mapElement.innerHTML = '<div class="map-placeholder">GIS鍦板浘鍔犺浇涓�...</div>'
+ // 瀹為檯椤圭洰涓繖閲屽簲璇ヤ娇鐢ㄧ湡瀹炵殑鍦板浘API锛屽楂樺痉鍦板浘銆佺櫨搴﹀湴鍥剧瓑
+ }
+ },
+ initDeviceStatusChart() {
+ const chartDom = document.getElementById('deviceStatusChart')
+ if (chartDom) {
+ const chart = echarts.init(chartDom)
+ const option = {
+ tooltip: {
+ trigger: 'item',
+ formatter: '{b}: {c} ({d}%)',
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
+ borderColor: '#ebeef5',
+ borderWidth: 1,
+ textStyle: {
+ color: '#303133',
+ },
+ },
+ legend: {
+ bottom: '0%',
+ left: 'center',
+ textStyle: {
+ color: '#606266',
+ fontSize: 12,
+ },
+ },
+ series: [
+ {
+ name: '璁惧鐘舵��',
+ type: 'pie',
+ radius: ['40%', '65%'],
+ center: ['50%', '45%'],
+ avoidLabelOverlap: false,
+ itemStyle: {
+ borderRadius: 8,
+ borderColor: '#ffffff',
+ borderWidth: 2,
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.1)',
+ },
+ label: {
+ show: true,
+ position: 'outside',
+ formatter: '{b}: {d}%',
+ fontSize: 12,
+ color: '#606266',
+ },
+ labelLine: {
+ show: true,
+ length: 10,
+ length2: 20,
+ lineStyle: {
+ color: '#606266',
+ width: 1,
+ },
+ },
+ data: [
+ {
+ value: this.overview.onlineDevices,
+ name: '鍦ㄧ嚎',
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#67c23a' },
+ { offset: 1, color: '#409eff' },
+ ]),
+ },
+ },
+ {
+ value: this.overview.offlineDevices,
+ name: '绂荤嚎',
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#f56c6c' },
+ { offset: 1, color: '#e6a23c' },
+ ]),
+ },
+ },
+ ],
+ },
+ ],
+ }
+ chart.setOption(option)
+
+ // 鍝嶅簲寮忚皟鏁�
+ window.addEventListener('resize', () => {
+ chart.resize()
+ })
+ }
+ },
+ startAutoRefresh() {
+ // 姣�30绉掕嚜鍔ㄥ埛鏂版暟鎹�
+ this.refreshTimer = setInterval(() => {
+ this.updateMetrics()
+ // 杩欓噷搴旇鍚屾椂鏇存柊鍦板浘鐐逛綅鏁版嵁
+ }, 30000)
+ },
+ viewDetails() {
+ // 璺宠浆鍒颁紒涓氱洃鎺ц鎯呴〉
+ this.$router.push('/monitor/enterprise-detail')
+ },
+ },
+}
+</script>
+
+<style scoped>
+.data-dashboard {
+ width: 100%;
+ height: 100vh;
+ background-color: #f5f7fa;
+ color: #303133;
+ padding: 20px;
+ box-sizing: border-box;
+ display: grid;
+ grid-template-rows: auto 1fr;
+ grid-template-columns: 1fr 300px;
+ grid-template-areas:
+ 'top overview'
+ 'map overview';
+ gap: 20px;
+}
+
+.top-cards {
+ grid-area: top;
+}
+
+.time-period-card {
+ background-color: #ffffff;
+ border: 1px solid #ebeef5;
+ border-radius: 12px;
+ padding: 24px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.time-period-card .card-title {
+ font-size: 14px;
+ color: #909399;
+ font-weight: 500;
+ margin-bottom: 16px;
+ text-align: center;
+}
+
+.time-tab-container {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+}
+
+.time-tab {
+ padding: 2px 4px;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 500;
+ transition: all 0.3s ease;
+ color: #606266;
+ text-align: center;
+ border: 1px solid #ebeef5;
+ background-color: #f9f9f9;
+}
+
+.time-tab.active {
+ background-color: #409eff;
+ color: #ffffff;
+ border-color: #409eff;
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+}
+
+.time-tab:hover:not(.active) {
+ color: #409eff;
+ border-color: #c6e2ff;
+ background-color: #ecf5ff;
+}
+
+.time-tab.active {
+ background-color: #409eff;
+ color: #ffffff;
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+}
+
+.time-tab:hover:not(.active) {
+ color: #409eff;
+ background-color: rgba(64, 158, 255, 0.1);
+}
+
+.cards-container {
+ display: grid;
+ grid-template-columns: 120px repeat(4, 1fr);
+ gap: 20px;
+}
+
+.metric-card {
+ background-color: #ffffff;
+ border: 1px solid #ebeef5;
+ border-radius: 12px;
+ padding: 24px;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+ position: relative;
+ overflow: hidden;
+}
+
+.metric-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 4px;
+ height: 100%;
+ background-color: #409eff;
+}
+
+.metric-card:nth-child(1)::before {
+ background-color: #f56c6c;
+}
+
+.metric-card:nth-child(2)::before {
+ background-color: #67c23a;
+}
+
+.metric-card:nth-child(3)::before {
+ background-color: #e6a23c;
+}
+
+.metric-card:nth-child(4)::before {
+ background-color: #909399;
+}
+
+.metric-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+}
+
+.card-title {
+ font-size: 14px;
+ color: #909399;
+ font-weight: 500;
+}
+
+.card-icon {
+ font-size: 20px;
+}
+
+.card-value {
+ font-size: 36px;
+ font-weight: bold;
+ margin: 16px 0;
+ color: #303133;
+ line-height: 1.2;
+}
+
+.card-trend {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 13px;
+ padding-top: 12px;
+ border-top: 1px solid #f0f2f5;
+}
+
+.trend-arrow {
+ font-size: 16px;
+ font-weight: bold;
+}
+
+.trend-arrow.up {
+ color: #67c23a;
+}
+
+.trend-arrow.down {
+ color: #f56c6c;
+}
+
+.trend-text {
+ color: #606266;
+ font-weight: 500;
+}
+
+.trend-label {
+ color: #909399;
+ font-size: 12px;
+}
+
+.map-section {
+ grid-area: map;
+ background-color: #ffffff;
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+ position: relative;
+ overflow: hidden;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.map-container {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+
+.map-placeholder {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #909399;
+ font-size: 18px;
+}
+
+.overview-section {
+ grid-area: overview;
+}
+
+.overview-card {
+ background-color: #ffffff;
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+ padding: 20px 0px;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.overview-title {
+ font-size: 16px;
+ font-weight: bold;
+ margin-bottom: 20px;
+ text-align: center;
+ color: #303133;
+}
+
+.overview-items-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+}
+
+.overview-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+ text-align: center;
+ padding: 12px 0;
+}
+
+.overview-item:last-child {
+ border-right: none;
+}
+
+.overview-label {
+ font-size: 14px;
+ color: #606266;
+ font-weight: 500;
+ margin-bottom: 8px;
+}
+
+.overview-value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #303133;
+}
+
+.device-status-chart {
+ flex: 1;
+ margin-top: 20px;
+ min-height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ /* background-color: #c6e2ff; */
+}
+
+.dialog-content {
+ color: #333;
+}
+
+.dialog-footer {
+ text-align: right;
+}
+
+/* 闂儊鏁堟灉 */
+@keyframes blink {
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+.blink {
+ animation: blink 1s infinite;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+ .data-dashboard {
+ grid-template-columns: 1fr;
+ grid-template-areas:
+ 'top'
+ 'map'
+ 'overview';
+ height: auto;
+ }
+
+ .cards-container {
+ grid-template-columns: 160px repeat(2, 1fr);
+ }
+
+ .overview-section {
+ height: 300px;
+ }
+}
+
+@media (max-width: 768px) {
+ .cards-container {
+ grid-template-columns: 1fr;
+ grid-template-rows: auto repeat(4, auto);
+ }
+
+ .time-period-card {
+ order: -1;
+ }
+
+ .time-tab-container {
+ flex-direction: row;
+ }
+
+ .time-tab {
+ flex: 1;
+ padding: 8px 0;
+ }
+}
+</style>
diff --git a/src/views/monitor/DataException.vue b/src/views/monitor/DataException.vue
index 159f6c5..b678d8a 100644
--- a/src/views/monitor/DataException.vue
+++ b/src/views/monitor/DataException.vue
@@ -1,92 +1,84 @@
<template>
- <el-row ref="h1">
- <el-col>
- <!-- 鑿滃崟璇绘爣棰� -->
- <div ref="h1" class="header-container">
- <span class="describe-info">搴楅摵鍚嶉�夋嫨锛�</span>
- <!-- 搴楅摵鍚� 绾ц仈 -->
- <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
-
- <!-- 寮傚父绫诲瀷閫夋嫨 -->
- <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)"> </ExceptionType>
-
- <TimeSelect @submit-time="giveTime"></TimeSelect>
+ <div class="data-exception-container">
+ <!-- 鎼滅储鍖哄煙 -->
+ <div ref="h1" class="search-container">
+ <!-- <div class="search-header">
+ <h3>鏌ヨ琛ㄦ牸</h3>
+ </div> -->
+ <el-row>
+ <div class="search-form">
+ <div class="form-row">
+ <div class="form-item">
+ <span class="form-label">搴楅摵璁惧锛�</span>
+ <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
+ </div>
+ <div class="form-item">
+ <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)">
+ </ExceptionType>
+ </div>
+ </div>
+ <div class="form-row">
+ <div class="form-item full-width">
+ <TimeSelect @submit-time="giveTime" :useNewStyle="true"></TimeSelect>
+ </div>
+ </div>
+ </div>
+ <div class="form-actions">
+ <el-button type="primary" :loading="button.queryButton" @click="showTable"
+ >鏌ヨ</el-button
+ >
+ <el-tooltip
+ class="box-item"
+ effect="dark"
+ content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
+ placement="top-start"
+ >
+ <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
+ <i-ep-Download />
+ </el-icon>
+ </el-tooltip>
+ </div>
+ </el-row>
+ <div class="summary-info">
+ <span>{{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span>
</div>
- <div ref="h2" style="display: flex; margin-top: 2px; justify-content: right">
- <el-button
- type="primary"
- plain
- style="margin-left: 20px"
- :loading="button.queryButton"
- @click="showTable"
- >鏌ヨ</el-button
- >
+ </div>
- <el-tooltip
- class="box-item"
- effect="dark"
- content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
- placement="top-start"
- >
- <!-- 鍋氭垚鍑芥暟js鏂囦欢 -->
- <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
- <i-ep-Download />
- <!-- 瀵煎嚭涓篍xcel -->
- </el-icon>
- </el-tooltip>
- </div>
- <div style="display: flex; justify-content: right; margin-right: 40px">
- <span class="collapse-header-text">
- 闈欏畨鍖� {{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span
- >
- </div>
- <br />
-
- <el-collapse ref="h3" v-model="activeNames">
+ <!-- 寮傚父鍒嗘瀽 -->
+ <div class="analysis-container">
+ <el-collapse v-model="activeNames">
<el-collapse-item name="1">
<template #title>
- <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+ <div class="collapse-title">
<h4 class="collapse-header">寮傚父鍒嗘瀽</h4>
<el-icon class="header-icon">
<i-ep-info-filled />
</el-icon>
- </el-tooltip>
-
- <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
- </el-tooltip>
+ </div>
</template>
- <el-card class="box-card">
- <el-row :gutter="25">
+ <el-card class="analysis-card">
+ <el-row :gutter="24">
<el-col :span="8">
- <div style="display: flex">
- <img
- src="@/assets/exceed.jpg"
- style="width: 25px; height: 25px; margin-top: 5px"
- />
- <span
- style="font-size: 16px; font-weight: bold; margin-top: 4px; margin-left: 4px"
- >娌圭儫娴撳害瓒呮爣</span
- >
- </div>
-
- <div class="box-card-label">
- <el-scrollbar>
- <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
- <span style="font-size: 20px">{{ exception0.length }} /{{ shopsTotal }} </span>
- <span style="font-size: 17px">
- ({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
- >
- {{ shopsTotal }}
- <span class="right-text">
+ <div class="analysis-item">
+ <div class="item-header">
+ <img src="@/assets/exceed.jpg" class="item-icon" />
+ <span class="item-title">娌圭儫娴撳害瓒呮爣</span>
+ </div>
+ <div class="item-content">
+ <div class="item-stats">
+ <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span class="stats-value">{{ exception0.length }} /{{ shopsTotal }}</span>
+ <span class="stats-percent"
+ >({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ </div>
+ <div class="item-percent">
寮傚父鏁板崰姣旓細{{ ((exception0Num / exceptionAllNum) * 100).toFixed(1) }}%
- </span>
- </el-scrollbar>
- </div>
-
- <hr />
- <div class="box-card-butcontainer">
- <el-card class="sub-box-card">
- <el-scrollbar max-height="70px">
+ </div>
+ </div>
+ <hr class="item-divider" />
+ <div class="item-shops">
+ <el-scrollbar max-height="80px">
<ExceptionText
v-for="(item, index) in exception0"
:key="item"
@@ -100,39 +92,30 @@
<span v-if="index < exception0.length - 1" class="text-blank">,</span>
</ExceptionText>
</el-scrollbar>
- </el-card>
+ </div>
</div>
</el-col>
-
<el-col :span="8">
- <div style="display: flex">
- <img
- src="@/assets/exception.jpg"
- style="width: 25px; height: 25px; margin-top: 5px"
- />
- <span
- style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
- >渚涚數寮傚父</span
- >
- </div>
- <div class="box-card-label">
- <el-scrollbar>
- <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
- <span style="font-size: 20px">{{ exception1.length }} /{{ shopsTotal }}</span>
- <span style="font-size: 17px">
- ({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
- >
- <span class="right-text">
+ <div class="analysis-item">
+ <div class="item-header">
+ <img src="@/assets/exception.jpg" class="item-icon" />
+ <span class="item-title">渚涚數寮傚父</span>
+ </div>
+ <div class="item-content">
+ <div class="item-stats">
+ <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span class="stats-value">{{ exception1.length }} /{{ shopsTotal }}</span>
+ <span class="stats-percent"
+ >({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ </div>
+ <div class="item-percent">
寮傚父鏁板崰姣旓細{{ ((exception1Num / exceptionAllNum) * 100).toFixed(1) }}%
- </span>
- </el-scrollbar>
- </div>
-
- <hr />
-
- <div>
- <el-card class="sub-box-card">
- <el-scrollbar max-height="70px">
+ </div>
+ </div>
+ <hr class="item-divider" />
+ <div class="item-shops">
+ <el-scrollbar max-height="80px">
<ExceptionText
v-for="(item, index) in exception1"
:key="item"
@@ -146,35 +129,28 @@
<span v-if="index < exception1.length - 1" class="text-blank">,</span>
</ExceptionText>
</el-scrollbar>
- </el-card>
+ </div>
</div>
</el-col>
-
<el-col :span="8">
- <div style="display: flex">
- <img
- src="@/assets/offline.jpg"
- style="width: 25px; height: 25px; margin-top: 5px"
- />
- <span
- style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
- >璁惧鎴栫綉缁滃紓甯�</span
- >
- </div>
- <div class="box-card-label">
- <el-scrollbar>
- <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
- <span style="font-size: 20px">{{ exception2.length }} /{{ shopsTotal }}</span>
- <span style="font-size: 17px">
- ({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
- >
- <span class="right-text"> 寮傚父鏁板崰姣旓細{{ connectException }}% </span>
- </el-scrollbar>
- </div>
- <hr />
- <div>
- <el-card class="sub-box-card">
- <el-scrollbar max-height="70px">
+ <div class="analysis-item">
+ <div class="item-header">
+ <img src="@/assets/offline.jpg" class="item-icon" />
+ <span class="item-title">璁惧鎴栫綉缁滃紓甯�</span>
+ </div>
+ <div class="item-content">
+ <div class="item-stats">
+ <span class="stats-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span class="stats-value">{{ exception2.length }} /{{ shopsTotal }}</span>
+ <span class="stats-percent"
+ >({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ </div>
+ <div class="item-percent">寮傚父鏁板崰姣旓細{{ connectException }}%</div>
+ </div>
+ <hr class="item-divider" />
+ <div class="item-shops">
+ <el-scrollbar max-height="80px">
<ExceptionText
v-for="(item, index) in exception2"
:key="item"
@@ -188,212 +164,198 @@
<span v-if="index < exception2.length - 1" class="text-blank">,</span>
</ExceptionText>
</el-scrollbar>
- </el-card>
+ </div>
</div>
</el-col>
</el-row>
</el-card>
</el-collapse-item>
</el-collapse>
+ </div>
- <h4 class="table-text">寮傚父鏁版嵁</h4>
- </el-col>
- </el-row>
- <el-card class="table-page" v-show="!isNoData">
- <el-table
- ref="tableH"
- size="small"
- v-loading="loading"
- :data="displayData"
- style="width: 100%"
- border
- :height="tableHeight"
- :cell-class-name="tableCellClassName"
- >
- <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.diName">
- <div class="cell ellipsis">{{ row.diName }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
-
- <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.devId">
- <div class="cell ellipsis">{{ row.devId }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
-
- <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.diSupplier">
- <div class="cell ellipsis">{{ row.diSupplier }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
-
- <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.exception">
- <div class="cell ellipsis">{{ row.exception }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column label="寮傚父绫诲瀷" align="center">
- <template #default="{ row }">
- <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
- <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
- <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
- </template>
- </el-table-column>
- <el-table-column prop="region" label="鍦板尯" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.region">
- <div class="cell ellipsis">{{ row.region }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
-
- <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.beginTime">
- <div class="cell ellipsis">{{ row.beginTime }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.endTime">
- <div class="cell ellipsis">{{ row.endTime }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" align="center">
- <template #default="{ row }">
- <el-button type="primary" class="table-button" @click="showDrawer(row)"
- >鏌ョ湅璇︽儏</el-button
- >
- </template>
- </el-table-column>
- </el-table>
-
- <el-pagination
- ref="h4"
- background
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- :total="total"
- :page-size="pageSize"
- layout="total,prev, pager, next, jumper"
- />
- </el-card>
- <el-empty v-show="isNoData" :image-size="200" />
- <!-- 瀵硅瘽妗� -->
- <div>
- <el-dialog v-model="centerDialogVisible" draggable align-center>
- <template #header>
- <div style="font-size: 17px">
- 搴楅摵鍚嶏細{{ rowShopName }}
- <span style="margin-left: 40px">寮傚父绫诲瀷锛�</span>
- <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
- <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
- <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
- <div style="margin-top: 10px">
- 寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~
- {{ rowEndTime }}
- </div>
- </div>
-
- <div class="dialog-button-position">
- <el-button
- type="danger"
- :loading="button.preButton"
- :disabled="isPreCantouch || banTouch"
- @click="getPreviousRowData"
- >涓婃潯寮傚父</el-button
- >
- <el-button
- type="danger"
- :loading="button.afterButton"
- :disabled="isNextCantouch || banTouch"
- @click="getNextRowData"
- >涓嬫潯寮傚父</el-button
- >
- </div>
- </template>
-
- <!-- 瓒呮爣鏁版嵁鏃� -->
- <!-- 鎶樼嚎鍥� -->
-
- <!-- 鎺夌嚎 -->
- <!-- <div
- ref="ref"
- v-show="isOfflineShow"
- style="
- width: 100%;
- height: 300px;
- /* min-width: 100px; */
- margin-bottom: 20px;
- margin-left: 10px;
- min-width: 350px;
- "
- ></div> -->
-
- <ExceptionTypeLineChart
- :option="option"
- :is-open-dialog="centerDialogVisible"
- v-loading="chartLoading"
- ></ExceptionTypeLineChart>
-
- <!-- -->
- <div style="margin-top: 40px; margin-bottom: 5px; border: 1px">
- <el-table :data="exceedingData" height="360" border style="margin-top: 25px">
- <el-table-column
- type="index"
- label="搴忓彿"
- width="60px"
- align="center"
- fixed
- :index="indexMethod"
- ></el-table-column>
- <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
- <el-table-column
- prop="mvStatCode"
- label="璁惧缂栧彿"
- align="center"
- show-overflow-tooltip
- />
- <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center" show-overflow-tooltip />
- <el-table-column
- prop="mvDataTime"
- label="閲囬泦鏃堕棿"
- align="center"
- show-overflow-tooltip
- />
-
- <el-table-column
- prop="mvFumeConcentration2"
- label="娌圭儫娴撳害(mg/m鲁)"
- align="center"
- show-overflow-tooltip
- />
+ <!-- 寮傚父鏁版嵁琛ㄦ牸 -->
+ <div class="table-container">
+ <h4 class="table-title">寮傚父鏁版嵁</h4>
+ <el-card v-show="!isNoData">
+ <el-table
+ ref="tableH"
+ v-loading="loading"
+ :data="displayData"
+ style="width: 100%"
+ border
+ :height="tableHeight"
+ :cell-class-name="tableCellClassName"
+ >
+ <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.diName">
+ <div class="cell ellipsis">{{ row.diName }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.devId">
+ <div class="cell ellipsis">{{ row.devId }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.diSupplier">
+ <div class="cell ellipsis">{{ row.diSupplier }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.exception">
+ <div class="cell ellipsis">{{ row.exception }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column label="寮傚父绫诲瀷" align="center">
+ <template #default="{ row }">
+ <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+ <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
+ <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="region" label="鍦板尯" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.region">
+ <div class="cell ellipsis">{{ row.region }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.beginTime">
+ <div class="cell ellipsis">{{ row.beginTime }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.endTime">
+ <div class="cell ellipsis">{{ row.endTime }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" width="120">
+ <template #default="{ row }">
+ <el-button type="primary" size="small" @click="showDrawer(row)">鏌ョ湅</el-button>
+ </template>
+ </el-table-column>
</el-table>
- </div>
+ <div class="pagination-container">
+ <el-pagination
+ ref="h4"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ :total="total"
+ :page-size="pageSize"
+ layout="total, prev, pager, next, jumper"
+ />
+ </div>
+ </el-card>
+ <el-empty v-show="isNoData" :image-size="200" />
+ </div>
- <el-tag type="success" class="mx-1" effect="dark" round
- ><span class="table-line-lable" v-show="rowExceptionType == '0'">寮傚父璁板綍锛� </span>
- <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
- <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
- <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
- </el-tag>
- </el-dialog>
+ <!-- 瀵硅瘽妗� -->
+ <div>
+ <el-dialog v-model="centerDialogVisible" draggable align-center class="detail-dialog">
+ <template #header>
+ <div class="dialog-header">
+ <div class="dialog-title">
+ <span>搴楅摵鍚嶏細{{ rowShopName }}</span>
+ <span class="dialog-info"
+ >寮傚父绫诲瀷锛�
+ <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+ <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
+ <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
+ </span>
+ <div class="dialog-time">寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~ {{ rowEndTime }}</div>
+ </div>
+ <div class="dialog-actions">
+ <el-button
+ type="primary"
+ :loading="button.preButton"
+ :disabled="isPreCantouch || banTouch"
+ @click="getPreviousRowData"
+ >涓婃潯寮傚父</el-button
+ >
+ <el-button
+ type="primary"
+ :loading="button.afterButton"
+ :disabled="isNextCantouch || banTouch"
+ @click="getNextRowData"
+ >涓嬫潯寮傚父</el-button
+ >
+ </div>
+ </div>
+ </template>
+
+ <ExceptionTypeLineChart
+ :option="option"
+ :is-open-dialog="centerDialogVisible"
+ v-loading="chartLoading"
+ ></ExceptionTypeLineChart>
+
+ <div class="dialog-table-container">
+ <el-table :data="exceedingData" height="360" border style="margin-top: 20px">
+ <el-table-column
+ type="index"
+ label="搴忓彿"
+ width="60px"
+ align="center"
+ fixed
+ :index="indexMethod"
+ ></el-table-column>
+ <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
+ <el-table-column
+ prop="mvStatCode"
+ label="璁惧缂栧彿"
+ align="center"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="diSupplier"
+ label="渚涘簲鍟�"
+ align="center"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="mvDataTime"
+ label="閲囬泦鏃堕棿"
+ align="center"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="mvFumeConcentration2"
+ label="娌圭儫娴撳害(mg/m鲁)"
+ align="center"
+ show-overflow-tooltip
+ />
+ </el-table>
+ </div>
+
+ <div class="dialog-footer">
+ <el-tag type="success" effect="dark" round
+ ><span v-show="rowExceptionType == '0'">寮傚父璁板綍锛�</span>
+ <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
+ <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
+ <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
+ </el-tag>
+ </div>
+ </el-dialog>
+ </div>
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
import ExceptionType from '@/sfc/ExceptionType.vue'
import TimeSelect from '@/sfc/TimeSelect.vue'
import ExceptionText from '@/sfc/ExceptionText.vue'
@@ -632,7 +594,7 @@
//鍔熻兘锛� 鍔ㄦ�佽绠楄〃鏍奸珮搴�
calcTableHeight() {
- const h1 = this.$refs.h1.$el.offsetHeight
+ const h1 = this.$refs.h1.offsetHeight
const h2 = this.$refs.h4.$el.offsetHeight
this.tableHeight = `calc(100vh - ${h1}px - ${h2}px - 45px - var(--el-main-padding) * 2 - var(--el-card-padding))`
},
@@ -1530,12 +1492,241 @@
</script>
<style scoped>
-.header-container {
- display: flex;
- margin-left: 20px;
- /* flex-wrap: wrap;
- align-items: center; */
+/* 鍏ㄥ眬瀹瑰櫒 */
+.data-exception-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
}
+
+/* 鎼滅储鍖哄煙 */
+.search-container {
+ background-color: white;
+ border-radius: 8px;
+ padding: 20px;
+ margin-bottom: 20px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.search-header {
+ margin-bottom: 20px;
+}
+
+.search-header h3 {
+ margin: 0;
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
+
+.search-form {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ flex: 1;
+}
+
+.form-row {
+ display: flex;
+ align-items: flex-start;
+ gap: 16px;
+ flex-wrap: wrap;
+}
+
+.form-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex: 1;
+ min-width: 200px;
+}
+
+.form-item.full-width {
+ flex: 100%;
+}
+
+.form-label {
+ font-weight: bolder;
+ white-space: nowrap;
+}
+
+.form-actions {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.summary-info {
+ text-align: right;
+ font-size: 14px;
+ color: #999;
+ margin-top: 8px;
+}
+
+/* 寮傚父鍒嗘瀽 */
+.analysis-container {
+ background-color: white;
+ border-radius: 8px;
+ padding: 20px;
+ margin-bottom: 20px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.collapse-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.collapse-header {
+ margin: 0;
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
+
+.header-icon {
+ color: #1890ff;
+}
+
+.analysis-card {
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.analysis-item {
+ height: 180px;
+ display: flex;
+ flex-direction: column;
+}
+
+.item-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 12px;
+}
+
+.item-icon {
+ width: 24px;
+ height: 24px;
+}
+
+.item-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #333;
+}
+
+.item-content {
+ flex: 1;
+ margin-bottom: 12px;
+}
+
+.item-stats {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 4px;
+}
+
+.stats-label {
+ font-size: 13px;
+ color: #666;
+}
+
+.stats-value {
+ font-size: 18px;
+ font-weight: 600;
+ color: #333;
+}
+
+.stats-percent {
+ font-size: 13px;
+ color: #999;
+}
+
+.item-percent {
+ font-size: 13px;
+ color: #666;
+ margin-top: 4px;
+}
+
+.item-divider {
+ margin: 10px 0;
+ border: 0.5px solid #f0f0f0;
+}
+
+.item-shops {
+ flex: 1;
+}
+
+/* 琛ㄦ牸鍖哄煙 */
+.table-container {
+ background-color: white;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.table-title {
+ margin: 0 0 16px 0;
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
+
+.pagination-container {
+ margin-top: 16px;
+ display: flex;
+ justify-content: flex-end;
+}
+
+/* 瀵硅瘽妗� */
+.detail-dialog {
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ width: 100%;
+}
+
+.dialog-title {
+ font-size: 16px;
+ color: #333;
+}
+
+.dialog-info {
+ margin-left: 24px;
+ color: #666;
+}
+
+.dialog-time {
+ margin-top: 8px;
+ font-size: 14px;
+ color: #666;
+}
+
+.dialog-actions {
+ display: flex;
+ gap: 8px;
+}
+
+.dialog-table-container {
+ margin-top: 20px;
+}
+
+.dialog-footer {
+ margin-top: 20px;
+ text-align: right;
+}
+
+/* 閫氱敤鏍峰紡 */
.ellipsis {
white-space: nowrap;
overflow: hidden;
@@ -1543,148 +1734,127 @@
}
.iconExcel {
- font-size: 25px;
- margin-left: 20px;
- bottom: -6px;
+ font-size: 20px;
+ cursor: pointer;
+ color: #1890ff;
}
-/* 鍙紶鏍囩澶村彉涓哄彲鐐瑰嚮鐘舵�� */
.clickable {
cursor: pointer;
}
-.card-header {
- margin: 0;
-}
-body {
- margin: 0;
-}
-.exception-divider-rowline {
- margin: 10px 0px;
-}
-/* 寮傚父鍒嗘瀽鏁版嵁涓庢寜閽� */
-.exception-container {
- display: flex;
-}
-.example-showcase .el-loading-mask {
- z-index: 9;
-}
-
-.scrollbar-demo-item {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 20px;
- margin: 10px;
- text-align: center;
- border-radius: 4px;
- background: var(--el-color-primary-light-9);
- color: var(--el-color-primary);
-}
-.collapse-header {
- margin-left: 5px;
- font-size: 18px;
-}
-.collapse-header-text {
- margin-top: 5px;
- font-size: 14px;
- color: gray;
-}
-
-.box-card-label {
- font-size: 14px;
- white-space: nowrap;
-}
-
-.right-text {
- /* float :right; */
- /* text-align: right; */
- margin-left: 80px;
-}
-:deep().el-card {
- border-radius: 9px;
-}
-
-/* 鈥樻煡鐪嬭鎯呪�� 鐨勫脊鍑烘楂樺害璋冩暣 */
-:deep().el-dialog {
- height: 98%;
- /* 涓嶅嚭鐜版粴鍔ㄦ潯 */
- overflow-y: hidden;
- border-radius: 9px;
-}
-.table-page {
- margin-left: 20px;
-}
-
-.table-text {
- font-size: 18px;
- margin: 5px 0px 10px 20px;
-}
.text-blank {
margin-right: 10px;
color: #000000;
}
-/* 搴楅摵鍚嶉�夋嫨鏂囨湰 */
-.describe-info {
- margin-top: 5px;
- font-weight: bold;
- white-space: nowrap;
-}
-/* 鏃堕棿閫夋嫨鏂囨湰 */
-.describe-time-text {
- margin-left: 30px;
- margin-top: 5px;
- font-weight: bold;
-}
-/* 寮傚父琛ㄦ牸涓嬫爣绛句腑鐨勬暟缁� */
.table-line-num {
font-weight: bold;
color: black;
}
-.button_info.el-button_inner {
- text-align: left;
+
+/* 琛ㄦ牸琛屾牱寮� */
+:deep().el-table__row .exceeding-row {
+ background-color: #fff1f0;
+ color: #cf1322;
}
+
+:deep().el-table__row .abnormal-power-supply {
+ background-color: #fffbe6;
+ color: #d48806;
+}
+
+:deep().el-table__row .disconnect {
+ background-color: #e6f7ff;
+ color: #1890ff;
+}
+
+/* 琛ㄦ牸鏍峰紡 */
+:deep().el-table {
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+:deep().el-table th {
+ background-color: #fafafa;
+ font-weight: 600;
+}
+
+/* 鎸夐挳鏍峰紡 */
+:deep().el-button--primary {
+ background-color: #1890ff;
+ border-color: #1890ff;
+}
+
+:deep().el-button--primary:hover {
+ background-color: #40a9ff;
+ border-color: #40a9ff;
+}
+
+/* 鍗$墖鏍峰紡 */
+:deep().el-card {
+ border-radius: 8px;
+ border: 1px solid #f0f0f0;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 1200px) {
+ .search-form {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .form-actions {
+ margin-left: 0;
+ margin-top: 12px;
+ }
+}
+
+/* 鍘熸湁鏍峰紡鍏煎 */
+.header-container {
+ display: flex;
+ margin-left: 0;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 16px;
+}
+
+.describe-info {
+ margin-top: 0;
+ font-weight: 500;
+ white-space: nowrap;
+ color: #666;
+}
+
+.table-page {
+ margin-left: 0;
+}
+
+.table-text {
+ font-size: 16px;
+ margin: 0 0 16px 0;
+ font-weight: 600;
+ color: #333;
+}
+
.el-collapse {
- margin-left: 20px;
+ margin-left: 0;
}
-:deep().el-collapse .el-collapse-item__content {
- padding-bottom: 0px;
-}
+
.box-card {
- height: 190px;
+ height: auto;
+ min-height: 190px;
}
.sub-box-card {
- height: 100px;
+ height: auto;
+ min-height: 100px;
border: 0px;
}
-.mx-1 {
- margin-bottom: 0px;
-}
.dialog-button-position {
display: flex;
justify-content: right;
margin-bottom: 10px;
-}
-
-:deep().el-table__row .exceeding-row {
- background-color: #f53f3f;
-}
-:deep().el-table__row .abnormal-power-supply {
- background-color: #fdf4bf;
-}
-:deep().el-table__row .disconnect {
- background-color: #f7ba1e;
-}
-
-.el-table {
- color: #000000;
-}
-
-/* 琛ㄦ牸涓殑鎸夐挳瀹藉害閾烘弧 */
-.table-button {
- width: 100%;
}
</style>
diff --git a/src/views/monitor/DataException_old.vue b/src/views/monitor/DataException_old.vue
new file mode 100644
index 0000000..159f6c5
--- /dev/null
+++ b/src/views/monitor/DataException_old.vue
@@ -0,0 +1,1690 @@
+<template>
+ <el-row ref="h1">
+ <el-col>
+ <!-- 鑿滃崟璇绘爣棰� -->
+ <div ref="h1" class="header-container">
+ <span class="describe-info">搴楅摵鍚嶉�夋嫨锛�</span>
+ <!-- 搴楅摵鍚� 绾ц仈 -->
+ <ShopNameAndID @submit-id="(n) => (deviceId[1] = n)"></ShopNameAndID>
+
+ <!-- 寮傚父绫诲瀷閫夋嫨 -->
+ <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)"> </ExceptionType>
+
+ <TimeSelect @submit-time="giveTime"></TimeSelect>
+ </div>
+ <div ref="h2" style="display: flex; margin-top: 2px; justify-content: right">
+ <el-button
+ type="primary"
+ plain
+ style="margin-left: 20px"
+ :loading="button.queryButton"
+ @click="showTable"
+ >鏌ヨ</el-button
+ >
+
+ <el-tooltip
+ class="box-item"
+ effect="dark"
+ content="鐐瑰嚮鍙鍑篍xcel鏂囦欢"
+ placement="top-start"
+ >
+ <!-- 鍋氭垚鍑芥暟js鏂囦欢 -->
+ <el-icon class="iconExcel clickable" title="瀵煎嚭Excel鏂囦欢" @click="exportDom">
+ <i-ep-Download />
+ <!-- 瀵煎嚭涓篍xcel -->
+ </el-icon>
+ </el-tooltip>
+ </div>
+ <div style="display: flex; justify-content: right; margin-right: 40px">
+ <span class="collapse-header-text">
+ 闈欏畨鍖� {{ beginTime }} 鈥斺�� {{ endTime }} 娌圭儫鐩戞祴寮傚父淇℃伅姹囨��</span
+ >
+ </div>
+ <br />
+
+ <el-collapse ref="h3" v-model="activeNames">
+ <el-collapse-item name="1">
+ <template #title>
+ <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+ <h4 class="collapse-header">寮傚父鍒嗘瀽</h4>
+ <el-icon class="header-icon">
+ <i-ep-info-filled />
+ </el-icon>
+ </el-tooltip>
+
+ <el-tooltip class="box-item" effect="dark" content="鐐瑰嚮鍙姌鍙�" placement="right-start">
+ </el-tooltip>
+ </template>
+ <el-card class="box-card">
+ <el-row :gutter="25">
+ <el-col :span="8">
+ <div style="display: flex">
+ <img
+ src="@/assets/exceed.jpg"
+ style="width: 25px; height: 25px; margin-top: 5px"
+ />
+ <span
+ style="font-size: 16px; font-weight: bold; margin-top: 4px; margin-left: 4px"
+ >娌圭儫娴撳害瓒呮爣</span
+ >
+ </div>
+
+ <div class="box-card-label">
+ <el-scrollbar>
+ <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span style="font-size: 20px">{{ exception0.length }} /{{ shopsTotal }} </span>
+ <span style="font-size: 17px">
+ ({{ ((exception0.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ {{ shopsTotal }}
+ <span class="right-text">
+ 寮傚父鏁板崰姣旓細{{ ((exception0Num / exceptionAllNum) * 100).toFixed(1) }}%
+ </span>
+ </el-scrollbar>
+ </div>
+
+ <hr />
+ <div class="box-card-butcontainer">
+ <el-card class="sub-box-card">
+ <el-scrollbar max-height="70px">
+ <ExceptionText
+ v-for="(item, index) in exception0"
+ :key="item"
+ :devId="item.devId"
+ exception-value="0"
+ :begin-time="beginTime"
+ :end-time="endTime"
+ @submit-exception-data="getAbnormalDataByClick"
+ >
+ {{ item.diName }}
+ <span v-if="index < exception0.length - 1" class="text-blank">,</span>
+ </ExceptionText>
+ </el-scrollbar>
+ </el-card>
+ </div>
+ </el-col>
+
+ <el-col :span="8">
+ <div style="display: flex">
+ <img
+ src="@/assets/exception.jpg"
+ style="width: 25px; height: 25px; margin-top: 5px"
+ />
+ <span
+ style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
+ >渚涚數寮傚父</span
+ >
+ </div>
+ <div class="box-card-label">
+ <el-scrollbar>
+ <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span style="font-size: 20px">{{ exception1.length }} /{{ shopsTotal }}</span>
+ <span style="font-size: 17px">
+ ({{ ((exception1.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ <span class="right-text">
+ 寮傚父鏁板崰姣旓細{{ ((exception1Num / exceptionAllNum) * 100).toFixed(1) }}%
+ </span>
+ </el-scrollbar>
+ </div>
+
+ <hr />
+
+ <div>
+ <el-card class="sub-box-card">
+ <el-scrollbar max-height="70px">
+ <ExceptionText
+ v-for="(item, index) in exception1"
+ :key="item"
+ :devId="item.devId"
+ exception-value="1"
+ :begin-time="beginTime"
+ :end-time="endTime"
+ @submit-exception-data="getAbnormalDataByClick"
+ >
+ {{ item.diName }}
+ <span v-if="index < exception1.length - 1" class="text-blank">,</span>
+ </ExceptionText>
+ </el-scrollbar>
+ </el-card>
+ </div>
+ </el-col>
+
+ <el-col :span="8">
+ <div style="display: flex">
+ <img
+ src="@/assets/offline.jpg"
+ style="width: 25px; height: 25px; margin-top: 5px"
+ />
+ <span
+ style="font-size: 16px; font-weight: bold; margin-top: 5px; margin-left: 4px"
+ >璁惧鎴栫綉缁滃紓甯�</span
+ >
+ </div>
+ <div class="box-card-label">
+ <el-scrollbar>
+ <span class="box-card-label">寮傚父搴楅摵鍗犳瘮锛�</span>
+ <span style="font-size: 20px">{{ exception2.length }} /{{ shopsTotal }}</span>
+ <span style="font-size: 17px">
+ ({{ ((exception2.length / shopsTotal) * 100).toFixed(1) }}%)</span
+ >
+ <span class="right-text"> 寮傚父鏁板崰姣旓細{{ connectException }}% </span>
+ </el-scrollbar>
+ </div>
+ <hr />
+ <div>
+ <el-card class="sub-box-card">
+ <el-scrollbar max-height="70px">
+ <ExceptionText
+ v-for="(item, index) in exception2"
+ :key="item"
+ :devId="item.devId"
+ exception-value="2"
+ :begin-time="beginTime"
+ :end-time="endTime"
+ @submit-exception-data="getAbnormalDataByClick"
+ >
+ {{ item.diName }}
+ <span v-if="index < exception2.length - 1" class="text-blank">,</span>
+ </ExceptionText>
+ </el-scrollbar>
+ </el-card>
+ </div>
+ </el-col>
+ </el-row>
+ </el-card>
+ </el-collapse-item>
+ </el-collapse>
+
+ <h4 class="table-text">寮傚父鏁版嵁</h4>
+ </el-col>
+ </el-row>
+ <el-card class="table-page" v-show="!isNoData">
+ <el-table
+ ref="tableH"
+ size="small"
+ v-loading="loading"
+ :data="displayData"
+ style="width: 100%"
+ border
+ :height="tableHeight"
+ :cell-class-name="tableCellClassName"
+ >
+ <el-table-column prop="diName" label="搴楅摵鍚嶇О" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.diName">
+ <div class="cell ellipsis">{{ row.diName }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+
+ <el-table-column prop="devId" label="璁惧缂栧彿" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.devId">
+ <div class="cell ellipsis">{{ row.devId }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+
+ <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.diSupplier">
+ <div class="cell ellipsis">{{ row.diSupplier }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+
+ <el-table-column prop="exception" label="寮傚父鍒嗙被" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.exception">
+ <div class="cell ellipsis">{{ row.exception }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column label="寮傚父绫诲瀷" align="center">
+ <template #default="{ row }">
+ <span v-if="row.exceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+ <span v-else-if="row.exceptionType == '1'">鐤戜技渚涚數寮傚父</span>
+ <span v-else-if="row.exceptionType == '2'">鎺夌嚎</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="region" label="鍦板尯" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.region">
+ <div class="cell ellipsis">{{ row.region }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+
+ <el-table-column prop="beginTime" label="寮�濮嬫椂闂�" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.beginTime">
+ <div class="cell ellipsis">{{ row.beginTime }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column prop="endTime" label="缁撴潫鏃堕棿" align="center">
+ <template #default="{ row }">
+ <el-tooltip effect="dark" :content="row.endTime">
+ <div class="cell ellipsis">{{ row.endTime }}</div>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center">
+ <template #default="{ row }">
+ <el-button type="primary" class="table-button" @click="showDrawer(row)"
+ >鏌ョ湅璇︽儏</el-button
+ >
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <el-pagination
+ ref="h4"
+ background
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ :total="total"
+ :page-size="pageSize"
+ layout="total,prev, pager, next, jumper"
+ />
+ </el-card>
+ <el-empty v-show="isNoData" :image-size="200" />
+ <!-- 瀵硅瘽妗� -->
+ <div>
+ <el-dialog v-model="centerDialogVisible" draggable align-center>
+ <template #header>
+ <div style="font-size: 17px">
+ 搴楅摵鍚嶏細{{ rowShopName }}
+ <span style="margin-left: 40px">寮傚父绫诲瀷锛�</span>
+ <span v-if="rowExceptionType == '0'">娌圭儫鏁版嵁瓒呮爣</span>
+ <span v-else-if="rowExceptionType == '1'">渚涚數寮傚父</span>
+ <span v-else-if="rowExceptionType == '2'">鎺夌嚎</span>
+ <div style="margin-top: 10px">
+ 寮傚父鏃堕棿娈碉細{{ rowBeginTime }} ~
+ {{ rowEndTime }}
+ </div>
+ </div>
+
+ <div class="dialog-button-position">
+ <el-button
+ type="danger"
+ :loading="button.preButton"
+ :disabled="isPreCantouch || banTouch"
+ @click="getPreviousRowData"
+ >涓婃潯寮傚父</el-button
+ >
+ <el-button
+ type="danger"
+ :loading="button.afterButton"
+ :disabled="isNextCantouch || banTouch"
+ @click="getNextRowData"
+ >涓嬫潯寮傚父</el-button
+ >
+ </div>
+ </template>
+
+ <!-- 瓒呮爣鏁版嵁鏃� -->
+ <!-- 鎶樼嚎鍥� -->
+
+ <!-- 鎺夌嚎 -->
+ <!-- <div
+ ref="ref"
+ v-show="isOfflineShow"
+ style="
+ width: 100%;
+ height: 300px;
+ /* min-width: 100px; */
+ margin-bottom: 20px;
+ margin-left: 10px;
+ min-width: 350px;
+ "
+ ></div> -->
+
+ <ExceptionTypeLineChart
+ :option="option"
+ :is-open-dialog="centerDialogVisible"
+ v-loading="chartLoading"
+ ></ExceptionTypeLineChart>
+
+ <!-- -->
+ <div style="margin-top: 40px; margin-bottom: 5px; border: 1px">
+ <el-table :data="exceedingData" height="360" border style="margin-top: 25px">
+ <el-table-column
+ type="index"
+ label="搴忓彿"
+ width="60px"
+ align="center"
+ fixed
+ :index="indexMethod"
+ ></el-table-column>
+ <el-table-column fixed prop="diName" label="搴楅摵鍚嶇О" show-overflow-tooltip />
+ <el-table-column
+ prop="mvStatCode"
+ label="璁惧缂栧彿"
+ align="center"
+ show-overflow-tooltip
+ />
+ <el-table-column prop="diSupplier" label="渚涘簲鍟�" align="center" show-overflow-tooltip />
+ <el-table-column
+ prop="mvDataTime"
+ label="閲囬泦鏃堕棿"
+ align="center"
+ show-overflow-tooltip
+ />
+
+ <el-table-column
+ prop="mvFumeConcentration2"
+ label="娌圭儫娴撳害(mg/m鲁)"
+ align="center"
+ show-overflow-tooltip
+ />
+ </el-table>
+ </div>
+
+ <el-tag type="success" class="mx-1" effect="dark" round
+ ><span class="table-line-lable" v-show="rowExceptionType == '0'">寮傚父璁板綍锛� </span>
+ <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缂哄け鏁版嵁锛�</span>
+ <span class="table-line-num">{{ exceptionTotal }}鏉�</span>
+ <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> (閫昏緫璁$畻)</span>
+ </el-tag>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { defineAsyncComponent } from 'vue'
+import ExceptionType from '@/sfc/ExceptionType.vue'
+import TimeSelect from '@/sfc/TimeSelect.vue'
+import ExceptionText from '@/sfc/ExceptionText.vue'
+
+import * as XLSX from 'xlsx/xlsx.mjs'
+import dayjs from 'dayjs'
+import axiosInstanceInstance from '@/utils/request.js'
+
+const ShopNameAndID = defineAsyncComponent(() => import('@/sfc/ShopNameAndID.vue'))
+
+// 寮傚父鍥惧舰寮傛缁勪欢
+const ExceptionTypeLineChart = defineAsyncComponent(
+ () => import('@/sfc/ExceptionTypeLineChart.vue'),
+)
+export default {
+ name: 'TablePage',
+ components: {
+ ExceptionType,
+ TimeSelect,
+ ShopNameAndID,
+ ExceptionText,
+ ExceptionTypeLineChart,
+ },
+ data() {
+ return {
+ exception0Num: 0,
+ exception1Num: 0,
+ exception2Num: 0,
+ // 鎶樼嚎鍥惧姞杞戒腑
+ chartLoading: false,
+ button: {
+ // 鏌ヨ鎸夐挳
+ queryButton: false,
+ // 涓婁竴鏉℃寜閽�
+ preButton: false,
+ // 涓嬩竴鏉℃寜閽�
+ afterButton: false,
+ //
+ banTouch: 0,
+ },
+ // 寮傚父鎶樼嚎鍥剧殑閰嶇疆
+ option: {},
+ // 鎶樼嚎鍥惧睍绀�
+ isChartShow: false,
+ // table鍏冪礌
+ tableRef: null,
+ // 寮傚父琛ㄦ牸鏁版嵁
+ tableHeight: 300,
+ // 绌烘暟鎹姸鎬�
+ isNoData: false,
+ // 寮瑰嚭妗嗕腑琛ㄦ牸鏉℃暟
+ exceptionTotal: 0,
+ // 鏃犳暟鎹椂鐨勬椂闂存暟缁勶紝鍏冪礌鐩稿樊10鍒嗛挓
+ // abnormalTimeTenMinute: [],
+ // 搴楅摵鎬绘暟
+ shopsTotal: 0,
+
+ // 鈥欎笂涓�鏉♀�樻寜閽槸鍚﹀彲浠ヨ鐐瑰嚮鐘舵��
+ isPreCantouch: false,
+ // 鈥欎笅涓�鏉♀�樻寜閽槸鍚﹀彲浠ヨ鐐瑰嚮鐘舵��
+ isNextCantouch: false,
+
+ // 瀵硅瘽妗嗘槸鍚﹀睍绀�
+ centerDialogVisible: false,
+
+ // 鎶藉眽澶撮儴淇℃伅
+ // 鎶樼嚎鍥惧搴旂殑褰撳墠琛ㄦ牸琛屾暟鎹�
+ // 搴楅摵鍚�
+ rowShopName: '',
+ // 寮傚父绫诲瀷
+ rowExceptionType: '',
+ // 寮傚父寮�濮嬫椂闂�
+ rowBeginTime: '',
+ // 寮傚父缁撴潫鏃堕棿
+ rowEndTime: '',
+ // 寮傚父鐨勮澶囩紪鍙�
+ rowMvStatCode: '',
+ // 渚涘簲鍟�
+ rowDiSupplier: '',
+ // 琛ㄦ牸鐨勪竴琛屾暟鎹�
+ rowTable: [],
+ //鎷兼帴鐨勬墍鏈夋暟鎹�
+ allExceptionTimeData: [],
+ // 鏃犳暟鎹椂澧炲姞鐨勫墠30鍒嗛挓鏁版嵁
+ beforeData: [],
+ // 鏃犳暟鎹椂澧炲姞鐨勫悗40鍒嗛挓鏁版嵁
+ afterData: [],
+
+ // -1琛ㄧず鏈�夋嫨琛ㄦ牸鐨勮
+ selectedRowIndex: -1,
+
+ // 榛樿閫夋嫨鐨勬姌鍙犻潰鏉跨紪鍙�
+ activeNames: ['1'],
+ // 寮傚父鏃剁殑琛ㄦ牸
+ abnormalTb: [],
+ // 寮傚父鐨勮捣姝㈡椂闂�
+ abnormalBt: '',
+ abnormalEt: '',
+ // 鏄惁灞曠ず鏃堕棿杞� 鍚�
+ isAbnormal: false,
+ // 淇濆瓨鐫�寮傚父绫诲瀷0瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+ exception0: [],
+ // 淇濆瓨鐫�寮傚父绫诲瀷1瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+ exception1: [],
+ // 淇濆瓨鐫�寮傚父绫诲瀷2瀵瑰簲鐨勫簵閾哄悕绉板拰璁惧缂栧彿
+ exception2: [],
+ // 鍔犺浇鍔ㄧ敾
+ loading: false,
+ // 鎶藉眽鍔犺浇鍔ㄧ敾
+ loadingDrawer: true,
+ // 鍒嗛〉灞曠ず鏁版嵁
+
+ // 寮傚父琛ㄧ殑鏁版嵁
+ displayData: [],
+ // 瀛樻斁鍚庣杩斿洖鐨刯son鏁版嵁
+ jsonData: [],
+ // 鍒嗛〉鐨勮捣濮嬬储寮�
+ startIndex: 0,
+ // 褰撳墠椤�
+ currentPage: 1,
+ // 姣忛〉鏉℃暟
+ pageSize: 10,
+ total: 0,
+ // 閫夋嫨搴楅摵鍚�
+ deviceId: [],
+ deviceInfo: [],
+ // 鏃堕棿閫夋嫨鍣ㄥ紑濮嬫椂闂�
+ beginTime: '',
+ // 鏃堕棿閫夋嫨鍣ㄧ粨鏉熸椂闂�
+ endTime: '',
+ // 寮傚父琛ㄦ暟鎹�
+ abnormalData: [],
+ // 寮瑰嚭鐨勫璇濇涓殑寮傚父琛ㄦ牸鏁版嵁
+ exceedingData: [],
+ drawerVisible: false,
+ // 琛ㄦ牸鐨勪竴琛屾暟鎹�
+ drawerData: {},
+ // 鎶藉眽鏂瑰悜锛屼粠鍙冲悜宸︽墦寮�
+ drawerDirection: 'rtl',
+ optionsTime: [
+ // 鏃堕棿棰楃矑搴�
+ {
+ value: '10',
+ label: '10鍒嗛挓鏁版嵁',
+ disabled: true,
+ },
+ ],
+ // 搴楅摵鍚� 绾ц仈閫夋嫨鍣�
+ optionsShop: [],
+ // 寮傚父绫诲瀷閫夋嫨鍣�
+ exceptionValue: [],
+ }
+ },
+ // 鐩戝惉 鍒ゆ柇鎸夐挳鏄惁鍙偣鍑�
+ watch: {
+ selectedRowIndex(newVaue) {
+ // 澶勪簬琛ㄦ牸鐨勬渶鍚庝竴鏉℃暟鎹� 璁剧疆鈥樹笂涓�鏉♀�欐寜閽笉鍙偣
+ if (newVaue === this.displayData.length - 1) {
+ this.isPreCantouch = true
+ //鐢ㄦ埛鍏堢偣浜嗙涓�鏉★紝pre涓簍rue,鐒跺悗鐐瑰嚮鏈�鍚庝竴鏉�,next涓簍rue銆傛鏃朵袱涓寜閽兘琚皝閿�
+ if (this.isNextCantouch == true) {
+ this.isNextCantouch = false
+ }
+ }
+ // 澶勪簬琛ㄦ牸绗竴鏉℃暟鎹� 璁剧疆鈥樹笅涓�鏉♀�欐寜閽笉鍙偣
+ else if (newVaue === 0) {
+ this.isNextCantouch = true
+ //鐢ㄦ埛鍏堢偣浜嗚〃鏍兼渶鍚庝竴鏉�,next涓簍rue,鐒跺悗鐐瑰嚮绗竴鏉★紝pre涓簍rue銆傛鏃朵袱涓寜閽兘琚皝閿�
+ if (this.isPreCantouch == true) {
+ this.isPreCantouch = false
+ }
+ }
+ // 澶勪簬琛ㄦ牸鐨勪腑闂磋 灏嗘寜閽缃负鍙偣鍑荤姸鎬�
+ else {
+ this.isPreCantouch = false
+ this.isNextCantouch = false
+ }
+ },
+
+ // 褰撻�夋嫨鐨勬椂闂村彂鐢熷彉鍖栨椂锛屽紓甯稿垎鏋愰儴鍒嗙殑寮傚父搴楅摵鏁伴噺鍚屾鍙樺寲
+ beginTime() {
+ this.getShopNames()
+ },
+ endTime() {
+ this.getShopNames()
+ },
+ centerDialogVisible() {
+ window.addEventListener('resize', this.updateChart)
+ },
+ },
+ computed: {
+ exceptionAllNum() {
+ let sum = this.exception0Num + this.exception1Num + this.exception2Num
+ return sum == 0 ? 1 : sum
+ },
+ connectException() {
+ let sum = this.exception0Num + this.exception1Num + this.exception2Num
+ if (sum == 0) {
+ return 0
+ } else {
+ return (100 - (this.exception0Num / sum) * 100 - (this.exception1Num / sum) * 100).toFixed(
+ 1,
+ )
+ }
+ },
+ },
+ mounted() {
+ // 浠庢帴鍙h幏鍙栧簵閾哄悕绉� 缁欑骇鑱斾笅鎷夋
+ this.getDeviceInfo()
+ // 灞曠ず鏈�杩�7澶╂暟鎹�
+ this.getRecentSevenDays()
+ // 鏍规嵁寮傚父绫诲瀷杩斿洖搴楅摵鍚嶇О鍜岃澶囩紪鍙� 娓叉煋寮傚父鍒嗘瀽閮ㄥ垎瀵瑰簲鐨勫簵閾哄悕
+ this.getShopNames()
+ this.calcTableHeight()
+ window.addEventListener('resize', this.updateChart)
+ },
+ methods: {
+ // 鍔熻兘锛氬璇濇琛ㄦ牸搴忓彿閫掑
+ // 鏃堕棿锛�2023-8-17
+ indexMethod(index) {
+ return index + 1
+ },
+
+ // 鍔熻兘锛氭敼鍙樿〃鏍兼煇涓崟鍏冩牸鐨勯鑹�
+ tableCellClassName({ row, column, rowIndex, columnIndex }) {
+ if (columnIndex == 4) {
+ if (row.exceptionType == '0') {
+ return 'exceeding-row'
+ } else if (row.exceptionType == '1') {
+ return 'abnormal-power-supply'
+ } else if (row.exceptionType == '2') {
+ return 'disconnect'
+ }
+ }
+ },
+
+ //鍔熻兘锛� 鍔ㄦ�佽绠楄〃鏍奸珮搴�
+ calcTableHeight() {
+ const h1 = this.$refs.h1.$el.offsetHeight
+ const h2 = this.$refs.h4.$el.offsetHeight
+ this.tableHeight = `calc(100vh - ${h1}px - ${h2}px - 45px - var(--el-main-padding) * 2 - var(--el-card-padding))`
+ },
+
+ //鍔熻兘锛� 鏃堕棿鏄惁瓒呰繃10鍒嗛挓
+ isTimeDifferenceGreaterThan10Minutes(dateString1, dateString2) {
+ const date1 = new Date(dateString1)
+ const date2 = new Date(dateString2)
+
+ // 璁$畻涓や釜鏃ユ湡鐨勬椂闂村樊锛堟绉掞級
+ const timeDifferenceMs = Math.abs(date1 - date2)
+
+ // 杞崲涓哄垎閽�
+ const timeDifferenceMinutes = Math.floor(timeDifferenceMs / (1000 * 60))
+
+ // 鍒ゆ柇鏃堕棿宸槸鍚﹀ぇ浜�10鍒嗛挓
+ return timeDifferenceMinutes > 10
+ },
+
+ // 浠�10鍒嗛挓涓洪棿闅旇繑鍥炴椂闂村瓧绗︿覆鏁扮粍
+ generateTimePoints(timePoints, yAxisData) {
+ let updatedTimePoints = []
+ let yAxisDataAdressed = []
+ for (let i = 0; i < timePoints.length; i++) {
+ updatedTimePoints.push(timePoints[i])
+ yAxisDataAdressed.push(yAxisData[i])
+ if (i < timePoints.length - 1) {
+ let current = timePoints[i]
+ let next = timePoints[i + 1]
+ while (this.isTimeDifferenceGreaterThan10Minutes(current, next)) {
+ current = dayjs(current).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ updatedTimePoints.push(current)
+ yAxisDataAdressed.push(null)
+ }
+ }
+ }
+ let obj = {}
+ obj['time'] = updatedTimePoints
+ obj['data'] = yAxisDataAdressed
+ return obj
+ },
+
+ isExceedOneMonth(dateStr1, dateStr2) {
+ // 瓒呰繃涓�涓湀锛岃繑鍥濼rue锛屽惁鍒欒繑鍥濬alse
+ // 灏嗘棩鏈熷瓧绗︿覆杞负鏃ユ湡瀵硅薄
+ const date1 = new Date(dateStr1)
+ const date2 = new Date(dateStr2)
+
+ // 鑾峰彇涓や釜鏃ユ湡鐨勫勾銆佹湀銆佹棩
+ const year1 = date1.getFullYear()
+ const month1 = date1.getMonth()
+ const day1 = date1.getDate()
+
+ const year2 = date2.getFullYear()
+ const month2 = date2.getMonth()
+ const day2 = date2.getDate()
+
+ // 鍒ゆ柇涓や釜鏃ユ湡鏄惁鐩稿樊涓�涓湀
+ if (year1 === year2) {
+ // 骞翠唤鐩哥瓑锛屾瘮杈冩湀浠藉樊鍊�
+ if (Math.abs(month1 - month2) === 1) {
+ // 鏈堜唤宸�间负1锛岃繕闇�瑕佸垽鏂叿浣撴棩鏈�
+ if ((month1 < month2 && day1 < day2) || (month1 > month2 && day1 > day2)) {
+ return true
+ }
+ }
+ } else if (Math.abs(year1 - year2) === 1) {
+ // 骞翠唤宸�间负1锛屾瘮杈冩湀浠藉拰鏃ユ湡
+ if (
+ (year1 < year2 && month1 === 11 && month2 === 0 && day1 < day2) ||
+ (year1 > year2 && month1 === 0 && month2 === 11 && day1 > day2)
+ ) {
+ return true
+ }
+ }
+
+ // 榛樿杩斿洖false锛岃〃绀轰袱涓棩鏈熷瓧绗︿覆涓嶇浉宸竴涓湀
+ return false
+ },
+
+ // 鍒氭墦寮�鍗$墖鏃剁涓�涓浘褰笉浼氳嚜鍔ㄤ几缂� 褰撶偣鍑讳笂/涓嬩竴鏉℃椂浼氳嚜鍔ㄤ几缂�
+ // 鍥惧舰鍝嶅簲寮忓彉鍖�
+ // updateChart() {
+ // this.$nextTick(() => {
+ // if (this.chart1) {
+ // this.chart1.resize();
+ // }
+ // if (this.chart2) {
+ // this.chart2.resize();
+ // }
+ // });
+ // },
+
+ // 浠庢椂闂撮�夋嫨鍣ㄧ粍浠舵嬁鍒板紑濮嬪拰缁撴潫鏃堕棿
+ giveTime(val) {
+ //灏嗕腑鍥芥爣鍑嗘椂闂磋浆涓烘寚瀹氭牸寮�(璇ョ粍浠惰繑鍥炵殑鏍囧噯鏃堕棿鐨勬牸寮忥紝鎵�浠ュ繀椤荤殑鍔犺繖涓嚱鏁�)
+ this.beginTime = dayjs(val[0]).format('YYYY-MM-DD HH:mm:ss')
+ this.endTime = dayjs(val[1]).format('YYYY-MM-DD HH:mm:ss')
+ },
+
+ // 鍙傛暟锛氬紓甯哥殑寮�濮嬪拰缁撴潫鏃堕棿銆傝繑鍥炴椂闂存暟缁勶紝浠庡紑濮嬫椂闂寸殑鍚�10鍒嗛挓鍒扮粨鏉熸椂闂翠负姝€��
+ // 姣斿12:00:00-13:00:00 鎵�浠ヨ繑鍥炵殑鏁扮粍鍏冪礌鏄� 12:10:00 ,12:20:00,12:30:00....13:00:00
+ descTenTime(begin, end) {
+ let time = []
+ if (begin == end) {
+ time.push(begin)
+ return time
+ }
+ // 淇濈暀缁撴灉 00 10 20 30
+ let temp = dayjs(begin).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ while (temp != end) {
+ time.push(temp)
+ temp = dayjs(temp).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ }
+ // 鍔犱笂寮傚父鐨勭粨鏉熸椂闂�
+ time.push(temp)
+ return time
+ },
+
+ // 淇濆瓨褰撳墠閫夋嫨鐨勮鎵�鏈変俊鎭�
+ setinfo(index) {
+ this.rowShopName = this.displayData[index].diName
+ this.rowExceptionType = this.displayData[index].exceptionType
+ this.rowBeginTime = this.displayData[index].beginTime
+ this.rowEndTime = this.displayData[index].endTime
+ this.rowMvStatCode = this.displayData[index].devId
+ this.rowDiSupplier = this.displayData[index].diSupplier
+ },
+
+ //鍔熻兘锛� 渚涚數寮傚父鍜屾帀绾挎椂鐨勮〃鏍兼暟鎹�
+ setExceptionData() {
+ // 鏃犳暟鎹椂鐨勬椂闂存暟缁� 鏃堕棿鐩稿樊10鍒嗛挓
+ const abnormalTimeTenMinute = this.descTenTime(this.rowBeginTime, this.rowEndTime)
+ // 鍘婚櫎渚涚數寮傚父鍜屾帀绾垮尯闂寸殑绗竴涓湁鍏冪礌鐨勫��
+ this.exceedingData = []
+
+ for (let i = 0; i < abnormalTimeTenMinute.length; i++) {
+ this.exceedingData.push({
+ mvStatCode: this.rowMvStatCode,
+ diName: this.rowShopName,
+ diSupplier: this.rowDiSupplier,
+ mvDataTime: abnormalTimeTenMinute[i],
+ mvFumeConcentration2: '',
+ })
+ }
+
+ // 淇濆瓨鏃犳暟鎹椂琛ㄦ牸鏉℃暟
+ this.exceptionTotal = abnormalTimeTenMinute.length
+ },
+ // 鐐瑰嚮琛ㄦ牸鐨勮鏃�
+ selectTableRow(row) {
+ // 鑾峰彇褰撳墠琛岀殑绱㈠紩
+ this.selectedRowIndex = this.displayData.indexOf(row)
+ // 杩涘叆鎶藉眽椤甸潰鏇存柊澶撮儴鏁版嵁
+ this.setinfo(this.selectedRowIndex)
+ },
+
+ // 鑾峰彇鑾峰彇琛ㄦ牸涓嬩竴琛屾暟鎹�
+ getNextRowData() {
+ // 涓嶆槸琛ㄦ牸鐨勭涓�琛�
+ if (this.selectedRowIndex !== 0) {
+ // 鐐瑰嚮杩囩▼涓� 閿佷綇涓婁笅鏉℃寜閽� 鍦ㄨ缃畬鍥惧舰閰嶇疆椤瑰悗瑙i攣
+ this.banTouch = 1
+
+ //寰楀埌涓婁竴琛屾暟鎹储寮�
+ this.selectedRowIndex = this.selectedRowIndex - 1
+ //璇锋眰鏁版嵁 鏀瑰彉exceedingData
+ this.setinfo(this.selectedRowIndex)
+ let params = {}
+ if (this.drawerData.devId) {
+ params['devId'] = this.displayData[this.selectedRowIndex].devId
+ }
+ if (this.drawerData.beginTime) {
+ params['beginTime'] = this.displayData[this.selectedRowIndex].beginTime
+ }
+ if (this.drawerData.endTime) {
+ params['endTime'] = this.displayData[this.selectedRowIndex].endTime
+ }
+ this.button.afterButton = true
+ axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+ // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+ this.exceedingData = response.data.data
+ this.drawChartTest()
+ this.exceptionTotal = this.exceedingData.length
+ this.button.afterButton = false
+ })
+ }
+ },
+
+ // 鑾峰彇鑾峰彇琛ㄦ牸涓嬩竴琛屾暟鎹�
+ getPreviousRowData() {
+ // 涓嶆槸琛ㄦ牸鐨勭涓�琛�
+ if (this.selectedRowIndex < this.displayData.length - 1) {
+ // 鐐瑰嚮杩囩▼涓� 閿佷綇涓婁笅鏉℃寜閽� 鍦ㄨ缃畬鍥惧舰閰嶇疆椤瑰悗瑙i攣
+ this.banTouch = 1
+
+ //寰楀埌涓婁竴琛屾暟鎹储寮�
+ this.selectedRowIndex = this.selectedRowIndex + 1
+
+ //璇锋眰鏁版嵁 鏀瑰彉exceedingData
+ this.setinfo(this.selectedRowIndex)
+ let params = {}
+ if (this.drawerData.devId) {
+ params['devId'] = this.displayData[this.selectedRowIndex].devId
+ }
+ if (this.drawerData.beginTime) {
+ params['beginTime'] = this.displayData[this.selectedRowIndex].beginTime
+ }
+ if (this.drawerData.endTime) {
+ params['endTime'] = this.displayData[this.selectedRowIndex].endTime
+ }
+ this.button.preButton = true
+ axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+ // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+ this.exceedingData = response.data.data
+ this.drawChartTest()
+ this.exceptionTotal = this.exceedingData.length
+ this.button.preButton = false
+ })
+ }
+ },
+
+ // 鈥樻煡鐪嬭鎯呪�� 寮瑰嚭妗嗛儴鍒�
+ showDrawer(row) {
+ // 璁$畻褰撳墠琛岀殑绱㈠紩
+ this.selectTableRow(row)
+
+ this.rowTable = row
+
+ // 琛ㄦ牸鐨勮鏁版嵁浠ュ璞″舰寮忕粰drawerData
+ this.drawerData = row
+
+ this.centerDialogVisible = true
+
+ // 鏍规嵁琛屾暟鎹姹傝缁嗚秴鏍囨暟鎹覆鏌撴姌绾垮浘
+ let params = {}
+ if (this.drawerData.devId) {
+ params['devId'] = this.drawerData.devId
+ }
+ if (this.drawerData.beginTime) {
+ params['beginTime'] = this.drawerData.beginTime
+ }
+ if (this.drawerData.endTime) {
+ params['endTime'] = this.drawerData.endTime
+ }
+
+ axiosInstanceInstance.get('/fume/exceed', { params: params }).then((response) => {
+ // 淇濆瓨杩斿洖鐨勮秴鏍囨暟鎹�
+ this.exceedingData = response.data.data
+ this.drawChartTest()
+ this.exceptionTotal = this.exceedingData.length
+ })
+ },
+
+ // 鐢ㄦ埛鏍规嵁杈撳叆鐨勬潯浠舵煡璇�
+ showTable() {
+ if (this.isExceedOneMonth(this.beginTime, this.endTime)) {
+ alert('鏃堕棿璺ㄥ害涓嶈兘瓒呰繃涓�涓湀')
+ return
+ }
+ let params = {}
+
+ if (this.deviceId[1]) {
+ params['devId'] = this.deviceId[1]
+ }
+ if (this.exceptionValue.length != 0) {
+ params['exceptionValue'] = this.exceptionValue.join()
+ }
+
+ if (this.beginTime) {
+ params['beginTime'] = this.beginTime
+ }
+ if (this.endTime) {
+ params['endTime'] = this.endTime
+ }
+ this.loading = true
+ this.button.queryButton = true
+
+ axiosInstanceInstance.get('/fume/abnormalthree', { params: params }).then((response) => {
+ this.abnormalData = response.data.data
+ this.total = this.abnormalData.length
+ this.loading = false
+ this.button.queryButton = false
+ if (response.data.data.length == 0) {
+ ElMessage('璇ユ椂娈垫棤鏁版嵁')
+ this.isNoData = true
+ return
+ }
+ // 绉婚櫎绌烘暟鎹姸鎬�
+ this.isNoData = false
+ this.handleCurrentChange(1)
+ })
+ },
+ handleSizeChange(val) {
+ this.pageSize = val
+ // 鏀瑰彉姣忛〉鏄剧ず鏁扮洰鏃惰烦鍒扮涓�椤�
+ this.handleCurrentChange(1)
+ },
+ handleCurrentChange(val) {
+ const startIndex = (val - 1) * this.pageSize
+ const endIndex = startIndex + this.pageSize
+
+ this.displayData = this.abnormalData.slice(startIndex, endIndex)
+ },
+
+ //鐩稿樊澶氬皯涓崄鍒嗛挓 璁$畻涓苟涓嶅寘鎷紑濮嬫椂闂达紝浣嗗寘鎷粨鏉熸椂闂淬��
+ diffTenMinutesNum(beginNormal, endNormal) {
+ // 灏嗗紑濮嬫椂闂村拰缁撴潫鏃堕棿杞崲涓篸ayjs瀵硅薄
+ const start = dayjs(beginNormal)
+ const end = dayjs(endNormal)
+
+ // 璁$畻缁撴潫鏃堕棿鍑忓幓寮�濮嬫椂闂翠腑闂寸浉宸灏戜釜鍗佸垎閽�
+ const diffInMinutes = end.diff(start, 'minute')
+ const diffInTenMinutes = Math.floor(diffInMinutes / 10)
+ return diffInTenMinutes
+ },
+
+ // 鍙傛暟锛氬紓甯哥殑寮�濮嬫椂闂达紝寮傚父鐨勭粨鏉熸椂闂淬��
+ // 鍔熻兘锛氳繑鍥炲紑濮嬫椂闂寸殑鍓�30鍒嗛挓鐨勬椂闂寸偣锛岀粨鏉熸椂闂村悗40鍒嗛挓鐨勬椂闂寸偣
+ before30AndAfter40(begin, end) {
+ let time = []
+ const before30MinBegin = dayjs(begin).subtract(30, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ // 鍚庝竴娈电殑寮�濮嬫椂闂�
+ const after10MinBegin = dayjs(end).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ // 寰�鍚�40鍒嗛挓
+ const after40MinEnd = dayjs(end).add(40, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ time.push(before30MinBegin)
+ time.push(after10MinBegin)
+ time.push(after40MinEnd)
+ return time
+ },
+
+ // 鍙傛暟锛氳澶囩紪鍙凤紝 寮�濮嬫椂闂达紝 缁撴潫鏃堕棿
+ // 鍔熻兘锛氳繑鍥炴煇璁惧鍦ㄨ鏃舵鍘嗗彶鏁版嵁鐨刧et璇锋眰鍙傛暟銆�
+ requestGetParms(devnum, begin, end) {
+ return {
+ devId: devnum,
+ beginTime: begin,
+ endTime: end,
+ }
+ },
+ // 鍙傛暟锛氬璞℃暟缁�(璇ュ璞′腑鐨勫睘鎬т笉鑳芥槸寮曠敤绫诲瀷锛屽惁鍒欐嫹璐濈殑鍊艰繕鏄細鐩镐簰褰卞搷)
+ // 鍔熻兘锛氭嫹璐濊瀵硅薄鏁扮粍銆�
+ shallowCopyList(itemIsObjOfList) {
+ let tempList = []
+ itemIsObjOfList.forEach((item) => {
+ tempList.push({ ...item })
+ })
+ return tempList
+ },
+
+ // 鍙傛暟锛氭坊鍔犻灏炬椂闂存暟鎹殑寮傚父鏁版嵁鏁扮粍(鍏冪礌涓哄璞�)
+ // 鍔熻兘锛氬涓棿寮傚父鍖洪棿鏃堕棿鍜屽�艰繘琛岃ˉ鍏咃紝杩斿洖澶勭悊鍚庣殑缁撴灉
+ // 璇︾粏鎻忚堪锛氶亶鍘嗘暟缁勶紝褰撳彂鐜版暟缁勫厓绱犱负绌烘椂锛岃缃鍏冪礌鐨勬椂闂翠负涓婁竴涓厓绱犳椂闂寸殑鍚�10鍒嗛挓锛屽苟鎶婃祿搴﹀�艰缃负null(涓婁釜鍏冪礌鐨勬椂闂翠竴瀹氫笉涓虹┖锛屾棤闇�鍐嶅幓鍒ゆ柇涓婁釜鍏冪礌涓虹┖鐨勬儏鍐�)銆�
+ addTenMinutes(exceptionDataArr) {
+ // x杞� 鏃ユ湡鏃堕棿
+ let dateList = []
+ // y杞� 瓒呮爣娌圭儫娴撳害
+ let fumeExceeding = []
+ let obj = {}
+ for (let i = 0; i < exceptionDataArr.length; i++) {
+ if (exceptionDataArr[i] == null) {
+ //x杞存棩鏈熴�傚厓绱犱负null鏃讹紝 璁剧疆璇ュ厓绱犵殑鏃堕棿涓哄墠涓�鍏冪礌鐨勬椂闂村悗10鍒嗛挓
+ dateList.push(
+ dayjs(dateList[dateList.length - 1])
+ .add(10, 'minute')
+ .format('YYYY-MM-DD HH:mm:ss'),
+ )
+ // 瓒呮爣娌圭儫娴撳害
+ fumeExceeding.push(null)
+ } else {
+ //x杞存棩鏈�
+ dateList.push(exceptionDataArr[i].mvDataTime)
+ // 瓒呮爣娌圭儫娴撳害
+ fumeExceeding.push(exceptionDataArr[i].mvFumeConcentration2)
+ }
+ }
+ obj['dateList'] = dateList
+ obj['fumeExceeding'] = fumeExceeding
+ return obj
+ },
+
+ // 鍙傛暟锛氬姞涓婂墠鍚庡尯闂寸殑寮傚父鏁版嵁锛屾椂闂村瓧绗︿覆
+ // 鍔熻兘锛氬垽鏂璬ata涓槸鍚︽湁璇ユ棩鏈熸椂闂达紝瀛樺湪杩斿洖璇ユ椂闂村搴旂殑娴撳害鍊硷紝鍚﹀垯杩斿洖-1
+ findTimeInExceptionData(data, time) {
+ for (let i = 0; i < data.length; i++) {
+ if (data[i] == null) {
+ continue
+ }
+ if (data[i]['mvDataTime'] == time) {
+ return data[i]['mvFumeConcentration2']
+ }
+ }
+ return -1
+ },
+ // 鍙傛暟:鍓嶅尯闂寸殑寮�濮嬫椂闂达紝 鍚庡尯闂寸殑缁撴潫鏃堕棿, 鍔犱笂鍓嶅悗鍖洪棿鐨勬�绘椂闂存鐨勫紓甯告暟鎹殑瀵硅薄鏁扮粍
+ // 鍔熻兘锛氭牴鎹紑濮嬪拰缁撴潫鏃堕棿,杩斿洖浠�10鍒嗛挓涓洪棿闅旂殑鏃堕棿鍜屽搴旂殑鍊�
+ keepContinuousByEachTenMinutes(intervalStarTime, intervalEndTime, headAndTailExceptionData) {
+ let xAxis = []
+ let yAxis = []
+ let obj = {}
+ let current = intervalStarTime
+ let tail = dayjs(intervalEndTime).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ while (current != tail) {
+ let value = this.findTimeInExceptionData(headAndTailExceptionData, current)
+ if (value != -1) {
+ xAxis.push(current)
+ yAxis.push(value)
+ } else {
+ xAxis.push(current)
+ yAxis.push(null)
+ }
+ current = dayjs(current).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss')
+ }
+ obj['xAxis'] = xAxis
+ obj['yAxis'] = yAxis
+ return obj
+ },
+
+ // 鍙傛暟锛氳秴鏍囨暟鎹墠闈㈠尯闂寸殑鏁版嵁
+ // 鍔熻兘锛氳繑鍥為櫎鍘绘渶鍚庝竴涓厓绱犵殑鏁扮粍
+ removeLastItemOfBeforeData(beforeDataOfExceeding) {
+ let tempList = []
+ if (beforeDataOfExceeding.length == 1) {
+ return tempList
+ } else {
+ for (let i = 0; i < beforeDataOfExceeding.length - 1; i++) {
+ tempList.push({ ...beforeDataOfExceeding[i] })
+ }
+ return tempList
+ }
+ },
+
+ // 璁剧疆option
+ // 鍙傛暟锛歺杞存椂闂达紝 y杞存补鐑熸祿搴︼紝 寮傚父绫诲埆(0浠h〃瓒呮爣锛�1浠h〃渚涚數寮傚父鍜屾帀绾�), 寮傚父寮�濮嬫椂闂达紝寮傚父缁撴潫鏃堕棿锛屽紓甯稿紑濮嬫椂闂村湪鏁翠釜鍖洪棿鐨勭储寮曚笅鏍囷紝寮傚父缁撴潫鏃堕棿鍦ㄦ暣涓尯闂寸殑绱㈠紩涓嬫爣
+ setOption(
+ xData,
+ yData,
+ exceptionCategory,
+ exceptionBeginTime,
+ exceptionEndTime,
+ beginIndex,
+ endIndex,
+ ) {
+ this.option = {}
+ // 瓒呮爣
+ if (exceptionCategory == 0) {
+ this.option = {
+ tooltip: {},
+ toolbox: {
+ // 宸ュ叿鏍�
+ feature: {
+ // dataZoom: {
+ // yAxisIndex: 'none'
+ // },
+ // 淇濆瓨涓哄浘鐗�
+ saveAsImage: {},
+ },
+ },
+ xAxis: {
+ type: 'category',
+ data: xData,
+ name: '鏃堕棿',
+ axisLabel: {
+ formatter: function (value) {
+ return value.slice(11, -3)
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ name: 'mg/m鲁',
+ },
+ series: [
+ {
+ name: '娌圭儫娴撳害',
+ type: 'line',
+ data: yData.map((item) => {
+ if (item >= 1) {
+ return {
+ value: item,
+ itemStyle: {
+ color: 'red',
+ },
+ }
+ }
+ return item
+ }),
+ // 鍙樻崲鎸囧畾鏃堕棿鍖洪棿鐨勮儗鏅鑹�
+ markArea: {
+ itemStyle: {
+ color: 'rgba(255, 173, 177, 0.4)',
+ },
+ data: [
+ [
+ {
+ name: '瓒呮爣鏃堕棿娈�',
+ xAxis: exceptionBeginTime,
+ },
+ {
+ xAxis: exceptionEndTime,
+ },
+ ],
+ ],
+ },
+ markLine: {
+ symbol: 'none',
+ itemStyle: {
+ // 鍩虹嚎鍏叡鏍峰紡
+ normal: {
+ lineStyle: {
+ type: 'dashed',
+ },
+ label: {
+ show: true,
+ position: 'end',
+ formatter: '{b}',
+ },
+ },
+ },
+ data: [
+ {
+ name: '瓒呮爣',
+ type: 'average',
+ yAxis: 1,
+ lineStyle: {
+ // color: '#ff0000'
+ color: 'red',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ // 鎸囧畾鏃堕棿鍖洪棿鐨勭嚎娈靛彉棰滆壊
+ visualMap: {
+ show: false,
+ dimension: 0,
+ pieces: [
+ {
+ lte: beginIndex,
+ color: 'green',
+ },
+ {
+ gt: beginIndex,
+ lte: endIndex,
+ color: 'red',
+ },
+ {
+ gt: endIndex,
+ lte: xData.length - 1,
+ color: 'green',
+ },
+ ],
+ },
+ }
+ }
+ // 渚涚數寮傚父鍜屾帀绾�
+ else if (exceptionCategory == 1) {
+ this.option = {
+ tooltip: {},
+ toolbox: {
+ // 宸ュ叿鏍�
+ feature: {
+ // dataZoom: {
+ // // 鍖哄煙缂╂斁
+ // yAxisIndex: 'none'
+ // },
+ // 淇濆瓨涓哄浘鐗�
+ saveAsImage: {},
+ },
+ },
+ xAxis: {
+ type: 'category',
+ data: xData,
+ name: '鏃堕棿',
+ axisLabel: {
+ formatter: function (value) {
+ return value.slice(11, -3)
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ name: 'mg/m鲁',
+ },
+ series: [
+ {
+ name: '娌圭儫鏁版嵁',
+ type: 'line',
+ data: yData,
+ markLine: {
+ silent: true,
+ data: [
+ // 鏍囨敞鏃犳暟鎹椂闂存鐨勬晥鏋滐紝灏嗚繖涓椂闂存鐨勬暟杞撮儴鍒嗗彉涓虹孩鑹�
+ {
+ name: '鏃犳暟鎹�',
+ xAxis: exceptionBeginTime,
+ },
+ {
+ xAxis: exceptionEndTime,
+ },
+ ],
+ lineStyle: {
+ color: 'red',
+ },
+ },
+ },
+ ],
+ }
+ }
+ this.banTouch = 0
+ },
+
+ // 鍔熻兘锛氱偣鍑� 鈥樻煡鐪嬭鎯呪�欙紝 鈥樹笅涓�鏉♀�欐寜閽椂浼� 鍏堥�昏緫璁$畻銆傛渶鍚庡睍绀哄浘褰�
+ drawChartTest() {
+ this.beforeData = []
+ this.afterData = []
+ this.allExceptionTimeData = []
+ //寮傚父鐨勫紑濮嬫椂闂� 缁撴潫鏃堕棿
+ let exceptionBeginTime = this.rowBeginTime
+ let exceptionEndTime = this.rowEndTime
+
+ // beforeAndAfterTime[0]:鍓�30鍒嗛挓鐨勬椂闂寸偣
+ // beforeAndAfterTime[1]:鍚�10鍒嗛挓鐨勬椂闂寸偣
+ // beforeAndAfterTime[2]:鍚�40鍒嗛挓鐨勬椂闂寸偣
+ let beforeAndAfterTime = this.before30AndAfter40(exceptionBeginTime, exceptionEndTime)
+
+ // 鏋勯�犲紓甯告椂闂村墠鐨勫尯闂存暟鎹姹傚弬鏁�
+ let paramsBefore = this.requestGetParms(
+ this.displayData[this.selectedRowIndex].devId,
+ beforeAndAfterTime[0],
+ this.displayData[this.selectedRowIndex].beginTime,
+ )
+
+ // 鏋勯�犲紓甯告椂闂村悗鐨勫尯闂存暟鎹姹傚弬鏁�
+ let paramsAfter = this.requestGetParms(
+ this.displayData[this.selectedRowIndex].devId,
+ beforeAndAfterTime[1],
+ beforeAndAfterTime[2],
+ )
+
+ // 鎶樼嚎鍥惧姞杞戒腑鏁堟灉
+ this.chartLoading = true
+ // 璇锋眰鍓嶅崐娈�
+ axiosInstanceInstance.get('/fume/history', { params: paramsBefore }).then((result1) => {
+ this.beforeData = result1.data.data
+ // 璇锋眰鍚庡崐娈�
+ axiosInstanceInstance.get('/fume/history', { params: paramsAfter }).then((result2) => {
+ this.afterData = result2.data.data
+ //淇濆瓨寮傚父鍖洪棿鐨勫��
+ let tempArr = []
+ // 淇濆瓨寮傚父鍖洪棿鍓嶅悗鐨勫��
+ let before = []
+ let after = []
+
+ // 鍒ゆ柇鏄惁鏄緵鐢靛紓甯告垨鎺夌嚎
+ if (this.rowExceptionType === '1' || this.rowExceptionType === '2') {
+ // 閲嶆瀯琛ㄦ牸 缂哄け寮傚父鏁版嵁鑷姩濉厖
+ this.setExceptionData()
+
+ //鐩稿樊鍑犱釜10鍒嗛挓
+ const TenMinuteNum = this.diffTenMinutesNum(exceptionBeginTime, exceptionEndTime)
+ //鐢╪ull濉厖涓紓甯告棤鏁版嵁鐨勬椂闂�
+ for (let i = 0; i < TenMinuteNum; i++) {
+ tempArr.push(null)
+ }
+ before = this.shallowCopyList(this.beforeData)
+
+ after = this.shallowCopyList(this.afterData)
+ // after = this.afterData
+ }
+ // 瓒呮爣
+ else {
+ let beforeTemp = this.removeLastItemOfBeforeData(this.beforeData)
+ // 鍓嶅悗鍖洪棿鍙樉绀鸿窛绂昏秴鏍囧尯闂存椂闂存渶杩戠殑娴撳害灏忎簬1鐨勬椂闂寸偣
+ for (let i = beforeTemp.length - 1; i >= 0; i--) {
+ if (beforeTemp[i].mvFumeConcentration2 >= 1) {
+ break
+ }
+ if (beforeTemp[i].mvFumeConcentration2 < 1) {
+ before.unshift(this.beforeData[i])
+ }
+ }
+
+ for (let i = 0; i < this.afterData.length; i++) {
+ if (this.afterData[i].mvFumeConcentration2 >= 1) {
+ break
+ }
+ if (this.afterData[i].mvFumeConcentration2 < 1) {
+ after.unshift(this.afterData[i])
+ }
+ }
+ tempArr = this.shallowCopyList(this.exceedingData)
+ }
+
+ // 灏嗗墠鍚庡尯闂存暟鎹� 涓� 寮傚父鍖洪棿鏁版嵁 鍚堝苟
+ this.allExceptionTimeData = [...before, ...tempArr, ...after]
+ // x杞存棩鏈熸椂闂�
+ let dateList
+ // y杞� 瓒呮爣娌圭儫娴撳害
+ let fumeExceeding
+ let timeAndValue
+
+ // 浠庢坊鍔犱簡棣栦綅鍖洪棿鐨勫紑濮嬪拰缁撴潫鏃堕棿杩涜閬嶅巻 淇濊瘉鏃堕棿浠�10鍒嗛挓涓洪棿闅�
+ timeAndValue = this.keepContinuousByEachTenMinutes(
+ beforeAndAfterTime[0],
+ beforeAndAfterTime[2],
+ this.allExceptionTimeData,
+ )
+
+ dateList = timeAndValue['xAxis']
+ fumeExceeding = timeAndValue['yAxis']
+
+ // 鎻愬彇寮傚父璧峰鏃堕棿鐐瑰湪鏁翠釜鍖洪棿鍐呯殑鏁版嵁绱㈠紩
+ let startIndex = dateList.findIndex((item) => item === exceptionBeginTime)
+ let endIndex = dateList.findIndex((item) => item === exceptionEndTime)
+
+ // 渚涚數寮傚父鍜屾帀绾挎儏鍐� 瓒呮爣鎯呭喌
+ if (this.rowExceptionType === '1' || this.rowExceptionType === '2') {
+ this.setOption(
+ dateList,
+ fumeExceeding,
+ 1,
+ exceptionBeginTime,
+ exceptionEndTime,
+ startIndex,
+ endIndex,
+ )
+ } else {
+ // 瓒呮爣鎯呭喌
+ this.setOption(
+ dateList,
+ fumeExceeding,
+ 0,
+ exceptionBeginTime,
+ exceptionEndTime,
+ startIndex,
+ endIndex,
+ )
+ }
+ this.chartLoading = false
+ })
+ })
+ },
+
+ getDeviceInfo() {
+ // 绾ц仈涓嬫媺妗嗘暟鎹� 浠庢帴鍙d腑鍔ㄦ�佽幏鍙�
+ axiosInstanceInstance.get('/fume/device').then((result) => {
+ this.deviceInfo = result.data.data
+ // 鑾峰彇鍒版�荤殑搴楅摵鏁伴噺
+ this.shopsTotal = result.data.data.length
+ this.deviceInfo.forEach((item) => {
+ this.optionsShop[this.optionsShop.length] = {
+ value: item.diName,
+ label: item.diName,
+ children: [
+ {
+ value: item.diCode,
+ label: item.diCode,
+ },
+ ],
+ }
+ })
+ })
+ },
+ exportDom() {
+ // 瀵煎嚭涓篍xcel鏂囦欢
+ const fields = ['devId', 'exceptionType', 'region', 'beginTime', 'endTime']
+ const itemsFormatted = this.abnormalData.map((item) => {
+ const newItem = {}
+ fields.forEach((field) => {
+ newItem[field] = item[field]
+ })
+ return newItem
+ })
+ // 鍒涘缓xlsx瀵硅薄
+ const xls = XLSX.utils.json_to_sheet(itemsFormatted)
+ // 缂栬緫琛ㄥご琛� 淇敼琛ㄥご
+ xls['A1'].v = '璁惧缂栧彿'
+ xls['B1'].v = '寮傚父绫诲瀷'
+ xls['C1'].v = '鍦板尯'
+ xls['D1'].v = '寮�濮嬫椂闂�'
+ xls['E1'].v = '缁撴潫鏃堕棿'
+ // 鍒涘缓workbook锛屽苟鎶妔heet娣诲姞杩涘幓
+ const wb = XLSX.utils.book_new()
+ XLSX.utils.book_append_sheet(wb, xls, 'Sheet1')
+ // 灏唚orkbook杞负浜岃繘鍒秞lsx鏂囦欢骞朵笅杞�
+ XLSX.writeFile(wb, '鍒嗘瀽鏁版嵁.xlsx')
+ },
+
+ getAbnormalDataByClick(val) {
+ this.abnormalData = val
+ this.total = this.abnormalData.length
+ // 榛樿鏄剧ず绗竴椤�
+ this.handleCurrentChange(1)
+ },
+
+ // 鏍规嵁寮傚父绫诲瀷杩斿洖搴楅摵鍚嶇О鍜岃澶囩紪鍙�
+ // 姣斿娌圭儫瓒呮爣瀵瑰簲鐨勬墍鏈夊簵閾哄悕绉板拰璁惧缂栧彿锛堝凡鍘婚櫎閲嶅鐨勫簵閾哄悕锛�
+ getShopNames() {
+ axiosInstanceInstance
+ .get('/fume/shopname', {
+ params: {
+ exceptionType: '0',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception0 = result.data.data
+ })
+ axiosInstanceInstance
+ .get('/fume/shopname', {
+ params: {
+ exceptionType: '1',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception1 = result.data.data
+ })
+ axiosInstanceInstance
+ .get('/fume/shopname', {
+ params: {
+ exceptionType: '2',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception2 = result.data.data
+ })
+
+ /* 寮傚父鏁伴噺 */
+ axiosInstanceInstance
+ .get('/fume/exceptionnum', {
+ params: {
+ exceptionType: '0',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception0Num = result.data.data
+ })
+ axiosInstanceInstance
+ .get('/fume/exceptionnum', {
+ params: {
+ exceptionType: '1',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception1Num = result.data.data
+ })
+ axiosInstanceInstance
+ .get('/fume/exceptionnum', {
+ params: {
+ exceptionType: '2',
+ beginTime: this.beginTime,
+ endTime: this.endTime,
+ },
+ })
+ .then((result) => {
+ this.exception2Num = result.data.data
+ })
+ },
+
+ // 椤甸潰鍔犺浇鏃堕粯璁ゅ睍绀�7澶╁紓甯歌〃鏁版嵁
+ getRecentSevenDays() {
+ // 缁欑骇鑱旈�夋嫨鍣ㄨ缃粯璁ょ殑閫夋嫨椤�
+ this.devId = ['浠樺皬濮愬湪鎴愰兘', 'qinshi_31010320210010']
+ let params = {}
+ params['beginTime'] = this.beginTime
+ params['endTime'] = this.endTime
+ axiosInstanceInstance.get('/fume/abnormalthree', { params: params }).then((response) => {
+ if (response.data.data.length == 0) {
+ ElMessage('璇ユ椂娈垫棤鏁版嵁')
+ return
+ }
+ // 淇濆瓨杩斿洖鐨�
+ this.abnormalData = response.data.data
+ // 鍒嗛〉
+ this.total = this.abnormalData.length
+ // 榛樿鏄剧ず绗竴椤�
+ this.handleCurrentChange(1)
+ this.loading = false
+ })
+ },
+ },
+}
+</script>
+
+<style scoped>
+.header-container {
+ display: flex;
+ margin-left: 20px;
+ /* flex-wrap: wrap;
+ align-items: center; */
+}
+.ellipsis {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.iconExcel {
+ font-size: 25px;
+ margin-left: 20px;
+ bottom: -6px;
+}
+
+/* 鍙紶鏍囩澶村彉涓哄彲鐐瑰嚮鐘舵�� */
+.clickable {
+ cursor: pointer;
+}
+.card-header {
+ margin: 0;
+}
+
+body {
+ margin: 0;
+}
+.exception-divider-rowline {
+ margin: 10px 0px;
+}
+/* 寮傚父鍒嗘瀽鏁版嵁涓庢寜閽� */
+.exception-container {
+ display: flex;
+}
+.example-showcase .el-loading-mask {
+ z-index: 9;
+}
+
+.scrollbar-demo-item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 20px;
+ margin: 10px;
+ text-align: center;
+ border-radius: 4px;
+ background: var(--el-color-primary-light-9);
+ color: var(--el-color-primary);
+}
+.collapse-header {
+ margin-left: 5px;
+ font-size: 18px;
+}
+.collapse-header-text {
+ margin-top: 5px;
+ font-size: 14px;
+ color: gray;
+}
+
+.box-card-label {
+ font-size: 14px;
+ white-space: nowrap;
+}
+
+.right-text {
+ /* float :right; */
+ /* text-align: right; */
+ margin-left: 80px;
+}
+:deep().el-card {
+ border-radius: 9px;
+}
+
+/* 鈥樻煡鐪嬭鎯呪�� 鐨勫脊鍑烘楂樺害璋冩暣 */
+:deep().el-dialog {
+ height: 98%;
+ /* 涓嶅嚭鐜版粴鍔ㄦ潯 */
+ overflow-y: hidden;
+ border-radius: 9px;
+}
+.table-page {
+ margin-left: 20px;
+}
+
+.table-text {
+ font-size: 18px;
+ margin: 5px 0px 10px 20px;
+}
+.text-blank {
+ margin-right: 10px;
+ color: #000000;
+}
+/* 搴楅摵鍚嶉�夋嫨鏂囨湰 */
+.describe-info {
+ margin-top: 5px;
+ font-weight: bold;
+ white-space: nowrap;
+}
+/* 鏃堕棿閫夋嫨鏂囨湰 */
+.describe-time-text {
+ margin-left: 30px;
+ margin-top: 5px;
+ font-weight: bold;
+}
+
+/* 寮傚父琛ㄦ牸涓嬫爣绛句腑鐨勬暟缁� */
+.table-line-num {
+ font-weight: bold;
+ color: black;
+}
+.button_info.el-button_inner {
+ text-align: left;
+}
+.el-collapse {
+ margin-left: 20px;
+}
+:deep().el-collapse .el-collapse-item__content {
+ padding-bottom: 0px;
+}
+.box-card {
+ height: 190px;
+}
+
+.sub-box-card {
+ height: 100px;
+ border: 0px;
+}
+
+.mx-1 {
+ margin-bottom: 0px;
+}
+.dialog-button-position {
+ display: flex;
+ justify-content: right;
+ margin-bottom: 10px;
+}
+
+:deep().el-table__row .exceeding-row {
+ background-color: #f53f3f;
+}
+:deep().el-table__row .abnormal-power-supply {
+ background-color: #fdf4bf;
+}
+:deep().el-table__row .disconnect {
+ background-color: #f7ba1e;
+}
+
+.el-table {
+ color: #000000;
+}
+
+/* 琛ㄦ牸涓殑鎸夐挳瀹藉害閾烘弧 */
+.table-button {
+ width: 100%;
+}
+</style>
diff --git a/src/views/monitor/DataHistory.vue b/src/views/monitor/DataHistory.vue
index ea6fadc..d1a9eee 100644
--- a/src/views/monitor/DataHistory.vue
+++ b/src/views/monitor/DataHistory.vue
@@ -1,6 +1,7 @@
<!-- 鍘嗗彶鏁版嵁 -->
<script>
import { defineAsyncComponent } from 'vue'
+import { ElMessage } from 'element-plus'
import * as XLSX from 'xlsx/xlsx.mjs'
import dayjs from 'dayjs'
import axiosInstanceInstance from '@/utils/request.js'
@@ -440,9 +441,8 @@
<template>
<!-- solid #000000 -->
<div style="margin: 20px; padding: 10px; border: 1px; height: 620px">
- <h1 style="margin-bottom: 20px; display: flex; white-space: nowrap">娌圭儫鍘嗗彶鏁版嵁</h1>
<div style="display: flex">
- <span class="palce-text"><span class="palce-text-area">鍖哄煙锛�</span>闈欏畨鍖� </span>
+ <!-- <span class="palce-text"><span class="palce-text-area">鍖哄煙锛�</span>闈欏畨鍖� </span> -->
<!-- 搴楅摵鍚� 绾ц仈 -->
<!-- <el-cascader v-model="devId" :options="optionsShop" :props="{ expandTrigger: 'hover' }" placeholder="璇烽�夋嫨搴楅摵鍚�"
@@ -550,51 +550,15 @@
:data="displayData"
style="width: 100%; margin-top: 25px"
height="500px"
- table-layout="auto"
+ table-layout="fixed"
+ :show-overflow-tooltip="true"
>
- <el-table-column fixed prop="mvStatCode" label="璁惧缂栧彿">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.mvStatCode">
- <div class="cell ellipsis">{{ row.mvStatCode }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column prop="diName" label="搴楅摵鍚嶇О">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.diName">
- <div class="cell ellipsis">{{ row.diName }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
-
- <el-table-column prop="mvDataTime" label="閲囬泦鏃堕棿">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.mvDataTime">
- <div class="cell ellipsis">{{ row.mvDataTime }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column prop="mvFanElectricity" label="椋庢満鐢垫祦(A)">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.mvFanElectricity">
- <div class="cell ellipsis">{{ row.mvFanElectricity }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column prop="mvPurifierElectricity" label="鍑�鍖栧櫒鐢垫祦(A)">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.mvPurifierElectricity">
- <div class="cell ellipsis">{{ row.mvPurifierElectricity }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
- <el-table-column prop="mvFumeConcentration2" label="娌圭儫娴撳害(mg/m鲁)">
- <template #default="{ row }">
- <el-tooltip effect="dark" :content="row.mvFumeConcentration2">
- <div class="cell ellipsis">{{ row.mvFumeConcentration2 }}</div>
- </el-tooltip>
- </template>
- </el-table-column>
+ <el-table-column fixed prop="mvStatCode" label="璁惧缂栧彿"> </el-table-column>
+ <el-table-column prop="diName" label="搴楅摵鍚嶇О"> </el-table-column>
+ <el-table-column prop="mvDataTime" label="閲囬泦鏃堕棿"> </el-table-column>
+ <el-table-column prop="mvFanElectricity" label="椋庢満鐢垫祦(A)"> </el-table-column>
+ <el-table-column prop="mvPurifierElectricity" label="鍑�鍖栧櫒鐢垫祦(A)"> </el-table-column>
+ <el-table-column prop="mvFumeConcentration2" label="娌圭儫娴撳害(mg/m鲁)"> </el-table-column>
</el-table>
<el-pagination
background
--
Gitblit v1.9.3