From 87a971f080881598bc2380d5f72252be88ab8982 Mon Sep 17 00:00:00 2001
From: zhangchen <1652267879@qq.com>
Date: 星期二, 08 七月 2025 17:39:08 +0800
Subject: [PATCH] ID1825-设备号弹窗修改完成

---
 src/views/mobile/bedsideAuxiliaryScreen/components/UnplannedSchedule.vue   |    5 
 package-lock.json                                                          |  229 +++++++++++++++++
 src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue              |   21 +
 src/store/bedsideAuxiliaryScreen.ts                                        |   73 +++++
 src/main.ts                                                                |    5 
 vite.config.ts                                                             |    2 
 src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue |  317 ++++++++++++++++++++++++
 tsconfig.json                                                              |    1 
 package.json                                                               |    1 
 src/img/upload.png                                                         |    0 
 src/views/mobile/bedsideAuxiliaryScreen/index.vue                          |    3 
 postcss.config.js                                                          |    3 
 src/utils/cache.ts                                                         |   69 +++++
 src/img/close.png                                                          |    0 
 14 files changed, 722 insertions(+), 7 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 35c566b..5383b81 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
         "echarts": "^5.6.0",
         "element-plus": "^2.9.2",
         "event-source-polyfill": "^1.0.31",
+        "pinia": "^3.0.3",
         "qs": "^6.14.0",
         "speak-tts": "^2.0.8",
         "vant": "^3.4.3",
@@ -1013,6 +1014,30 @@
       "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
       "license": "MIT"
     },
+    "node_modules/@vue/devtools-kit": {
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz",
+      "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-shared": "^7.7.7",
+        "birpc": "^2.3.0",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.2"
+      }
+    },
+    "node_modules/@vue/devtools-shared": {
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz",
+      "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==",
+      "license": "MIT",
+      "dependencies": {
+        "rfdc": "^1.4.1"
+      }
+    },
     "node_modules/@vue/language-core": {
       "version": "2.2.0",
       "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.0.tgz",
@@ -1266,6 +1291,15 @@
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
       "dev": true
+    },
+    "node_modules/birpc": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.4.0.tgz",
+      "integrity": "sha512-5IdNxTyhXHv2UlgnPHQ0h+5ypVmkrYHzL8QT+DwFZ//2N/oNV8Ch+BCRmTJ3x6/z9Axo/cXYBc9eprsUVK/Jsg==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
     },
     "node_modules/brace-expansion": {
       "version": "2.0.1",
@@ -1737,6 +1771,12 @@
         "he": "bin/he"
       }
     },
+    "node_modules/hookable": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+      "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+      "license": "MIT"
+    },
     "node_modules/iconv-lite": {
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -1919,6 +1959,12 @@
       "funding": {
         "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==",
+      "license": "MIT"
     },
     "node_modules/muggle-string": {
       "version": "0.4.1",
@@ -4674,6 +4720,12 @@
       "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
       "dev": true
     },
+    "node_modules/perfect-debounce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+      "license": "MIT"
+    },
     "node_modules/picocolors": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@@ -4688,6 +4740,36 @@
       "optional": true,
       "engines": {
         "node": ">=6"
+      }
+    },
+    "node_modules/pinia": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz",
+      "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^7.7.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.4.4",
+        "vue": "^2.7.0 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia/node_modules/@vue/devtools-api": {
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
+      "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-kit": "^7.7.7"
       }
     },
     "node_modules/postcss": {
@@ -4755,6 +4837,12 @@
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
+    },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "license": "MIT"
     },
     "node_modules/rollup": {
       "version": "4.30.1",
@@ -4930,6 +5018,54 @@
       "resolved": "https://registry.npmmirror.com/speak-tts/-/speak-tts-2.0.8.tgz",
       "integrity": "sha512-VY6Q6mRjdou6bF+x0LspvM7GJhBxHx8CLyGPTNQQ7jrztiGutyI4QNZn0cA17c4uk0FnFbA4PaMI3skeZ6PiFg==",
       "license": "MIT"
+    },
+    "node_modules/speakingurl": {
+      "version": "14.0.1",
+      "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+      "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/superjson": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
+      "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+      "license": "MIT",
+      "dependencies": {
+        "copy-anything": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/superjson/node_modules/copy-anything": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
+      "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+      "license": "MIT",
+      "dependencies": {
+        "is-what": "^4.1.8"
+      },
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/superjson/node_modules/is-what": {
+      "version": "4.1.16",
+      "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
+      "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
     },
     "node_modules/terser": {
       "version": "5.43.1",
@@ -5721,6 +5857,28 @@
       "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
       "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
     },
+    "@vue/devtools-kit": {
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz",
+      "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==",
+      "requires": {
+        "@vue/devtools-shared": "^7.7.7",
+        "birpc": "^2.3.0",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.2"
+      }
+    },
+    "@vue/devtools-shared": {
+      "version": "7.7.7",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz",
+      "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==",
+      "requires": {
+        "rfdc": "^1.4.1"
+      }
+    },
     "@vue/language-core": {
       "version": "2.2.0",
       "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.0.tgz",
@@ -5886,6 +6044,11 @@
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
       "dev": true
+    },
+    "birpc": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.4.0.tgz",
+      "integrity": "sha512-5IdNxTyhXHv2UlgnPHQ0h+5ypVmkrYHzL8QT+DwFZ//2N/oNV8Ch+BCRmTJ3x6/z9Axo/cXYBc9eprsUVK/Jsg=="
     },
     "brace-expansion": {
       "version": "2.0.1",
@@ -6204,6 +6367,11 @@
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
+    "hookable": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+      "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
+    },
     "iconv-lite": {
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -6324,6 +6492,11 @@
       "requires": {
         "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=="
     },
     "muggle-string": {
       "version": "0.4.1",
@@ -8146,6 +8319,11 @@
       "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
       "dev": true
     },
+    "perfect-debounce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
+    },
     "picocolors": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@@ -8157,6 +8335,24 @@
       "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
       "dev": true,
       "optional": true
+    },
+    "pinia": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz",
+      "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
+      "requires": {
+        "@vue/devtools-api": "^7.7.2"
+      },
+      "dependencies": {
+        "@vue/devtools-api": {
+          "version": "7.7.7",
+          "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
+          "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==",
+          "requires": {
+            "@vue/devtools-kit": "^7.7.7"
+          }
+        }
+      }
     },
     "postcss": {
       "version": "8.4.49",
@@ -8194,6 +8390,11 @@
       "requires": {
         "side-channel": "^1.1.0"
       }
+    },
+    "rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
     },
     "rollup": {
       "version": "4.30.1",
@@ -8318,6 +8519,34 @@
       "resolved": "https://registry.npmmirror.com/speak-tts/-/speak-tts-2.0.8.tgz",
       "integrity": "sha512-VY6Q6mRjdou6bF+x0LspvM7GJhBxHx8CLyGPTNQQ7jrztiGutyI4QNZn0cA17c4uk0FnFbA4PaMI3skeZ6PiFg=="
     },
+    "speakingurl": {
+      "version": "14.0.1",
+      "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+      "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="
+    },
+    "superjson": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
+      "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+      "requires": {
+        "copy-anything": "^3.0.2"
+      },
+      "dependencies": {
+        "copy-anything": {
+          "version": "3.0.5",
+          "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
+          "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+          "requires": {
+            "is-what": "^4.1.8"
+          }
+        },
+        "is-what": {
+          "version": "4.1.16",
+          "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
+          "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="
+        }
+      }
+    },
     "terser": {
       "version": "5.43.1",
       "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
diff --git a/package.json b/package.json
index f6bb524..9eab2a0 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
     "echarts": "^5.6.0",
     "element-plus": "^2.9.2",
     "event-source-polyfill": "^1.0.31",
+    "pinia": "^3.0.3",
     "qs": "^6.14.0",
     "speak-tts": "^2.0.8",
     "vant": "^3.4.3",
diff --git a/postcss.config.js b/postcss.config.js
index 3b8ce2d..b493b9a 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -18,7 +18,8 @@
           return true;
         }
         return false;
-      }
+      },
+      minPixelValue: 2,
     }
   }
 }
diff --git a/src/img/close.png b/src/img/close.png
new file mode 100644
index 0000000..65a365d
--- /dev/null
+++ b/src/img/close.png
Binary files differ
diff --git a/src/img/upload.png b/src/img/upload.png
new file mode 100644
index 0000000..4a2b5b8
--- /dev/null
+++ b/src/img/upload.png
Binary files differ
diff --git a/src/main.ts b/src/main.ts
index 960ccbc..9147bbe 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -8,11 +8,12 @@
 import router from './router';
 import App from './App.vue'
 import VConsole from 'vconsole'
+import { createPinia } from 'pinia'
 
 if (import.meta.env.VITE_ENV === 'development') {
 // 如果需要在手机平板上打开控制台,安装一个这个
     const vConsole = new VConsole()
 }
+const pinia = createPinia()
 
-
-createApp(App).use(router).use(ElementPlus).use(Vant).mount('#app')
+createApp(App).use(router).use(pinia).use(ElementPlus).use(Vant).mount('#app')
diff --git a/src/store/bedsideAuxiliaryScreen.ts b/src/store/bedsideAuxiliaryScreen.ts
new file mode 100644
index 0000000..5dbdc80
--- /dev/null
+++ b/src/store/bedsideAuxiliaryScreen.ts
@@ -0,0 +1,73 @@
+import { defineStore } from "pinia";
+import { ref } from "vue";
+import cache from "../utils/cache";
+import { EventSourcePolyfill } from "event-source-polyfill";
+
+export const useBedsideAuxiliaryScreenStore = defineStore(
+  "bedsideAuxiliaryScreen",
+  () => {
+    const deviceCode = ref<string>(cache.get("devcieCode") || ""); // 设备编号
+
+    /**
+     * 设置设备编号
+     * @param code
+     */
+    const setDeviceCode = (code: string) => {
+      deviceCode.value = code;
+      cache.set("devcieCode", code);
+    };
+
+    // SSE 相关状态
+    const source = ref<EventSource | null>(null);
+    const message = ref<string | null>(null);
+    const isConnected = ref(false);
+
+    /**
+     * 连接 SSE 服务
+     * @param url SSE 地址
+     */
+    const connect = (url: string) => {
+      if (source.value) return; // 已连接,避免重复连接
+
+      source.value = new EventSourcePolyfill(url, {
+        heartbeatTimeout: 60000,
+      });
+
+      source.value.onopen = () => {
+        console.log("[SSE] 连接成功");
+        isConnected.value = true;
+      };
+
+      source.value.onerror = (e) => {
+        console.warn("[SSE] 错误,等待重连中", e);
+        isConnected.value = false;
+      };
+
+      source.value.onmessage = (e) => {
+        console.log("[SSE] 消息:", e.data);
+        message.value = e.data;
+      };
+    };
+
+    /**
+     * 关闭 SSE 连接
+     */
+    const close = () => {
+      if (source.value) {
+        source.value.close();
+        source.value = null;
+        isConnected.value = false;
+        console.log("[SSE] 连接已关闭");
+      }
+    };
+    return {
+      deviceCode,
+      setDeviceCode,
+      source,
+      message,
+      isConnected,
+      connect,
+      close
+    };
+  }
+);
diff --git a/src/utils/cache.ts b/src/utils/cache.ts
new file mode 100644
index 0000000..d351a77
--- /dev/null
+++ b/src/utils/cache.ts
@@ -0,0 +1,69 @@
+class Cache {
+  /**
+   * 设置本地缓存
+   * @param key 键名
+   * @param value 值(会自动序列化为 JSON)
+   */
+  set<T = any>(key: string, value: T): void {
+    try {
+      const json = JSON.stringify(value)
+      localStorage.setItem(key, json)
+    } catch (e) {
+      console.error(`缓存写入失败(${key}):`, e)
+    }
+  }
+
+  /**
+   * 获取本地缓存
+   * @param key 键名
+   * @returns 反序列化后的值,失败返回 null
+   */
+  get<T = any>(key: string): T | null {
+    try {
+      const json = localStorage.getItem(key)
+      return json ? JSON.parse(json) as T : null
+    } catch (e) {
+      console.error(`缓存读取失败(${key}):`, e)
+      return null
+    }
+  }
+
+  /**
+   * 删除指定缓存项
+   * @param key 键名
+   */
+  delete(key: string): void {
+    try {
+      localStorage.removeItem(key)
+    } catch (e) {
+      console.error(`缓存删除失败(${key}):`, e)
+    }
+  }
+
+  /**
+   * 判断某项缓存是否存在
+   * @param key 键名
+   * @returns 是否存在
+   */
+  has(key: string): boolean {
+    try {
+      return localStorage.getItem(key) !== null
+    } catch (e) {
+      console.error(`缓存判断失败(${key}):`, e)
+      return false
+    }
+  }
+
+  /**
+   * 清空所有本地缓存
+   */
+  clear(): void {
+    try {
+      localStorage.clear()
+    } catch (e) {
+      console.error('缓存清空失败:', e)
+    }
+  }
+}
+
+export default new Cache()
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
index 5f2b8f3..9b08031 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
@@ -19,14 +19,24 @@
     </div>
     <div class="header-right">
       <img :src="atRegularTimeImg" class="btn-img" alt="" />
-      <img :src="setUpImg" class="btn-img" alt="" />
+      <img
+        :src="setUpImg"
+        class="btn-img"
+        alt=""
+        @click="openSettingDeviceDialog"
+      />
       <img :src="userImg" class="btn-img" alt="" />
     </div>
   </div>
+  <!-- 设置设备编号组件 -->
+  <SettingDeviceDialog ref="settingDeviceDialogRef" />
 </template>
 
 <script lang="ts" setup name="Header">
-import { computed } from "vue";
+import { ref, computed, defineAsyncComponent } from "vue";
+const SettingDeviceDialog = defineAsyncComponent(
+  () => import("./SettingDeviceDialog.vue")
+);
 import atRegularTimeImg from "../../../../img/dingshi.png";
 import setUpImg from "../../../../img/shezhi.png";
 import userImg from "../../../../img/user.png";
@@ -45,6 +55,8 @@
 }
 const props = defineProps<Props>();
 
+const settingDeviceDialogRef = ref<any>(null);
+
 const formTypeNoText = computed(() => {
   if (props.formNo) {
     let result = props?.formType === 1 ? "住院号" : "门诊号";
@@ -53,11 +65,14 @@
   }
   return "";
 });
+
+const openSettingDeviceDialog = () => {
+  settingDeviceDialogRef.value?.openDialog();
+};
 </script>
 
 <style lang="less" scoped>
 .bedside-auxiliary-screen-header {
-  width: 100%;
   height: 25px;
   padding: 0 15px 0 12px;
   display: flex;
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue
new file mode 100644
index 0000000..9d0a1cb
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue
@@ -0,0 +1,317 @@
+<template>
+  <div class="setting-device-dialog-container">
+    <el-dialog
+      v-model="isShow"
+      center
+      title="设置编号"
+      width="80%"
+      :show-close="false"
+    >
+      <template #header>
+        <div class="setting-dialog-header">
+          <span class="header-title">设置编号</span>
+          <img
+            :src="closeImg"
+            class="header-close"
+            @click="handleCancel"
+            alt=""
+          />
+        </div>
+      </template>
+      <div class="setting-device-dialog-content">
+        <div class="content-row1">
+          <div class="row1-label">设备编号</div>
+          <div class="row1-inp-box">
+            <input
+              v-model="devcieCode"
+              type="text"
+              class="row1-inp"
+              placeholder="请输入设备编号或扫码二维码"
+            />
+          </div>
+        </div>
+        <div class="content-row2">
+          <el-upload
+            v-loading="isUploading"
+            class="upload-demo"
+            drag
+            :show-file-list="false"
+            accept="image/*"
+            :limit="1"
+            :before-upload="onBeforeUpload"
+          >
+            <div class="el-upload__text">
+              <img :src="uploadImg" class="upload-img" alt="" />
+              <p class="upload-text">点击虚线区域选择文件并识别二维码</p>
+              <div class="upload-btn">二维码上传</div>
+            </div>
+          </el-upload>
+        </div>
+      </div>
+      <template #footer>
+        <div class="my-button cancel" @click="handleCancel">取消</div>
+        <div class="my-button confirm" @click="handleConfirm">确认</div>
+        <div class="my-button refresh" @click="handleRefresh">刷新</div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ElMessage, UploadRawFile } from "element-plus";
+import { ref } from "vue";
+import {
+  BrowserMultiFormatReader,
+  NotFoundException,
+  ChecksumException,
+  FormatException,
+} from "@zxing/library";
+import closeImg from "@/img/close.png";
+import uploadImg from "@/img/upload.png";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+const isShow = ref(false);
+const isUploading = ref(false);
+const devcieCode = ref("");
+
+const openDialog = () => {
+  devcieCode.value = bedsideAuxiliaryScreenStore.deviceCode + "";
+  isShow.value = true;
+};
+
+const onBeforeUpload = async (uploadFile: UploadRawFile) => {
+  const file = uploadFile;
+  if (!file) return;
+
+  isUploading.value = true;
+  try {
+    const result = await decodeQRCodeFromFile(file);
+    devcieCode.value = result;
+    ElMessage.success("识别成功");
+  } catch (err) {
+    if (err instanceof NotFoundException) {
+      ElMessage.error("未找到二维码");
+    } else if (err instanceof ChecksumException) {
+      ElMessage.error("校验错误");
+    } else if (err instanceof FormatException) {
+      ElMessage.error("格式错误");
+    } else {
+      ElMessage.error("识别错误请重新识别");
+      console.error(err);
+    }
+  } finally {
+    isUploading.value = false;
+  }
+  return false;
+};
+
+const decodeQRCodeFromFile = async (file: File): Promise<string> => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+
+    reader.onload = async (e: any) => {
+      const imageBase64 = e.target.result;
+      const codeReader = new BrowserMultiFormatReader();
+
+      try {
+        const result = await codeReader.decodeFromImage(undefined, imageBase64);
+        resolve(result.getText());
+      } catch (err) {
+        reject(err);
+      }
+    };
+
+    reader.onerror = () => reject(new Error("读取文件失败"));
+    reader.readAsDataURL(file);
+  });
+};
+
+const handleCancel = () => {
+  isShow.value = false;
+};
+
+const handleConfirm = () => {
+  bedsideAuxiliaryScreenStore.setDeviceCode(devcieCode.value + "");
+  handleCancel();
+};
+
+const handleRefresh = () => {};
+
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style lang="less" scoped>
+.setting-device-dialog-container {
+  ::v-deep(.el-dialog) {
+    padding: 0;
+    border-radius: 6px;
+    overflow: hidden;
+  }
+  ::v-deep(.el-dialog__footer) {
+    padding: 4px;
+  }
+  ::v-deep(.el-upload-dragger) {
+    height: 65px;
+    padding: 0 !important;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  ::v-deep(.el-upload-dragger .el-icon--upload) {
+    display: none;
+  }
+  ::v-deep(.el-dialog__header) {
+    padding-bottom: 6px;
+  }
+  .setting-dialog-header {
+    position: relative;
+    height: 16px;
+    background: #769aff;
+    .header-title {
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translateX(-50%) translateY(-50%);
+      font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
+      font-weight: 500;
+      font-size: 8px;
+      color: #ffffff;
+      line-height: 11px;
+      text-align: center;
+    }
+    .header-close {
+      position: absolute;
+      top: 50%;
+      transform: translateY(-50%);
+      right: 6px;
+      width: 15px;
+      height: 15px;
+      transition: transform 0.2s;
+
+      &:active {
+        opacity: 0.6;
+        transform: translateY(-50%) scale(0.95);
+      }
+    }
+  }
+  .setting-device-dialog-content {
+    padding: 0 12px 6px;
+    margin-bottom: 4px;
+    border-bottom: 1px solid #d8d8d8;
+    .content-row1 {
+      display: flex;
+      align-items: center;
+      margin-bottom: 6px;
+
+      .row1-label {
+        margin-right: 6px;
+        padding: 0 4px;
+        background: #769aff;
+        border-radius: 2px;
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 600;
+        font-size: 8px;
+        line-height: 16px;
+        color: #ffffff;
+        font-style: normal;
+      }
+      .row1-inp-box {
+        flex: 1;
+        height: 16px;
+        border-radius: 2px;
+        border: 1px solid #979797;
+        overflow: hidden;
+
+        .row1-inp {
+          width: 100%;
+          height: 100%;
+          border: none;
+          outline: none;
+          padding: 0 4px; // 给一点水平 padding 更美观
+          line-height: 16px;
+          font-size: 9px;
+          font-family: PingFangSC, PingFang SC;
+          vertical-align: middle; // ✅ 关键设置
+          box-sizing: border-box; // 避免padding撑高
+
+          &::placeholder {
+            font-family: inherit;
+            font-size: inherit;
+            line-height: inherit;
+            color: #aaaaaa;
+            opacity: 1;
+          }
+        }
+      }
+    }
+
+    .el-upload__text {
+      display: flex;
+      align-items: center;
+      flex-direction: column;
+      justify-content: center;
+      .upload-img {
+        height: 8px;
+      }
+      .upload-text {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 500;
+        font-size: 5px;
+        color: #5a6470;
+        letter-spacing: 0px;
+        text-align: center;
+        font-style: normal;
+      }
+      .upload-btn {
+        padding: 0 2px;
+        background-color: #409eff;
+        border-radius: 1px;
+        font-family: PingFangSC, PingFang SC;
+        font-size: 4px;
+        color: #fff;
+        letter-spacing: 0px;
+        line-height: 8px;
+        text-align: center;
+        font-style: normal;
+      }
+    }
+  }
+
+  .my-button {
+    display: inline-block;
+    border-radius: 2px;
+    padding: 0px 10px;
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 500;
+    font-size: 7px;
+    color: #ffffff;
+    line-height: 16px;
+    letter-spacing: 1px;
+    text-align: center;
+    font-style: normal;
+    transition: transform 0.1s ease, opacity 0.1s ease;
+    cursor: pointer;
+    &:active {
+      transform: scale(0.95);
+      opacity: 0.8;
+    }
+
+    &:not(:first-child) {
+      margin-left: 6px;
+    }
+    &.cancel {
+      background: #bbc6dd;
+    }
+    &.confirm {
+      background: #769aff;
+    }
+    &.refresh {
+      background: #e6a23c;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/UnplannedSchedule.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/UnplannedSchedule.vue
index 5569c00..52d92bd 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/UnplannedSchedule.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/UnplannedSchedule.vue
@@ -3,6 +3,11 @@
 </template>
 
 <script lang="ts" setup name="UnplannedSchedule">
+interface Props {
+    height: number;
+}
+const props = defineProps<Props>();
+
 // @ts-ignore
 import Card from './Card.vue';
 </script>
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/index.vue
index f098537..54417c7 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/index.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/index.vue
@@ -6,8 +6,11 @@
 </template>
 
 <script lang="ts" setup>
+import { defineAsyncComponent } from 'vue';
 // @ts-ignore
 import Header from './components/Header.vue';
+
+
 </script>
 
 <style lang="less" scoped>
diff --git a/tsconfig.json b/tsconfig.json
index cb5a989..3fb0cf2 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,6 +5,7 @@
     "moduleResolution": "node",
     "baseUrl": ".",
     "paths": {
+      "@/*": ["src/*"],
       "*": ["node_modules/*", "src/types/*"]
     },
     "esModuleInterop": true,
diff --git a/vite.config.ts b/vite.config.ts
index 08b537c..144989a 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -14,7 +14,7 @@
   },
   resolve: {
     alias: {
-      '@': '/src'
+      '@': path.resolve(__dirname, 'src')
     }
   }
 });
\ No newline at end of file

--
Gitblit v1.8.0