瀏覽代碼

增加websocket手环预警信息接收

xiongxing 5 天之前
父節點
當前提交
8e1f4ffda9
共有 7 個文件被更改,包括 761 次插入571 次删除
  1. 1 0
      .env
  2. 11 163
      package-lock.json
  3. 1 0
      package.json
  4. 342 9
      src/layout/index.vue
  5. 3 0
      src/utils/mitt.js
  6. 394 398
      src/views/index/index.vue
  7. 9 1
      src/views/index/roomdetail.vue

+ 1 - 0
.env

@@ -5,6 +5,7 @@
 #VITE_API_URL='https://home.ynims.com/dataScreen/dataBigScreen/'
 #VITE_API_URL='https://home.ynims.com/dataScreen/dataBigScreen/'
 VITE_API_URL='http://47.107.245.0:48080/'
 VITE_API_URL='http://47.107.245.0:48080/'
 VITE_API_APP_URL='http://47.112.126.153:7060/'
 VITE_API_APP_URL='http://47.112.126.153:7060/'
+VITE_API_WSS_URL='ws://47.112.126.153:7061/ws/monitor/'
 # VITE_API_APP_URL='https://home.ynims.com:6060'
 # VITE_API_APP_URL='https://home.ynims.com:6060'
 
 
 
 

+ 11 - 163
package-lock.json

@@ -16,6 +16,7 @@
 				"axios": "^1.6.8",
 				"axios": "^1.6.8",
 				"echarts": "^5.5.0",
 				"echarts": "^5.5.0",
 				"ezuikit-flv": "^2.0.2",
 				"ezuikit-flv": "^2.0.2",
+				"mitt": "^3.0.1",
 				"pinia": "^2.1.7",
 				"pinia": "^2.1.7",
 				"postcss-pxtorem": "^6.1.0",
 				"postcss-pxtorem": "^6.1.0",
 				"socket.io-client": "^4.7.5",
 				"socket.io-client": "^4.7.5",
@@ -474,61 +475,6 @@
 				"node": ">=12"
 				"node": ">=12"
 			}
 			}
 		},
 		},
-		"node_modules/@ezuikit/player-base": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/player-base/-/player-base-0.1.0.tgz",
-			"integrity": "sha512-IcJqnZr9FmjBCnIrmqY7oHdyDuYxRWhDZB+K+gi+4oenFjFV4aLCCG7RFPxkidHzi3TTF2f1Bm5yObZzNDqkfw==",
-			"dependencies": {
-				"@ezuikit/utils-collect": "^0.1.0",
-				"@ezuikit/utils-logger": "^1.0.1",
-				"@ezuikit/utils-tools": "^1.0.2",
-				"eventemitter3": "^5.0.1",
-				"lodash-es": "^4.17.21",
-				"screenfull": "^6.0.2",
-				"ua-parser-js": "1.0.37"
-			}
-		},
-		"node_modules/@ezuikit/player-hls": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/player-hls/-/player-hls-0.1.0.tgz",
-			"integrity": "sha512-T5PCj65mw3mP1MpfJOrx/MXpNZFMrW37fjjYnil1rCuy6ACGBNWXFVvOlzuh5k7G4DFV+HjbbMJnG21icNdZnw==",
-			"dependencies": {
-				"@ezuikit/player-base": "0.1.0",
-				"@ezuikit/utils-collect": "^0.1.0",
-				"@ezuikit/utils-i18n": "^1.0.1",
-				"@ezuikit/utils-logger": "^1.0.1",
-				"@ezuikit/utils-tools": "^1.0.2",
-				"dayjs": "^1.11.10",
-				"eventemitter3": "^5.0.1",
-				"hls.js": "^1.5.7",
-				"lodash-es": "^4.17.21",
-				"screenfull": "^6.0.2",
-				"ua-parser-js": "1.0.37"
-			}
-		},
-		"node_modules/@ezuikit/utils-collect": {
-			"version": "0.1.1",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-collect/-/utils-collect-0.1.1.tgz",
-			"integrity": "sha512-BgEOnTtAq8rQRBAKv5rLXbQLGOnfOZ6NS0QTmiviey80JbMJlxrLiqmjL5lxvkm4JtCcXCtSgPA4tskQKN4eDA=="
-		},
-		"node_modules/@ezuikit/utils-i18n": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-i18n/-/utils-i18n-1.1.1.tgz",
-			"integrity": "sha512-PZe37fHfjUbhArXaoWMxbGOnU1R6k8XV7NroB3n2uL+z06SajozxO5TQARrk7Z72USQPvUsyaKIBcwVNjWK6/w==",
-			"dependencies": {
-				"deepmerge": "^4.3.1"
-			}
-		},
-		"node_modules/@ezuikit/utils-logger": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-logger/-/utils-logger-1.1.0.tgz",
-			"integrity": "sha512-l/PiFZIC/VtW2l1oEjZEXfeYKFkPvX1kAlljXc1nRImNOI9t71/2oyTTkqkZvMLP/EG5regD9wuQplcvtfubUg=="
-		},
-		"node_modules/@ezuikit/utils-tools": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-tools/-/utils-tools-1.1.0.tgz",
-			"integrity": "sha512-mujPtXIhZnuJrJySu1/Z6X90sMJQStZydurZcfetMCH6pqIYN4P+1w6+P8PCTR6k4LJp5nY9+eNnKa7AZ8OBKA=="
-		},
 		"node_modules/@jridgewell/sourcemap-codec": {
 		"node_modules/@jridgewell/sourcemap-codec": {
 			"version": "1.4.15",
 			"version": "1.4.15",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -1604,11 +1550,6 @@
 				"node": ">= 0.4"
 				"node": ">= 0.4"
 			}
 			}
 		},
 		},
-		"node_modules/hls.js": {
-			"version": "1.6.13",
-			"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.13.tgz",
-			"integrity": "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA=="
-		},
 		"node_modules/immutable": {
 		"node_modules/immutable": {
 			"version": "4.3.5",
 			"version": "4.3.5",
 			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
 			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
@@ -1798,6 +1739,11 @@
 				"url": "https://github.com/sponsors/isaacs"
 				"url": "https://github.com/sponsors/isaacs"
 			}
 			}
 		},
 		},
+		"node_modules/mitt": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+			"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+		},
 		"node_modules/ms": {
 		"node_modules/ms": {
 			"version": "2.1.2",
 			"version": "2.1.2",
 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -2138,17 +2084,6 @@
 				"node": ">=14.0.0"
 				"node": ">=14.0.0"
 			}
 			}
 		},
 		},
-		"node_modules/screenfull": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.2.tgz",
-			"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==",
-			"engines": {
-				"node": "^14.13.1 || >=16.0.0"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
 		"node_modules/scroll-into-view-if-needed": {
 		"node_modules/scroll-into-view-if-needed": {
 			"version": "2.2.31",
 			"version": "2.2.31",
 			"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
 			"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
@@ -2251,28 +2186,6 @@
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
 			"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
 			"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
 		},
 		},
-		"node_modules/ua-parser-js": {
-			"version": "1.0.37",
-			"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
-			"integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==",
-			"funding": [
-				{
-					"type": "opencollective",
-					"url": "https://opencollective.com/ua-parser-js"
-				},
-				{
-					"type": "paypal",
-					"url": "https://paypal.me/faisalman"
-				},
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/faisalman"
-				}
-			],
-			"engines": {
-				"node": "*"
-			}
-		},
 		"node_modules/unplugin": {
 		"node_modules/unplugin": {
 			"version": "1.10.0",
 			"version": "1.10.0",
 			"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz",
 			"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz",
@@ -2845,61 +2758,6 @@
 			"dev": true,
 			"dev": true,
 			"optional": true
 			"optional": true
 		},
 		},
-		"@ezuikit/player-base": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/player-base/-/player-base-0.1.0.tgz",
-			"integrity": "sha512-IcJqnZr9FmjBCnIrmqY7oHdyDuYxRWhDZB+K+gi+4oenFjFV4aLCCG7RFPxkidHzi3TTF2f1Bm5yObZzNDqkfw==",
-			"requires": {
-				"@ezuikit/utils-collect": "^0.1.0",
-				"@ezuikit/utils-logger": "^1.0.1",
-				"@ezuikit/utils-tools": "^1.0.2",
-				"eventemitter3": "^5.0.1",
-				"lodash-es": "^4.17.21",
-				"screenfull": "^6.0.2",
-				"ua-parser-js": "1.0.37"
-			}
-		},
-		"@ezuikit/player-hls": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/player-hls/-/player-hls-0.1.0.tgz",
-			"integrity": "sha512-T5PCj65mw3mP1MpfJOrx/MXpNZFMrW37fjjYnil1rCuy6ACGBNWXFVvOlzuh5k7G4DFV+HjbbMJnG21icNdZnw==",
-			"requires": {
-				"@ezuikit/player-base": "0.1.0",
-				"@ezuikit/utils-collect": "^0.1.0",
-				"@ezuikit/utils-i18n": "^1.0.1",
-				"@ezuikit/utils-logger": "^1.0.1",
-				"@ezuikit/utils-tools": "^1.0.2",
-				"dayjs": "^1.11.10",
-				"eventemitter3": "^5.0.1",
-				"hls.js": "^1.5.7",
-				"lodash-es": "^4.17.21",
-				"screenfull": "^6.0.2",
-				"ua-parser-js": "1.0.37"
-			}
-		},
-		"@ezuikit/utils-collect": {
-			"version": "0.1.1",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-collect/-/utils-collect-0.1.1.tgz",
-			"integrity": "sha512-BgEOnTtAq8rQRBAKv5rLXbQLGOnfOZ6NS0QTmiviey80JbMJlxrLiqmjL5lxvkm4JtCcXCtSgPA4tskQKN4eDA=="
-		},
-		"@ezuikit/utils-i18n": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-i18n/-/utils-i18n-1.1.1.tgz",
-			"integrity": "sha512-PZe37fHfjUbhArXaoWMxbGOnU1R6k8XV7NroB3n2uL+z06SajozxO5TQARrk7Z72USQPvUsyaKIBcwVNjWK6/w==",
-			"requires": {
-				"deepmerge": "^4.3.1"
-			}
-		},
-		"@ezuikit/utils-logger": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-logger/-/utils-logger-1.1.0.tgz",
-			"integrity": "sha512-l/PiFZIC/VtW2l1oEjZEXfeYKFkPvX1kAlljXc1nRImNOI9t71/2oyTTkqkZvMLP/EG5regD9wuQplcvtfubUg=="
-		},
-		"@ezuikit/utils-tools": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/@ezuikit/utils-tools/-/utils-tools-1.1.0.tgz",
-			"integrity": "sha512-mujPtXIhZnuJrJySu1/Z6X90sMJQStZydurZcfetMCH6pqIYN4P+1w6+P8PCTR6k4LJp5nY9+eNnKa7AZ8OBKA=="
-		},
 		"@jridgewell/sourcemap-codec": {
 		"@jridgewell/sourcemap-codec": {
 			"version": "1.4.15",
 			"version": "1.4.15",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -3696,11 +3554,6 @@
 				"function-bind": "^1.1.2"
 				"function-bind": "^1.1.2"
 			}
 			}
 		},
 		},
-		"hls.js": {
-			"version": "1.6.13",
-			"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.13.tgz",
-			"integrity": "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA=="
-		},
 		"immutable": {
 		"immutable": {
 			"version": "4.3.5",
 			"version": "4.3.5",
 			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
 			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
@@ -3841,6 +3694,11 @@
 				"brace-expansion": "^2.0.1"
 				"brace-expansion": "^2.0.1"
 			}
 			}
 		},
 		},
+		"mitt": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+			"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+		},
 		"ms": {
 		"ms": {
 			"version": "2.1.2",
 			"version": "2.1.2",
 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -4040,11 +3898,6 @@
 				"source-map-js": ">=0.6.2 <2.0.0"
 				"source-map-js": ">=0.6.2 <2.0.0"
 			}
 			}
 		},
 		},
-		"screenfull": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.2.tgz",
-			"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw=="
-		},
 		"scroll-into-view-if-needed": {
 		"scroll-into-view-if-needed": {
 			"version": "2.2.31",
 			"version": "2.2.31",
 			"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
 			"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
@@ -4123,11 +3976,6 @@
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
 			"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
 			"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
 		},
 		},
-		"ua-parser-js": {
-			"version": "1.0.37",
-			"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
-			"integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ=="
-		},
 		"unplugin": {
 		"unplugin": {
 			"version": "1.10.0",
 			"version": "1.10.0",
 			"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz",
 			"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.0.tgz",

+ 1 - 0
package.json

@@ -17,6 +17,7 @@
 		"axios": "^1.6.8",
 		"axios": "^1.6.8",
 		"echarts": "^5.5.0",
 		"echarts": "^5.5.0",
 		"ezuikit-flv": "^2.0.2",
 		"ezuikit-flv": "^2.0.2",
+		"mitt": "^3.0.1",
 		"pinia": "^2.1.7",
 		"pinia": "^2.1.7",
 		"postcss-pxtorem": "^6.1.0",
 		"postcss-pxtorem": "^6.1.0",
 		"socket.io-client": "^4.7.5",
 		"socket.io-client": "^4.7.5",

+ 342 - 9
src/layout/index.vue

@@ -1,12 +1,12 @@
 <script setup>
 <script setup>
-	import { defineProps, onMounted, ref, watch } from 'vue';
+	import { defineProps, onMounted, ref, watch, onUnmounted, h } from 'vue';
 	import { RouterView, useRoute, useRouter } from 'vue-router';
 	import { RouterView, useRoute, useRouter } from 'vue-router';
 	import { SlackCircleFilled, FullscreenOutlined, CaretDownOutlined, VideoCameraFilled } from '@ant-design/icons-vue';
 	import { SlackCircleFilled, FullscreenOutlined, CaretDownOutlined, VideoCameraFilled } from '@ant-design/icons-vue';
 	import { findAllChannelsByUserAPI, getOrganCameraListAPI, getWeatherAPi } from '@/api/layout/index.js';
 	import { findAllChannelsByUserAPI, getOrganCameraListAPI, getWeatherAPi } from '@/api/layout/index.js';
 	import { useMechanismStore } from '@/store/index.js';
 	import { useMechanismStore } from '@/store/index.js';
 	import { toggle } from '@/utils/full.js';
 	import { toggle } from '@/utils/full.js';
-	import { message } from 'ant-design-vue';
-
+	import { message, notification } from 'ant-design-vue';
+	import $bus from '@/utils/mitt.js';
 	const store = useMechanismStore();
 	const store = useMechanismStore();
 
 
 	const router = useRouter();
 	const router = useRouter();
@@ -51,11 +51,6 @@
 		router.push(item.path);
 		router.push(item.path);
 	};
 	};
 	const title = ref(0);
 	const title = ref(0);
-	onMounted(() => {
-		findAllChannelsByUser();
-		// get_weatherinfofun();
-		title.value = route.query.title ? route.query.title : '';
-	});
 
 
 	watch(store, val => {
 	watch(store, val => {
 		title.value = route.query.title ? route.query.title : '';
 		title.value = route.query.title ? route.query.title : '';
@@ -160,6 +155,344 @@
 			}
 			}
 		});
 		});
 	};
 	};
+
+	onUnmounted(() => {
+		// 清理定时器
+		stopHeartbeat();
+		if (reconnectTimeout) {
+			clearTimeout(reconnectTimeout);
+		}
+		// 断开连接
+		if (socket.value) {
+			socket.value.close(1000, '页面关闭');
+		}
+	});
+
+	onMounted(() => {
+		findAllChannelsByUser();
+		// get_weatherinfofun();
+		title.value = route.query.title ? route.query.title : '';
+		// 页面加载后自动连接
+		setTimeout(() => {
+			connect();
+		}, 1000);
+
+		// 页面可见性变化处理
+		document.addEventListener('visibilitychange', () => {
+			if (document.hidden) {
+				console.log('页面切换到后台');
+			} else {
+				console.log('页面回到前台');
+				// 检查连接健康状态
+				const now = Date.now();
+				const timeSinceLastActivity = now - lastActivity;
+
+				if (timeSinceLastActivity > 60000) {
+					// 60秒无活动
+					// 连接长时间无活动,检查连接状态
+					if (socket.value) {
+						sendMessage({ type: 'PING', timestamp: now });
+					}
+				}
+			}
+		});
+
+		// 网络状态监测
+		window.addEventListener('online', () => {
+			if (!socket.value) {
+				connect();
+			}
+		});
+
+		window.addEventListener('offline', () => {
+			console.log('网络连接断开');
+		});
+	});
+
+	// websocket设备连接
+	// 响应式数据
+	const socket = ref(null);
+	const isConnecting = ref(false);
+	const connectionId = ref(null);
+	const reconnectAttempts = ref(0);
+	const maxReconnectAttempts = ref(10);
+	const lastActivityTime = ref('-');
+	const initTime = ref(new Date().toLocaleTimeString());
+	const events = ref([]);
+	// 定时器引用
+	let heartbeatInterval = null;
+	let heartbeatTimeout = null;
+	let reconnectTimeout = null;
+	let lastActivity = Date.now();
+
+	// 连接websocket方法
+	const connect = () => {
+		// 连接已存在或连接中,跳过重复连接
+		if (isConnecting.value || socket.value) {
+			return;
+		}
+		isConnecting.value = true;
+		// 连接中...
+		// 清除之前的重连定时器
+		if (reconnectTimeout) {
+			clearTimeout(reconnectTimeout);
+			reconnectTimeout = null;
+		}
+		try {
+			const clientId = generateClientId();
+			// 连接地址: ${wsUrl}
+			const wsUrl = import.meta.env.VITE_API_WSS_URL + clientId;
+			socket.value = new WebSocket(wsUrl);
+			socket.value.onopen = handleOpen;
+			socket.value.onmessage = handleMessage;
+			socket.value.onclose = handleClose;
+			socket.value.onerror = handleError;
+		} catch (error) {
+			// 连接创建错误: ${error.message}
+			handleConnectionFailure();
+		}
+	};
+
+	const sendMessage = message => {
+		if (socket.value && socket.value.readyState === WebSocket.OPEN) {
+			try {
+				socket.value.send(JSON.stringify(message));
+				lastActivity = Date.now();
+				updateLastActivity();
+				return true;
+			} catch (error) {
+				// 发送消息失败: ${error.message}
+				return false;
+			}
+		} else {
+			// 无法发送消息: WebSocket未连接
+			return false;
+		}
+	};
+
+	// 连接成功
+	const handleOpen = event => {
+		isConnecting.value = false;
+		reconnectAttempts.value = 0;
+		lastActivity = Date.now();
+		// WebSocket连接成功
+		// 启动心跳机制
+		startHeartbeat();
+		// 发送身份验证消息
+		sendMessage({
+			type: 'AUTH',
+			clientType: 'MONITOR_SCREEN',
+			clientId: generateClientId(),
+			timestamp: Date.now()
+		});
+	};
+
+	// 获取到服务器发送的消息
+	const handleMessage = event => {
+		try {
+			lastActivity = Date.now();
+			updateLastActivity();
+			const data = JSON.parse(event.data);
+			// 收到消息: ${JSON.stringify(data)}
+			processIncomingData(data);
+		} catch (error) {
+			// '消息解析错误:', error, '原始数据:', event.data
+			console.error('消息解析错误:', error, '原始数据:', event.data);
+		}
+	};
+
+	const handleClose = event => {
+		isConnecting.value = false;
+		socket.value = null;
+		connectionId.value = null;
+		// 停止心跳和定时器
+		stopHeartbeat();
+		if (reconnectTimeout) {
+			clearTimeout(reconnectTimeout);
+			reconnectTimeout = null;
+		}
+		// `WebSocket连接关闭: 代码 ${event.code}, 原因: ${event.reason || '未知'}`
+		// 自动重连逻辑
+		if (reconnectAttempts.value < maxReconnectAttempts.value) {
+			reconnectAttempts.value++;
+			const delay = Math.min(3000 * Math.pow(1.5, reconnectAttempts.value - 1), 30000);
+			// `${Math.round(delay / 1000)}秒后尝试重连 (${reconnectAttempts.value}/${maxReconnectAttempts.value})`
+			reconnectTimeout = setTimeout(() => {
+				if (!socket.value && !isConnecting.value) {
+					connect();
+				}
+			}, delay);
+		} else {
+			console.log('已达到最大重连次数,停止自动重连');
+		}
+	};
+
+	const handleError = event => {
+		console.error('WebSocket错误详情:', event);
+	};
+
+	// 心跳检测
+	const startHeartbeat = () => {
+		// 每25秒发送一次心跳(比服务器超时时间短)
+		heartbeatInterval = setInterval(() => {
+			if (socket.value && socket.value.readyState === WebSocket.OPEN) {
+				const success = sendMessage({
+					type: 'PING',
+					timestamp: Date.now(),
+					clientTime: Date.now()
+				});
+
+				if (success) {
+					// 设置心跳超时检测
+					if (heartbeatTimeout) {
+						clearTimeout(heartbeatTimeout);
+					}
+
+					heartbeatTimeout = setTimeout(() => {
+						addLog('心跳响应超时,连接可能已断开', 'error');
+						if (socket.value) {
+							socket.value.close(1000, '心跳超时');
+						}
+					}, 10000); // 10秒超时
+				}
+			}
+		}, 25000);
+	};
+
+	const stopHeartbeat = () => {
+		if (heartbeatInterval) {
+			clearInterval(heartbeatInterval);
+			heartbeatInterval = null;
+		}
+		if (heartbeatTimeout) {
+			clearTimeout(heartbeatTimeout);
+			heartbeatTimeout = null;
+		}
+	};
+
+	const processIncomingData = data => {
+		if (!data || !data.type) {
+			// 收到无效消息格式
+			return;
+		}
+
+		switch (data.type) {
+			case 'CONNECT_SUCCESS':
+				handleConnectSuccess(data);
+				break;
+			case 'AUTH_SUCCESS':
+				handleAuthSuccess(data);
+				break;
+			case 'SOS_ALERT':
+				// 需要展示的数据
+				handleSOSAlert(data);
+				break;
+			case 'DEVICE_DATA_UPDATE':
+				handleDeviceData(data);
+				break;
+			case 'SYSTEM_STATS_UPDATE':
+				handleStatsUpdate(data);
+				break;
+			case 'PONG':
+				handlePong(data);
+				break;
+			default:
+				handleGenericMessage(data);
+		}
+	};
+
+	const handleConnectSuccess = data => {
+		console.log('WebSocket连接成功');
+		// 连接成功,连接ID: ${connectionId.value}
+		connectionId.value = data.connectionId;
+	};
+
+	const handleAuthSuccess = data => {
+		console.log('身份验证成功');
+	};
+
+	const handleSOSAlert = alertData => {
+		console.log('alertData', alertData);
+		try {
+			const alert = alertData.data || alertData;
+			// 发送确认消息
+			sendMessage({
+				type: 'SOS_ACK',
+				alertId: alert.timestamp,
+				timestamp: Date.now()
+			});
+			notification.warning({
+				message: h('div', {
+					style: {
+						color: '#fff',
+						fontSize: '18px'
+					},
+					innerHTML: `
+					<div>🚨🚨 SOS紧急预警 🚨🚨</div>
+					`
+				}),
+				// duration: 10,
+				duration: null,
+				class: 'my-warning-notification',
+				style: {
+					background: 'linear-gradient(135deg, #1e4184 0%, #3469e3 100%) !important',
+					border: '1px solid rgba(42, 157, 143, 0.3) !important',
+					'box-shadow': '0 4px 20px rgba(0, 0, 0, 0.5) !important',
+					color: '#fff !important'
+				},
+				description: h('div', {
+					innerHTML: `
+	         <div>长者姓名: ${alert.elderName || '未知'}</div>
+	         <div>长者房间: ${alert.roomName || '未知'}</div>
+	         <div>院区名称: ${alert.organizationName || '未知'}</div>
+	         <div>时间: ${new Date(alert.timestamp).toLocaleString()}</div>
+	       `
+				})
+			});
+			$bus.emit('roomDetails', 1);
+			// 重新获取信息
+			// overviewStatistics()
+			// <div>设备: ${alert.deviceId || '未知'}</div>
+			//  ${alert.location ? `<div>位置: 经度${alert.location.longitude?.toFixed(6)}, 纬度${alert.location.latitude?.toFixed(6)}</div>` : ''}
+		} catch (error) {
+			console.error('处理SOS告警错误:', error);
+		}
+	};
+
+	const handleDeviceData = deviceData => {
+		console.log('deviceData', deviceData);
+	};
+
+	const handleStatsUpdate = statsData => {
+		console.log('statsData', statsData);
+	};
+
+	const handlePong = heartbeat => {
+		// 心跳响应接收
+		if (heartbeatTimeout) {
+			clearTimeout(heartbeatTimeout);
+			heartbeatTimeout = null;
+		}
+	};
+
+	const handleGenericMessage = data => {
+		console.log('data', data);
+	};
+
+	const updateLastActivity = () => {
+		lastActivityTime.value = new Date().toLocaleTimeString();
+	};
+
+	const generateClientId = () => {
+		const timestamp = Date.now();
+		const random = Math.random().toString(36).substr(2, 9);
+		return `monitor_${timestamp}_${random}`;
+	};
+
+	const handleConnectionFailure = () => {
+		isConnecting.value = false;
+		socket.value = null;
+	};
 </script>
 </script>
 
 
 <template>
 <template>
@@ -268,7 +601,7 @@
 
 
 	.layout {
 	.layout {
 		.title {
 		.title {
-			z-index: 10;
+			z-index: 50;
 			position: absolute;
 			position: absolute;
 			top: 0;
 			top: 0;
 			right: 0;
 			right: 0;

+ 3 - 0
src/utils/mitt.js

@@ -0,0 +1,3 @@
+import mitt from 'mitt';
+const $bus = mitt();
+export default $bus;

+ 394 - 398
src/views/index/index.vue

@@ -1,52 +1,51 @@
 <template>
 <template>
-  <div class="index">
-    <div class="box-line box-line-left">
-      <!-- <img src="@/assets/img/index/index-line.png" alt="" /> -->
-      <div class="putImg" id="main" style="width: 32px; height: 1348px"></div>
-    </div>
-    <div class="box-line box-line-right">
-      <!-- <img src="@/assets/img/index/index-line.png" alt="" /> -->
-      <div class="putImg" id="main" style="width: 32px; height: 1348px"></div>
-    </div>
-    <div class="backPlateBox center_map" v-show="mapshow">
-      <MapBox></MapBox>
-    </div>
-    <!-- <div class="backPlateBox addressbox" v-show="!mapshow">
+	<div class="index">
+		<div class="box-line box-line-left">
+			<!-- <img src="@/assets/img/index/index-line.png" alt="" /> -->
+			<div class="putImg" id="main" style="width: 32px; height: 1348px"></div>
+		</div>
+		<div class="box-line box-line-right">
+			<!-- <img src="@/assets/img/index/index-line.png" alt="" /> -->
+			<div class="putImg" id="main" style="width: 32px; height: 1348px"></div>
+		</div>
+		<div class="backPlateBox center_map" v-show="mapshow">
+			<MapBox></MapBox>
+		</div>
+		<!-- <div class="backPlateBox addressbox" v-show="!mapshow">
       <AddressBox @set_adresinfo="set_adresinfo"></AddressBox>
       <AddressBox @set_adresinfo="set_adresinfo"></AddressBox>
     </div> -->
     </div> -->
 
 
-    <div class="backPlateBox box1" v-if='mapshow==1'>
-      <BackgroundPlate title="概况统计" :url="Backimg1">
-        <TheBox1 :overviewStatisticsData="box1_data"  v-if="box2_show" />
-      </BackgroundPlate>
-    </div> 
-    <div class="backPlateBox box1" v-else>
-      <BackgroundPlate title="概况统计" :url="Backimg1">
-        <TheBox1_2 :overviewStatisticsData="box1_data"  v-if="box2_show" />
-      </BackgroundPlate>
-    </div> 
-
-    <div class="backPlateBox box2">
-      <BackgroundPlate title="长者趋势统计" :url="Backimg2">
-        <TheBox2 :box2_data="box2_data"  v-if="box2_show" />
-      </BackgroundPlate>
-    </div>
-
-    <div class="backPlateBox box3">
-      <!-- <BackgroundPlate title="年龄及性别统计" :url="Backimg3"> -->
-      <BackgroundPlate title="病种人数统计" :url="Backimg3">
-        <TheBox3  :box3_data="box3_data" v-if="box3_show"  @set_listdata="set_dataarr" :id="'yuj' + Math.random()" />
-        
-      </BackgroundPlate>
-    </div>
-
-    <!-- <div class="backPlateBox boxwidthele">
+		<div class="backPlateBox box1" v-if="mapshow == 1">
+			<BackgroundPlate title="概况统计" :url="Backimg1">
+				<TheBox1 :overviewStatisticsData="box1_data" v-if="box2_show" />
+			</BackgroundPlate>
+		</div>
+		<div class="backPlateBox box1" v-else>
+			<BackgroundPlate title="概况统计" :url="Backimg1">
+				<TheBox1_2 :overviewStatisticsData="box1_data" v-if="box2_show" />
+			</BackgroundPlate>
+		</div>
+
+		<div class="backPlateBox box2">
+			<BackgroundPlate title="长者趋势统计" :url="Backimg2">
+				<TheBox2 :box2_data="box2_data" v-if="box2_show" />
+			</BackgroundPlate>
+		</div>
+
+		<div class="backPlateBox box3">
+			<!-- <BackgroundPlate title="年龄及性别统计" :url="Backimg3"> -->
+			<BackgroundPlate title="病种人数统计" :url="Backimg3">
+				<TheBox3 :box3_data="box3_data" v-if="box3_show" @set_listdata="set_dataarr" :id="'yuj' + Math.random()" />
+			</BackgroundPlate>
+		</div>
+
+		<!-- <div class="backPlateBox boxwidthele">
       <BackgroundPlate title="海珠颐年养老" :url="Backimg8">
       <BackgroundPlate title="海珠颐年养老" :url="Backimg8">
         <text class="" @click="jump_detialfun"> 123661</text>
         <text class="" @click="jump_detialfun"> 123661</text>
       </BackgroundPlate>
       </BackgroundPlate>
     </div> -->
     </div> -->
 
 
-    <!-- <div class="backPlateBox box4">
+		<!-- <div class="backPlateBox box4">
       <BackgroundPlate title="护理级别统计" :url="Backimg4">
       <BackgroundPlate title="护理级别统计" :url="Backimg4">
         <TheBox4 />
         <TheBox4 />
       </BackgroundPlate>
       </BackgroundPlate>
@@ -57,369 +56,366 @@
         <TheBox5 />
         <TheBox5 />
       </BackgroundPlate>
       </BackgroundPlate>
     </div> -->
     </div> -->
-    <div class="backPlateBox right_router"   >
-      <RouterView  @dow_map="donw_mappop" :right_data="right_data" v-if="right_show"   />
-    </div>
-
-   <div class="backPlateBox box6" v-show="mapshow" >
-      <BackgroundPlate title="户籍地统计" :url="Backimg7">
-        <TheBox6 :box6_data="box6_data"  v-if="box6_show" />
-      </BackgroundPlate>
-    </div>
- 
-    <div class="backPlateBox box7" v-if="mapshow" >
-      <BackgroundPlate title="近6个月入住统计" :url="Backimg6">
-        <TheBox7  :box7_data="box7_data"  v-if="box7_show" />
-      </BackgroundPlate>
-    </div>
-
-    <div class="backPlateBox box8" v-if="mapshow" >
-      <BackgroundPlate title="业务统计" :url="Backimg5">
-        <TheBox8    :businessStatisticsDats="box8_data"  v-if="box2_show" />
-      </BackgroundPlate>
-    </div> 
- <!--    <div class="backPlateBox mapbox" v-if="!mapshow">
+		<div class="backPlateBox right_router">
+			<RouterView @dow_map="donw_mappop" :right_data="right_data" v-if="right_show" />
+		</div>
+
+		<div class="backPlateBox box6" v-show="mapshow">
+			<BackgroundPlate title="户籍地统计" :url="Backimg7">
+				<TheBox6 :box6_data="box6_data" v-if="box6_show" />
+			</BackgroundPlate>
+		</div>
+
+		<div class="backPlateBox box7" v-if="mapshow">
+			<BackgroundPlate title="近6个月入住统计" :url="Backimg6">
+				<TheBox7 :box7_data="box7_data" v-if="box7_show" />
+			</BackgroundPlate>
+		</div>
+
+		<div class="backPlateBox box8" v-if="mapshow">
+			<BackgroundPlate title="业务统计" :url="Backimg5">
+				<TheBox8 :businessStatisticsDats="box8_data" v-if="box2_show" />
+			</BackgroundPlate>
+		</div>
+		<!--    <div class="backPlateBox mapbox" v-if="!mapshow">
       <ShowMap @dow_map="donw_mappop" :adres_value="adres_value"></ShowMap>
       <ShowMap @dow_map="donw_mappop" :adres_value="adres_value"></ShowMap>
     </div> -->
     </div> -->
-  </div>
+	</div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import BackgroundPlate from "@/components/BackgroundPlate/BackgroundPlate.vue";
-import TheBox1 from "./components/box1.vue";
-import TheBox1_2 from "./components/box1_2.vue";
-import TheBox2 from "./components/box2.vue";
-import TheBox3 from "./components/box3.vue";
-
-import EchartBox from "./components/echart_box.vue";
-import TheBox4 from "./components/box4.vue";
-import TheBox5 from "./components/box5.vue";
-import TheBox6 from "./components/box6.vue";
-import TheBox7 from "./components/box7.vue";
-import TheBox8 from "./components/box8.vue";
-import MapBox from "./components/map.vue";
-import AddressBox from "./components/addressbox.vue";
-import Backimg1 from "../../assets/img/index/index_bock_back1.png";
-import Backimg2 from "../../assets/img/index/index_bock_back2.png";
-import Backimg3 from "../../assets/img/index/index_bock_back3.png";
-import Backimg4 from "../../assets/img/index/index_bock_back4.png";
-import Backimg5 from "../../assets/img/index/index_bock_back5.png";
-import Backimg6 from "../../assets/img/index/index_bock_back6.png";
-import Backimg7 from "../../assets/img/index/index_bock_back7.png";
-import Backimg8 from "../../assets/img/index/index_bock_centerbottom.png";
-
-import { overviewStatisticsAPI } from "@/api/index/index.js";
-
-import { onMounted, defineProps, ref, nextTick } from "vue";
-import { useMechanismStore } from "@/store/index.js";
-const store = useMechanismStore();
-const mapshow = ref(true);
-const box1_data = ref({});
-const box2_data = ref({});
-const box3_data = ref({});
-const box6_data = ref({});
-const box7_data = ref({});
-const box8_data = ref({});
-const right_data = ref({});
-const box2_show = ref(false);
-const box3_show = ref(false);
-const box6_show = ref(false);
-const box7_show = ref(false);
-const box8_show = ref(false);
-const right_show = ref(false);
-
-
-const adres_value = ref({});
-const donw_mappop = (res) => {
-  if(res==1){
-    mapshow.value = 1;
-    box2_show.value = false 
-    overviewStatistics()
-  }else{
-     box2_show.value = false 
-    mapshow.value = 0;
-    console.log(res.elderlyTrendsYearBarChart)
-    box1_data.value=res.overviewSummary
-    box2_data.value=res.elderlyTrendsYearBarChart
-    // box3_data.value=res.diseaseType
-     setTimeout(() => {
-      box2_show.value = true 
-     }, 100);
-  }
-};
-
-onMounted(() => {
-  // GroupTenant();
-  store.setRoomDetail(false);
-  overviewStatistics();
-});
- 
-function overviewStatistics() {
-  let parmars = {};
-   parmars = {
-      queryFlag: 1,
-    };
-  // if (store.isRoomDetailpage) {
-  //   parmars = {
-  //     tenantIds: store.rooMdetialId,
-  //     queryFlag: 2,
-  //   };
-  // } else {
-  //   parmars = {
-  //     tenantIds: store.tentantId,
-  //     queryFlag: 1,
-  //   };
-  // }
-  overviewStatisticsAPI(parmars).then((res) => {
-    box1_data.value=res.data.overviewSummary
-    box2_data.value=res.data.elderlyTrendsYearBarChart
-    box3_data.value=res.data.diseaseType
-     box6_data.value=res.data
-     box7_data.value=res.data.elderlyTrendsMonthBarChart
-      box8_data.value=res.data.business
-    right_data.value=res.data.tenantList
-     box2_show.value = true 
-     box3_show.value = true 
-     box6_show.value = true 
-     box7_show.value = true 
-     box8_show.value = true 
-     right_show.value = true 
-  });
-}
-
-
-const box3_datalist = ref([1]);
-const box3_current = ref(0);
-
-function set_dataarr(event) {
-  box3_datalist.value = event;
-}
-function set_current(event) {
-  box3_current.value = event;
-}
-
-const set_adresinfo = (info) => {
-  if (!mapshow.value) {
-    mapshow.value = true;
-  }
-  adres_value.value = info;
-};
+	import BackgroundPlate from '@/components/BackgroundPlate/BackgroundPlate.vue';
+	import TheBox1 from './components/box1.vue';
+	import TheBox1_2 from './components/box1_2.vue';
+	import TheBox2 from './components/box2.vue';
+	import TheBox3 from './components/box3.vue';
+
+	import EchartBox from './components/echart_box.vue';
+	import TheBox4 from './components/box4.vue';
+	import TheBox5 from './components/box5.vue';
+	import TheBox6 from './components/box6.vue';
+	import TheBox7 from './components/box7.vue';
+	import TheBox8 from './components/box8.vue';
+	import MapBox from './components/map.vue';
+	import AddressBox from './components/addressbox.vue';
+	import Backimg1 from '../../assets/img/index/index_bock_back1.png';
+	import Backimg2 from '../../assets/img/index/index_bock_back2.png';
+	import Backimg3 from '../../assets/img/index/index_bock_back3.png';
+	import Backimg4 from '../../assets/img/index/index_bock_back4.png';
+	import Backimg5 from '../../assets/img/index/index_bock_back5.png';
+	import Backimg6 from '../../assets/img/index/index_bock_back6.png';
+	import Backimg7 from '../../assets/img/index/index_bock_back7.png';
+	import Backimg8 from '../../assets/img/index/index_bock_centerbottom.png';
+
+	import { overviewStatisticsAPI } from '@/api/index/index.js';
+
+	import { onMounted, defineProps, ref, nextTick } from 'vue';
+	import { useMechanismStore } from '@/store/index.js';
+
+	const store = useMechanismStore();
+	const mapshow = ref(true);
+	const box1_data = ref({});
+	const box2_data = ref({});
+	const box3_data = ref({});
+	const box6_data = ref({});
+	const box7_data = ref({});
+	const box8_data = ref({});
+	const right_data = ref({});
+	const box2_show = ref(false);
+	const box3_show = ref(false);
+	const box6_show = ref(false);
+	const box7_show = ref(false);
+	const box8_show = ref(false);
+	const right_show = ref(false);
+
+	const adres_value = ref({});
+	const donw_mappop = res => {
+		if (res == 1) {
+			mapshow.value = 1;
+			box2_show.value = false;
+			overviewStatistics();
+		} else {
+			box2_show.value = false;
+			mapshow.value = 0;
+			console.log(res.elderlyTrendsYearBarChart);
+			box1_data.value = res.overviewSummary;
+			box2_data.value = res.elderlyTrendsYearBarChart;
+			// box3_data.value=res.diseaseType
+			setTimeout(() => {
+				box2_show.value = true;
+			}, 100);
+		}
+	};
+
+	function overviewStatistics() {
+		let parmars = {};
+		parmars = {
+			queryFlag: 1
+		};
+		// if (store.isRoomDetailpage) {
+		//   parmars = {
+		//     tenantIds: store.rooMdetialId,
+		//     queryFlag: 2,
+		//   };
+		// } else {
+		//   parmars = {
+		//     tenantIds: store.tentantId,
+		//     queryFlag: 1,
+		//   };
+		// }
+		overviewStatisticsAPI(parmars).then(res => {
+			box1_data.value = res.data.overviewSummary;
+			box2_data.value = res.data.elderlyTrendsYearBarChart;
+			box3_data.value = res.data.diseaseType;
+			box6_data.value = res.data;
+			box7_data.value = res.data.elderlyTrendsMonthBarChart;
+			box8_data.value = res.data.business;
+			right_data.value = res.data.tenantList;
+			box2_show.value = true;
+			box3_show.value = true;
+			box6_show.value = true;
+			box7_show.value = true;
+			box8_show.value = true;
+			right_show.value = true;
+		});
+	}
+
+	const box3_datalist = ref([1]);
+	const box3_current = ref(0);
+
+	function set_dataarr(event) {
+		box3_datalist.value = event;
+	}
+	function set_current(event) {
+		box3_current.value = event;
+	}
+
+	const set_adresinfo = info => {
+		if (!mapshow.value) {
+			mapshow.value = true;
+		}
+		adres_value.value = info;
+	};
+
+	onMounted(() => {
+		// GroupTenant();
+		store.setRoomDetail(false);
+		overviewStatistics();
+	});
 </script>
 </script>
-
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-.index {
-  height: 100%;
-  width: 100%;
-  box-sizing: border-box;
-  position: relative;
-
-  .box-line {
-    width: 34px;
-    height: 100%;
-    overflow: hidden;
-    position: absolute;
-    top: 0;
-    .putImg {
-      // position: relative;
-      // width: 400px;
-      height: 100%;
-      // background: transparent url(.. /w32h9436steps7.png) no-repeat 0px 0px;
-      background: transparent url("../../assets/img/index/w32h9436steps7.png")
-        no-repeat 0px 0px;
-      -webkit-animation: cartoonRun 2s infinite steps(7, end);
-      -moz-animation: cartoonRun 2s infinite steps(7, end);
-      -ms-animation: cartoonRun 2s infinite steps(7, end);
-      animation: cartoonRun 2s infinite steps(7, end);
-    }
-
-    img {
-      width: 100%;
-      height: 100%;
-    }
-  }
-
-  .box-line-right {
-    right: 564px;
-  }
-  .box-line-left {
-    left: 564px;
-  }
-  .addressbox {
-    width: 400px;
-    height: 200px;
-    z-index: 1;
-    left: 590px;
-    border: 2px solid rgb(32, 128, 255);
-    background: rgba(26, 38, 53, 0.5);
-    border-radius: 5px;
-    filter: inherit(60px);
-    border-top-left-radius: 30px;
-    border-bottom-right-radius: 30px;
-    top: 420px;
-  }
-  .center_map {
-    width: 100%;
-    height: 100%;
-    top: -30px;
-  }
-  .mapbox {
-    top: 30px;
-    width: 740px;
-    height: 600px;
-    left: 590px;
-  }
-  .box1 {
-    width: 527px;
-    height: 208px;
-    top: 30px;
-    left: 25px;
-  }
-
-  .box2 {
-    width: 527px;
-    height: 319px;
-    top: 246px;
-    left: 25px;
-  }
-
-  .box3 {
-    width: 527px;
-    height: 290px;
-    top: 573px;
-    left: 25px;
-    .echarbox {
-      width: 100%;
-      height: 100%;
-    }
-  }
-
-  .box4 {
-    width: 358px;
-    height: 225px;
-    background-color: rgba(20, 31, 45, 0.8);
-    left: 594px;
-    bottom: 28px;
-  }
-  .right_router {
-    width: 1300px;
-    right: 25px;
-    top: 30px;
-  }
-
-  .box5 {
-    width: 358px;
-    height: 225px;
-    background-color: rgba(20, 31, 45, 0.8);
-    right: 594px;
-    bottom: 28px;
-  }
-
-  .box6 {
-    width: 527px;
-    height: 408px;
-    top: 462px;
-    right: 25px;
-  }
-
-  .box7 {
-    width: 527px;
-    height: 208px;
-    top: 246px;
-    right: 25px;
-  }
-
-  .box8 {
-    width: 527px;
-    height: 208px;
-    top: 30px;
-    right: 25px;
-  }
-
-  .boxwidthele {
-    width: 730px;
-    height: 225px;
-    left: 596px;
-    bottom: 28px;
-  }
-
-  @-webkit-keyframes cartoonRun {
-    0% {
-      background-position-y: 0px;
-    }
-
-    100% {
-      background-position-y: -9436px;
-    }
-  }
-
-  @-moz-keyframes cartoonRun {
-    0% {
-      background-position-y: 0px;
-    }
-
-    100% {
-      background-position-y: -9436px;
-    }
-  }
-
-  @-ms-keyframes cartoonRun {
-    0% {
-      background-position-y: 0px;
-    }
-
-    100% {
-      background-position-y: -9436px;
-    }
-  }
-
-  @keyframes cartoonRun {
-    0% {
-      background-position-y: 0px;
-    }
-
-    100% {
-      background-position-y: -9436px;
-    }
-  }
-
-  @-webkit-keyframes cartoonRunReverse {
-    0% {
-      background-position-y: -8088px;
-    }
-
-    100% {
-      background-position-y: 1348px;
-    }
-  }
-
-  @-moz-keyframes cartoonRunReverse {
-    0% {
-      background-position-y: -8088px;
-    }
-
-    100% {
-      background-position-y: 1348px;
-    }
-  }
-
-  @-ms-keyframes cartoonRunReverse {
-    0% {
-      background-position-y: -8088px;
-    }
-
-    100% {
-      background-position-y: 1348px;
-    }
-  }
-
-  @keyframes cartoonRunReverse {
-    0% {
-      background-position-y: -8088px;
-    }
-
-    100% {
-      background-position-y: 1348px;
-    }
-  }
-}
+	.index {
+		height: 100%;
+		width: 100%;
+		box-sizing: border-box;
+		position: relative;
+
+		.box-line {
+			width: 34px;
+			height: 100%;
+			overflow: hidden;
+			position: absolute;
+			top: 0;
+			.putImg {
+				// position: relative;
+				// width: 400px;
+				height: 100%;
+				// background: transparent url(.. /w32h9436steps7.png) no-repeat 0px 0px;
+				background: transparent url('../../assets/img/index/w32h9436steps7.png') no-repeat 0px 0px;
+				-webkit-animation: cartoonRun 2s infinite steps(7, end);
+				-moz-animation: cartoonRun 2s infinite steps(7, end);
+				-ms-animation: cartoonRun 2s infinite steps(7, end);
+				animation: cartoonRun 2s infinite steps(7, end);
+			}
+
+			img {
+				width: 100%;
+				height: 100%;
+			}
+		}
+
+		.box-line-right {
+			right: 564px;
+		}
+		.box-line-left {
+			left: 564px;
+		}
+		.addressbox {
+			width: 400px;
+			height: 200px;
+			z-index: 1;
+			left: 590px;
+			border: 2px solid rgb(32, 128, 255);
+			background: rgba(26, 38, 53, 0.5);
+			border-radius: 5px;
+			filter: inherit(60px);
+			border-top-left-radius: 30px;
+			border-bottom-right-radius: 30px;
+			top: 420px;
+		}
+		.center_map {
+			width: 100%;
+			height: 100%;
+			top: -30px;
+		}
+		.mapbox {
+			top: 30px;
+			width: 740px;
+			height: 600px;
+			left: 590px;
+		}
+		.box1 {
+			width: 527px;
+			height: 208px;
+			top: 30px;
+			left: 25px;
+		}
+
+		.box2 {
+			width: 527px;
+			height: 319px;
+			top: 246px;
+			left: 25px;
+		}
+
+		.box3 {
+			width: 527px;
+			height: 290px;
+			top: 573px;
+			left: 25px;
+			.echarbox {
+				width: 100%;
+				height: 100%;
+			}
+		}
+
+		.box4 {
+			width: 358px;
+			height: 225px;
+			background-color: rgba(20, 31, 45, 0.8);
+			left: 594px;
+			bottom: 28px;
+		}
+		.right_router {
+			width: 1300px;
+			right: 25px;
+			top: 30px;
+		}
+
+		.box5 {
+			width: 358px;
+			height: 225px;
+			background-color: rgba(20, 31, 45, 0.8);
+			right: 594px;
+			bottom: 28px;
+		}
+
+		.box6 {
+			width: 527px;
+			height: 408px;
+			top: 462px;
+			right: 25px;
+		}
+
+		.box7 {
+			width: 527px;
+			height: 208px;
+			top: 246px;
+			right: 25px;
+		}
+
+		.box8 {
+			width: 527px;
+			height: 208px;
+			top: 30px;
+			right: 25px;
+		}
+
+		.boxwidthele {
+			width: 730px;
+			height: 225px;
+			left: 596px;
+			bottom: 28px;
+		}
+
+		@-webkit-keyframes cartoonRun {
+			0% {
+				background-position-y: 0px;
+			}
+
+			100% {
+				background-position-y: -9436px;
+			}
+		}
+
+		@-moz-keyframes cartoonRun {
+			0% {
+				background-position-y: 0px;
+			}
+
+			100% {
+				background-position-y: -9436px;
+			}
+		}
+
+		@-ms-keyframes cartoonRun {
+			0% {
+				background-position-y: 0px;
+			}
+
+			100% {
+				background-position-y: -9436px;
+			}
+		}
+
+		@keyframes cartoonRun {
+			0% {
+				background-position-y: 0px;
+			}
+
+			100% {
+				background-position-y: -9436px;
+			}
+		}
+
+		@-webkit-keyframes cartoonRunReverse {
+			0% {
+				background-position-y: -8088px;
+			}
+
+			100% {
+				background-position-y: 1348px;
+			}
+		}
+
+		@-moz-keyframes cartoonRunReverse {
+			0% {
+				background-position-y: -8088px;
+			}
+
+			100% {
+				background-position-y: 1348px;
+			}
+		}
+
+		@-ms-keyframes cartoonRunReverse {
+			0% {
+				background-position-y: -8088px;
+			}
+
+			100% {
+				background-position-y: 1348px;
+			}
+		}
+
+		@keyframes cartoonRunReverse {
+			0% {
+				background-position-y: -8088px;
+			}
+
+			100% {
+				background-position-y: 1348px;
+			}
+		}
+	}
 </style>
 </style>

+ 9 - 1
src/views/index/roomdetail.vue

@@ -73,10 +73,11 @@
 	import ToadayActive from '../../assets/img/index/index_todayactive.png';
 	import ToadayActive from '../../assets/img/index/index_todayactive.png';
 	import ToastBack from '../../assets/img/index/index_detailtoast.png';
 	import ToastBack from '../../assets/img/index/index_detailtoast.png';
 	import { useRouter, useRoute } from 'vue-router';
 	import { useRouter, useRoute } from 'vue-router';
-	import { onMounted, ref, onBeforeUnmount, watch } from 'vue';
+	import { onMounted, ref, onBeforeUnmount, watch, inject } from 'vue';
 	import { useMechanismStore } from '@/store/index.js';
 	import { useMechanismStore } from '@/store/index.js';
 
 
 	import { getHomeInfoHomeData } from '@/api/index/index.js';
 	import { getHomeInfoHomeData } from '@/api/index/index.js';
+	import $bus from '@/utils/mitt.js';
 
 
 	const emit = defineEmits(['dow_map']);
 	const emit = defineEmits(['dow_map']);
 	const store = useMechanismStore();
 	const store = useMechanismStore();
@@ -112,6 +113,13 @@
 		store.tenantId = route.query.tenantId;
 		store.tenantId = route.query.tenantId;
 		tenantName.value = route.query.title;
 		tenantName.value = route.query.title;
 		get_homemestfun();
 		get_homemestfun();
+
+		$bus.on('roomDetails', data => {
+			console.log('监听全局emit预警事件data', data);
+			if (data) {
+				get_homemestfun();
+			}
+		});
 	});
 	});
 
 
 	const backpagefun = () => {
 	const backpagefun = () => {