From 8e8d00477b1f30183d0d09cd7ec744067595dc46 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期三, 18 三月 2026 17:29:15 +0800
Subject: [PATCH] 2026.3.18
---
src/views/monitor/DataDashboard.vue | 104 ++++++++++-
src/assets/offline.png | 0
components.d.ts | 24 +-
src/debug/debugdata.js | 16 +
src/assets/exceed.png | 0
src/constants/menu.js | 13
src/views/system/SystemManage.vue | 58 +++++
src/components/core/AppAside.vue | 4
src/assets/exception.png | 0
src/utils/map/marks.js | 279 ++++++++++++++++++++++++++----
10 files changed, 421 insertions(+), 77 deletions(-)
diff --git a/components.d.ts b/components.d.ts
index 9882412..f866cd1 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -39,7 +39,6 @@
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
ElDialog: typeof import('element-plus/es')['ElDialog']
- ElDivider: typeof import('element-plus/es')['ElDivider']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import('element-plus/es')['ElForm']
@@ -47,9 +46,8 @@
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
- ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
ElInput: typeof import('element-plus/es')['ElInput']
- ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+ ElLink: typeof import('element-plus/es')['ElLink']
ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
@@ -57,12 +55,12 @@
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
+ ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
+ ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSpace: typeof import('element-plus/es')['ElSpace']
- ElStep: typeof import('element-plus/es')['ElStep']
- ElSteps: typeof import('element-plus/es')['ElSteps']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
@@ -72,8 +70,6 @@
ElTag: typeof import('element-plus/es')['ElTag']
ElText: typeof import('element-plus/es')['ElText']
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']
FYBgTaskCard: typeof import('./src/components/bg-task/FYBgTaskCard.vue')['default']
FYBgTaskDialog: typeof import('./src/components/bg-task/FYBgTaskDialog.vue')['default']
@@ -100,6 +96,8 @@
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']
+ IEpDownload: typeof import('~icons/ep/download')['default']
+ IEpInfoFilled: typeof import('~icons/ep/info-filled')['default']
ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
@@ -149,7 +147,6 @@
const ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
const ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
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 ElEmpty: typeof import('element-plus/es')['ElEmpty']
const ElForm: typeof import('element-plus/es')['ElForm']
@@ -157,9 +154,8 @@
const ElHeader: typeof import('element-plus/es')['ElHeader']
const ElIcon: typeof import('element-plus/es')['ElIcon']
const ElImage: typeof import('element-plus/es')['ElImage']
- const ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
const ElInput: typeof import('element-plus/es')['ElInput']
- const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+ const ElLink: typeof import('element-plus/es')['ElLink']
const ElMain: typeof import('element-plus/es')['ElMain']
const ElMenu: typeof import('element-plus/es')['ElMenu']
const ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
@@ -167,12 +163,12 @@
const ElOption: typeof import('element-plus/es')['ElOption']
const ElPagination: typeof import('element-plus/es')['ElPagination']
const ElPopover: typeof import('element-plus/es')['ElPopover']
+ const ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
+ const ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
const ElRow: typeof import('element-plus/es')['ElRow']
const ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
const ElSelect: typeof import('element-plus/es')['ElSelect']
const ElSpace: typeof import('element-plus/es')['ElSpace']
- const ElStep: typeof import('element-plus/es')['ElStep']
- const ElSteps: typeof import('element-plus/es')['ElSteps']
const ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
const ElSwitch: typeof import('element-plus/es')['ElSwitch']
const ElTable: typeof import('element-plus/es')['ElTable']
@@ -182,8 +178,6 @@
const ElTag: typeof import('element-plus/es')['ElTag']
const ElText: typeof import('element-plus/es')['ElText']
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 FYBgTaskCard: typeof import('./src/components/bg-task/FYBgTaskCard.vue')['default']
const FYBgTaskDialog: typeof import('./src/components/bg-task/FYBgTaskDialog.vue')['default']
@@ -210,6 +204,8 @@
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 IEpDownload: typeof import('~icons/ep/download')['default']
+ const IEpInfoFilled: typeof import('~icons/ep/info-filled')['default']
const ItemDevice: typeof import('./src/components/list-item/ItemDevice.vue')['default']
const ItemMonitorObj: typeof import('./src/components/list-item/ItemMonitorObj.vue')['default']
const ItemScene: typeof import('./src/components/list-item/ItemScene.vue')['default']
diff --git a/src/assets/exceed.png b/src/assets/exceed.png
new file mode 100644
index 0000000..a8c2b5f
--- /dev/null
+++ b/src/assets/exceed.png
Binary files differ
diff --git a/src/assets/exception.png b/src/assets/exception.png
new file mode 100644
index 0000000..f5418a1
--- /dev/null
+++ b/src/assets/exception.png
Binary files differ
diff --git a/src/assets/offline.png b/src/assets/offline.png
new file mode 100644
index 0000000..28675e2
--- /dev/null
+++ b/src/assets/offline.png
Binary files differ
diff --git a/src/components/core/AppAside.vue b/src/components/core/AppAside.vue
index e7a1501..b700b9a 100644
--- a/src/components/core/AppAside.vue
+++ b/src/components/core/AppAside.vue
@@ -33,7 +33,7 @@
<!-- </el-scrollbar> -->
<!-- 鍟嗘爣 -->
<el-row ref="subTitleRef" class="sub-title" justify="center">
- <el-space>{{ collapse ? '' : subTitle }}</el-space>
+ <!-- <el-space>{{ collapse ? '' : subTitle }}</el-space> -->
</el-row>
</el-scrollbar>
</el-aside>
@@ -55,7 +55,7 @@
return {
// collapse: false,
menuHeight: '80vh',
- title: '娌圭儫鏅鸿兘鐩戞祴涓庣洃绠�',
+ title: '椁愰ギ娌圭儫鏅鸿兘鐩戞祴鐩戠',
subTitle: '漏涓婃捣椋炵窘鐜繚绉戞妧鏈夐檺鍏徃',
appIcon: AppIcon,
}
diff --git a/src/constants/menu.js b/src/constants/menu.js
index 550f076..d13ac9d 100644
--- a/src/constants/menu.js
+++ b/src/constants/menu.js
@@ -96,6 +96,11 @@
name: '鐜俊鐮�',
children: [
{
+ path: '/index/inspection/scene-info',
+ icon: 'solar:shop-2-line-duotone',
+ name: '搴楅摵绠$悊',
+ },
+ {
path: '/index/analysis/auto-evalution',
icon: 'solar:pie-chart-3-line-duotone',
name: '鑷姩璇勪及',
@@ -103,18 +108,14 @@
{
path: '/index/analysis/huanxincode-manage',
icon: 'solar:archive-down-minimlistic-line-duotone',
- name: '鐜俊鐮�',
+ name: '璇勪及鎺掑悕',
},
{
path: '/index/inspection/report-manage',
icon: 'solar:folder-favourite-bookmark-line-duotone',
name: '璇勪及鎶ュ憡',
},
- {
- path: '/index/inspection/scene-info',
- icon: 'solar:shop-2-line-duotone',
- name: '搴楅摵绠$悊',
- },
+
// {
// path: '/index/analysis/data-product',
// icon: 'solar:document-add-line-duotone',
diff --git a/src/debug/debugdata.js b/src/debug/debugdata.js
index 6964a64..c500697 100644
--- a/src/debug/debugdata.js
+++ b/src/debug/debugdata.js
@@ -68,6 +68,12 @@
// 鍏堟坊鍔犳寚瀹氱殑搴楅摵
specifiedShops.forEach((name, index) => {
+ // 闅忔満鐢熸垚鍦ㄧ嚎鐘舵�侊紙80%姒傜巼鍦ㄧ嚎锛�
+ const isOnline = Math.random() < 0.8
+ // 闅忔満鐢熸垚寮傚父鐘舵�侊紙鍙湁鍦ㄧ嚎鏃舵墠鍙兘鏈夊紓甯革級
+ // 0: 娌圭儫娴撳害瓒呮爣, 1: 渚涚數寮傚父, 2: 璁惧鎴栫綉缁滃紓甯�, 3: 鏃犲紓甯�
+ const exceptionStatus = isOnline ? Math.floor(Math.random() * 4) : 2 // 绂荤嚎鏃堕粯璁や负璁惧鎴栫綉缁滃紓甯�
+
shops.push({
shop: {
name: name,
@@ -76,6 +82,8 @@
longitude: 121.45 + Math.random() * 0.1,
ringCodeLevel: ringCodeLevels[Math.floor(Math.random() * ringCodeLevels.length)],
ringCodePublishTime: '2023-03-16 10:00:00',
+ isOnline: isOnline,
+ exceptionStatus: exceptionStatus,
},
recentData: generateRecentData(),
})
@@ -88,6 +96,12 @@
const suffix = nameSuffixes[Math.floor(Math.random() * nameSuffixes.length)]
const randomName = `${prefix}${cuisine}${suffix}${i}`
+ // 闅忔満鐢熸垚鍦ㄧ嚎鐘舵�侊紙80%姒傜巼鍦ㄧ嚎锛�
+ const isOnline = Math.random() < 0.8
+ // 闅忔満鐢熸垚寮傚父鐘舵�侊紙鍙湁鍦ㄧ嚎鏃舵墠鍙兘鏈夊紓甯革級
+ // 0: 娌圭儫娴撳害瓒呮爣, 1: 渚涚數寮傚父, 2: 璁惧鎴栫綉缁滃紓甯�, 3: 鏃犲紓甯�
+ const exceptionStatus = isOnline ? Math.floor(Math.random() * 4) : 2 // 绂荤嚎鏃堕粯璁や负璁惧鎴栫綉缁滃紓甯�
+
shops.push({
shop: {
name: randomName,
@@ -96,6 +110,8 @@
longitude: 121.41 + Math.random() * 0.1,
ringCodeLevel: ringCodeLevels[Math.floor(Math.random() * ringCodeLevels.length)],
ringCodePublishTime: '2023-03-16 10:00:00',
+ isOnline: isOnline,
+ exceptionStatus: exceptionStatus,
},
recentData: generateRecentData(),
})
diff --git a/src/utils/map/marks.js b/src/utils/map/marks.js
index a8911b6..e5f0327 100644
--- a/src/utils/map/marks.js
+++ b/src/utils/map/marks.js
@@ -6,17 +6,22 @@
import { useToolboxStore } from '@/stores/toolbox'
import util from './util'
import * as echarts from 'echarts'
+import exceedIcon from '@/assets/exceed.png'
+import exceptionIcon from '@/assets/exception.png'
+import offlineIcon from '@/assets/offline.png'
const toolboxStore = useToolboxStore()
var _massMarks = undefined
-// 鐜俊鐮佺瓑绾у拰瀵瑰簲棰滆壊
-const ringCodeLevelColors = [
- '#52c41a', // 缁胯壊
- '#faad14', // 榛勮壊
- '#f5222d', // 绾㈣壊
-]
+// 鐘舵�佸浘鏍囬厤缃�
+const statusIcons = {
+ exceed: exceedIcon, // 娌圭儫娴撳害瓒呮爣
+ exception: exceptionIcon, // 渚涚數寮傚父
+ offline: offlineIcon, // 璁惧鎴栫綉缁滃紓甯�
+ online: createCustomMarkerOnline(), // 鍦ㄧ嚎鐘舵��
+ offlineStatus: createCustomMarkerOffline(), // 绂荤嚎鐘舵��
+}
/**
* 缁樺埗娴烽噺鐐规爣璁�
@@ -28,6 +33,8 @@
* @param {number} shops[].shop.longitude 缁忓害
* @param {string} shops[].shop.ringCodeLevel 鏈�鏂扮幆淇$爜绛夌骇
* @param {string} shops[].shop.ringCodePublishTime 鏈�鏂扮幆淇$爜鍙戝竷鏃堕棿
+ * @param {boolean} shops[].shop.isOnline 鍦ㄧ嚎鐘舵��
+ * @param {number} shops[].shop.exceptionStatus 寮傚父鐘舵�侊紙0: 娌圭儫娴撳害瓒呮爣, 1: 渚涚數寮傚父, 2: 璁惧鎴栫綉缁滃紓甯�, 3: 鏃犲紓甯革級
* @param {Array} shops[].recentData 杩�1灏忔椂鐨勭洃娴嬫暟鎹�
* @param {string} shops[].recentData[].sampleTime 鏁版嵁閲囨牱鏃堕棿
* @param {number} shops[].recentData[].oilSmokeConcentration 娌圭儫娴撳害
@@ -36,21 +43,65 @@
*/
function drawMassMarks(shops) {
// 閰嶇疆鏍峰紡
- const massMarksStyle = ringCodeLevelColors.map((color, index) => ({
- url: createCustomMarker(color),
- size: new AMap.Size(20, 20),
- anchor: new AMap.Pixel(10, 10),
- }))
+ const massMarksStyle = [
+ {
+ url: statusIcons.exceed,
+ size: new AMap.Size(20, 20),
+ anchor: new AMap.Pixel(10, 10),
+ },
+ {
+ url: statusIcons.exception,
+ size: new AMap.Size(20, 20),
+ anchor: new AMap.Pixel(10, 10),
+ },
+ {
+ url: statusIcons.offline,
+ size: new AMap.Size(20, 20),
+ anchor: new AMap.Pixel(10, 10),
+ },
+ {
+ url: statusIcons.online,
+ size: new AMap.Size(32, 32),
+ anchor: new AMap.Pixel(10, 10),
+ },
+ {
+ url: statusIcons.offlineStatus,
+ size: new AMap.Size(32, 32),
+ anchor: new AMap.Pixel(10, 10),
+ },
+ ]
// 鍑嗗娴烽噺鐐规暟鎹�
const massMarksData = shops.map((shop, index) => {
- // 鏍规嵁鐜俊鐮佺瓑绾ц幏鍙栭鑹�
- const color = getColorByRingCodeLevel(shop.shop.ringCodeLevel)
+ // 鏍规嵁寮傚父鐘舵�佸拰鍦ㄧ嚎鐘舵�佽幏鍙栨牱寮忕储寮�
+ let styleIndex = 3 // 榛樿鍦ㄧ嚎鐘舵��
+
+ if (shop.shop.exceptionStatus !== undefined) {
+ switch (shop.shop.exceptionStatus) {
+ case 0: // 娌圭儫娴撳害瓒呮爣
+ styleIndex = 0
+ break
+ case 1: // 渚涚數寮傚父
+ styleIndex = 1
+ break
+ case 2: // 璁惧鎴栫綉缁滃紓甯�
+ styleIndex = 2
+ break
+ case 3: // 鏃犲紓甯革紝鏍规嵁鍦ㄧ嚎鐘舵�佸喅瀹�
+ styleIndex = shop.shop.isOnline ? 3 : 4
+ break
+ default:
+ styleIndex = shop.shop.isOnline ? 3 : 4
+ }
+ } else {
+ // 娌℃湁寮傚父鐘舵�佹椂锛屾牴鎹湪绾跨姸鎬佸喅瀹�
+ styleIndex = shop.shop.isOnline ? 3 : 4
+ }
return {
id: index,
name: shop.shop.name,
lnglat: [shop.shop.longitude, shop.shop.latitude],
- style: shop.shop.ringCodeLevel, // 鏍峰紡绱㈠紩锛屽搴� massMarksStyle
+ style: styleIndex, // 鏍峰紡绱㈠紩锛屽搴� massMarksStyle
extData: shop, // 瀛樺偍瀹屾暣鐨勫簵閾轰俊鎭�
}
})
@@ -134,6 +185,46 @@
}
/**
+ * 鏍规嵁寮傚父鐘舵�佽幏鍙栦腑鏂�
+ * @param {number} status 寮傚父鐘舵��
+ * @returns {string} 涓枃琛ㄧず
+ */
+function getExceptionStatusText(status) {
+ switch (status + '') {
+ case '0':
+ return '娌圭儫娴撳害瓒呮爣'
+ case '1':
+ return '渚涚數寮傚父'
+ case '2':
+ return '璁惧鎴栫綉缁滃紓甯�'
+ case '3':
+ return '鏃犲紓甯�'
+ default:
+ return '鏈煡鐘舵��'
+ }
+}
+
+/**
+ * 鏍规嵁寮傚父鐘舵�佽幏鍙栭鑹�
+ * @param {number} status 寮傚父鐘舵��
+ * @returns {string} 棰滆壊鍊�
+ */
+function getColorByExceptionStatus(status) {
+ switch (status + '') {
+ case '0':
+ return '#f5222d' // 娌圭儫娴撳害瓒呮爣 - 绾㈣壊
+ case '1':
+ return '#faad14' // 渚涚數寮傚父 - 榛勮壊
+ case '2':
+ return '#8c8c8c' // 璁惧鎴栫綉缁滃紓甯� - 鐏拌壊
+ case '3':
+ return '#52c41a' // 鏃犲紓甯� - 缁胯壊
+ default:
+ return '#8c8c8c' // 鐏拌壊
+ }
+}
+
+/**
* 鍒涘缓鑷畾涔夋爣璁�
* @param {string} color 鏍囪棰滆壊
* @returns {string} 鏍囪鐨凷VG URL
@@ -149,41 +240,151 @@
}
/**
+ * 鍒涘缓鍦ㄧ嚎鐘舵�佺殑SVG鏍囪锛堟补鐑熺洃娴嬭澶囧舰璞★級
+ * @returns {string} 鏍囪鐨凷VG URL
+ */
+function createCustomMarkerOnline() {
+ const svg = `
+ <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <!-- 璁惧涓讳綋 - 鍦嗚鐭╁舰 -->
+ <rect x="5" y="8" width="22" height="16" rx="3" fill="#52c41a" stroke="white" stroke-width="2"/>
+
+ <!-- 璁惧椤堕儴 - 寮у舰 -->
+ <path d="M5 8 Q16 3 27 8" stroke="white" stroke-width="2" fill="#389e0d"/>
+
+ <!-- 璁惧搴曢儴 - 寮у舰 -->
+ <path d="M5 24 Q16 29 27 24" stroke="white" stroke-width="2" fill="#389e0d"/>
+
+ <!-- 璁惧鏄剧ず灞� -->
+ <rect x="8" y="11" width="16" height="10" rx="2" fill="white"/>
+
+ <!-- 鏄剧ず灞忔暟鎹� -->
+ <path d="M11 14 L21 14" stroke="#52c41a" stroke-width="1.5"/>
+ <path d="M11 17 L18 17" stroke="#52c41a" stroke-width="1.5"/>
+ <path d="M11 20 L15 20" stroke="#52c41a" stroke-width="1.5"/>
+
+ <!-- 璁惧澶╃嚎 -->
+ <line x1="16" y1="8" x2="16" y2="3" stroke="white" stroke-width="1.5"/>
+ <circle cx="16" cy="3" r="1.5" fill="white"/>
+
+ <!-- 璁惧鎸囩ず鐏� -->
+ <circle cx="27" cy="16" r="3" fill="#ffffff"/>
+ <circle cx="27" cy="16" r="1.5" fill="#52c41a"/>
+
+ <!-- 瑁呴グ绾挎潯 -->
+ <line x1="5" y1="13" x2="6" y2="13" stroke="white" stroke-width="1.5"/>
+ <line x1="5" y1="19" x2="6" y2="19" stroke="white" stroke-width="1.5"/>
+ </svg>
+ `
+ return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg)))
+}
+
+/**
+ * 鍒涘缓绂荤嚎鐘舵�佺殑SVG鏍囪锛堟补鐑熺洃娴嬭澶囧舰璞★級
+ * @returns {string} 鏍囪鐨凷VG URL
+ */
+function createCustomMarkerOffline() {
+ const svg = `
+ <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <!-- 璁惧涓讳綋 - 鍦嗚鐭╁舰 -->
+ <rect x="5" y="8" width="22" height="16" rx="3" fill="#8c8c8c" stroke="white" stroke-width="2"/>
+
+ <!-- 璁惧椤堕儴 - 寮у舰 -->
+ <path d="M5 8 Q16 3 27 8" stroke="white" stroke-width="2" fill="#666666"/>
+
+ <!-- 璁惧搴曢儴 - 寮у舰 -->
+ <path d="M5 24 Q16 29 27 24" stroke="white" stroke-width="2" fill="#666666"/>
+
+ <!-- 璁惧鏄剧ず灞� -->
+ <rect x="8" y="11" width="16" height="10" rx="2" fill="white"/>
+
+ <!-- 鏄剧ず灞忔棤鏁版嵁 - 浜ゅ弶绾� -->
+ <line x1="11" y1="12" x2="21" y2="22" stroke="#8c8c8c" stroke-width="2"/>
+ <line x1="11" y1="22" x2="21" y2="12" stroke="#8c8c8c" stroke-width="2"/>
+
+ <!-- 璁惧澶╃嚎 -->
+ <line x1="16" y1="8" x2="16" y2="3" stroke="white" stroke-width="1.5"/>
+ <circle cx="16" cy="3" r="1.5" fill="white"/>
+
+ <!-- 璁惧鎸囩ず鐏� -->
+ <circle cx="27" cy="16" r="3" fill="#ffffff"/>
+ <circle cx="27" cy="16" r="1.5" fill="#8c8c8c"/>
+
+ <!-- 瑁呴グ绾挎潯 -->
+ <line x1="5" y1="13" x2="6" y2="13" stroke="white" stroke-width="1.5"/>
+ <line x1="5" y1="19" x2="6" y2="19" stroke="white" stroke-width="1.5"/>
+ </svg>
+ `
+ return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg)))
+}
+
+/**
* 鏄剧ず搴楅摵淇℃伅绐楀彛
* @param {Object} shop 搴楅摵瀵硅薄
*/
function showShopInfoWindow(shop) {
// 鍑嗗淇℃伅绐楀彛鍐呭
- // const content = `
- // <div style="padding: 10px; max-width: 300px;">
- // <h3 style="margin: 0 0 10px 0; color: #333;">${shop.shop.name}</h3>
- // <div style="font-size: 14px; line-height: 1.5;">
- // <p><strong>鍦板潃锛�</strong>${shop.shop.address}</p>
- // <p><strong>鐜俊鐮佺瓑绾э細</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${shop.shop.ringCodeLevel}</span></p>
- // <p><strong>鐜俊鐮佸彂甯冩椂闂达細</strong>${shop.shop.ringCodePublishTime}</p>
- // <h4 style="margin: 10px 0 5px 0; color: #666;">杩�1灏忔椂鐩戞祴鏁版嵁</h4>
- // <div style="max-height: 150px; overflow-y: auto;">
- // ${shop.recentData
- // .map(
- // (item) => `
- // <div style="padding: 5px; border-bottom: 1px solid #f0f0f0;">
- // <p><strong>閲囨牱鏃堕棿锛�</strong>${item.sampleTime}</p>
- // <p><strong>娌圭儫娴撳害锛�</strong>${item.oilSmokeConcentration} mg/m鲁</p>
- // <p><strong>鍑�鍖栧櫒鐢垫祦锛�</strong>${item.purifierCurrent} A</p>
- // <p><strong>椋庢満鐢垫祦锛�</strong>${item.fanCurrent} A</p>
- // </div>
- // `,
- // )
- // .join('')}
- // </div>
- // </div>
- // </div>
- // `
+ // 鑾峰彇鍦ㄧ嚎鐘舵�佹枃鏈�
+ const onlineStatusText = shop.shop.isOnline ? '鍦ㄧ嚎' : '绂荤嚎'
+ // 鑾峰彇寮傚父鐘舵�佹枃鏈�
+ const exceptionStatusText = getExceptionStatusText(shop.shop.exceptionStatus)
+ // 鑾峰彇寮傚父鐘舵�侀鑹�
+ const exceptionStatusColor = getColorByExceptionStatus(shop.shop.exceptionStatus)
+
+ // 鏍规嵁鐘舵�佽幏鍙栧搴旂殑鍥炬爣
+ let statusIcon = statusIcons.online // 榛樿鍦ㄧ嚎鍥炬爣
+ if (shop.shop.exceptionStatus !== undefined) {
+ switch (shop.shop.exceptionStatus) {
+ case 0:
+ statusIcon = statusIcons.exceed
+ break
+ case 1:
+ statusIcon = statusIcons.exception
+ break
+ case 2:
+ statusIcon = statusIcons.offline
+ break
+ case 3:
+ statusIcon = shop.shop.isOnline ? statusIcons.online : statusIcons.offlineStatus
+ break
+ default:
+ statusIcon = shop.shop.isOnline ? statusIcons.online : statusIcons.offlineStatus
+ }
+ } else {
+ statusIcon = shop.shop.isOnline ? statusIcons.online : statusIcons.offlineStatus
+ }
+
+ // 鏍规嵁鍦ㄧ嚎鐘舵�佽幏鍙栧浘鏍�
+ const onlineIcon = shop.shop.isOnline ? statusIcons.online : statusIcons.offlineStatus
+
+ // 鏍规嵁寮傚父鐘舵�佽幏鍙栧浘鏍�
+ let exceptionIcon = statusIcons.online // 榛樿鍦ㄧ嚎鍥炬爣
+ if (shop.shop.exceptionStatus !== undefined) {
+ switch (shop.shop.exceptionStatus) {
+ case 0:
+ exceptionIcon = statusIcons.exceed
+ break
+ case 1:
+ exceptionIcon = statusIcons.exception
+ break
+ case 2:
+ exceptionIcon = statusIcons.offline
+ break
+ case 3:
+ exceptionIcon = statusIcons.online
+ break
+ default:
+ exceptionIcon = statusIcons.online
+ }
+ }
+
const content = `
<div style="padding: 10px; width: 400px;">
<h3 style="margin: 0 0 10px 0; color: #333;">${shop.shop.name}</h3>
<div style="font-size: 14px; line-height: 1.5;">
<p><strong>鍦板潃锛�</strong>${shop.shop.address}</p>
+ <p><strong>鍦ㄧ嚎鐘舵�侊細</strong><span style="color: ${shop.shop.isOnline ? '#52c41a' : '#8c8c8c'}">${onlineStatusText}</span> </p>
+ <p><strong>寮傚父鐘舵�侊細</strong><span style="color: ${exceptionStatusColor}">${exceptionStatusText}</span></p>
<p><strong>鐜俊鐮佺瓑绾э細</strong><span style="color: ${getColorByRingCodeLevel(shop.shop.ringCodeLevel)}">${getRingCodeLevelText(shop.shop.ringCodeLevel)}</span></p>
<p><strong>鐜俊鐮佸彂甯冩椂闂达細</strong>${shop.shop.ringCodePublishTime}</p>
<h4 style="margin: 10px 0 5px 0; color: #666;">杩�1灏忔椂鐩戞祴鏁版嵁</h4>
diff --git a/src/views/monitor/DataDashboard.vue b/src/views/monitor/DataDashboard.vue
index 65cd655..45fa087 100644
--- a/src/views/monitor/DataDashboard.vue
+++ b/src/views/monitor/DataDashboard.vue
@@ -186,10 +186,10 @@
</div>
</div>
- <!-- 浠诲姟瀹屾垚鐜� -->
+ <!-- 宸℃煡鐐规 -->
<div class="metric-card">
<div class="card-header">
- <div class="card-title">浠诲姟瀹屾垚鐜�</div>
+ <div class="card-title">宸℃煡鐐规</div>
<div class="card-icon task-icon">
<svg
width="20"
@@ -215,18 +215,18 @@
</svg>
</div>
</div>
- <div class="card-value">{{ metrics.taskCompletionRate }}%</div>
+ <div class="card-value">{{ metrics.inspectionPoints }}</div>
<div class="card-trend">
<span
class="trend-arrow"
:class="{
- up: metrics.taskCompletionRateTrend > 0,
- down: metrics.taskCompletionRateTrend < 0,
+ up: metrics.inspectionPointsTrend > 0,
+ down: metrics.inspectionPointsTrend < 0,
}"
>
- {{ metrics.taskCompletionRateTrend > 0 ? '鈫�' : '鈫�' }}
+ {{ metrics.inspectionPointsTrend > 0 ? '鈫�' : '鈫�' }}
</span>
- <span class="trend-text">{{ Math.abs(metrics.taskCompletionRateTrend) }}%</span>
+ <span class="trend-text">{{ Math.abs(metrics.inspectionPointsTrend) }}</span>
<span class="trend-label">{{ getCompareLabel() }}</span>
</div>
</div>
@@ -306,6 +306,43 @@
<!-- 璁惧鐘舵�侀ゼ鍥� -->
<div class="device-status-chart">
<canvas id="deviceStatusChart"></canvas>
+ </div>
+ </div>
+
+ <!-- 鍦板浘鍥句緥 -->
+ <div class="map-legend">
+ <div class="legend-header">
+ <h4>鍥句緥</h4>
+ </div>
+ <div class="legend-items">
+ <div class="legend-item">
+ <img src="@/assets/exceed.png" alt="娌圭儫娴撳害瓒呮爣" class="legend-icon" />
+ <span class="legend-text">娌圭儫娴撳害瓒呮爣</span>
+ </div>
+ <div class="legend-item">
+ <img src="@/assets/exception.png" alt="渚涚數寮傚父" class="legend-icon" />
+ <span class="legend-text">渚涚數寮傚父</span>
+ </div>
+ <div class="legend-item">
+ <img src="@/assets/offline.png" alt="璁惧鎴栫綉缁滃紓甯�" class="legend-icon" />
+ <span class="legend-text">璁惧鎴栫綉缁滃紓甯�</span>
+ </div>
+ <div class="legend-item">
+ <img
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSI1IiB5PSI4IiB3aWR0aD0iMjIiIGhlaWdodD0iMTYiIHJ4PSIzIiBmaWxsPSIjNTJjNDFhIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNNSA4IFEgMTYgMyAyNyA4IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiMzODllMGQiLz48cGF0aCBkPSJNNSAyNCBRIDE2IDI5IDI3IDI0IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cmVjdCB4PSI4IiB5PSIxMSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjEwIiByeD0iMiIgZmlsbD0id2hpdGUiLz48cGF0aCBkPSJNMTIgMTQgTCAyMSAxNCIgc3Ryb2tlPSIjNTJjNDFhIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxwYXRoIGQ9Ik0xMiAxNyBMIDE4IDE3IiBzdHJva2U9IiM1MmM0MWEiIHN0cm9rZS13aWR0aD0iMS41Ii8+PHBhdGggZD0iTTEyIDIwIEwgMTUgMjAiIHN0cm9rZT0iIzUyYzQxYSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48bGluZSB4MT0iMTYiIHkxPSI4IiB4Mj0iMTYiIHkyPSIzIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxjaXJjbGUgY3g9IjE2IiBjeT0iMyIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIvPjxjaXJjbGUgY3g9IjI3IiBjeT0iMTYiIHI9IjMiIGZpbGw9IiNmZmZmZmYiLz48Y2lyY2xlIGN4PSIyNyIgY3k9IjE2IiByPSIxLjUiIGZpbGw9IiM1MmM0MWEiLz48bGluZSB4MT0iNSIgeTE9IjEzIiB4Mj0iNiIgeTI9IjEzIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuNSIvPjxsaW5lIHgxPSI1IiB5MT0iMTkiIHgyPSI2IiB5Mj0iMTkiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PC9zdmc+"
+ alt="鍦ㄧ嚎鐘舵��"
+ class="legend-icon"
+ />
+ <span class="legend-text">鍦ㄧ嚎鐘舵��</span>
+ </div>
+ <div class="legend-item">
+ <img
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSI1IiB5PSI4IiB3aWR0aD0iMjIiIGhlaWdodD0iMTYiIHJ4PSIzIiBmaWxsPSIjOGM4YzhjIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNNSA4IFEgMTYgMyAyNyA4IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cGF0aCBkPSJNNSAyNCBRIDE2IDI5IDI3IDI0IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiM2NjY2NjYiLz48cmVjdCB4PSI4IiB5PSIxMSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjEwIiByeD0iMiIgZmlsbD0id2hpdGUiLz48bGluZSB4MT0iMTEiIHkxPSIxMiIgeDI9IjIxIiB5Mj0iMjIiIHN0cm9rZT0iIzhjOGM4YyIgc3Ryb2tlLXdpZHRoPSIyIi8+PGxpbmUgeDE9IjExIiB5MT0iMjIiIHgyPSIyMSIgeTI9IjEyIiBzdHJva2U9IiM4YzhjOGMiIHN0cm9rZS13aWR0aD0iMiIvPjxsaW5lIHgxPSIxNiIgeTE9IjgiIHgyPSIxNiIgeTI9IjMiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PGNpcmNsZSBjeD0iMTYiIGN5PSIzIiByPSIxLjUiIGZpbGw9IndoaXRlIi8+PGNpcmNsZSBjeD0iMjciIGN5PSIxNiIgcj0iMyIgZmlsbD0iI2ZmZmZmZiIvPjxjaXJjbGUgY3g9IjI3IiBjeT0iMTYiIHI9IjEuNSIgZmlsbD0iIzhjOGM4YyIvPjxsaW5lIHgxPSI1IiB5MT0iMTMiIHgyPSI2IiB5Mj0iMTMiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS41Ii8+PGxpbmUgeDE9IjUiIHkxPSIxOSIgeDI9IjYiIHkyPSIxOSIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48L3N2Zz4="
+ alt="绂荤嚎鐘舵��"
+ class="legend-icon"
+ />
+ <span class="legend-text">绂荤嚎鐘舵��</span>
+ </div>
</div>
</div>
<!-- 宸℃煡鎯呭喌缁熻鍗$墖 -->
@@ -469,8 +506,8 @@
onlineRateTrend: 2,
purifierEfficiency: 85,
purifierEfficiencyTrend: -3,
- taskCompletionRate: 78,
- taskCompletionRateTrend: 10,
+ inspectionPoints: 350,
+ inspectionPointsTrend: 50,
},
overview: {
totalShops: 245,
@@ -601,8 +638,8 @@
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,
+ inspectionPoints: Math.floor(Math.random() * 100) + 300,
+ inspectionPointsTrend: Math.floor(Math.random() * 100) - 50,
}
// 鏇存柊宸℃煡缁熻鏁版嵁
@@ -1263,6 +1300,51 @@
animation: blink 1s infinite;
}
+/* 鍦板浘鍥句緥鏍峰紡 */
+.map-legend {
+ position: absolute;
+ bottom: 4px;
+ right: 4px;
+ width: 200px;
+ background-color: rgba(255, 255, 255, 0.9);
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ padding: 16px;
+ z-index: 10;
+}
+
+.legend-header {
+ margin-bottom: 12px;
+}
+
+.legend-header h4 {
+ font-size: 14px;
+ font-weight: 600;
+ color: #262626;
+ margin: 0;
+ text-align: center;
+}
+
+.legend-items {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.legend-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 12px;
+ color: #4e5969;
+}
+
+.legend-icon {
+ width: 24px;
+ height: 24px;
+ object-fit: contain;
+}
+
/* 鍝嶅簲寮忚璁� */
/* @media (max-width: 1200px) {
.top-cards {
diff --git a/src/views/system/SystemManage.vue b/src/views/system/SystemManage.vue
index 188cfc4..c345b68 100644
--- a/src/views/system/SystemManage.vue
+++ b/src/views/system/SystemManage.vue
@@ -202,12 +202,60 @@
// 鐢ㄦ埛绠$悊鐩稿叧
const users = ref([
- { id: 1, username: 'admin', name: '绠$悊鍛�', role: 'admin', status: 'active' },
- { id: 2, username: 'user1', name: '鐢ㄦ埛1', role: 'user', status: 'active' },
{
- id: 3,
- username: 'restaurant1',
- name: '搴楅摵绠$悊鍛�1',
+ id: 1,
+ username: 'fuxiaojie',
+ name: '浠樺皬濮愬湪鎴愰兘',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ { id: 2, username: 'jike', name: '鍚夊埢鑱旂洘', role: 'restaurant_admin', status: 'active' },
+ { id: 3, username: 'jiazaitala', name: '瀹跺湪濉斿暒', role: 'restaurant_admin', status: 'active' },
+ { id: 4, username: 'langlailiao', name: '鐙兼潵浜�', role: 'restaurant_admin', status: 'active' },
+ { id: 5, username: 'lekaisai', name: '涔愬嚡鎾掓槦娓稿簵', role: 'restaurant_admin', status: 'active' },
+ {
+ id: 6,
+ username: 'xinyuan',
+ name: '棣ㄨ繙缇庨灏忛晣锛堝搱灏肩編椋熷箍鍦猴級',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ { id: 7, username: 'bangyuehan', name: '妫掔害缈�', role: 'restaurant_admin', status: 'active' },
+ { id: 8, username: 'nangtang', name: '寮勫爞鍜亾', role: 'restaurant_admin', status: 'active' },
+ {
+ id: 9,
+ username: 'yangji',
+ name: '鏉ㄨ榻愰綈鍝堝皵鐑よ倝',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ {
+ id: 10,
+ username: 'rensheng',
+ name: '涓婃捣绋斾紶椁愰ギ绠$悊鏈夐檺鍏徃锛堜汉鐢熶竴涓诧級',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ { id: 11, username: 'yuanjia', name: '缂樺', role: 'restaurant_admin', status: 'active' },
+ {
+ id: 12,
+ username: 'quansheng',
+ name: '娉夌洓椁愰ギ锛堜笂娴凤級鏈夐檺鍏徃锛堥鍏跺锛�',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ { id: 13, username: 'fengmao', name: '涓拌寕鐑や覆', role: 'restaurant_admin', status: 'active' },
+ {
+ id: 14,
+ username: 'taihuang',
+ name: '涓婃捣娉扮厡椁愰ギ绠$悊鏈夐檺鍏徃锛堟嘲鐓岄浮锛�',
+ role: 'restaurant_admin',
+ status: 'active',
+ },
+ {
+ id: 15,
+ username: 'chenxi',
+ name: '寰愭眹鍖鸿景鐔欓棣�(灏忛搧鍚涗覆鐑у眳閰掑眿)',
role: 'restaurant_admin',
status: 'active',
},
--
Gitblit v1.9.3