From 64aaf44b6b2948631ebd0d9840d51e5e31ae5479 Mon Sep 17 00:00:00 2001
From: zhangchen <1652267879@qq.com>
Date: 星期五, 25 七月 2025 01:44:25 +0800
Subject: [PATCH] Merge branch 'ID1825-床旁副屏改版' into test

---
 src/views/mobile/bedsideAuxiliaryScreen/pages/NotSignedIn.vue              |  320 +++
 src/views/mobile/bedsideAuxiliaryScreen/components/BlockBotttom.vue        |   48 
 package-lock.json                                                          |  266 ++
 src/views/mobile/bedsideAuxiliaryScreen/components/Card.vue                |   87 
 vite.config.ts                                                             |    6 
 src/views/mobile/bedsideAuxiliaryScreen/components/ProgressBar.vue         |   45 
 src/utils/utils.ts                                                         |   31 
 src/views/registerSuu/index.vue                                            |    3 
 src/img/xinlv2.png                                                         |    0 
 src/img/yizhu.png                                                          |    0 
 src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue                 |  441 ++++
 src/img/upload.png                                                         |    0 
 src/router/index.ts                                                        |   10 
 src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/index.vue  |  184 ++
 src/views/mobile/bedsideAuxiliaryScreen/index.vue                          |   93 +
 src/composables/useWindowSize.ts                                           |   21 
 src/img/close.png                                                          |    0 
 src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue              |  211 ++
 src/store/type/task.type.ts                                                |   12 
 src/img/user.png                                                           |    0 
 src/store/bedsideAuxiliaryScreen.ts                                        |  193 ++
 src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue           |  981 +++++++++++
 src/img/add.png                                                            |    0 
 src/main.ts                                                                |    6 
 src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/type.ts    |  375 ++++
 src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue |  330 +++
 src/views/mobile/bedsideAuxiliaryScreen/pages/UnplannedSchedule.vue        |  238 ++
 tsconfig.json                                                              |    1 
 src/store/type/bedsideAuxiliaryScreen.type.ts                              |  593 ++++++
 src/style.css                                                              |   49 
 package.json                                                               |    5 
 src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue       |  438 ++++
 src/views/register/index.vue                                               |    5 
 src/img/dingshi2.png                                                       |    0 
 src/img/jiaoHao.png                                                        |    0 
 postcss.config.js                                                          |   25 
 src/img/kaiShi.png                                                         |    0 
 src/utils/cache.ts                                                         |   69 
 src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue          |  248 ++
 39 files changed, 5,276 insertions(+), 58 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 514fea6..da5de25 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,9 +11,11 @@
         "@vant/icons": "^3.0.2",
         "@zxing/library": "^0.21.3",
         "axios": "^1.9.0",
+        "dayjs": "^1.11.13",
         "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",
@@ -25,9 +27,11 @@
         "@vitejs/plugin-vue": "^5.2.1",
         "@vue/compiler-sfc": "^3.5.13",
         "@vue/tsconfig": "^0.7.0",
+        "amfe-flexible": "^2.2.1",
         "install": "^0.13.0",
         "less": "^4.2.1",
         "npm": "^11.4.2",
+        "postcss-pxtorem": "^6.1.0",
         "typescript": "~5.6.2",
         "vite": "^6.0.5",
         "vue-tsc": "^2.2.0"
@@ -1011,6 +1015,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",
@@ -1229,6 +1257,13 @@
       "integrity": "sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==",
       "dev": true
     },
+    "node_modules/amfe-flexible": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/amfe-flexible/-/amfe-flexible-2.2.1.tgz",
+      "integrity": "sha512-L2VfvDzoETBjhRptg5u/IUuzHSuxm22JpSRb404p/TBGeRfwWmmNEbB+TFPIP/sS/+pbM18bCFH9QnMojLuPNw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/async-validator": {
       "version": "4.2.5",
       "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
@@ -1257,6 +1292,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",
@@ -1369,7 +1413,7 @@
     },
     "node_modules/dayjs": {
       "version": "1.11.13",
-      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
       "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
       "license": "MIT"
     },
@@ -1728,6 +1772,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",
@@ -1910,6 +1960,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",
@@ -4665,6 +4721,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",
@@ -4679,6 +4741,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": {
@@ -4706,6 +4798,16 @@
       },
       "engines": {
         "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/postcss-pxtorem": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-pxtorem/-/postcss-pxtorem-6.1.0.tgz",
+      "integrity": "sha512-ROODSNci9ADal3zUcPHOF/K83TiCgNSPXQFSbwyPHNV8ioHIE4SaC+FPOufd8jsr5jV2uIz29v1Uqy1c4ov42g==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "postcss": "^8.0.0"
       }
     },
     "node_modules/proxy-from-env": {
@@ -4736,6 +4838,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",
@@ -4911,6 +5019,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",
@@ -5702,6 +5858,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",
@@ -5836,6 +6014,12 @@
       "integrity": "sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==",
       "dev": true
     },
+    "amfe-flexible": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/amfe-flexible/-/amfe-flexible-2.2.1.tgz",
+      "integrity": "sha512-L2VfvDzoETBjhRptg5u/IUuzHSuxm22JpSRb404p/TBGeRfwWmmNEbB+TFPIP/sS/+pbM18bCFH9QnMojLuPNw==",
+      "dev": true
+    },
     "async-validator": {
       "version": "4.2.5",
       "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
@@ -5861,6 +6045,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",
@@ -5939,7 +6128,7 @@
     },
     "dayjs": {
       "version": "1.11.13",
-      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
       "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
     },
     "de-indent": {
@@ -6179,6 +6368,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",
@@ -6299,6 +6493,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",
@@ -8121,6 +8320,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",
@@ -8133,6 +8337,24 @@
       "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",
       "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.49.tgz",
@@ -8142,6 +8364,13 @@
         "picocolors": "^1.1.1",
         "source-map-js": "^1.2.1"
       }
+    },
+    "postcss-pxtorem": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-pxtorem/-/postcss-pxtorem-6.1.0.tgz",
+      "integrity": "sha512-ROODSNci9ADal3zUcPHOF/K83TiCgNSPXQFSbwyPHNV8ioHIE4SaC+FPOufd8jsr5jV2uIz29v1Uqy1c4ov42g==",
+      "dev": true,
+      "requires": {}
     },
     "proxy-from-env": {
       "version": "1.1.0",
@@ -8162,6 +8391,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",
@@ -8286,6 +8520,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 cd23980..a432161 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,6 @@
   "name": "my-project",
   "private": true,
   "version": "0.0.0",
-  "type": "module",
   "scripts": {
     "dev": "vite",
     "dev:prod": "vite --mode production",
@@ -16,9 +15,11 @@
     "@vant/icons": "^3.0.2",
     "@zxing/library": "^0.21.3",
     "axios": "^1.9.0",
+    "dayjs": "^1.11.13",
     "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",
@@ -30,9 +31,11 @@
     "@vitejs/plugin-vue": "^5.2.1",
     "@vue/compiler-sfc": "^3.5.13",
     "@vue/tsconfig": "^0.7.0",
+    "amfe-flexible": "^2.2.1",
     "install": "^0.13.0",
     "less": "^4.2.1",
     "npm": "^11.4.2",
+    "postcss-pxtorem": "^6.1.0",
     "typescript": "~5.6.2",
     "vite": "^6.0.5",
     "vue-tsc": "^2.2.0"
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..86ee644
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,25 @@
+module.exports = {
+  plugins: {
+    'postcss-pxtorem': {
+      rootValue: 37.5,
+      propList: ['*'],
+      // include: file => {
+      //   if (!file) return false;
+      //   const normalized = file.replace(/\\/g, '/');
+      //   // 只转换 mobile 目录里的样式 OR element-plus 目录里的样式
+      //   // 但 element-plus 样式只在 mobile 目录被引用时才生效,需保证引用范围
+      //   return normalized.includes('/src/views/mobile/') || normalized.includes('/node_modules/element-plus/');
+      // },
+      // exclude: file => {
+      //   if (!file) return false;
+      //   const normalized = file.replace(/\\/g, '/');
+      //   // 排除除 element-plus 外的 node_modules,防止无关样式被转
+      //   if (/node_modules/.test(normalized) && !normalized.includes('/node_modules/element-plus/')) {
+      //     return true;
+      //   }
+      //   return false;
+      // },
+      minPixelValue: 2,
+    }
+  }
+}
diff --git a/src/composables/useWindowSize.ts b/src/composables/useWindowSize.ts
new file mode 100644
index 0000000..87a4238
--- /dev/null
+++ b/src/composables/useWindowSize.ts
@@ -0,0 +1,21 @@
+import { ref, onMounted, onUnmounted } from 'vue';
+
+export function useWindowSize() {
+  const width = ref(window.innerWidth);
+  const height = ref(window.innerHeight);
+
+  const updateSize = () => {
+    width.value = window.innerWidth;
+    height.value = window.innerHeight;
+  };
+
+  onMounted(() => {
+    window.addEventListener('resize', updateSize);
+  });
+
+  onUnmounted(() => {
+    window.removeEventListener('resize', updateSize);
+  });
+
+  return { width, height };
+}
diff --git a/src/img/add.png b/src/img/add.png
new file mode 100644
index 0000000..f3fcd48
--- /dev/null
+++ b/src/img/add.png
Binary files differ
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/dingshi2.png b/src/img/dingshi2.png
new file mode 100644
index 0000000..cd22f8f
--- /dev/null
+++ b/src/img/dingshi2.png
Binary files differ
diff --git a/src/img/jiaoHao.png b/src/img/jiaoHao.png
new file mode 100644
index 0000000..7df51ec
--- /dev/null
+++ b/src/img/jiaoHao.png
Binary files differ
diff --git a/src/img/kaiShi.png b/src/img/kaiShi.png
new file mode 100644
index 0000000..fe1e4c2
--- /dev/null
+++ b/src/img/kaiShi.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/img/user.png b/src/img/user.png
new file mode 100644
index 0000000..c1d05d5
--- /dev/null
+++ b/src/img/user.png
Binary files differ
diff --git a/src/img/xinlv2.png b/src/img/xinlv2.png
new file mode 100644
index 0000000..75e1f92
--- /dev/null
+++ b/src/img/xinlv2.png
Binary files differ
diff --git a/src/img/yizhu.png b/src/img/yizhu.png
new file mode 100644
index 0000000..8a880d2
--- /dev/null
+++ b/src/img/yizhu.png
Binary files differ
diff --git a/src/main.ts b/src/main.ts
index 9a03e28..9147bbe 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,3 +1,4 @@
+import 'amfe-flexible';
 import { createApp } from 'vue'
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'   
@@ -7,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/router/index.ts b/src/router/index.ts
index e4a8204..9fbbaad 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -1,17 +1,23 @@
 // router/index.ts
 import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
-import Home from '../views/Home.vue'; // 假设这是你的主页组件
-import deviceWindows from '../views/deviceWindows.vue'
+// import Home from '../views/Home.vue'; // 假设这是你的主页组件
+// import deviceWindows from '../views/deviceWindows.vue'
 import deviceWindows2 from '../views/deviceWindoes2.vue'
 import test from '../views/test.vue'; // 搜索结果页,接收查询参数
 import registerForNutrition from '../views/register/index.vue'
 import registerSuu from '../views/registerSuu/index.vue'
+import bedsideAuxiliaryScreen from '../views/mobile/bedsideAuxiliaryScreen/index.vue';
 
 // 定义路由规则,并为每个路由指定类型安全的 props
 const routes: Array<RouteRecordRaw> = [
   {
     path: '/',
     name: 'Home',
+    component: bedsideAuxiliaryScreen,
+  },
+  {
+    path: '/test2',
+    name: 'test2',
     component: deviceWindows2,
   },
   {
diff --git a/src/store/bedsideAuxiliaryScreen.ts b/src/store/bedsideAuxiliaryScreen.ts
new file mode 100644
index 0000000..11ff7fa
--- /dev/null
+++ b/src/store/bedsideAuxiliaryScreen.ts
@@ -0,0 +1,193 @@
+import { defineStore } from "pinia";
+import { ref } from "vue";
+import dayjs from "dayjs";
+import cache from "../utils/cache";
+import { EventSourcePolyfill } from "event-source-polyfill";
+import type { BedsideAuxiliaryScreen, SseMsgData } from "./type/bedsideAuxiliaryScreen.type";
+import type { Task } from "./type/task.type";
+import {
+  defaultDeviceData,
+  defaultconsumablesCollection,
+  formatDeviceData,
+} from "./type/bedsideAuxiliaryScreen.type";
+import { ElMessage } from "element-plus/es";
+
+export const useBedsideAuxiliaryScreenStore = defineStore(
+  "bedsideAuxiliaryScreen",
+  () => {
+    /** 设备编号 */
+    const deviceCode = ref<string>(cache.get("devcieCode") || "");
+
+    /** 设备信息数据 */
+    const deviceData = ref<BedsideAuxiliaryScreen>(defaultDeviceData());
+
+    /** 任务列表 */
+    const taskData = ref<Task[]>([]);
+
+    /**
+     * 设置设备编号
+     * @param code
+     */
+    const setDeviceCode = (code: string) => {
+      deviceCode.value = code;
+      cache.set("devcieCode", code);
+    };
+
+    /**
+     * 清除设备信息
+     */
+    const clearDevice = () => {
+      deviceData.value = defaultDeviceData();
+    };
+
+    /**
+     * 追加定时任务
+     * @param taskItem
+     */
+    const pushTask = (taskItem: Task) => {
+      taskData.value.push(taskItem);
+    };
+
+    /**
+     * 是否将当前任务设置为已过期
+     * @param i
+     */
+    // const deleteTask = (i: number) => {
+    //   const task = taskData.value[i];
+    //   if (task) {
+    //     // 二次判断,判断任务时间是否早于或等于当前时间
+    //     const taskTime = dayjs(task.taskDate).second(0).millisecond(0);
+    //     const now = dayjs().second(0).millisecond(0); // 秒和毫秒都去掉
+    //     if (!taskTime.isAfter(now)) {
+    //       taskData.value[i].overdue = true
+    //     }
+    //   }
+    // };
+
+    /** 设置当前定时任务 */
+    const setSyncTask = (taskItem: Task) => {
+      taskData.value = [taskItem];
+    };
+
+    /** 清除当前定时任务 */
+    const clearTask = () => {
+      taskData.value = [];
+    };
+
+    // SSE 相关状态
+    const source = ref<EventSource | null>(null);
+    const message = ref<string | null>(null);
+    const isConnected = ref(false);
+
+    // 重连控制
+    let retryCount = 0;
+    const maxRetryCount = 60;
+    const baseRetryDelay = 1000; // 1秒开始重连延迟
+
+    /**
+     * 连接 SSE 服务
+     * @param url SSE 地址
+     */
+    const connect = (url: string) => {
+      if (source.value) return; // 已连接,避免重复连接
+      ElMessage.success("正在连接设备,请稍候...");
+
+      source.value = new EventSourcePolyfill(url, {
+        heartbeatTimeout: 60000,
+      });
+
+      source.value.onopen = () => {
+        console.log("[SSE] 连接成功");
+        ElMessage.success("链接服务成功");
+        isConnected.value = true;
+        retryCount = 0; // 成功连接后重置重试计数
+      };
+
+      source.value.onerror = (e) => {
+        console.warn("[SSE] 错误,等待重连中", e);
+        isConnected.value = false;
+        close(); // 关闭旧连接,避免残留
+        if (retryCount < maxRetryCount) {
+          const delay = baseRetryDelay * Math.pow(2, retryCount); // 指数退避
+          retryCount++;
+          console.log(`[SSE] 第${retryCount}次重连,延迟${delay}ms`);
+          ElMessage.warning(
+            `链接服务失败, 第${retryCount}次重连,请耐心等待重连。。`
+          );
+          setTimeout(() => {
+            connect(url);
+          }, delay);
+        } else {
+          console.error("[SSE] 重连次数达到上限,停止重连");
+          ElMessage.error("重连次数达到上限,请检查网络或设备状态");
+        }
+      };
+
+      source.value.onmessage = (e) => {
+        console.log("[SSE] 消息:", e.data);
+        const msg = e.data;
+        let dif = msg.indexOf("event:message");
+        let beng = msg.indexOf("{");
+        let end = msg.length - 1;
+        if (beng !== -1 && end !== -1 && dif !== -1) {
+          const datax = msg.slice(beng, end + 1);
+          const dataBody = JSON.parse(datax) as SseMsgData;
+          console.log("dataBody: ", dataBody);
+          // 倒计时提示文本
+          if (dataBody.倒计时?.提醒文本) {
+            const taskTime = dayjs(dataBody.倒计时?.当前服务器时间).add(dataBody.倒计时?.设定提醒倒计时, 'minute')
+            setSyncTask({
+              deviceCode: dataBody.IOT信息.设备唯一编号,
+              recordCode: dataBody.透析状态?.透析单编号,
+              taskDate: taskTime.format('YYYY-MM-DD HH:mm'),
+              taskName: dataBody.倒计时?.提醒文本,
+              overdue: false,
+              countdown: dataBody.倒计时?.设定提醒倒计时
+            })
+          } else {
+            clearTask();
+          }
+
+          deviceData.value = formatDeviceData(dataBody);
+        }
+      };
+    };
+
+    /**
+     * 关闭 SSE 连接
+     */
+    const close = () => {
+      if (source.value) {
+        source.value.close();
+        source.value = null;
+        isConnected.value = false;
+        clearDevice();
+        clearTask();
+        console.log("[SSE] 连接已关闭");
+      }
+    };
+
+    /** 刷新 SSE 连接 */
+    const refresh = (url: string) => {
+      retryCount = 0;
+      close(); // 先关闭旧连接
+      connect(url); // 再重新连接
+    };
+
+    return {
+      deviceCode,
+      deviceData,
+      setDeviceCode,
+      source,
+      message,
+      isConnected,
+      connect,
+      close,
+      refresh,
+      taskData,
+      pushTask,
+      setSyncTask,
+      clearTask,
+    };
+  }
+);
diff --git a/src/store/type/bedsideAuxiliaryScreen.type.ts b/src/store/type/bedsideAuxiliaryScreen.type.ts
new file mode 100644
index 0000000..a5526ef
--- /dev/null
+++ b/src/store/type/bedsideAuxiliaryScreen.type.ts
@@ -0,0 +1,593 @@
+import { tryConvertToInt } from "@/utils/utils";
+import cache from "@/utils/cache";
+export interface IotInfo {
+  属性历史列表: any[];
+  床号: string;
+  状态列表: IotInfoStatus[];
+  设备唯一编号: string;
+  设备序列号: string;
+}
+
+export interface IotInfoStatus {
+  是否为警告标记: number;
+  状态名称: string;
+  状态类型: string;
+  状态颜色: string;
+}
+
+export interface ConsumablesCollection {
+  抗凝剂: string[];
+  护理包: string[];
+  滤过器: string[];
+  穿刺针: string[];
+  管路: string[];
+  透析器: string[];
+  透析模式: string[];
+}
+
+enum EPushType {
+  SPHYGMOMANOMETR = "床旁血压计",
+  CENTRAL_MONITORING = "中央监控大屏信息",
+}
+
+type PushType = "床旁血压计" | "中央监控大屏信息";
+
+export interface KtvItem {
+  时间: string;
+  ktv: string;
+}
+
+export interface DialysisStatus {
+  clientCode: string;
+  deviceHospitalCode: string;
+  iot_传输时间: number | null;
+  iot_当前脱水量: number | null;
+  iot_脱水目标量: number | null;
+  iot_脱水速率: number | null;
+  iot_透析液流速: number | null;
+  iot_跨膜压: number | null;
+  iot_透析时间: number | null;
+  iot_静脉压: number | null;
+  iot_血流量: number | null;
+  sortOrder: number | null;
+  txTime: number | null;
+  上次透后称重: number | null;
+  体重增加: number | null;
+  体重增长率: number | null;
+  分区编号: string;
+  处方脱水量: number | null;
+  实时ktv: string;
+  实时ktv计算结果列表: null | {
+    realTimeKtvCalcDetailResultInfo: KtvItem[];
+    透析单编号: string;
+  };
+  实时脱水量: number | null;
+  干体重: number | null;
+  年龄: number | null;
+  异常检验指标: AnomalyIndex[] | null;
+  当前血温: number | null;
+  性别: string;
+  患者头像: string;
+  患者姓名: string;
+  患者来源: 0 | 1;
+  患者编号: string;
+  患者透析号: string;
+  患者门诊住院号: string;
+  抗凝剂列表: Anticoagulant[] | null;
+  护理包列表: string[] | null;
+  报警_脱水量设定不一致: boolean;
+  最后一条血压: number | null;
+  最近平均脱水量: string;
+  最近最大脱水量: string;
+  最近最大脱水量日期: string;
+  此次脱水量: number | null;
+  监测血压是否低于百分之30: boolean;
+  监测血压是否高于百分之30: boolean;
+  监测记录列表: any[];
+  穿刺针列表: PunctureNeedle[] | null;
+  第一条血压: number | null;
+  管路列表: Piping[] | null;
+  置换方式: string;
+  脉搏列表: any[] | null;
+  血压低值列表: any[] | null;
+  血管通路列表: VascularAccess[] | null;
+  设备分区位置: any;
+  设备分区类型: number | null;
+  设备号: string;
+  设备名称: string;
+  设备序列号: string;
+  设备状态列表: IotInfoStatus[] | null;
+  设备编号: string;
+  超滤速度过快: boolean;
+  跨膜压列表: any[] | null;
+  跨膜压是否大于200: boolean;
+  跨膜压是否小于0: boolean;
+  透前称重: number | null;
+  透前脉搏: number | null;
+  透前血压_伸缩压: number | null;
+  透前血压_舒张压: number | null;
+  透析单医嘱列表: any[] | null;
+  透析单编号: string | null;
+  透析器: string;
+  透析器列表: Dialyzer[] | null;
+  透析处方是否已确认: number;
+  透析处方的时长: number | null;
+  透析处方的时长_分钟: string;
+  透析处方的时长_小时: string;
+  透析开始时间: number | null;
+  透析方案: string;
+  透析液列表: any[];
+  透析状态: string; // '0.0'这种格式的,得格式化一下
+  透析结束时间: number | null;
+  透析处方备注: string;
+  最近最大脱水量透析时长: string;
+}
+
+export interface VascularAccess {
+  位置: string;
+  类型: string;
+}
+
+export interface Dialyzer extends item {}
+
+export interface Piping extends item {}
+
+export interface PunctureNeedle extends item {}
+
+export interface item {
+  name: string;
+  单位: string;
+  数量: number | null;
+}
+
+export interface Anticoagulant {
+  name: string;
+  单位: string;
+  数量: number | null;
+  总量: number | null;
+  是否为追加: number | null;
+  维持剂量: number | null;
+  追加剂量: number | null;
+  首剂: number | null;
+}
+
+export interface AnomalyIndex {
+  单位: string;
+  参考值: string;
+  结果标记: string;
+  项目名称: string;
+  项目结果: string;
+}
+
+export interface Countdown {
+  当前服务器时间?: string;
+  提醒文本?: string;
+  提醒文本字典?: any[];
+  设定提醒倒计时?: number;
+}
+
+export interface SseMsgData {
+  IOT信息: IotInfo | null;
+  使用耗材字典: ConsumablesCollection | null; // 当透析状态为治疗中时该字段为null
+  倒计时: Countdown | null;
+  推送类型: PushType;
+  透析状态: DialysisStatus | null;
+}
+
+export interface BedsideAuxiliaryScreen {
+  deviceCode: string;
+  devicdeNo: string | number;
+  recordCode: string;
+  patientCode: string;
+  patientName: string;
+  patientPhone: string;
+  age: string;
+  gender: string;
+  patForm: PatForm;
+  patFormNumber: string;
+  treatmentStatus: MedStatus;
+  consumablesCollection: ConsumablesCollection;
+  pageType: PageType;
+  notSignedIn: NotSignedIn;
+  signedIn: SignedIn;
+  underTreatment: UnderTreatment;
+}
+
+export enum EPageType {
+  NOT_INIT = 0, // 未初始化(没有设备编号)
+  LOADING = 1, // 加载中
+  UNPLANNED_SCHEDULE = 2, // 未排班
+  NOT_SIGNED_IN = 3, // 未签到
+  SIGNED_IN = 4, // 已签到
+  DURING_DIALYSIS = 5, // 透析中
+  SPHYGMOMANOMETER = 6, // 床旁血压计
+}
+
+export type PageType =
+  | EPageType.NOT_INIT
+  | EPageType.LOADING
+  | EPageType.UNPLANNED_SCHEDULE
+  | EPageType.NOT_SIGNED_IN
+  | EPageType.SIGNED_IN
+  | EPageType.DURING_DIALYSIS
+  | EPageType.SPHYGMOMANOMETER;
+
+export enum EMedStatus {
+  /** 未签到 */
+  NOT_CHECKED_IN = 0,
+  /** 已签到 */
+  SIGNED_IN = 1,
+  /** 透析中 */
+  DURING_DIALYSIS = 2,
+  /** 已结束 */
+  END = 2.5,
+  /** 已检查 */
+  CHECKED = 3,
+  /** 已归档 */
+  ARCHIVED = 4,
+}
+
+export type MedStatus =
+  | EMedStatus.NOT_CHECKED_IN
+  | EMedStatus.SIGNED_IN
+  | EMedStatus.DURING_DIALYSIS
+  | EMedStatus.END
+  | EMedStatus.CHECKED
+  | EMedStatus.ARCHIVED;
+
+export enum EPatForm {
+  OUTPATIENT_SERVICE = 0,
+  BE_IN_HOSPITAL = 1,
+}
+
+export type PatForm = EPatForm.BE_IN_HOSPITAL | EPatForm.OUTPATIENT_SERVICE;
+
+export interface NotSignedIn {
+  dialysisMode: string;
+  dialyzerList: Dialyzer[];
+  pipingList: Piping[];
+  dialysateList: any[];
+  anticoagulant: Anticoagulant[];
+  carePackage: any[];
+  punctureNeedle: PunctureNeedle[];
+  vascularAccess: VascularAccess[];
+}
+
+export const defaultconsumablesCollection = (): ConsumablesCollection => {
+  return {
+    抗凝剂: [],
+    护理包: [],
+    滤过器: [],
+    穿刺针: [],
+    管路: [],
+    透析器: [],
+    透析模式: [],
+  };
+};
+
+export const defalutNotSignedIn = (): NotSignedIn => {
+  return {
+    dialysisMode: "", // 透析模式
+    dialyzerList: [], // 透析器列表
+    pipingList: [], // 一次性使用管路列表
+    dialysateList: [], // 透析液列表
+    anticoagulant: [], // 抗凝剂列表
+    carePackage: [], // 一次性使用透析护理包列表
+    punctureNeedle: [], // 穿刺针列表
+    vascularAccess: [], // 血管通路列表
+  };
+};
+
+export interface SignedIn {
+  abnormalItems: AnomalyIndex[];
+  dialysisPlan: string; // 透析方案
+  prescriptionDehydrationVolume: number | null; // 透析处方脱水量
+  dialyzer: string; // 透析器
+  averageDehydrationRate: string; // 最近平均脱水量
+  maximumDehydrationCapacity: string; // 最近最大脱水量
+  maximumDehydrationCapacityDate: string; // 最近最大脱水量日期
+  dryWeight: number | null; // 干体重
+  preDialysisWeight: number | null; // 透前称重
+  weightAfterLastDialysis: number | null; // 上次透后称重
+  weightIncrease: number | null; // 体重增加
+  weightIncreaseRate: number | null; // 体重增长率
+}
+
+export const defaultSignedIn = (): SignedIn => {
+  return {
+    abnormalItems: [], // 异常指标列表
+    dialysisPlan: "", // 透析方案
+    prescriptionDehydrationVolume: null, // 透析处方脱水量
+    dialyzer: "", // 透析器
+    averageDehydrationRate: "", // 最近平均脱水量
+    maximumDehydrationCapacity: "", // 最近最大脱水量
+    maximumDehydrationCapacityDate: "", // 最近最大脱水量日期
+    dryWeight: null, // 干体重
+    preDialysisWeight: null, // 透前称重
+    weightAfterLastDialysis: null, // 上次透后称重
+    weightIncrease: null, // 体重增加
+    weightIncreaseRate: null, // 体重增长率
+  };
+};
+
+export interface UnderTreatment {
+  substituteMode: string; // 置换方式
+  dialysisPlan: string; // 透析方案
+  dialyzer: string; // 透析器
+  averageDehydrationRate: string; // 平均脱水量
+  maximumDehydrationCapacity: string; // 最大脱水量
+  maximumDehydrationCapacityDate: string; // 最大脱水量日期
+  maximumDehydrationDuration: string; // 最大脱水量那天的时长
+  prescriptionRemarks: string; // 透析处方备注
+  abnormalItems: AnomalyIndex[]; // 异常指标列表
+  prescriptionDialysisDurationHour: string; // 透析处方的时长(小时部分)
+  prescriptionDialysisDurationMin: string; // 透析处方的时长(分钟部分)
+  prescriptionDialysisDuration: number | null; // 透析处方的时长(单位:小时)
+  dialysisStartTime: number | null; // 透析开始时间(时间戳)
+  dialysisEndTime: number | null; // 透析结束时间(时间戳)
+  dialysisDuration: number | null; // 已透析时长(单位:分钟)
+  prescriptionDehydrationVolume: number | null; // 透析处方脱水量 【】
+  currentDehydrationVolume: number | null; // 当前脱水量 【实时脱水量】
+  currentUltrafiltrationRate: number | null; // 当前超滤速率
+  currentBloodTemperature: number | null; // 当前血温
+  venousPressure: number | null; // 静脉压
+  transmembranePressure: number | null; // 跨膜压
+  ktv: string; // 实时ktv
+  monitoringRecord: MonitoringRecord[]; // 监测记录列表
+  doctorAdvice: any[]; // 透析单医嘱列表
+  bloodFlow: string; // 血流量
+  bloodVolumeMonitoring: number | null; // 血容量监测
+  dialysisFluidFlowRate: number | null; // 透析液流量
+  ktvList: KtvItem[]; // 实时ktv计算结果列表
+}
+
+export interface MonitoringRecord {
+  伸缩压: string; // 血压伸缩压
+  舒张压: string; // 血压舒张压
+  脉搏: string; // 脉搏
+}
+
+export const defaultUnderTreatment = (): UnderTreatment => {
+  return {
+    substituteMode: "",
+    dialysisPlan: "",
+    dialyzer: "",
+    averageDehydrationRate: "",
+    maximumDehydrationCapacity: "",
+    maximumDehydrationCapacityDate: "",
+    maximumDehydrationDuration: "",
+    prescriptionRemarks: "",
+    abnormalItems: [],
+    prescriptionDialysisDurationHour: "",
+    prescriptionDialysisDurationMin: "",
+    dialysisStartTime: null,
+    dialysisEndTime: null,
+    dialysisDuration: null,
+    prescriptionDehydrationVolume: null,
+    currentDehydrationVolume: null,
+    currentUltrafiltrationRate: null,
+    currentBloodTemperature: null,
+    venousPressure: null,
+    transmembranePressure: null,
+    ktv: "",
+    monitoringRecord: [],
+    doctorAdvice: [],
+    bloodFlow: "",
+    bloodVolumeMonitoring: null,
+    dialysisFluidFlowRate: null,
+    ktvList: [],
+    prescriptionDialysisDuration: null, // 透析处方的时长(单位:小时)
+  };
+};
+
+export const defaultDeviceData = (): BedsideAuxiliaryScreen => {
+  const pageType = cache.get("devcieCode")
+    ? EPageType.LOADING
+    : EPatForm.OUTPATIENT_SERVICE;
+  return {
+    deviceCode: "", // 设备code
+    devicdeNo: "", // 设备号
+    recordCode: "", // 透析单code
+    patientCode: "", // 患者code
+    patientName: "", // 患者姓名
+    patientPhone: "", // 患者头像
+    age: "", // 年龄
+    gender: "", // 性别
+    patForm: EPatForm.OUTPATIENT_SERVICE, // 患者来源
+    patFormNumber: "", // 住院门诊号
+    // @ts-ignore
+    pageType, // 当前要展示的页面
+    treatmentStatus: EMedStatus.NOT_CHECKED_IN, // 透析状态
+    consumablesCollection: defaultconsumablesCollection(), // 未排班时需要的数据
+    notSignedIn: defalutNotSignedIn(), // 未签到时需要的数据
+    signedIn: defaultSignedIn(), // 已签到时需要的数据
+    underTreatment: defaultUnderTreatment(), // 治疗中需要的数据
+  };
+};
+
+export const formatDeviceData = (
+  seeMsg: SseMsgData
+): BedsideAuxiliaryScreen => {
+
+  const result = defaultDeviceData();
+
+  // 默认床号(设备号)
+  result.devicdeNo = seeMsg.IOT信息?.床号;
+  result.deviceCode = seeMsg.IOT信息?.设备唯一编号;
+
+  if (seeMsg.推送类型 === EPushType.SPHYGMOMANOMETR) {
+    result.pageType = EPageType.SPHYGMOMANOMETER;
+  } else if (seeMsg.推送类型 === EPushType.CENTRAL_MONITORING) {
+    // 判断是否存在透析状态,如果不存在就是没有排班
+    if (seeMsg.透析状态 === null || !seeMsg.透析状态) {
+      result.pageType = EPageType.UNPLANNED_SCHEDULE;
+      result.consumablesCollection =
+        seeMsg?.使用耗材字典 ?? defaultconsumablesCollection();
+    } else {
+      const treatmentStatus = tryConvertToInt(
+        seeMsg.透析状态?.透析状态
+      ) as MedStatus;
+
+      // 这里就是有排班的
+      result.treatmentStatus = treatmentStatus;
+      result.recordCode = seeMsg.透析状态?.透析单编号;
+      result.patientCode = seeMsg.透析状态?.患者编号;
+      result.patientName = seeMsg.透析状态?.患者姓名;
+      result.patientPhone = seeMsg.透析状态?.患者头像;
+      result.age = seeMsg.透析状态?.年龄 + "";
+      result.gender = seeMsg.透析状态?.性别 + "";
+      result.patForm = seeMsg.透析状态?.患者来源;
+      result.patFormNumber = seeMsg.透析状态?.患者门诊住院号;
+
+      // 未签到页面需要显示的
+      if (treatmentStatus === EMedStatus.NOT_CHECKED_IN) {
+        result.pageType = EPageType.NOT_SIGNED_IN;
+        const notSignedIn = defalutNotSignedIn();
+        notSignedIn.dialysisMode = seeMsg.透析状态?.透析方案 ?? "";
+        notSignedIn.dialyzerList = seeMsg.透析状态?.透析器列表 ?? [];
+        notSignedIn.pipingList = seeMsg.透析状态?.管路列表 ?? [];
+        notSignedIn.dialysateList = seeMsg.透析状态?.透析液列表 ?? [];
+        notSignedIn.carePackage = seeMsg.透析状态?.护理包列表 ?? [];
+        notSignedIn.punctureNeedle = seeMsg.透析状态?.穿刺针列表 ?? [];
+        notSignedIn.vascularAccess = seeMsg.透析状态?.血管通路列表 ?? [];
+        notSignedIn.anticoagulant = seeMsg.透析状态?.抗凝剂列表 ?? [];
+
+        result.notSignedIn = notSignedIn;
+      }
+      // 已签到未开始透析需要显示的
+      else if (treatmentStatus === EMedStatus.SIGNED_IN) {
+        result.pageType = EPageType.SIGNED_IN;
+        const signedIn = defaultSignedIn();
+        signedIn.abnormalItems = seeMsg.透析状态?.异常检验指标 ?? [];
+        signedIn.dialysisPlan = seeMsg.透析状态?.透析方案 ?? "";
+        signedIn.prescriptionDehydrationVolume =
+          seeMsg.透析状态?.处方脱水量 ?? null;
+        signedIn.dialyzer = seeMsg.透析状态?.透析器 ?? "";
+        signedIn.averageDehydrationRate = seeMsg.透析状态?.最近平均脱水量 ?? "";
+        signedIn.maximumDehydrationCapacity =
+          seeMsg.透析状态?.最近最大脱水量 ?? "";
+        signedIn.maximumDehydrationCapacityDate =
+          seeMsg.透析状态?.最近最大脱水量日期 ?? "";
+        signedIn.dryWeight = seeMsg.透析状态?.干体重 ?? null;
+        signedIn.preDialysisWeight = seeMsg.透析状态?.透前称重 ?? null;
+        signedIn.weightAfterLastDialysis =
+          seeMsg.透析状态?.上次透后称重 ?? null;
+        signedIn.weightIncrease = seeMsg.透析状态?.体重增加 ?? null;
+        signedIn.weightIncreaseRate = seeMsg.透析状态?.体重增长率 ?? null;
+
+        result.signedIn = signedIn;
+      }
+      // 剩下的全使用治疗中的页面
+      else {
+        result.pageType = EPageType.DURING_DIALYSIS;
+        const underTreatment = defaultUnderTreatment();
+        underTreatment.substituteMode = seeMsg.透析状态?.置换方式 ?? "";
+        underTreatment.dialysisPlan = seeMsg.透析状态?.透析方案 ?? "";
+        underTreatment.dialyzer = seeMsg.透析状态?.透析器 ?? "";
+        underTreatment.averageDehydrationRate =
+          seeMsg.透析状态?.最近平均脱水量 ?? "";
+        underTreatment.maximumDehydrationCapacity =
+          seeMsg.透析状态?.最近最大脱水量 ?? "";
+        underTreatment.maximumDehydrationCapacityDate =
+          seeMsg.透析状态?.最近最大脱水量日期 ?? "";
+        underTreatment.maximumDehydrationDuration =
+          seeMsg.透析状态?.最近最大脱水量透析时长 ?? "";
+        underTreatment.prescriptionRemarks =
+          seeMsg.透析状态?.透析处方备注 ?? "";
+        underTreatment.abnormalItems = seeMsg.透析状态?.异常检验指标 ?? [];
+        underTreatment.prescriptionDialysisDuration =
+          seeMsg.透析状态?.透析处方的时长 ?? null;
+        underTreatment.prescriptionDialysisDurationHour =
+          seeMsg.透析状态?.透析处方的时长_小时 ?? "";
+        underTreatment.prescriptionDialysisDurationMin =
+          seeMsg.透析状态?.透析处方的时长_分钟 ?? "";
+        underTreatment.dialysisStartTime =
+          seeMsg.透析状态?.透析开始时间 ?? null;
+        underTreatment.dialysisEndTime = seeMsg.透析状态?.透析结束时间 ?? null;
+        underTreatment.dialysisDuration = seeMsg.透析状态?.iot_透析时间 ?? null;
+        underTreatment.prescriptionDehydrationVolume =
+          seeMsg.透析状态?.iot_脱水目标量 ?? null;
+        underTreatment.currentDehydrationVolume =
+          seeMsg.透析状态?.iot_当前脱水量 ?? null;
+        underTreatment.currentUltrafiltrationRate =
+          seeMsg.透析状态?.iot_脱水速率 ?? null;
+        underTreatment.currentBloodTemperature =
+          seeMsg.透析状态?.当前血温 ?? null;
+        underTreatment.venousPressure = seeMsg.透析状态?.iot_静脉压 ?? null;
+        underTreatment.transmembranePressure =
+          seeMsg.透析状态?.iot_跨膜压 ?? null;
+        underTreatment.ktv = seeMsg.透析状态?.实时ktv ?? "";
+        underTreatment.monitoringRecord = seeMsg.透析状态?.监测记录列表 ?? [];
+        underTreatment.doctorAdvice = seeMsg.透析状态?.透析单医嘱列表 ?? [];
+        underTreatment.bloodFlow = "";
+        underTreatment.dialysisFluidFlowRate =
+          seeMsg.透析状态?.iot_血流量 ?? null;
+        underTreatment.bloodVolumeMonitoring =
+          seeMsg.透析状态?.iot_透析液流速 ?? null;
+        underTreatment.ktvList =
+          seeMsg.透析状态?.实时ktv计算结果列表
+            ?.realTimeKtvCalcDetailResultInfo ?? [];
+        result.underTreatment = underTreatment;
+      }
+    }
+  }
+  return result;
+};
+
+export const getItemName = (name: string) => {
+  if (name) {
+    if (name === "血红蛋白") {
+      return "HGB ";
+    } else if (name === "铁蛋白") {
+      return "FER ";
+    } else if (name === "白蛋白") {
+      return "ALB ";
+    } else if (name === "钙") {
+      return "Ca ";
+    } else if (name === "钾") {
+      return "K ";
+    } else if (name === "无机磷") {
+      return "P ";
+    } else if (name === "甲状旁腺激素") {
+      return "PTH ";
+    } else {
+      return name;
+    }
+  } else {
+    return "";
+  }
+};
+
+export const formatTestColr = (reg: string) => {
+  const heightFlag = ["↑", "g"];
+  const lowFlag = ["d", "↓"];
+  let color = "#333";
+  if (heightFlag.includes(reg)) {
+    color = "#CA7070";
+  } else if (lowFlag.includes(reg)) {
+    color = "#409eff";
+  }
+  return color;
+};
+
+export const formatTestFlag = (reg: string) => {
+  const heightFlag = ["↑", "g"];
+  const lowFlag = ["d", "↓"];
+  if (heightFlag.includes(reg)) {
+    return "↑";
+  } else if (lowFlag.includes(reg)) {
+    return "↓";
+  } else {
+    return "";
+  }
+};
+
+export const formatSubstituteMode = (mode: string) => {
+  let result = "";
+  if (mode === "前置换") {
+    result = "前";
+  } else if (mode === "后置换") {
+    result = "后";
+  }
+  return result;
+};
diff --git a/src/store/type/task.type.ts b/src/store/type/task.type.ts
new file mode 100644
index 0000000..75b2189
--- /dev/null
+++ b/src/store/type/task.type.ts
@@ -0,0 +1,12 @@
+export interface Task {
+  /** 设备code */
+  deviceCode: string;
+  /** 透析单code */
+  recordCode?: string;
+  /** 任务提醒时间 */
+  taskDate: string;
+  /** 任务名称 */
+  taskName: string;
+  /** 是否过期 */
+  overdue: boolean;
+}
diff --git a/src/style.css b/src/style.css
index 9b05ea2..e69de29 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1,49 +0,0 @@
-:root {
-  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
-  line-height: 1.5;
-  font-weight: 400;
-
-  color-scheme: light dark;
-  color: rgba(255, 255, 255, 0.87);
-  background-color: #242424;
-
-  font-synthesis: none;
-  text-rendering: optimizeLegibility;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-html, body {
-  margin: 0;
-  padding: 0;
-  width: 100%;
-  height: 100%;
-}
-
-#app {
-  width: 100%;
-  height: 100%;
-  border: 1px rgb(23, 7, 7) solid;
-  background-color: lightblue; /* 可选:用于可视化效果 */
-}
-
-@media (prefers-color-scheme: light) {
-  :root {
-    color: #213547;
-    background-color: #ffffff;
-  }
-  a:hover {
-    color: #747bff;
-  }
-  button {
-    background-color: #f9f9f9;
-  }
-}
-.el-loading-spinner .el-loading-text {
-  font-size: 16px; /* 修改为你需要的字体大小 */
-}
-.el-dialog {
-  padding: 0;
-  padding-bottom: 20px;
-  border-radius: 10px;
-}
\ No newline at end of file
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/utils/utils.ts b/src/utils/utils.ts
new file mode 100644
index 0000000..4081f1e
--- /dev/null
+++ b/src/utils/utils.ts
@@ -0,0 +1,31 @@
+/**
+ * 计算某个类名元素的可用高度(视口高度 - 元素顶部距离)
+ * @param className 元素类名(不带.)
+ * @returns 可用高度(px),找不到元素则返回 0
+ */
+export function getAvailableHeightByClass(className: string): number {
+  const el = document.querySelector(`.${className}`) as HTMLElement | null
+  if (!el) return 0
+  const rect = el.getBoundingClientRect()
+  return window.innerHeight - rect.top
+}
+
+/**
+ * 将字符串转为数字
+ * @param value 
+ * @returns 
+ */
+export function tryConvertToInt(value: string): string | number {
+  const num = Number(value);
+  // 判断是否是有效数字且是整数(小数部分为 0)
+  if (!isNaN(num) && Number.isInteger(num)) {
+    return num;
+  }
+
+  // 判断是否是有效数字且小数部分为 0(例如 "1.0")
+  if (!isNaN(num) && Number(value).toString().endsWith('.0')) {
+    return parseInt(value, 10);
+  }
+
+  return value;
+}
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/BlockBotttom.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/BlockBotttom.vue
new file mode 100644
index 0000000..a96995c
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/BlockBotttom.vue
@@ -0,0 +1,48 @@
+<template>
+  <div
+    class="block-botttom"
+    :style="{
+      '--backgroundColor': props.backgroundColor,
+    }"
+    @click="props.onClick"
+  >
+    <img :src="icon" alt="" class="icon" />
+    <span class="text">{{ text }}</span>
+  </div>
+</template>
+
+<script lang="ts" setup name="BlockBotttom">
+interface Props {
+  icon: string; // 图标
+  text: string; // 文本
+  backgroundColor: string; // 背景颜色
+  onClick: () => void; // 点击事件
+}
+const props = defineProps<Props>();
+</script>
+
+<style lang="less" scoped>
+.block-botttom {
+  width: 18px;
+  height: 18px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  background: var(--backgroundColor, #70a3dd);
+  border-radius: 2px;
+  .icon {
+    margin-bottom: 2px;
+    width: 6px;
+    height: 6px;
+  }
+  .text {
+    font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
+    font-weight: 500;
+    font-size: 3px;
+    color: #ffffff;
+    text-align: left;
+    font-style: normal;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Card.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Card.vue
new file mode 100644
index 0000000..6faafca
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Card.vue
@@ -0,0 +1,87 @@
+<template>
+  <div
+    class="bedside-auxiliary-screen-card"
+    :style="{
+      '--bg-color': props.backgroundColor,
+    }"
+  >
+    <div class="card-header" :class="props.headerClassName">
+      <img :src="props.icon" class="card-icon" alt="" srcset="" />
+      <span class="card-title">{{ props.title }}</span>
+    </div>
+    <div class="card-main">
+      <slot />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup name="Card">
+interface Props {
+  backgroundColor: string; // 背景颜色
+  title: string; // 标题
+  icon: string;
+  height?: number;
+  headerClassName?: string; // 头部类名
+}
+const props = defineProps<Props>();
+</script>
+
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+.bedside-auxiliary-screen-card {
+  display: flex;
+  flex-direction: column;
+  // height: 100%;
+  padding: 3px 4px;
+  border-radius: 2px;
+  background-color: var(--bg-color, #70a3dd);
+  overflow: hidden;
+  overflow-y: auto;
+  height: 100%;
+
+  .card-header {
+    flex: 0 0 6px;
+    display: flex;
+    align-items: center;
+    margin-bottom: 2px;
+
+    .card-icon {
+      width: 6px;
+      height: 6px;
+      margin-right: 2px;
+    }
+
+    .card-title {
+      flex: 1;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 4px;
+      color: #333333;
+      text-align: left;
+      font-style: normal;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+
+  .card-main {
+    flex: 1;
+    overflow: hidden;
+    overflow-y: auto;
+    min-height: 0;
+  }
+  .card-main > * {
+    min-height: 0;
+    overflow: hidden;
+  }
+}
+:deep(.el-scrollbar__view) {
+  min-height: 0;
+  height: 100%;
+  overflow: hidden;
+  overflow-y: auto;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/index.vue
new file mode 100644
index 0000000..a193436
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/index.vue
@@ -0,0 +1,184 @@
+<template>
+  <div class="doctor_advice_container" :style="{ height: height }">
+    <div class="doctor_advice_list">
+      <div
+        v-for="(item, index) in drugOrders"
+        :key="index"
+        class="doctor_advice_item"
+      >
+        <div class="doctor_advice_item_name">{{ item.name }}</div>
+        <template v-if="item?.children && item.children.length > 0">
+          <div
+            v-for="(child, childIndex) in item.children"
+            :key="childIndex"
+            class="doctor_advice_item_sub"
+          >
+            <img :src="trunImgSrc" alt="" />
+            <span>{{ child }}</span>
+          </div>
+        </template>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { PropType, computed } from "vue";
+import type { Order } from "./type"
+import trunImgSrc from "@/assets/turn.png";
+
+export default {
+  name: "DoctorAdvice",
+  props: {
+    // 容器的高度
+    height: {
+      type: String,
+      default: '100%',
+      required: false,
+    },
+    // 医嘱列表
+    list: {
+      type: Array as PropType<Order[]>,
+      default: () => [],
+    },
+  },
+  setup(props) {
+    const drugOrders = computed(() => {
+      // 格式化主医嘱数据(浅拷贝)
+      const formatList = props.list
+        .filter((e) => e.orderIsSub !== 1)
+        .map((e) => ({ ...e }));
+
+      // 处理子医嘱并挂载到对应主医嘱上
+      props.list.forEach((e) => {
+        if (e.orderIsSub === 1) {
+          const i = formatList.findIndex((v) => v.code === e.orderMainCode);
+          if (i !== -1) {
+            if (!formatList[i].subDrugOrders) {
+              formatList[i].subDrugOrders = [];
+            }
+            formatList[i].subDrugOrders.push(e);
+          }
+        }
+      });
+
+      // 构建显示用的 name 和子医嘱 children
+      return formatList.map((order) => {
+        let name = "";
+
+        if (order.orderNameInfo) {
+          name = order.orderNameInfo.itemName || "";
+          const drugSpec = order.orderNameInfo.feeDrugInfo?.drugSpec;
+          if (drugSpec) {
+            name += ` (${drugSpec})`;
+          }
+        }
+
+        if (order.orderUsage && order.orderUsage !== 0) {
+          name += ` ${order.orderUsage}${
+            order.orderNameInfo?.feeDrugInfo?.drugUnitName || ""
+          }`;
+        }
+
+        if (order.orderCount) {
+          name += ` ${order.orderCount}`;
+          const pkgUnit = order.orderNameInfo?.feeDrugInfo?.drugPackageUnitName;
+          if (pkgUnit) {
+            name += pkgUnit;
+          }
+        }
+
+        if (order.orderFromInfo?.dictText) {
+          name += ` ${order.orderFromInfo.dictText}`;
+        }
+
+        if (order.orderFreqInfo?.dictText) {
+          name += ` ${order.orderFreqInfo.dictText}`;
+        }
+
+        const children: string[] = [];
+
+        if (order.subDrugOrders?.length) {
+          order.subDrugOrders.forEach((child: any) => {
+            let subName = child.orderNameInfo?.itemName || "";
+
+            const childSpec = child.orderNameInfo?.feeDrugInfo?.drugSpec;
+            if (childSpec) {
+              subName += ` (${childSpec})`;
+            }
+
+            if (child.orderUsage) {
+              const unit = child.orderNameInfo?.feeDrugInfo?.drugUnitName || "";
+              subName += ` ${child.orderUsage}${unit}`;
+            }
+
+            if (child.orderCount) {
+              const pkgUnit =
+                child.orderNameInfo?.feeDrugInfo?.drugPackageUnitName;
+              if (pkgUnit) {
+                subName += ` ${child.orderCount}${pkgUnit}`;
+              }
+            }
+
+            children.push(subName);
+          });
+        }
+
+        return {
+          name,
+          children,
+        };
+      });
+    });
+
+    return {
+      drugOrders,
+      trunImgSrc,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.doctor_advice_container {
+  box-sizing: border-box;
+}
+.doctor_advice_container .doctor_advice_list {
+  box-sizing: border-box;
+  height: 100%;
+  background: #ffffff;
+  overflow: hidden;
+  overflow-y: auto;
+}
+.doctor_advice_container .doctor_advice_item {
+  box-sizing: border-box;
+  border-bottom: 1px solid #e6e5e5;
+}
+.doctor_advice_container .doctor_advice_item:last-child {
+  /* box-sizing: border-box;
+  border-bottom: none; */
+}
+.doctor_advice_container .doctor_advice_item .doctor_advice_item_name {
+  box-sizing: border-box;
+  font-weight: 400;
+  font-size: 5px;
+  color: #333333;
+  line-height: 12px;
+  text-align: left;
+  font-style: normal;
+}
+.doctor_advice_container .doctor_advice_item_sub {
+  padding-left: 1px;
+  font-weight: 400;
+  font-size: 5px;
+  color: #777777;
+  line-height: 12px;
+  text-align: left;
+  font-style: normal;
+}
+.doctor_advice_container .doctor_advice_item_sub img {
+  width: 7px;
+  height: 7px;
+  margin-right: 2px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/type.ts b/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/type.ts
new file mode 100644
index 0000000..7808a58
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/DoctorAdvice/type.ts
@@ -0,0 +1,375 @@
+export interface Order {
+    orderType: number;
+    code: string;
+    orderFreq: string;
+    orderDoctor: string;
+    confirmUserInfo: any | null; 
+    remark: string | null;
+    isConfirm: number;
+    isDeleted: number;
+    orderExecuteCheckUser: any | null; 
+    orderIsSub: number;
+    orderExecuteTime: any | null; 
+    id: number;
+    recordCode: string;
+    deletedTime: any | null; 
+    orderExecutePatient: any | null; 
+    orderExecuteUser: any | null; 
+    orderName: string;
+    orderExecuteCheckUserInfo: any | null; 
+    subDrugOrders: any | null; 
+    orderSort: number;
+    orderCount: number;
+    hisOrderNo: string | null;
+    updateUser: any | null; 
+    confirmTime: any | null; 
+    confirmUser: any | null; 
+    updateTime: number;
+    orderDoctorInfo: UserDoctorInfo;
+    orderMainCode: string | null;
+    createTime: number;
+    orderFreqInfo: OrderFreqInfo;
+    orderNameInfo: OrderNameInfo;
+    createUser: any | null; 
+    orderFrom: string;
+    orderUsage: number;
+    orderIsSpin: number;
+    orderExecuteUserInfo: any | null; 
+    orderFromInfo: OrderFromInfo;
+    orderStartTime: number;
+}
+
+interface UserDoctorInfo {
+    isRecvAlarmEmail: number;
+    prepareWorkMedicineStat: any | null;
+    userDegree: any | null;
+    isRecvAlarmWechat: number;
+    listReadyRows: any | null;
+    selectedFieldsInInventory2OutPage: any | null;
+    currentClientInfo: any | null;
+    signedInCountByDa: any | null;
+    selectFieldsInShangjiCanshuPage: any | null;
+    relatedClients: any | null;
+    userWorkState: any | null;
+    userIdentityCode: any | null;
+    clientInfos: any | null;
+    userMobile: string;
+    id: number;
+    loginWechatMpId: any | null;
+    userIsTongluDoctor: number;
+    canModifyHistoryHms: boolean;
+    是否自动出库至二级默认仓库: any | null;
+    userGoDepartment: any | null;
+    userRfid: any | null;
+    userGraduateTime: any | null;
+    管理员能看到的客户列表: any | null;
+    userSortOrder: number;
+    userCustomSetting: string;
+    hisCode: any | null;
+    isRecvAlarm: any | null;
+    selectedFieldsInCleanStatPage: any | null;
+    排班时段选择项: any | null;
+    userVsRoleList: any | null;
+    userPassword: string;
+    code: string;
+    userSignPicUrl: any | null;
+    userFromDepartment: any | null;
+    roles: any | null;
+    userAvatar: any | null;
+    userNo: string;
+    admin: boolean;
+    remark: string;
+    userAdmin: boolean;
+    checkVersionCode: string;
+    selectedFieldsInMedStat2: any | null;
+    userTitle: string;
+    isDeleted: number;
+    nurse: boolean;
+    canDeleteHistoryHms: boolean;
+    userEmail: string;
+    deletedTime: any | null;
+    userWorkTimeFrom: any | null;
+    prepareWorkMedicine: any | null;
+    clientVsUserList: any | null;
+    isValid: number;
+    teamState: any | null;
+    updateUser: number;
+    updateTime: number;
+    隐藏自备药: any | null;
+    userName: string;
+    selectFieldsInTodayOrderPage: any | null;
+    isShow: number;
+    doctor: boolean;
+    isValidForClient: number;
+    loginWechatUnionId: any | null;
+    userGoDate: any | null;
+    createTime: number;
+    userInDate: any | null;
+    clientCode: any | null;
+    selectedFieldsInInventory2QueryPage: any | null;
+    signedInCountByStatistics: any | null;
+    createUser: number;
+    userGender: number;
+    userPinyin: string;
+    listStatInfo: any | null;
+}
+
+interface OrderFreqInfo {
+    code: string;
+    dictIsCustom: number;
+    updateUser: any | null;
+    remark: any | null;
+    updateTime: number;
+    dictNo: string;
+    dictType: string;
+    dictIsEnable: number;
+    isDeleted: number;
+    createTime: number;
+    hisCode: any | null;
+    sortOrder: number;
+    createUser: number;
+    id: number;
+    deletedTime: any | null;
+    dictText: string;
+}
+
+interface OrderNameInfo {
+    itemAgent: any | null;
+    itemPermissionCode: any | null;
+    inventoryItemTypeInfo: InventoryItemTypeInfo;
+    itemIsUse: number;
+    itemIsRestrictUse: number;
+    itemCode: string;
+    itemHisType: any | null;
+    itemUnit: any | null;
+    suntopItemCode: any | null;
+    itemOutPrice: number;
+    itemFactoryInfo: any | null;
+    itemName: string;
+    itemCommonUseInBothSide: any | null;
+    id: number;
+    当前使用量: any | null;
+    剩余总量: any | null;
+    storageCode: any | null;
+    入库总量: any | null;
+    透析器国网上报: DialyzerReport;
+    hisCode: any | null;
+    itemIsOutToPatient: number;
+    itemSalePrice: number;
+    itemIsReUse: number;
+    itemPackageUnit: any | null;
+    inStorageCountInfo: any | null;
+    itemPackageUnitName: string;
+    itemIsFavor: number;
+    itemSpec: string;
+    itemYibaoPrice: any | null;
+    inventoryTypeCode: string;
+    code: string;
+    itemLicenseCode: any | null;
+    itemAgentInfo: any | null;
+    itemOperator: any | null;
+    remark: any | null;
+    批号对象列表: any | null;
+    isDeleted: number;
+    itemIsEnableManage: number;
+    deletedTime: any | null;
+    itemIsUseAsXt: number;
+    itemName2: string;
+    inventoryItemType: number;
+    itemMoMaterial: any | null;
+    itemMoArea: number;
+    itemPinyin: string;
+    itemTxqCleanRate: any | null;
+    inventoryTypeName: any | null;
+    itemSortOrder: number;
+    updateUser: any | null;
+    updateTime: number;
+    结存: any | null;
+    isShow: number;
+    itemFactory: any | null;
+    feeDrugInfo: FeeDrugInfo;
+    itemOperatorInfo: any | null;
+    itemPackageCount: any | null;
+    createTime: number;
+    clientCode: string;
+    itemExtendJson: string;
+    itemPeriodAlarmDays: number;
+    itemRestrictUseRemark: any | null;
+    createUser: number;
+    itemUnitInfo: any | null;
+    itemInPrice: number;
+    itemInventoryAlarmCount: number;
+    itemYibaoCode: any | null;
+}
+
+interface InventoryItemTypeInfo {
+    code: string;
+    typeName: string;
+    updateUser: any | null;
+    remark: any | null;
+    updateTime: number;
+    typeCategory: number;
+    isShow: boolean;
+    isDeleted: number;
+    isEditable: number;
+    createTime: number;
+    clientCode: any | null;
+    sortOrder: number;
+    createUser: any | null;
+    id: number;
+    deletedTime: any | null;
+}
+
+interface DialyzerReport {
+    eSA_促红素种类: string;
+    抗凝剂_低分子肝素首剂量_IU: string;
+    抗凝剂_总剂量: string;
+    透析器透析膜: string;
+    铁剂_其它静脉种类: string;
+    eSA_用药方式: any[]; // 根据实际元素类型替换 any
+    eSA_静脉剂量单位: string;
+    铁剂_静脉剂量周: string;
+    抗凝剂_枸橼酸钠速率每小时_ml: string;
+    抗凝剂_阿加曲班追加速率_IU每小时: string;
+    抗凝剂_肝素追加速率_mg每小时: string;
+    透析器使用: string;
+    抗凝剂_低分子肝素单位: string;
+    抗凝剂_肝素首剂量_mg: string;
+    抗凝剂_枸橼酸钠_其它钠浓度: string;
+    抗凝剂_追加剂量: string;
+    抗凝剂_其它抗凝剂: string;
+    透析器类型: string;
+    抗凝剂_阿加曲班_追加时间小时: string;
+    抗凝剂_阿加曲班追加速率_mg每小时: string;
+    抗凝剂_低分子肝素首剂量_mg: string;
+    抗凝剂_阿加曲班首剂量_mg: string;
+    透析器通量: string;
+    抗凝剂_肝素首剂量_IU: string;
+    铁剂_静脉种类: string;
+    药品类型: string;
+    eSA_皮下剂量: string;
+    铁剂_口服剂量日: string;
+    eSA_静脉剂量: string;
+    抗凝剂_种类: string;
+    抗凝剂_阿加曲班_追加时间分钟: string;
+    eSA_促红素名称: string;
+    抗凝剂_低分子肝素类型: string;
+    铁剂_给药方式: string;
+    抗凝剂_首剂量: string;
+    抗凝剂_低分子肝素总剂量: string;
+    抗凝剂_低分子肝素追加时间: string;
+    抗凝剂_低分子肝素追加剂量_mg: string;
+    抗凝剂_肝素_追加时间小时: string;
+    铁剂_其它口服种类: string;
+    抗凝剂_阿加曲班首剂量_IU: string;
+    抗凝剂_枸橼酸钠_使用时间小时: string;
+    抗凝剂_肝素_追加时间分钟: string;
+    抗凝剂_枸橼酸钠浓度百分比: string;
+    抗凝剂_肝素单位: string;
+    抗凝剂_阿加曲班单位: string;
+    eSA_皮下剂量单位: string;
+    抗高血压药_分类: any[];
+    抗凝剂_枸橼酸钠_使用时间分钟: string;
+    抗凝剂_肝素追加速率_IU每小时: string;
+    铁剂_口服种类: string;
+    透析器膜面积: string;
+    抗凝剂_是否使用华法林: string;
+    抗凝剂_低分子肝素追加剂量_IU: string;
+    eSA_其它促红素说明: string;
+    铁剂_口服剂量单位: string;
+    铁剂_静脉剂量单位: string;
+}
+
+interface FeeDrugInfo {
+    drugBarcode: string;
+    drugIsNeedTest: number;
+    drugUsePeriodName: string;
+    drugProduceLocation: string;
+    drugPriceYibao: number;
+    drugUseTypeName: string;
+    drugPermissionCode: string;
+    drugCategory: number;
+    drugPackageType: number;
+    drugPackageUnitAlias: string;
+    drugSpec: string;
+    drugAntibioticLevel: number;
+    drugJixing: string;
+    drugHisCode: any | null;
+    drugInventoryPackageTypeName: any | null;
+    drugBenweiCode: string;
+    id: number;
+    drugUseMethodName: string;
+    drugIsFavor: number;
+    drugPackageUnitName: string;
+    drugPackageSum: number;
+    drugSortOrder: number;
+    drugYibaoCode: string;
+    inventoryItemDetailCode: string;
+    drugName2: string;
+    drugUseUnitName: string;
+    drugUnit: string;
+    drugUsePeriod: string;
+    drugInventoryPackageCount: number;
+    drugUseMethod: string;
+    drugName: string;
+    drugUseUnit: string;
+    drugInventoryPackageType: string;
+    drugUseOnetime: string;
+    code: string;
+    drugCode: string;
+    drugPackageUnit: string;
+    drugProduceFactoryName: any | null;
+    drugYlCode: string;
+    remark: string;
+    drugLimitUseText: string;
+    drugProduceFactory: string;
+    drugUnitName: string;
+    isDeleted: number;
+    drugInventoryAlertDays: number;
+    drugPriceIn: number;
+    drugStatus: number;
+    drugPriceCategory: number;
+    drugVsDiagnoseName: any | null;
+    drugSyncPrice: number;
+    deletedTime: any | null;
+    drugPackageUnitAliasName: string;
+    drugPinyin: string;
+    drugVsDiagnose: string;
+    drugGansuUseLimit: any | null;
+    drugProperty: string;
+    drugJixingName: string;
+    drugPriceSale: number;
+    updateUser: any | null;
+    drugTransfer1: any | null;
+    updateTime: number;
+    drugTransfer2: any | null;
+    drugUseType: string;
+    drugLimitUseType: number;
+    drugInventoryAlertValidDays: number;
+    createTime: number;
+    createUser: any | null;
+    drugMonitorCode: string;
+    drugPlusPercent: number;
+    drugInHospitalUseType: number;
+    drugSpecialProperty: number;
+    drugBaseType: number;
+}
+
+interface OrderFromInfo {
+    code: string;
+    dictIsCustom: number;
+    updateUser: any | null;
+    remark: any | null;
+    updateTime: number;
+    dictNo: string;
+    dictType: string;
+    dictIsEnable: number;
+    isDeleted: number;
+    createTime: number;
+    hisCode: any | null;
+    sortOrder: number;
+    createUser: any | null;
+    id: number;
+    deletedTime: any | null;
+    dictText: string;
+}
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
new file mode 100644
index 0000000..6efe7bc
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
@@ -0,0 +1,211 @@
+<template>
+  <div class="bedside-auxiliary-screen-header">
+    <div class="header-left">
+      <!-- 没有设备编号 -->
+      <span v-if="pageType === 0" class="info-text">未绑定设备</span>
+      <template v-else>
+        <!-- 设备号 -->
+        <span class="info-text">{{
+          bedsideAuxiliaryScreenStore.deviceData.devicdeNo
+        }}</span>
+        <!-- 加载中 -->
+        <span v-if="pageType === 1" class="info-text"
+          >页面初始化中,请耐心等待!</span
+        >
+        <!-- 未排班 -->
+        <span v-else-if="pageType === 2" class="info-text">当前尚未排班</span>
+        <!-- 有排班 -->
+        <template v-else>
+          <span class="info-text">{{ patientInfo.patientName }}</span>
+          <span class="info-text">{{ patientInfo.age }}岁</span>
+          <span class="info-text">{{ patientInfo.gender }}</span>
+          <span v-if="patientInfo.patFormNumber" class="info-text">
+            {{ patientInfo.patForm }}:{{ patientInfo.patFormNumber }}</span
+          >
+        </template>
+        {{ taskCountdown }}
+      </template>
+    </div>
+    <div class="header-right">
+      <img
+        :src="atRegularTimeImg"
+        class="btn-img"
+        alt=""
+        @click="openScheduledTaskDialog"
+      />
+      <img
+        :src="setUpImg"
+        class="btn-img"
+        alt=""
+        @click="openSettingDeviceDialog"
+      />
+      <img :src="userImg" class="btn-img" alt="" @click="openLoginDialog" />
+    </div>
+  </div>
+  <!-- 设置设备编号组件 -->
+  <SettingDeviceDialog ref="settingDeviceDialogRef" />
+  <!-- 定时任务组件 -->
+  <ScheduledTaskDialog ref="scheduledTaskDialogRef" />
+</template>
+
+<script lang="ts" setup name="Header">
+import {
+  ref,
+  computed,
+  defineAsyncComponent,
+  onMounted,
+  onUnmounted,
+  watch,
+} from "vue";
+import dayjs from "dayjs";
+import type { Task } from "@/store/type/task.type";
+const SettingDeviceDialog = defineAsyncComponent(
+  () => import("./SettingDeviceDialog.vue")
+);
+const ScheduledTaskDialog = defineAsyncComponent(
+  () => import("./ScheduledTask.vue")
+);
+import atRegularTimeImg from "../../../../img/dingshi.png";
+import setUpImg from "../../../../img/shezhi.png";
+import userImg from "../../../../img/user.png";
+
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import { EPatForm } from "@/store/type/bedsideAuxiliaryScreen.type";
+import { ElMessage } from "element-plus";
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+let timer: number;
+
+const settingDeviceDialogRef = ref<any>(null);
+const scheduledTaskDialogRef = ref<any>(null);
+const taskCountdown = ref(""); // 定时任务倒计时文本
+
+const pageType = computed(() => {
+  return bedsideAuxiliaryScreenStore.deviceData.pageType;
+});
+
+const patientInfo = computed(() => {
+  return {
+    patientName: bedsideAuxiliaryScreenStore.deviceData.patientName,
+    patientPhone: bedsideAuxiliaryScreenStore.deviceData.patientPhone,
+    age: bedsideAuxiliaryScreenStore.deviceData.age,
+    gender: bedsideAuxiliaryScreenStore.deviceData.gender,
+    patForm:
+      bedsideAuxiliaryScreenStore.deviceData.patForm ===
+      EPatForm.OUTPATIENT_SERVICE
+        ? "门诊号"
+        : "住院号",
+    patFormNumber: bedsideAuxiliaryScreenStore.deviceData.patFormNumber,
+  };
+});
+
+watch(
+  () => bedsideAuxiliaryScreenStore.taskData,
+  (newData: Task[]) => {
+    console.log('定时任务更新了')
+    if (
+      bedsideAuxiliaryScreenStore.deviceData.deviceCode &&
+      newData.length > 0
+    ) {
+      console.log('newData: ', newData)
+      updateCountdown(newData[0].taskDate);
+    } else {
+      taskCountdown.value = "";
+    }
+  },
+  { deep: true }
+);
+
+const openSettingDeviceDialog = () => {
+  settingDeviceDialogRef.value?.openDialog();
+};
+
+const openScheduledTaskDialog = () => {
+  scheduledTaskDialogRef.value?.openDialog();
+};
+
+const openLoginDialog = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+
+const getCountdown = (taskDate: string) => {
+  const now = dayjs();
+  const target = dayjs(taskDate).second(0).millisecond(0);
+
+  const diff = target.diff(now, "second");
+
+  if (diff <= 0) return "";
+
+  const minutes = Math.floor(diff / 60);
+  const seconds = diff % 60;
+
+  return `${minutes}m${seconds}s`;
+};
+
+const updateCountdown = (taskDate: string) => {
+  taskCountdown.value = getCountdown(taskDate);
+  timer = window.setInterval(updateCountdown, 1000);
+};
+
+onMounted(() => {
+  if (
+    bedsideAuxiliaryScreenStore.deviceData.deviceCode &&
+    bedsideAuxiliaryScreenStore.taskData.length > 0
+  ) {
+    getCountdown(bedsideAuxiliaryScreenStore.taskData[0].taskDate);
+  }
+});
+
+onUnmounted(() => {
+  timer && clearInterval(timer);
+});
+</script>
+
+<style lang="less" scoped>
+.bedside-auxiliary-screen-header {
+  height: 25px;
+  padding: 0 15px 0 12px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background: #70a3dd;
+  border-radius: 1px 0px 5px 5px;
+  .header-left {
+    display: flex;
+    align-items: center;
+    .info-text {
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 600;
+      font-size: 11px;
+      color: #ffffff;
+      text-align: left;
+      font-style: normal;
+      &:not(:first-child) {
+        margin-left: 6px;
+      }
+    }
+  }
+  .header-right {
+    display: flex;
+    align-items: center;
+    .btn-img {
+      height: 10px;
+      object-fit: contain;
+      cursor: pointer;
+      &:not(:first-child) {
+        margin-left: 9px;
+      }
+      &:active {
+        opacity: 0.6;
+        transform: scale(0.95);
+      }
+
+      transition: all 0.2s;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/ProgressBar.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/ProgressBar.vue
new file mode 100644
index 0000000..c92f52f
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/ProgressBar.vue
@@ -0,0 +1,45 @@
+<template>
+  <div class="progress-container" :style="{ backgroundColor: props.backgroundColor || '#d6def1' }">
+    <div
+      class="progress-bar"
+      :style="{
+        width: computedWidth,
+        backgroundColor: color,
+        borderRadius: '0 999px 999px 0',
+      }"
+    ></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed } from "vue";
+
+interface Props {
+  percent: number; // 0 ~ 100
+  color?: string;
+  backgroundColor?: string;
+  borderRadius?: string;
+}
+
+const props = defineProps<Props>();
+
+const computedWidth = computed(
+  () => Math.min(Math.max(props.percent, 0), 100) + "%"
+);
+</script>
+
+<style scoped>
+.progress-container {
+  width: 46px;
+  height: 6px;
+  background: #d6def1;
+  border-radius: 999px;
+  overflow: hidden;
+}
+
+.progress-bar {
+  height: 100%;
+  transition: width 0.3s ease;
+  border-radius: 0 999px 999px 0;
+}
+</style>
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue
new file mode 100644
index 0000000..9a4e12b
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue
@@ -0,0 +1,438 @@
+<template>
+  <div class="scheduled-task-container">
+    <el-dialog
+      v-model="isShow"
+      center
+      title="定时任务"
+      width="80%"
+      :show-close="false"
+      class="scheduled-task-dialog"
+      top="0"
+    >
+      <template #header>
+        <div class="scheduled-task-header">
+          <span class="header-title">创建定时任务</span>
+          <img
+            :src="closeImg"
+            class="header-close"
+            @click="handleCancel"
+            alt=""
+          />
+        </div>
+      </template>
+      <div class="scheduled-task-content">
+        <div class="content-left">
+          <div class="content-left-date">
+            <TimePicker v-model="timeValue" />
+            <div class="date-btn">
+              <div
+                v-for="(item, index) in dateOptions"
+                :key="index"
+                class="my-button date"
+                @click="onAddMinutesClick(item)"
+              >
+                {{ item.label }}
+              </div>
+            </div>
+          </div>
+          <div class="content-left-stereotyped-writing">
+            <div class="stereotyped-writing">
+              <input
+                v-model.trim="taskName"
+                type="text"
+                :disabled="isInpDisabled"
+                class="stereotyped-writing-input"
+                placeholder="请输入自定义内容"
+              />
+            </div>
+            <div class="stereotyped-writing-list">
+              <div
+                v-for="(item, index) in taskOptions"
+                :key="index"
+                class="my-button list-item"
+                @click="onStereotypedWritingClick(item)"
+                :class="taskItemCheck === item.value ? 'check' : ''"
+              >
+                {{ item.label }}
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="content-right"></div>
+      </div>
+      <template #footer>
+        <div class="my-button cancel" @click="handleCancel">取消</div>
+        <div class="my-button confirm" @click="handleConfirm">确认</div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from "vue";
+import dayjs from "dayjs";
+import { setTimeoutAlert } from "@/utils/httpApi";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+
+// @ts-ignore
+import TimePicker from "./TimePicker.vue";
+
+import closeImg from "@/img/close.png";
+import alertbaojin from "@/assets/alert.wav";
+import cxybaojing from "@/assets/cxy.mp3";
+import gybaojing from "@/assets/gy.mp3";
+import kclbaojing from "@/assets/kcl.mp3";
+import tdddbaojing from "@/assets/tzddd.mp3";
+import tzxllbaojing from "@/assets/tzxll.mp3";
+import cgbaojing from "@/assets/cg.mp3";
+import { ElMessage } from "element-plus";
+
+interface TaskItem {
+  label: string;
+  value: string;
+  backgroundColor: string;
+  promptTone: string;
+}
+
+interface DateItem {
+  label: string;
+  value: number;
+}
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+const isShow = ref(false);
+
+const taskName = ref(""); // 任务名称
+const isInpDisabled = ref(false); // 输入框是否禁用
+
+const timeValue = ref("");
+
+const detaCheck = ref<number | null>(); // 这个是判断时间按钮的
+
+const loading = ref(false);
+
+const taskOptions = ref<TaskItem[]>([
+  {
+    label: "测血压",
+    value: "测血压",
+    backgroundColor: "#E6A23C",
+    promptTone: cxybaojing,
+  },
+  {
+    label: "开超滤",
+    value: "开超滤",
+    backgroundColor: "#E6A23C",
+    promptTone: kclbaojing,
+  },
+  {
+    label: "给药",
+    value: "给药",
+    backgroundColor: "#E6A23C",
+    promptTone: gybaojing,
+  },
+  {
+    label: "调电导度",
+    value: "调电导度",
+    backgroundColor: "#E6A23C",
+    promptTone: tdddbaojing,
+  },
+  {
+    label: "调血流量",
+    value: "调血流量",
+    backgroundColor: "#E6A23C",
+    promptTone: tzxllbaojing,
+  },
+  {
+    label: "冲管",
+    value: "冲管",
+    backgroundColor: "#E6A23C",
+    promptTone: cgbaojing,
+  },
+]);
+
+const dateOptions = ref<DateItem[]>([
+  { label: "15分钟", value: 15 },
+  { label: "30分钟", value: 30 },
+  { label: "45分钟", value: 45 },
+  { label: "60分钟", value: 60 },
+]);
+
+const taskItemCheck = computed(() => {
+  return taskOptions.value.find((e) => e.value === taskName.value)?.value || "";
+});
+
+const openDialog = () => {
+  isShow.value = true;
+  const time = dayjs();
+  timeValue.value = time.format("HH:mm");
+};
+
+const onStereotypedWritingClick = (item: TaskItem) => {
+  if (taskName.value === item.value) {
+    taskName.value = "";
+    isInpDisabled.value = false;
+  } else {
+    taskName.value = item.value;
+    isInpDisabled.value = true;
+  }
+};
+
+const onAddMinutesClick = (item: DateItem) => {
+  // if (detaCheck.value === item.value) {
+  //     detaCheck.value = null;
+  //     timeValue.value = addMinutes(timeValue.value, -item.value)
+  // } else {
+  detaCheck.value = item.value;
+  timeValue.value = addMinutes(timeValue.value, item.value);
+  // console.log('addMinutes(timeValue.value, item.value): ', addMinutes(timeValue.value, item.value))
+  // }
+};
+
+const addMinutes = (time: string, delta: number): string => {
+  const [hours, minutes] = time.split(":").map(Number);
+  const totalMinutes = hours * 60 + minutes + delta;
+
+  // 处理负数和超过 1440(一天分钟数)情况
+  const normalized = (totalMinutes + 1440) % 1440;
+
+  const newHours = Math.floor(normalized / 60);
+  const newMinutes = normalized % 60;
+
+  return `${newHours.toString().padStart(2, "0")}:${newMinutes
+    .toString()
+    .padStart(2, "0")}`;
+};
+
+const handleCancel = () => {
+  isShow.value = false;
+};
+
+const handleConfirm = async () => {
+  const today = dayjs().format("YYYY-MM-DD");
+  const fullDateTime = dayjs(`${today} ${timeValue.value}`).second(0).millisecond(0); // 秒和毫秒都去掉,要不然间隔短了就是0分钟
+
+  const now = dayjs().second(0).millisecond(0);; // 秒和毫秒都去掉
+  if (!fullDateTime.isAfter(now))
+    return ElMessage.warning("任务提醒时间不能早于或等于当前时间");
+  if (!taskName.value) return ElMessage.warning("任务内容不能为空");
+  loading.value = true;
+  try {
+    const diffMinutes = fullDateTime.diff(now, "minute");
+    const params = {
+      deviceCode: bedsideAuxiliaryScreenStore.deviceData.deviceCode,
+      minutes: diffMinutes,
+      alertText: taskName.value,
+    }
+    const recordCode = bedsideAuxiliaryScreenStore.deviceData.recordCode;
+    const { data, message } = await setTimeoutAlert(params);
+    if (data !== "OK") return ElMessage.warning(message);
+    ElMessage.success('操作成功');
+    bedsideAuxiliaryScreenStore.setSyncTask({
+        deviceCode: params.deviceCode,
+        recordCode: recordCode,
+        taskDate: dayjs(fullDateTime).format("YYYY-MM-DD HH:mm"),
+        taskName: params.alertText,
+        overdue: false
+    });
+    handleCancel();
+  } finally {
+    loading.value = false;
+  }
+};
+
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+.scheduled-task-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;
+  }
+  .scheduled-task-header {
+    position: relative;
+    height: 16px;
+    background: #ff7472;
+    .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);
+      }
+    }
+  }
+  .scheduled-task-content {
+    padding: 0 12px 0px;
+    margin-bottom: 4px;
+    border-bottom: 1px solid #d8d8d8;
+    display: flex;
+    .content-left {
+      flex: 1;
+      border-right: 1px solid #d8d8d8;
+      padding-bottom: 6px;
+      padding-right: 12px;
+      .content-left-date {
+        border-bottom: 1px solid #d8d8d8;
+        display: flex;
+
+        .date-btn {
+          flex: 1;
+          display: flex;
+          flex-wrap: wrap;
+          gap: 9px;
+          margin-left: 5px;
+          justify-content: flex-end;
+          .date {
+            margin-left: 0;
+            padding: 0;
+            width: 50px;
+            height: 23px;
+            line-height: 23px;
+            text-align: center;
+            font-size: 11px;
+            background-color: #769aff;
+          }
+        }
+      }
+      .content-left-stereotyped-writing {
+        .stereotyped-writing {
+          position: relative;
+          height: 16px;
+          padding-top: 6px;
+          margin-bottom: 6px;
+          border-radius: 2px;
+          border: 1px solid #979797;
+          overflow: hidden;
+          .stereotyped-writing-input {
+            position: absolute;
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 100%;
+            border: none;
+            outline: none;
+            padding: 0 4px;
+            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;
+            }
+            &:disabled {
+              background-color: #f5f5f5; // 灰色背景
+              color: #999999; // 灰色文字
+              cursor: not-allowed;
+            }
+          }
+        }
+        .stereotyped-writing-list {
+          display: flex;
+          flex-wrap: wrap;
+          gap: 7px;
+          .list-item {
+            width: 40px;
+            margin-left: 0;
+            padding-left: 0;
+            padding-right: 0;
+            background-color: #e6a23c;
+            &.check {
+              background-color: #bbc6dd;
+            }
+          }
+        }
+      }
+    }
+    .content-right {
+      width: 59px;
+    }
+  }
+  .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>
+<style>
+.scheduled-task-dialog {
+  margin: 0 auto;
+  top: 50% !important;
+  transform: translateY(-50%) !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue
new file mode 100644
index 0000000..10d1d6e
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/SettingDeviceDialog.vue
@@ -0,0 +1,330 @@
+<template>
+  <div class="setting-device-dialog-container">
+    <el-dialog
+      v-model="isShow"
+      center
+      title="设置编号"
+      width="80%"
+      :show-close="false"
+      class="scheduled-task-dialog"
+    >
+      <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 + "");
+  handleRefresh();
+  handleCancel();
+};
+
+const handleRefresh = () => {
+    bedsideAuxiliaryScreenStore.refresh(
+    `${import.meta.env.VITE_SSE_BASE_URL}${devcieCode.value}`
+  );
+};
+
+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; 
+          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>
+<style>
+.scheduled-task-dialog {
+  margin: 0 auto;
+  top: 50% !important;
+  transform: translateY(-50%) !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue
new file mode 100644
index 0000000..1f1376f
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue
@@ -0,0 +1,248 @@
+<template>
+  <div class="time-picker">
+    <div class="picker-column" ref="hourRef" @scroll="onScroll('hour')">
+      <div
+        v-for="(h, index) in loopHours"
+        :key="index"
+        class="picker-item hours"
+        :class="getClassByIndex(index, selectedIndexHour)"
+        :style="getStyleByIndex(index, selectedIndexHour)"
+      >
+        {{ h.toString().padStart(2, "0") }}
+      </div>
+    </div>
+    <span class="colon">:</span>
+    <div class="picker-column" ref="minuteRef" @scroll="onScroll('minute')">
+      <div
+        v-for="(m, index) in loopMinutes"
+        :key="index"
+        class="picker-item minutes"
+        :class="getClassByIndex(index, selectedIndexMinute)"
+        :style="getStyleByIndex(index, selectedIndexMinute)"
+      >
+        {{ m.toString().padStart(2, "0") }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, onMounted, nextTick } from "vue";
+
+const props = defineProps<{ modelValue: string }>();
+const emit = defineEmits(["update:modelValue"]);
+
+const hours = Array.from({ length: 24 }, (_, i) => i);
+const minutes = Array.from({ length: 60 }, (_, i) => i);
+
+// 为循环滚动,前面后面都各补两个,要不要选不中最后一个
+function createLoopArray(arr: number[]) {
+  return [...arr.slice(-2), ...arr, ...arr.slice(0, 2)];
+}
+
+const loopHours = createLoopArray(hours);
+const loopMinutes = createLoopArray(minutes);
+
+const hourRef = ref<HTMLElement | null>(null);
+const minuteRef = ref<HTMLElement | null>(null);
+
+const ITEM_REM = 0.4;
+const itemHeight = remToPx(ITEM_REM);
+
+const selectedIndexHour = ref(2);
+const selectedIndexMinute = ref(2);
+
+const selectedHour = ref(hours[0]);
+const selectedMinute = ref(minutes[0]);
+
+// 标记程序主动滚动,防止滚动事件死循环
+const isProgrammaticScroll = {
+  hour: false,
+  minute: false,
+};
+
+// 初始化滚动,选中传入时间
+onMounted(() => {
+  const [h, m] = props.modelValue.split(":").map(Number);
+  const hourIdx = hours.indexOf(h);
+  const minuteIdx = minutes.indexOf(m);
+
+  selectedIndexHour.value = hourIdx === -1 ? 2 : hourIdx + 2;
+  selectedIndexMinute.value = minuteIdx === -1 ? 2 : minuteIdx + 2;
+
+  selectedHour.value = h;
+  selectedMinute.value = m;
+
+  nextTick(() => {
+    scrollToSelected("hour", selectedIndexHour.value);
+    scrollToSelected("minute", selectedIndexMinute.value);
+  });
+});
+
+watch(
+  () =>
+    `${selectedHour.value.toString().padStart(2, "0")}:${selectedMinute.value
+      .toString()
+      .padStart(2, "0")}`,
+  (val) => {
+    emit("update:modelValue", val);
+  }
+);
+
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    const [h, m] = newVal.split(":").map(Number);
+    const hourIdx = hours.indexOf(h);
+    const minuteIdx = minutes.indexOf(m);
+
+    if (hourIdx !== -1) {
+      selectedIndexHour.value = hourIdx + 2;
+      selectedHour.value = h;
+      scrollToSelected("hour", selectedIndexHour.value);
+    }
+
+    if (minuteIdx !== -1) {
+      selectedIndexMinute.value = minuteIdx + 2;
+      selectedMinute.value = m;
+      scrollToSelected("minute", selectedIndexMinute.value);
+    }
+  }
+);
+
+function onScroll(type: "hour" | "minute") {
+  if (isProgrammaticScroll[type]) {
+    // 程序滚动,忽略,避免死循环
+    isProgrammaticScroll[type] = false;
+    return;
+  }
+
+  const refEl = type === "hour" ? hourRef.value : minuteRef.value;
+  if (!refEl) return;
+
+  const scrollTop = refEl.scrollTop;
+  let index = Math.round(scrollTop / itemHeight + 2);
+
+  const arrLen = type === "hour" ? hours.length : minutes.length;
+
+  if (index < 2) {
+    isProgrammaticScroll[type] = true;
+    refEl.scrollTop = itemHeight * (arrLen + (index - 2));
+    index = arrLen + (index - 2);
+  } else if (index > arrLen + 1) {
+    isProgrammaticScroll[type] = true;
+    refEl.scrollTop = itemHeight * (index - arrLen - 2);
+    index = index - arrLen - 2;
+  }
+
+  if (type === "hour") {
+    selectedIndexHour.value = index;
+    selectedHour.value = loopHours[index];
+  } else {
+    selectedIndexMinute.value = index;
+    selectedMinute.value = loopMinutes[index];
+  }
+}
+
+function scrollToSelected(type: "hour" | "minute", index: number) {
+  const refEl = type === "hour" ? hourRef.value : minuteRef.value;
+  if (!refEl) return;
+
+  isProgrammaticScroll[type] = true;
+  refEl.scrollTo({
+    top: (index - 2) * itemHeight,
+    behavior: "auto",
+  });
+}
+
+function getClassByIndex(index: number, selectedIndex: number) {
+  const diff = Math.abs(index - selectedIndex);
+  return {
+    active: diff === 0,
+    medium: diff === 1,
+    small: diff === 2,
+  };
+}
+
+function getStyleByIndex(index: number, selectedIndex: number) {
+  const diff = Math.min(Math.abs(index - selectedIndex), 2);
+  return {
+    opacity: diff === 2 ? 0.4 : 1,
+    zIndex: 10 - diff,
+    transition: "opacity 0.3s ease",
+  };
+}
+
+function remToPx(rem: number) {
+  return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
+}
+</script>
+
+<style scoped lang="less">
+.time-picker {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 2rem; // 5 * 0.4rem 每个item高度0.4rem
+  overflow: hidden;
+
+  .picker-column {
+    height: 2rem;
+    width: 0.9rem;
+    overflow-y: scroll;
+    scroll-snap-type: y mandatory;
+    -webkit-overflow-scrolling: touch;
+    scrollbar-width: none; /* Firefox */
+    -ms-overflow-style: none; /* IE 10+ */
+    &::-webkit-scrollbar {
+      display: none; /* Chrome Safari */
+    }
+
+    .picker-item {
+      height: 0.4rem;
+      line-height: 0.4rem;
+      text-align: center;
+      font-size: 0.24rem;
+      scroll-snap-align: center;
+      user-select: none;
+      cursor: pointer;
+      transition: color 0.3s ease, font-size 0.3s ease;
+
+      &.active {
+        font-size: 0.5rem;
+        font-weight: 700;
+        color: #111;
+        &.hours {
+          text-align: left;
+        }
+        &.minutes {
+          text-align: right;
+        }
+      }
+      &.medium {
+        font-size: 0.3rem;
+        color: #666;
+        &.hours {
+          text-align: left;
+          padding-left: 0.2rem;
+        }
+        &.minutes {
+          text-align: right;
+          padding-right: 0.2rem;
+        }
+      }
+      &.small {
+        font-size: 0.24rem;
+        color: #aaa;
+      }
+    }
+  }
+
+  .colon {
+    font-size: 0.5rem;
+    font-weight: 600;
+    color: #444;
+    user-select: none;
+  }
+}
+</style>
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/index.vue
new file mode 100644
index 0000000..ab6c350
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/index.vue
@@ -0,0 +1,93 @@
+<template>
+  <div class="bedside-auxiliary-screen-container" :style="{ backgroundColor: backgroundColor }">
+    <Header />
+    <div class="bedside-auxiliary-screen-content">
+        <div class="content-position"></div>
+        <!-- <UnplannedSchedule v-if="cotentHeight > 0" :height="cotentHeight"  /> -->
+        <component v-if="cotentHeight > 0" :is="currentComponent" :height="cotentHeight" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, watch, computed, onMounted, defineAsyncComponent } from "vue";
+// @ts-ignore
+import Header from "./components/Header.vue";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import { EPageType } from '@/store/type/bedsideAuxiliaryScreen.type';
+import { getAvailableHeightByClass } from '@/utils/utils';
+import { useWindowSize } from '@/composables/useWindowSize';
+// 未排班时的组件
+const UnplannedSchedule = defineAsyncComponent(() => import('./pages/UnplannedSchedule.vue'));
+// 未签到时的组件
+const NotSignedIn = defineAsyncComponent(() => import('./pages/NotSignedIn.vue'));
+// 已签到时的组件
+const SignedIn = defineAsyncComponent(() => import('./pages/SignedIn.vue'));
+// 治疗中的组件
+const UnderTreatment = defineAsyncComponent(() => import('./pages/UnderTreatment.vue'));
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+const cotentHeight = ref(0);
+const { width, height } = useWindowSize();
+
+
+const backgroundColor = computed(() => {
+  let color = '#DAE5EC';
+  // 如果是未排班、加载中或未签到页面,背景色为白色
+  if ([EPageType.NOT_INIT, EPageType.LOADING, EPageType.UNPLANNED_SCHEDULE].includes(bedsideAuxiliaryScreenStore.deviceData.pageType)) {
+    color = '#fff';
+  }
+  return color;
+});
+
+const currentComponent = computed(() => {
+  let name: any = UnplannedSchedule;
+  // 未排班
+  if ([EPageType.NOT_INIT, EPageType.LOADING, EPageType.UNPLANNED_SCHEDULE].includes(bedsideAuxiliaryScreenStore.deviceData.pageType)) {
+    name = UnplannedSchedule;
+  }
+  // 未签到
+  else if (bedsideAuxiliaryScreenStore.deviceData.pageType === EPageType.NOT_SIGNED_IN) {
+    name = NotSignedIn
+  } 
+  // 已签到
+  else if (bedsideAuxiliaryScreenStore.deviceData.pageType === EPageType.SIGNED_IN) {
+    name = SignedIn;
+  }
+  // 透析中 
+  else {
+    name = UnderTreatment;
+  }
+  return name;
+});
+
+watch([width, height], () => {
+  cotentHeight.value = getAvailableHeightByClass('content-position')
+});
+
+
+onMounted(() => {
+  if (bedsideAuxiliaryScreenStore.deviceCode) {
+    bedsideAuxiliaryScreenStore.connect(
+      `${import.meta.env.VITE_SSE_BASE_URL}${
+        bedsideAuxiliaryScreenStore.deviceCode
+      }`
+    );
+  }
+  cotentHeight.value = getAvailableHeightByClass('content-position')
+});
+</script>
+
+<style lang="less" scoped>
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+.bedside-auxiliary-screen-container {
+  background-color: #409eff;
+  .bedside-auxiliary-screen-content {
+    padding: 6px 12px 0;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/NotSignedIn.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/NotSignedIn.vue
new file mode 100644
index 0000000..7f3d657
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/NotSignedIn.vue
@@ -0,0 +1,320 @@
+<template>
+  <div class="not-signed-in-container" :style="{ '--height': height + 'px' }">
+    <div class="row1-container">
+      <div class="row1-left">
+        <el-image
+          :src="pageData.patientPhone"
+          style="width: 100%; height: 100%"
+        >
+          <template #placeholder>
+            <div class="image-slot">加载中<span class="dot">...</span></div>
+          </template>
+        </el-image>
+      </div>
+      <div class="row1-center">
+        <div class="row1-center-row1">
+          <Card
+            title="透析模式"
+            :icon="tslImg"
+            background-color="#E5EEFF"
+            class="row1-center-row1-item"
+          >
+            <div class="dialysis-mode-content">
+              <span>{{ pageData.dialysisMode }}</span>
+            </div>
+          </Card>
+          <Card
+            title="治疗模式"
+            :icon="tslImg"
+            background-color="#F1EEFA"
+            class="row1-center-row1-item"
+          >
+            <div class="dialysis-mode-content item-2">
+              <span>未签到</span>
+            </div>
+          </Card>
+        </div>
+        <Card
+          title="一次性使用管路"
+          :icon="tslImg"
+          background-color="#D9F0E2"
+          class="row1-center-row2"
+        >
+          <div class="list-box-1">
+            <div
+              v-for="(item, index) in pageData.pipingList"
+              :key="index"
+              class="list-item"
+              style="color: #3ab859"
+            >
+              <div class="list-item-left">
+                {{ item.name }}
+              </div>
+              <div class="list-item-right">{{ item.数量 }}{{ item.单位 }}</div>
+            </div>
+          </div>
+        </Card>
+      </div>
+      <div class="row1-right">
+        <Card
+          title="透析器"
+          :icon="tslImg"
+          background-color="#F9DEDE"
+          class="row1-right-item"
+        >
+          <div class="list-box-1">
+            <div
+              v-for="(item, index) in pageData.dialyzerList"
+              :key="index"
+              class="list-item"
+            >
+              <div class="list-item-left">
+                {{ item.name }}
+              </div>
+              <div class="list-item-right">{{ item.数量 }}{{ item.单位 }}</div>
+            </div>
+          </div>
+        </Card>
+        <Card
+          title="透析液"
+          :icon="tslImg"
+          background-color="#EFE5FF"
+          class="row1-right-item"
+        >
+          <div class="list-box-1">
+            <div
+              v-for="(item, index) in pageData.dialysateList"
+              :key="index"
+              class="list-item"
+            >
+              <div class="list-item-left">
+                {{ item.name }}
+              </div>
+              <div class="list-item-right">{{ item.数量 }}{{ item.单位 }}</div>
+            </div>
+          </div>
+        </Card>
+      </div>
+    </div>
+    <div class="row2-container">
+      <Card
+        title="抗凝剂"
+        :icon="tslImg"
+        background-color="#FFEDD2"
+        class="row-item"
+      >
+        <div class="list-box-2">
+          <div
+            v-for="(item, index) in pageData.anticoagulant"
+            :key="index"
+            class="list-item"
+          >
+            <div class="list-item-name">
+              {{ item.name }}
+            </div>
+            <div class="list-item-num">
+              <span>首剂:{{ item.首剂 }}{{ item.单位 }}</span>
+              <span>追加/维持:{{ item.是否为追加 ? item.追加剂量 : item.维持剂量  }}{{ item.单位 }}</span>
+              <span>总量:{{ item.总量 }}{{ item.单位 }}</span>
+            </div>
+          </div>
+        </div>
+      </Card>
+      <Card
+        title="一次性使用透析护理包"
+        :icon="tslImg"
+        background-color="#E5EEFF"
+        class="row-item"
+      >
+        <div class="list-box-1">
+          <div
+            v-for="(item, index) in pageData.carePackage"
+            :key="index"
+            class="list-item"
+            style="color: #1D77BD"
+          >
+            <div class="list-item-left">
+              {{ item.name }}
+            </div>
+            <div class="list-item-right">{{ item.数量 }}{{ item.单位 }}</div>
+          </div>
+        </div>
+      </Card>
+    </div>
+    <div class="row3-container">
+      <Card
+        title="穿刺针"
+        :icon="tslImg"
+        background-color="#FFEDD2"
+        class="row-item"
+      >
+        <div class="list-box-1">
+          <div
+            v-for="(item, index) in pageData.punctureNeedle"
+            :key="index"
+            class="list-item"
+            style="color: #A78718"
+          >
+            <div class="list-item-left">
+              {{ item.name }}
+            </div>
+            <div class="list-item-right">{{ item.数量 }}{{ item.单位 }}</div>
+          </div>
+        </div>
+      </Card>
+      <Card
+        title="血管通路"
+        :icon="tslImg"
+        background-color="#E5EEFF"
+        class="row-item"
+      >
+        <div class="list-box-1">
+          <div
+            v-for="(item, index) in pageData.vascularAccess"
+            :key="index"
+            class="list-item"
+            style="color: #1D77BD"
+          >
+            <div class="list-item-left">{{ item.位置 }} {{ item.类型 }}</div>
+          </div>
+        </div>
+      </Card>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup name="NotSignedIn">
+import { computed } from "vue";
+// @ts-ignore
+import Card from "../components/Card.vue";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import tslImg from "@/img/tsl.png";
+
+interface Props {
+  height: number;
+}
+const props = defineProps<Props>();
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+const pageData = computed(() => {
+  return Object.assign(bedsideAuxiliaryScreenStore.deviceData.notSignedIn, {
+    patientPhone: bedsideAuxiliaryScreenStore.deviceData.patientPhone,
+  });
+});
+</script>
+
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+
+.not-signed-in-container {
+  display: flex;
+  flex-direction: column;
+  height: var(--height);
+  gap: 4px; // 行间间距
+  overflow: hidden;
+  padding-bottom: 2px;
+
+  .row1-container {
+    display: flex;
+    flex: 59.3; // 59.3%
+    min-height: 0;
+    gap: 4px; // 行间间距
+
+    .row1-left {
+      width: 75px;
+      border-radius: 2px;
+      overflow: hidden;
+    }
+    .row1-center,
+    .row1-right {
+      flex: 1;
+    }
+    .row1-center {
+      display: flex;
+      flex-direction: column;
+      gap: 4px; // 行间间距
+
+      .row1-center-row1 {
+        flex: 1;
+        display: flex;
+        gap: 4px; // 行间间距
+        .row1-center-row1-item {
+          flex: 1;
+          .dialysis-mode-content {
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-family: PingFangSC, PingFang SC;
+            font-weight: 500;
+            font-size: 11px;
+            color: #3a75b8;
+            text-align: center;
+            font-style: normal;
+            &.item-2 {
+              color: #333;
+            }
+          }
+        }
+      }
+      .row1-center-row2 {
+        flex: 1;
+      }
+    }
+    .row1-right {
+      display: flex;
+      flex-direction: column;
+      gap: 4px;
+      .row1-right-item {
+        flex: 1;
+      }
+    }
+  }
+
+  .row2-container,
+  .row3-container {
+    flex: 20.35;
+    min-height: 0;
+    display: flex;
+    gap: 4px;
+    .row-item {
+      flex: 1;
+    }
+  }
+  .list-box-1 {
+    .list-item {
+      display: flex;
+      align-items: center;
+      justify-content: space-around;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 5px;
+      color: #a78718;
+      line-height: 6px;
+      text-align: left;
+      font-style: normal;
+      .list-item-left {
+        flex: 1;
+      }
+      .list-item-right {
+      }
+    }
+  }
+  .list-box-2 {
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 500;
+    font-size: 5px;
+    color: #A78718;
+    text-align: left;
+    font-style: normal;
+    .list-item {
+     &:not(:last-child) {
+        margin-bottom: 3px;
+      }
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
new file mode 100644
index 0000000..68e24e7
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
@@ -0,0 +1,441 @@
+<template>
+  <div class="signed-in-container" :style="{ '--height': height + 'px' }">
+    <div class="row1">
+      <div class="row1-col1">
+        <el-image
+          :src="pageData.patientPhone"
+          style="width: 100%; height: 100%"
+        >
+          <template #placeholder>
+            <div class="image-slot">加载中<span class="dot">...</span></div>
+          </template>
+        </el-image>
+      </div>
+      <div class="row1-col2">
+        <Card
+          title="异常指标"
+          :icon="xinlvImg"
+          background-color="#ffffff"
+          header-class-name="mihi-header"
+        >
+          <div class="dialysis-mode-content">
+            <span
+              v-for="(item, index) in pageData.abnormalItems"
+              :key="index"
+              class="abnormal-indicator"
+              :style="{ color: formatTestColr(item.结果标记) }"
+            >
+              {{ getItemName(item.项目名称) }}
+              {{ formatTestFlag(item.结果标记) }}
+            </span>
+          </div>
+        </Card>
+      </div>
+      <div class="row1-col3">
+        <div class="row1-col3-row1">
+          <Card
+            title="治疗模式"
+            :icon="zlmsImg"
+            background-color="#ffffff"
+            class="row1-col3-row1-item"
+            header-class-name="mihi-header"
+          >
+            <div class="item-box dialysis-mode-content">
+              {{ pageData.dialysisPlan }}
+            </div>
+          </Card>
+          <Card
+            title="治疗状态"
+            :icon="zlztImg"
+            background-color="#ffffff"
+            class="row1-col3-row1-item"
+            header-class-name="mihi-header"
+          >
+            <div class="item-box treatment-status">已签到</div>
+          </Card>
+        </div>
+        <Card
+          title="处方脱水量"
+          :icon="cljdImg"
+          background-color="#ffffff"
+          class="row1-col3-row2"
+          header-class-name="mihi-header"
+        >
+          <div class="item-box prescription-ehydration-olume">
+            {{ pageData.prescriptionDehydrationVolume }} L
+          </div>
+        </Card>
+      </div>
+      <div class="row1-col4">
+        <Card
+          title="透析器(显示规格)"
+          :icon="txqImg"
+          background-color="#ffffff"
+          class="row1-col4-row"
+          header-class-name="mihi-header"
+        >
+          <div class="item-box dialyzer">
+            {{ pageData.dialyzer }}
+          </div>
+        </Card>
+        <Card
+          title="脱水量详情"
+          :icon="cljdImg"
+          background-color="#ffffff"
+          class="row1-col4-row"
+          header-class-name="mihi-header"
+        >
+          <div class="dehydrated-level">
+            <div class="dehydrated-level-item">
+              <span class="item-left"
+                >平均脱水量:{{ pageData.averageDehydrationRate }} L</span
+              >
+              <span class="item-right">(最近3周9次)</span>
+            </div>
+            <div class="dehydrated-level-item">
+              <span class="item-left"
+                >最大脱水量:{{ pageData.maximumDehydrationCapacity }} L</span
+              >
+              <span class="item-right"
+                >({{ pageData.maximumDehydrationCapacityDate }})</span
+              >
+            </div>
+          </div>
+        </Card>
+      </div>
+    </div>
+    <div class="row2">
+      <Card
+        title="干体重"
+        :icon="tizhongImg"
+        background-color="#ffffff"
+        class="row2-item"
+        header-class-name="big-header"
+      >
+        <div class="weight-box">
+          <span class="weight-text">{{ pageData.dryWeight }}</span>
+          <span class="unit-text">kg</span>
+        </div>
+      </Card>
+      <Card
+        title="透前体重"
+        :icon="tizhongImg"
+        background-color="#ffffff"
+        class="row2-item"
+        header-class-name="big-header"
+      >
+        <div class="weight-box">
+          <span class="weight-text">{{ pageData.preDialysisWeight }}</span>
+          <span class="unit-text">kg</span>
+        </div>
+      </Card>
+      <Card
+        title="上次透后体重"
+        :icon="tizhongImg"
+        background-color="#ffffff"
+        class="row2-item"
+        header-class-name="big-header"
+      >
+        <div class="weight-box">
+          <span class="weight-text">{{
+            pageData.weightAfterLastDialysis
+          }}</span>
+          <span class="unit-text">kg</span>
+        </div>
+      </Card>
+      <Card
+        title="体重增长"
+        :icon="tizhongImg"
+        background-color="#ffffff"
+        class="row2-item"
+        header-class-name="big-header"
+      >
+        <div class="weight-box">
+          <span v-if="pageData.weightIncreaseRate > 0" class="weight-text">+</span>
+          <span class="weight-text">{{ pageData.weightIncrease }}</span>
+          <span class="unit-text">kg</span>
+        </div>
+      </Card>
+      <Card
+        title="增长率"
+        :icon="tizhongImg"
+        background-color="#ffffff"
+        class="row2-item"
+        header-class-name="big-header"
+      >
+        <div class="weight-box">
+          <span class="weight-text">{{ pageData.weightIncreaseRate }}</span>
+          <span class="unit-text">%</span>
+        </div>
+      </Card>
+    </div>
+    <div class="row3">
+      <BlockBotttom
+        :icon="dingShiImg"
+        text="定时任务"
+        backgroundColor="#20C6B6"
+        @click="() => onScheduledTasksClick()"
+        class="btn"
+      />
+      <BlockBotttom
+        :icon="jiaoHaoImg"
+        text="叫号"
+        backgroundColor="#20C6B6"
+        @click="() => onCallBumberClick()"
+        class="btn"
+      />
+      <BlockBotttom
+        :icon="kaiShiImg"
+        text="开始"
+        backgroundColor="#409EFF"
+        @click="() => onStartClick()"
+        class="btn"
+      />
+    </div>
+  </div>
+</template>
+<script lang="ts" setup name="SignedIn">
+import { computed } from "vue";
+// @ts-ignore
+import Card from "../components/Card.vue";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import tslImg from "@/img/tsl.png";
+import dingShiImg from "@/img/dingshi2.png";
+import jiaoHaoImg from "@/img/jiaoHao.png";
+import kaiShiImg from "@/img/kaiShi.png";
+import xinlvImg from "@/img/xinlv.png";
+import zlmsImg from "@/img/zlms.png";
+import zlztImg from '@/img/txzt.png';
+import cljdImg from "@/img/cljd.png";
+import txqImg from "@/img/txq.png";
+import tizhongImg from "@/img/tizhong.png";
+
+import {
+  getItemName,
+  formatTestColr,
+  formatTestFlag,
+} from "@/store/type/bedsideAuxiliaryScreen.type";
+// @ts-ignore
+import BlockBotttom from "../components/BlockBotttom.vue";
+import { ElMessage } from "element-plus/es";
+
+interface Props {
+  height: number;
+}
+const props = defineProps<Props>();
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+const pageData = computed(() => {
+  return Object.assign(bedsideAuxiliaryScreenStore.deviceData.signedIn, {
+    patientPhone: bedsideAuxiliaryScreenStore.deviceData.patientPhone,
+  });
+});
+
+/** 点击定时任务 */
+const onScheduledTasksClick = () => {};
+
+const onCallBumberClick = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+
+const onStartClick = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+</script>
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+.signed-in-container {
+  position: relative;
+  height: var(--height);
+  overflow: hidden;
+  .row1 {
+    height: 37.44%;
+    margin-bottom: 4px;
+    overflow: hidden;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .row1-col1 {
+      flex: 0 0 14.86%;
+      height: 100%;
+      border-radius: 2px;
+      overflow: hidden;
+    }
+    .row1-col2 {
+      flex: 0 0 32.86%;
+      height: 100%;
+      .dialysis-mode-content {
+        height: 100%;
+        .abnormal-indicator {
+          display: inline-block;
+          margin-right: 6px;
+          margin-bottom: 4px;
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 600;
+          font-size: 5px;
+          line-height: 6px;
+          text-align: left;
+          font-style: normal;
+        }
+      }
+    }
+    .row1-col3 {
+      flex: 0 0 23.71%;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      gap: 4px;
+      .row1-col3-row1 {
+        flex: 1;
+        display: flex;
+        gap: 4px;
+        .row1-col3-row1-item {
+          flex: 1;
+        }
+      }
+      .row1-col3-row2 {
+        flex: 1;
+      }
+    }
+    .row1-col4 {
+      flex: 0 0 25.14%;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      gap: 4px;
+      .row1-col4-row {
+        flex: 1;
+        .dehydrated-level {
+          padding-left: 6px;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: space-between;
+          .dehydrated-level-item {
+            width: 100%;
+            display: flex;
+            align-items: center;
+            .item-left {
+              flex: 1;
+              font-family: PingFangSC, PingFang SC;
+              font-weight: 600;
+              font-size: 4px;
+              color: #333333;
+              line-height: 6px;
+              font-style: normal;
+            }
+            .item-right {
+              font-family: PingFangSC, PingFang SC;
+              font-weight: 600;
+              font-size: 4px;
+              color: #777777;
+              line-height: 6px;
+              font-style: normal;
+            }
+          }
+        }
+      }
+    }
+  }
+  .row2 {
+    height: 21.72%;
+    overflow: hidden;
+    display: flex;
+    gap: 4px;
+    .row2-item {
+      flex: 1;
+
+      .weight-box {
+        display: flex;
+        align-items: flex-end;
+        justify-content: center;
+        gap: 2px;
+        align-items: baseline;
+        .weight-text {
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 600;
+          font-size: 11px;
+          color: #333333;
+          text-align: center;
+          font-style: normal;
+        }
+        .unit-text {
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 600;
+          font-size: 7px;
+          color: #333333;
+          text-align: center;
+          font-style: normal;
+        }
+      }
+    }
+  }
+  .row3 {
+    position: absolute;
+    width: 100%;
+    bottom: 2px;
+    height: 13.33%;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    padding-right: 13px;
+    overflow: hidden;
+    background: #ffffff;
+    border-radius: 2px;
+    .btn {
+      margin-left: 9px;
+    }
+  }
+  .item-box {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 600;
+    font-size: 8px;
+    color: #70a3dd;
+    text-align: center;
+    font-style: normal;
+    &.dialysis-mode-content {
+      color: #d58e56;
+    }
+    &.treatment-status {
+      color: #70a3dd;
+    }
+    &.prescription-ehydration-olume {
+      color: #8079cb;
+    }
+  }
+  // card header class
+  :deep(.mihi-header) {
+    flex: 0 0 4px;
+    .card-icon {
+      width: 4px;
+      height: 4px;
+    }
+    .card-title {
+      font-size: 4px;
+    }
+  }
+  :deep(.big-header) {
+    flex: 0 0 9px;
+    .card-icon {
+      width: 9px;
+      height: 9px;
+    }
+    .card-title {
+      font-size: 5px;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
new file mode 100644
index 0000000..b05d642
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
@@ -0,0 +1,981 @@
+<template>
+  <div class="under-treatment-container" :style="{ '--height': height + 'px' }">
+    <div class="left-box">
+      <div class="left-row1">
+        <div class="left-row1-col1">
+          <el-image
+            :src="pageData.patientPhone"
+            style="width: 100%; height: 100%"
+          >
+            <template #placeholder>
+              <div class="image-slot">加载中<span class="dot">...</span></div>
+            </template>
+          </el-image>
+        </div>
+        <div class="left-row1-col2">
+          <Card
+            title="治疗模式"
+            :icon="zlmsImg"
+            background-color="#ffffff"
+            class="mini-card left-row1-col2-row1"
+            header-class-name="mini-header"
+          >
+            <div class="item-box dialysis-mode-content">
+              <div class="dialysis-mode-content-box">
+                <span class="mini-text">{{
+                  formatSubstituteMode(pageData.substituteMode)
+                }}</span>
+                <span class="text">{{ pageData.dialysisPlan }}</span>
+              </div>
+            </div>
+          </Card>
+          <Card
+            title="处方备注"
+            :icon="zlmsImg"
+            background-color="#ffffff"
+            class="mini-card left-row1-col2-item-row2"
+            header-class-name="mini-header"
+          >
+            <div class="prescription-remarks">
+              {{ pageData.prescriptionRemarks }}
+            </div>
+          </Card>
+        </div>
+        <div class="left-row1-col3">
+          <Card
+            title="透析器"
+            :icon="txqImg"
+            background-color="#ffffff"
+            class="mini-card left-row1-col3-row1"
+            header-class-name="mini-header"
+          >
+            <div class="item-box prescription-ehydration-olume">
+              <span class="text">{{ pageData.dialyzer }}</span>
+            </div>
+          </Card>
+          <Card
+            title="异常指标"
+            :icon="xinlvImg"
+            background-color="#ffffff"
+            class="mini-card left-row1-col3-row2"
+            header-class-name="mini-header"
+          >
+            <div class="dialysis-mode-content">
+              <span
+                v-for="(item, index) in pageData.abnormalItems"
+                :key="index"
+                class="abnormal-indicator"
+                :style="{ color: formatTestColr(item.结果标记) }"
+              >
+                {{ getItemName(item.项目名称) }}
+                {{ formatTestFlag(item.结果标记) }}
+              </span>
+            </div>
+          </Card>
+        </div>
+      </div>
+      <div class="left-row2">
+        <Card
+          title="血温监测"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card left-row2-col1"
+          header-class-name="mini-header"
+        >
+          <div class="item-box current-lood0emperature">
+            <span class="text">{{ pageData.currentBloodTemperature }}</span>
+          </div>
+        </Card>
+        <Card
+          title="血压监测"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card left-row2-col2"
+          header-class-name="mini-header"
+        >
+          <div class="item-box venous-pressure">
+            <span class="text"
+              >{{ pageData.venousPressure }}/{{
+                pageData.transmembranePressure
+              }}</span
+            >
+          </div>
+        </Card>
+        <Card
+          title="血压脉搏趋势图"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card ktv-card left-row2-col3"
+          header-class-name="mini-header"
+        >
+          <div style="height: 100%">
+            <div
+              ref="bloodPressureAndPulseEchartRef"
+              style="width: 100%; height: 100%"
+            ></div>
+          </div>
+        </Card>
+      </div>
+      <div class="left-row3">
+        <Card
+          title="血容量监测"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card left-row3-col1"
+          header-class-name="mini-header"
+        >
+          <div class="item-box current-lood0emperature">
+            <span class="text">{{ pageData.bloodVolumeMonitoring }}</span>
+          </div>
+        </Card>
+        <Card
+          title="KTV监测"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card left-row3-col2"
+          header-class-name="mini-header"
+        >
+          <div class="item-box venous-pressure">
+            <span class="text">{{ pageData.ktv }}</span>
+          </div>
+        </Card>
+        <Card
+          title="KTV趋势图"
+          :icon="xinLv2Img"
+          background-color="#ffffff"
+          class="mini-card ktv-card left-row3-col3"
+          header-class-name="mini-header"
+        >
+          <div style="height: 100%">
+            <div ref="ktvListEchartRef" style="width: 100%; height: 100%"></div>
+          </div>
+        </Card>
+      </div>
+      <div class="left-row4">
+        <Card
+          title="血流量"
+          :icon="txqImg"
+          background-color="#ffffff"
+          class="mini-card left-row4-col"
+          header-class-name="mini-header"
+        >
+          <div class="item-box current-lood0emperature">
+            <span class="text">{{ pageData.bloodFlow }}</span>
+          </div>
+        </Card>
+        <Card
+          title="透析液流量"
+          :icon="txqImg"
+          background-color="#ffffff"
+          class="mini-card left-row4-col"
+          header-class-name="mini-header"
+        >
+          <div class="item-box current-lood0emperature">
+            <span class="text">{{ pageData.dialysisFluidFlowRate }}</span>
+          </div>
+        </Card>
+      </div>
+    </div>
+    <div class="right-box">
+      <div class="right-box-row1">
+        <Card
+          title="治疗状态"
+          :icon="txztImg"
+          background-color="#ffffff"
+          class="mini-card right-box-row1-col1"
+          header-class-name="mini-header"
+        >
+          <div class="item-box treatment-status">
+            <span class="text">{{ treatmentStatusText }}</span>
+          </div>
+        </Card>
+        <Card
+          title="脱水量详情"
+          :icon="cljdImg"
+          background-color="#ffffff"
+          class="mini-card right-box-row1-col2"
+          header-class-name="mini-header"
+        >
+          <div class="dehydrated-level">
+            <div class="dehydrated-level-item">
+              <span class="item-left"
+                >平均脱水量:{{ pageData.averageDehydrationRate }} L</span
+              >
+              <span class="item-right">(最近3周9次)</span>
+            </div>
+            <div class="dehydrated-level-item">
+              <div class="item-left">
+                <span
+                  >最大脱水量:{{ pageData.maximumDehydrationCapacity }} L</span
+                >
+                <template v-if="pageData.maximumDehydrationDuration"
+                  >/
+                  <span class="level-dete">{{
+                    pageData.maximumDehydrationDuration
+                  }}</span>
+                </template>
+              </div>
+              <span class="item-right"
+                >({{ pageData.maximumDehydrationCapacityDate }})</span
+              >
+            </div>
+          </div>
+        </Card>
+      </div>
+      <div class="right-box-row2">
+        <Card
+          title="时间进度"
+          :icon="sjjdImg"
+          background-color="#ffffff"
+          class="mini-card right-box-row2-item"
+          header-class-name="mini-header"
+        >
+          <div class="progress-box">
+            <div class="item-num">
+              {{ jgTime4(pageData.dialysisDuration) }}/{{
+                pageData.prescriptionDialysisDuration
+              }}:{{ pageData.prescriptionDialysisDurationMin }}
+            </div>
+            <ProgressBar
+              :percent="
+                (Number(pageData.dialysisDuration) /
+                  (Number(pageData.prescriptionDialysisDuration) * 60)) *
+                100
+              "
+              color="#70A3DD"
+              backgroundColor="#D6DEF1"
+              borderRadius="50%"
+            />
+          </div>
+        </Card>
+        <Card
+          title="超滤进度"
+          :icon="cljdImg"
+          background-color="#ffffff"
+          class="mini-card right-box-row2-item"
+          header-class-name="mini-header"
+        >
+          <div class="progress-box">
+            <div class="item-num">
+              {{ pageData.currentDehydrationVolume }}/{{
+                pageData.currentDehydrationVolume
+              }}({{ pageData.currentUltrafiltrationRate }})
+            </div>
+            <ProgressBar
+              :percent="
+                (pageData.currentDehydrationVolume /
+                  pageData.prescriptionDehydrationVolume) *
+                100
+              "
+              color="#70CAAE"
+              backgroundColor="#D6DEF1"
+              borderRadius="50%"
+            />
+          </div>
+        </Card>
+      </div>
+      <div class="right-box-row3">
+        <Card
+          title="临时医嘱"
+          :icon="yizhuImg"
+          background-color="#ffffff"
+          class="mini-card right-box-row2-item"
+          header-class-name="mini-header"
+        >
+          <DoctorAdvice :list="pageData.doctorAdvice" />
+        </Card>
+      </div>
+      <div class="right-box-row4">
+        <BlockBotttom
+          :icon="dingShiImg"
+          text="定时任务"
+          backgroundColor="#20C6B6"
+          @click="() => onScheduledTasksClick()"
+          class="btn"
+        />
+        <BlockBotttom
+          :icon="jiaoHaoImg"
+          text="叫号"
+          backgroundColor="#20C6B6"
+          @click="() => onCallBumberClick()"
+          class="btn"
+        />
+        <BlockBotttom
+          :icon="addImg"
+          text="添加记录"
+          backgroundColor="#409EFF"
+          @click="() => onAddRecordClick()"
+          class="btn"
+        />
+        <BlockBotttom
+          v-if="!whetherDialysisHasBeenEnded"
+          :icon="kaiShiImg"
+          text="结束透析"
+          backgroundColor="#E6A23C"
+          @click="() => onEndClick()"
+          class="btn"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup name="UnderTreatment">
+import { computed, ref, onMounted, onBeforeUnmount, watch } from "vue";
+import * as echarts from "echarts";
+import dayjs from "dayjs";
+
+// @ts-ignore
+import Card from "../components/Card.vue";
+// @ts-ignore
+import ProgressBar from "../components/ProgressBar.vue";
+import DoctorAdvice from "../components/DoctorAdvice/index.vue";
+// @ts-ignore
+import BlockBotttom from "../components/BlockBotttom.vue";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import {
+  formatSubstituteMode,
+  formatTestColr,
+  getItemName,
+  formatTestFlag,
+  EMedStatus,
+} from "@/store/type/bedsideAuxiliaryScreen.type";
+import type {
+  KtvItem,
+  MonitoringRecord,
+} from "@/store/type/bedsideAuxiliaryScreen.type";
+import { formatDate, jgTime4, jgTime5 } from "@/utils/formatTime";
+import zlmsImg from "@/img/zlms.png";
+import dingShiImg from "@/img/dingshi2.png";
+import jiaoHaoImg from "@/img/jiaoHao.png";
+import kaiShiImg from "@/img/kaiShi.png";
+import addImg from "@/img/add.png";
+import txqImg from "@/img/txq.png";
+import xinlvImg from "@/img/xinlv.png";
+import xinLv2Img from "@/img/xinlv2.png";
+import txztImg from "@/img/txzt.png";
+import cljdImg from "@/img/cljd.png";
+import sjjdImg from "@/img/sjjd.png";
+import yizhuImg from "@/img/yizhu.png";
+import { ElMessage } from "element-plus";
+
+interface Props {
+  height: number;
+}
+const props = defineProps<Props>();
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+// ktv趋势图的
+const ktvListEchartRef = ref<HTMLElement | null>(null);
+// 血压脉搏趋势图的
+const bloodPressureAndPulseEchartRef = ref<HTMLElement | null>(null);
+
+const pageData = computed(() => {
+  return Object.assign(bedsideAuxiliaryScreenStore.deviceData.underTreatment, {
+    patientPhone: bedsideAuxiliaryScreenStore.deviceData.patientPhone,
+  });
+});
+
+const treatmentStatusText = computed(() => {
+  const status = +bedsideAuxiliaryScreenStore.deviceData.treatmentStatus;
+  if (status === EMedStatus.NOT_CHECKED_IN) return "未签到";
+  if (status === EMedStatus.SIGNED_IN) return "已签到";
+  if (status === EMedStatus.DURING_DIALYSIS) return "透析中";
+  if (status === EMedStatus.END) return "已结束";
+  if (status === EMedStatus.CHECKED) return "已检查";
+  if (status === EMedStatus.ARCHIVED) return "已归档";
+  return "未知状态";
+});
+
+/** 是否已结束透析 */
+const whetherDialysisHasBeenEnded = computed(() => {
+  return (
+    +bedsideAuxiliaryScreenStore.deviceData.treatmentStatus >= EMedStatus.END
+  );
+});
+
+watch(
+  () => pageData.value.ktvList,
+  (newVal) => {
+    generateKtvListEchart(newVal);
+  },
+  { deep: true }
+);
+
+watch(
+  () => pageData.value.monitoringRecord,
+  (newVal) => {
+    generatBloodPressureAndPulseEchart(newVal);
+  },
+  { deep: true }
+);
+
+/** 生成ktv趋势图 */
+const generateKtvListEchart = (ktvList: KtvItem[]) => {
+  if (!ktvListEchartRef.value) return;
+  // if (!ktvList || ktvList.length === 0) return;
+
+  // 检查是否已经有实例
+  let chart = echarts.getInstanceByDom(ktvListEchartRef.value);
+  if (!chart) {
+    chart = echarts.init(ktvListEchartRef.value);
+  }
+
+  const option = {
+    grid: {
+      top: 6,
+      bottom: 20,
+      right: 20,
+    },
+    xAxis: {
+      type: "category",
+      data: ktvList.map((item) => dayjs(item.时间).format("HH:mm")),
+      axisLine: { show: true },
+      axisTick: { show: true },
+      splitLine: { show: false },
+    },
+    yAxis: {
+      type: "value",
+      axisLine: { show: true },
+      axisTick: { show: true },
+      splitLine: { show: false },
+
+      splitNumber: 4,
+    },
+    series: [
+      {
+        data: ktvList.map((item) => item.ktv),
+        type: "line",
+        smooth: false,
+        symbol: "circle",
+        symbolSize: 6,
+        lineStyle: {
+          width: 2,
+          color: "#70CAAE",
+        },
+        itemStyle: {
+          color: "#70CAAE",
+        },
+      },
+    ],
+    tooltip: {
+      trigger: "axis",
+    },
+  };
+
+  chart.setOption(option, true); // 第二个参数为 true 表示全量更新
+};
+
+/** 生成血压脉搏趋势图 */
+const generatBloodPressureAndPulseEchart = (
+  bloodPressureAndPulses: MonitoringRecord[]
+) => {
+  if (!bloodPressureAndPulseEchartRef.value) return;
+
+  let chart = echarts.getInstanceByDom(bloodPressureAndPulseEchartRef.value);
+  if (!chart) {
+    chart = echarts.init(bloodPressureAndPulseEchartRef.value);
+  }
+
+  const telescopicPressureDatas: number[] = []; // 伸缩压
+  const diastolicPressureDatas: number[] = []; // 舒张压
+  const pulseDatas: number[] = []; // 脉搏
+  const xAxisData: string[] = []; // 横坐标
+
+  bloodPressureAndPulses.forEach((item, index) => {
+    telescopicPressureDatas.push(+item.伸缩压);
+    diastolicPressureDatas.push(+item.舒张压);
+    pulseDatas.push(+item.脉搏);
+    xAxisData.push(String(index + 1));
+  });
+
+  const option = {
+    grid: [
+      { top: "10%", height: "25%", left: 30, right: 20 },
+      { top: "38%", height: "25%", left: 30, right: 20 },
+      { top: "66%", height: "25%", left: 30, right: 20 },
+    ],
+    tooltip: {
+      trigger: "axis",
+    },
+    xAxis: [
+      {
+        type: "category",
+        data: xAxisData,
+        boundaryGap: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: false },
+        splitLine: { show: false },
+        gridIndex: 0,
+      },
+      {
+        type: "category",
+        data: xAxisData,
+        boundaryGap: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: false },
+        splitLine: { show: false },
+        gridIndex: 1,
+      },
+      {
+        type: "category",
+        data: xAxisData,
+        boundaryGap: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: true }, // 最下面一层显示时间轴
+        splitLine: { show: false },
+        gridIndex: 2,
+      },
+    ],
+    yAxis: [
+      {
+        type: "value",
+        show: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: false },
+        splitLine: { show: false },
+        min: "dataMin", // 自动以数据最小值为最小值
+        max: "dataMax",
+        gridIndex: 0,
+      },
+      {
+        type: "value",
+        show: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: false },
+        splitLine: { show: false },
+        min: "dataMin", // 自动以数据最小值为最小值
+        max: "dataMax",
+        gridIndex: 1,
+      },
+      {
+        type: "value",
+        show: false,
+        axisLine: { show: false },
+        axisTick: { show: false },
+        axisLabel: { show: false },
+        splitLine: { show: false },
+        min: "dataMin", // 自动以数据最小值为最小值
+        max: "dataMax",
+        gridIndex: 2,
+      },
+    ],
+    series: [
+      {
+        name: "伸缩压",
+        xAxisIndex: 0,
+        yAxisIndex: 0,
+        data: wrapData(telescopicPressureDatas),
+        type: "line",
+        smooth: false,
+        symbol: "circle",
+        symbolSize: 6,
+        lineStyle: { width: 2, color: "#FE0201" },
+        itemStyle: { color: "#FE0201" },
+        label: { color: "#FE0201" },
+      },
+      {
+        name: "舒张压",
+        xAxisIndex: 1,
+        yAxisIndex: 1,
+        data: wrapData(diastolicPressureDatas),
+        type: "line",
+        smooth: false,
+        symbol: "circle",
+        symbolSize: 6,
+        lineStyle: { width: 2, color: "#70A3DD" },
+        itemStyle: { color: "#70A3DD" },
+        label: { color: "#70A3DD" },
+      },
+      {
+        name: "脉搏",
+        xAxisIndex: 2,
+        yAxisIndex: 2,
+        data: wrapData(pulseDatas),
+        type: "line",
+        smooth: false,
+        symbol: "circle",
+        symbolSize: 6,
+        lineStyle: { width: 2, color: "#8079CB" },
+        itemStyle: { color: "#8079CB" },
+        label: { color: "#8079CB" },
+      },
+    ],
+  };
+
+  chart.setOption(option);
+};
+
+// 给首尾点加上 label
+const wrapData = (arr: number[]) => {
+  return arr.map((v, i) => ({
+    value: v,
+    label: {
+      show: i === 0 || i === arr.length - 1,
+      position: "top",
+      fontSize: 12,
+    },
+  }));
+};
+
+/** 定时任务 */
+const onScheduledTasksClick = () => {};
+
+/** 叫号 */
+const onCallBumberClick = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+
+/** 添加记录 */
+const onAddRecordClick = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+
+/** 结束透析 */
+const onEndClick = () => {
+  ElMessage({
+    message: "功能开发中,敬请期待!",
+    type: "warning",
+  });
+};
+
+onMounted(() => {
+  // 生成ktv趋势图
+  generateKtvListEchart(pageData.value.ktvList);
+  generatBloodPressureAndPulseEchart(pageData.value.monitoringRecord);
+});
+
+onBeforeUnmount(() => {
+  // 销毁图表实例
+  if (ktvListEchartRef.value) {
+    const chart = echarts.getInstanceByDom(ktvListEchartRef.value);
+    if (chart) {
+      chart.dispose();
+    }
+  }
+  if (bloodPressureAndPulseEchartRef.value) {
+    const chart = echarts.getInstanceByDom(
+      bloodPressureAndPulseEchartRef.value
+    );
+    if (chart) {
+      chart.dispose();
+    }
+  }
+});
+</script>
+
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+
+.under-treatment-container {
+  display: flex;
+  align-items: flex-start;
+  height: var(--height);
+  gap: 4px;
+  padding-bottom: 2px;
+  overflow: hidden;
+  .left-box {
+    width: 58.25%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+
+    .left-row1 {
+      width: 100%;
+      height: 38.97%;
+      display: flex;
+      gap: 4px;
+
+      .left-row1-col1,
+      .left-row1-col2,
+      .left-row1-col3 {
+        height: 100%;
+      }
+
+      .left-row1-col1 {
+        width: 26.94%;
+        border-radius: 2px;
+        overflow: hidden;
+      }
+      .left-row1-col2 {
+        width: 26.43%;
+        display: flex;
+        flex-direction: column;
+        gap: 4px;
+        .left-row1-col2-row1 {
+          height: 36.62%;
+        }
+
+        .left-row1-col2-item-row2 {
+          height: 63.38%;
+        }
+      }
+      .left-row1-col3 {
+        width: 46.63%;
+        display: flex;
+        flex-direction: column;
+        gap: 4px;
+        .left-row1-col3-row1 {
+          height: 36.62%;
+        }
+        .left-row1-col3-row2 {
+          height: 63.38%;
+          .dialysis-mode-content {
+            height: 100%;
+            .abnormal-indicator {
+              display: inline-block;
+              margin-right: 6px;
+              margin-bottom: 4px;
+              font-family: PingFangSC, PingFang SC;
+              font-weight: 600;
+              font-size: 5px;
+              line-height: 6px;
+              text-align: left;
+              font-style: normal;
+            }
+          }
+        }
+      }
+    }
+    .left-row2 {
+      width: 100%;
+      height: 21.03%;
+      display: flex;
+      gap: 4px;
+      .left-row2-col1 {
+        width: 26.94%;
+      }
+      .left-row2-col2 {
+        width: 26.43%;
+      }
+      .left-row2-col3 {
+        width: 46.62%;
+      }
+    }
+    .left-row3 {
+      width: 100%;
+      height: 21.03%;
+      display: flex;
+      gap: 4px;
+      .left-row3-col1 {
+        width: 26.94%;
+      }
+      .left-row3-col2 {
+        width: 26.43%;
+      }
+      .left-row3-col3 {
+        width: 46.62%;
+      }
+    }
+    .left-row4 {
+      width: 100%;
+      height: 11.79%;
+      display: flex;
+      gap: 4px;
+      .left-row4-col {
+        width: 50%;
+      }
+    }
+  }
+  .right-box {
+    width: 41.75%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+    .right-box-row1,
+    .right-box-row2,
+    .right-box-row3 .right-box-row4 {
+      width: 100%;
+    }
+    .right-box-row1 {
+      height: 14.44%;
+      display: flex;
+      gap: 4px;
+      .right-box-row1-col1 {
+        width: 36.17%;
+      }
+      .right-box-row1-col2 {
+        width: 63.83%;
+      }
+    }
+    .right-box-row2 {
+      height: 25%;
+      display: flex;
+      gap: 4px;
+      .right-box-row2-item {
+        width: 50%;
+      }
+    }
+    .right-box-row3 {
+      height: 47.78%;
+    }
+
+    .right-box-row4 {
+      height: 12.78%;
+      background: #ffffff;
+      border-radius: 2px;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      padding-right: 13px;
+      .btn {
+        margin-left: 9px;
+      }
+    }
+  }
+
+  .progress-box {
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+    .item-num {
+      margin-bottom: 4px;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 600;
+      font-size: 8px;
+      color: #333333;
+      text-align: left;
+      font-style: normal;
+    }
+  }
+
+  .item-box {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 600;
+    font-size: 8px;
+    color: #70a3dd;
+    text-align: center;
+    font-style: normal;
+    &.dialysis-mode-content {
+      color: #d58e56;
+      display: flex;
+      align-items: center;
+      // align-items: baseline;
+      .dialysis-mode-content-box {
+        display: flex;
+        align-items: flex-end;
+        line-height: 1;
+        .mini-text {
+          margin-right: 1px;
+          font-size: 5px;
+          color: #c9a589;
+        }
+      }
+    }
+    &.treatment-status {
+      color: #70a3dd;
+    }
+    &.prescription-ehydration-olume {
+      color: #8079cb;
+    }
+    &.current-lood0emperature {
+      color: #70a3dd;
+      font-size: 9px;
+    }
+    &.venous-pressure {
+      color: #70a3dd;
+      font-size: 9px;
+    }
+  }
+  .prescription-remarks {
+    font-family: PingFangSC, PingFang SC;
+    font-weight: 500;
+    font-size: 5px;
+    color: #d58e56;
+    line-height: 7px;
+    text-align: left;
+    font-style: normal;
+  }
+  .dehydrated-level {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: space-between;
+    .dehydrated-level-item {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      .item-left {
+        flex: 1;
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 600;
+        font-size: 4px;
+        color: #333333;
+        line-height: 6px;
+        font-style: normal;
+        .level-dete {
+          font-family: PingFangSC, PingFang SC;
+          font-weight: 600;
+          font-size: 4px;
+          color: #d58e56;
+          text-align: left;
+          font-style: normal;
+        }
+      }
+      .item-right {
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 600;
+        font-size: 4px;
+        color: #777777;
+        line-height: 6px;
+        font-style: normal;
+      }
+    }
+  }
+  // card header class
+  .mini-card {
+    padding: 2px;
+  }
+  .ktv-card {
+    overflow: visible;
+    .card-header {
+      margin-bottom: 0px;
+    }
+    ::v-deep(.card-main) {
+      overflow: visible !important;
+      div {
+        overflow: visible;
+      }
+    }
+  }
+  :deep(.mini-header) {
+    flex: 0 0 4px;
+    .card-icon {
+      width: 4px;
+      height: 4px;
+    }
+    .card-title {
+      font-size: 4px;
+    }
+  }
+  :deep(.big-header) {
+    flex: 0 0 9px;
+    .card-icon {
+      width: 9px;
+      height: 9px;
+    }
+    .card-title {
+      font-size: 5px;
+    }
+  }
+}
+</style>
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnplannedSchedule.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnplannedSchedule.vue
new file mode 100644
index 0000000..4fe780d
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnplannedSchedule.vue
@@ -0,0 +1,238 @@
+<template>
+  <div
+    class="unplanned-schedule-container"
+    :style="{ '--height': height + 'px' }"
+  >
+    <div class="row1-container">
+      <Card
+        title="抗凝剂"
+        :icon="tslImg"
+        background-color="#FFEDD2"
+        class="row1-left"
+      >
+        <div class="list-1">
+          <div
+            v-for="(item, index) in consumablesCollection.抗凝剂"
+            :key="index"
+            class="list-1-item"
+          >
+            {{ item }}
+          </div>
+        </div>
+      </Card>
+      <div class="row1-content">
+        <Card
+          title="透析模式"
+          :icon="tslImg"
+          background-color="#E5EEFF"
+          class="row1-content-card"
+        >
+          <div class="list-2">
+            <div
+              v-for="(item, index) in consumablesCollection.透析模式"
+              :key="index"
+              class="list-2-item"
+            >
+              {{ item }}
+            </div>
+          </div>
+        </Card>
+        <Card
+          title="一次性血液透析体外循环管路"
+          :icon="tslImg"
+          background-color="#D9F0E2"
+          class="row1-content-card"
+        >
+          <div class="list-3">
+            <div
+              v-for="(item, index) in consumablesCollection.管路"
+              :key="index"
+              class="list-3-item"
+            >
+              {{ item }}
+            </div>
+          </div>
+        </Card>
+        <Card
+          title="一次性使用透析护理包"
+          :icon="tslImg"
+          background-color="#F9DEDE"
+          class="row1-content-card"
+        />
+      </div>
+      <Card
+        title="一次性使用内瘘穿刺针"
+        :icon="tslImg"
+        background-color="#EFE5FF"
+        class="row1-right"
+      >
+        <div class="list-1">
+          <div
+            v-for="(item, index) in consumablesCollection.穿刺针"
+            :key="index"
+            class="list-1-item"
+          >
+            {{ item }}
+          </div>
+        </div>
+      </Card>
+    </div>
+    <div class="row2-container">
+      <Card
+        title="血液透析器"
+        :icon="tslImg"
+        background-color="#F6F5FA"
+        class="row2-card"
+      >
+        <div class="list-4">
+          <div
+            v-for="(item, index) in consumablesCollection.透析器"
+            :key="index"
+            class="list-4-item"
+          >
+            {{ item }}
+          </div>
+        </div>
+      </Card>
+      <Card
+        title="血液透析滤过器"
+        :icon="tslImg"
+        background-color="#F6F5FA"
+        class="row2-card"
+      >
+        <div class="list-4">
+          <div
+            v-for="(item, index) in consumablesCollection.滤过器"
+            :key="index"
+            class="list-4-item"
+          >
+            {{ item }}
+          </div>
+        </div>
+      </Card>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup name="UnplannedSchedule">
+import { computed } from "vue";
+// @ts-ignore
+import Card from "../components/Card.vue";
+import tslImg from "@/img/tsl.png";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+
+interface Props {
+  height: number;
+}
+const props = defineProps<Props>();
+
+const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+const consumablesCollection = computed(() => {
+  return bedsideAuxiliaryScreenStore.deviceData.consumablesCollection;
+});
+</script>
+
+<style lang="less" scoped>
+* {
+  box-sizing: border-box;
+}
+.unplanned-schedule-container {
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  height: var(--height);
+  overflow: hidden;
+  .row1-container {
+    flex: 1;
+    margin-bottom: 4px;
+    display: flex;
+    width: 100%;
+    gap: 4px;
+    min-height: 0;
+    > .row1-left,
+    .row1-right {
+      width: 103px;
+      flex-shrink: 0;
+    }
+
+    .row1-content {
+      flex: 1;
+      display: flex;
+      flex-direction: column;
+      gap: 4px;
+
+      // 卡片高度平均分(3个)
+      > .row1-content-card {
+        flex: 1;
+      }
+    }
+  }
+  .row2-container {
+    flex: 1;
+    margin-bottom: 4px;
+    display: flex;
+    width: 100%;
+    gap: 4px;
+    min-height: 0;
+    > .row2-card {
+      flex: 1;
+    }
+  }
+  .list-1 {
+    .list-1-item {
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 4px;
+      color: #a78718;
+      text-align: left;
+      font-style: normal;
+      &:not(:first-child) {
+        margin-top: 2px;
+      }
+    }
+  }
+  .list-2 {
+    .list-2-item {
+      display: inline-block;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 5px;
+      color: #3a75b8;
+      text-align: left;
+      font-style: normal;
+      &:not(:first-child) {
+        margin-left: 5px;
+      }
+    }
+  }
+  .list-3 {
+    .list-3-item {
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 4px;
+      color: #3ab859;
+      text-align: left;
+      font-style: normal;
+      &:not(:first-child) {
+        margin-top: 2px;
+      }
+    }
+  }
+  .list-4 {
+    .list-4-item {
+      display: inline-block;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 4px;
+      color: #333333;
+      text-align: left;
+      font-style: normal;
+      margin-bottom: 4px;
+      &:not(:first-child) {
+        margin-right: 2px;
+      }
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/register/index.vue b/src/views/register/index.vue
index 331e8d9..4902fbb 100644
--- a/src/views/register/index.vue
+++ b/src/views/register/index.vue
@@ -2,7 +2,7 @@
     <div class="register-form">
       <van-image width="100" height="100" :src="logo" />
       <h1>用户注册</h1>
-      <p>创建您的账户,开始使用我们的服务</p>
+      <p class="desc">创建您的账户,开始使用我们的服务</p>
   
       <van-form @submit="onSubmit">
         <!-- 用户名 -->
@@ -221,4 +221,7 @@
     color: #666;
     margin-bottom: 20px;
   }
+  .desc {
+    font-size: 14px;
+  }
   </style>
\ No newline at end of file
diff --git a/src/views/registerSuu/index.vue b/src/views/registerSuu/index.vue
index 72fcf5a..981fbe0 100644
--- a/src/views/registerSuu/index.vue
+++ b/src/views/registerSuu/index.vue
@@ -14,4 +14,7 @@
     color: #4caf50;
     margin-bottom: 20px;
   }
+p {
+  font-size: 14px;
+}
   </style>
\ No newline at end of file
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 51dbd15..97f5764 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,8 +1,12 @@
 import { defineConfig } from 'vite';
 import vue from '@vitejs/plugin-vue';
+import path from 'path';
 
 export default defineConfig({
   plugins: [vue()],
+   css: {
+    postcss: path.resolve(__dirname, 'postcss.config.js')
+  },
   server: {
     port: 3034, // 指定端口号为 3000
     strictPort: true, // 如果端口被占用,则抛出错误而不是尝试下一个可用端口
@@ -10,7 +14,7 @@
   },
   resolve: {
     alias: {
-      '@': '/src'
+      '@': path.resolve(__dirname, 'src')
     }
   },
   base:'/test'

--
Gitblit v1.8.0