diff --git a/api/device.js b/api/device.js
new file mode 100644
index 0000000..3d053c3
--- /dev/null
+++ b/api/device.js
@@ -0,0 +1,97 @@
+import request from '@/api/http/client'
+
+// 后端就绪后置为 false 即可恢复真实请求。
+const USE_MOCK = true
+
+// 模拟设备列表数据(后端 /device/list 就绪后删除)。
+const MOCK_DEVICES = [
+ { id: 1, name: '客厅体征监测仪', model: 'ED713', online: true },
+ { id: 2, name: '卧室体征监测仪', model: 'ED713', online: false },
+ { id: 3, name: '书房跌倒检测雷达', model: 'ED719', online: true },
+ { id: 4, name: '走廊跌倒检测雷达', model: 'ED719', online: false }
+]
+
+/**
+ * 获取指定场所下的设备列表。
+ * 约定:data 为数组,每项至少含 { id, name, model, online },model 取值 ED713 | ED719。
+ * @param {*} sceneId 场景 id,全部/未选择时可传 null
+ */
+export function getDeviceList(sceneId) {
+ if (USE_MOCK) {
+ // 模拟网络延迟,让 loading 态可见。
+ return new Promise((resolve) => setTimeout(() => resolve(MOCK_DEVICES), 500))
+ }
+ return request.get('/device/list', { sceneId })
+}
+
+// 模拟 ED713 实时体征数据(后端 /device/vitals 就绪后删除)。
+// 字段与 web 端 runTimeInfo.properties 对齐;枚举值见 detail 页映射表。
+const MOCK_VITALS = {
+ heartRate: 72,
+ respiratoryRate: 16,
+ bodyMovement: 3,
+ moveState: 3,
+ onbedStatus: 1,
+ bodyStatus: 2,
+ bodyPosition: 8
+}
+
+// 心率读数模拟状态:跨调用保留最近 50 个读数(与 web 端 pageSize:50 一致),
+// 每次轮询推进 2~3 个新读数、挤出最旧的——等价于 web 端每 3 秒按 createTime 倒序重拉最新 50 条。
+const heartState = {
+ series: [],
+ value: 72
+}
+
+// 心率读数小幅随机游走(60~90 BPM)。
+function driftHeartRate() {
+ heartState.value += Math.round((Math.random() - 0.5) * 4)
+ heartState.value = Math.min(90, Math.max(60, heartState.value))
+ return heartState.value
+}
+
+// 初始预填 50 个读数,首屏即有完整曲线。
+for (let i = 0; i < 50; i++) {
+ heartState.series.push(driftHeartRate())
+}
+
+// 推进若干新读数并保留最近 50 个。
+function pushHeartReadings() {
+ const n = 2 + Math.round(Math.random())
+ for (let i = 0; i < n; i++) {
+ heartState.series.push(driftHeartRate())
+ }
+ if (heartState.series.length > 50) {
+ heartState.series = heartState.series.slice(-50)
+ }
+}
+
+/**
+ * 获取 ED713 设备实时体征属性。
+ * 约定:data 含 { heartRate, respiratoryRate, bodyMovement, moveState, onbedStatus, bodyStatus, bodyPosition }。
+ * @param {*} deviceId 设备 id
+ */
+export function getVitalSigns(deviceId) {
+ if (USE_MOCK) {
+ const heartRate = driftHeartRate()
+ return new Promise((resolve) =>
+ setTimeout(() => resolve({ ...MOCK_VITALS, heartRate, deviceId }), 300)
+ )
+ }
+ return request.get('/device/vitals', { deviceId })
+}
+
+/**
+ * 获取心率历史序列(与 web 端一致:最近 50 条心率读数、按时间升序喂给面积图)。
+ * 约定:data 为 number 数组;每次调用推进若干新读数,曲线随轮询向左滚动。
+ * @param {*} deviceId 设备 id
+ */
+export function getHeartRateHistory(deviceId) {
+ if (USE_MOCK) {
+ pushHeartReadings()
+ return new Promise((resolve) =>
+ setTimeout(() => resolve([...heartState.series]), 300)
+ )
+ }
+ return request.get('/device/heart-history', { deviceId })
+}
diff --git a/components/vital-wave.vue b/components/vital-wave.vue
new file mode 100644
index 0000000..94f65ee
--- /dev/null
+++ b/components/vital-wave.vue
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+ 暂无数据
+
+
+
+
+
+
+
diff --git a/constants/routes.js b/constants/routes.js
index 3506cd0..685362a 100644
--- a/constants/routes.js
+++ b/constants/routes.js
@@ -8,6 +8,7 @@ export const ROUTES = Object.freeze({
MINE: '/pages/mine/index',
DEVICE_ADD: '/pages/device/add',
DEVICE_CONFIG: '/pages/device/config',
+ DEVICE_DETAIL: '/pages/device/detail',
SCENE_SELECT: '/pages/scene/select'
})
diff --git a/pages.json b/pages.json
index dade0f7..d5759f9 100644
--- a/pages.json
+++ b/pages.json
@@ -36,6 +36,12 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/device/detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "pages/scene/select",
"style": {
diff --git a/pages/device/detail.vue b/pages/device/detail.vue
new file mode 100644
index 0000000..016ba9a
--- /dev/null
+++ b/pages/device/detail.vue
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ❤
+ {{ valueOf(vitals.heartRate) }}
+ BPM
+
+
+ {{ online ? '正常' : '离线' }}
+
+
+
+
+ 心率健康
+
+
+
+
+
+
+
+
+ {{ m.label }}
+
+ {{ m.value }}
+ {{ m.unit }}
+
+
+
+
+
+
+
+ 设备型号
+ {{ deviceModel || '-' }}
+
+
+ 设备 ID
+ {{ deviceId || '-' }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
index 9a45e31..340de1a 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -29,8 +29,39 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ device.name }}
+
+
+
+ {{ device.online ? '在线' : '离线' }}
+
+
+
@@ -40,19 +71,31 @@