跳到主要内容

信息对象与数据结构

本文档基于 docs/archon/docs/assets/reflekt-health.sql 数据库导出文件编写,交叉参考需求文档(raw_requirements_context.mdproject_brief.md)、业务架构(business_architecture.md)、技术架构(technical_architecture.md)等,形成 Reflekt Health 真实数据模型。

Schema: reflekt-health(PostgreSQL)


第一部分:领域模型(代码层)

领域模型从业务视角描述核心业务对象及其关系,供后端 Agent 实现业务逻辑使用。 表名与业务域的映射关系:需求中定义的 ref_* 表对应实现中的 iot_* 表(iot_family_* 家族表 + 独立 iot_* 表)。

1.1 核心业务域

业务域英文核心职责数据库表归属
用户与认证User & AuthIoT 用户(家属账号)注册登录、AES-256 加密手机号iot_user
家庭域Family家庭档案、成员管理、设备绑定、消息、通话iot_family_* 系列表
设备域Device设备注册、状态管理、设备分享iot_deviceiot_device_share
健康数据域Health心率、血氧、步数、睡眠、体温iot_heart_rateiot_spoiot_pedoiot_sleep_rawiot_temperature
AI 对话域AI BrainAI 会话记忆、消息记录、AI 操作日志iot_ai_session_memoryiot_ai_session_messageai_operation_log
雷达事件域Radar跌倒事件上报、MQTT 订阅管理mqtt_fall_eventmqtt_subscriptionmqtt_inbound_message
提醒域Reminder提醒计划创建、播报、执行日志iot_family_reminder
告警域Alert告警触发、升级链路、通知下发待建(需求定义 ref_alertref_escalationref_notification 表尚未创建)
运营管理域Admin系统配置、字典、OSS、审计日志sys_* 系列表
定时任务域Scheduling分布式定时任务调度、重试机制sj_* 系列表

1.2 核心领域对象

对象名称中文名需求对应数据库表主要属性关联对象
IoTUserIoT用户(家属)CAREGIVERiot_userid, phone(AES), nickname, avatar, family_idFamily, Device
Family家庭FAMILYiot_family_archiveid, family_name, elder_name, elder_age, health_profile(JSON)IoTUser, Device, Elder
Elder被照护者ELDERiot_family_archive(同表内嵌)elder_name, elder_age, health_profile, baseline_hashFamily, Device, HealthData
Device设备DEVICEiot_deviceid, serial_number, device_type(luma/radar/watch), status, last_heartbeatFamily, DeviceEvent
DeviceEvent设备事件DEVICE_EVENTmqtt_fall_event(跌倒)、mqtt_inbound_message(通用)id, device_id, event_type, payload(JSON), event_timeDevice
HealthData健康数据DEVICE_EVENTiot_heart_rateiot_spoiot_pedoiot_sleep_rawiot_temperatureid, device_id, value, measured_atDevice, Elder
FamilyMessage家庭消息NOTIFICATIONiot_family_messageid, family_id, sender_id, content_type(voice/text), contentFamily, IoTUser
Reminder提醒计划REMINDERiot_family_reminderid, family_id, elder_id, content_type, schedule, frequency, need_confirmFamily, Elder
AISessionMemoryAI记忆话题MEMORYiot_ai_session_memoryid, family_id, elder_id, topic, elder_response_url, status(pending/answered/listened)Family, Elder
Alert告警事件ALERT待建 ref_alertid, elder_id, device_event_id, level(red/amber/normal), status, evidence_pack(JSON)Elder, DeviceEvent
Escalation升级链路ESCALATION待建 ref_escalationid, alert_id, level, caregiver_id, channel(push/sms/voice), statusAlert, IoTUser
Notification通知记录NOTIFICATION待建 ref_notificationid, alert_id, caregiver_id, channel, title, body, statusAlert, IoTUser

1.3 领域对象关系图

1.4 领域对象状态机

1.4.1 告警状态机(Alert — 待建)

1.4.2 设备状态机(Device)

1.4.3 六状态颜色语言(六态联动 Family App / Luma App 双端)

1.4.4 AI记忆话题状态机(AI Session Memory)

1.4.5 家庭通话状态机(Family Call)

1.4.6 家庭消息状态机(Family Message)


第二部分:数据字典(数据库层)

数据字典描述数据库表结构、字段定义、索引设计,供 DBA 和后端 Agent 创建数据库 Schema 使用。 ref_alertref_escalationref_notification 三表已在需求文档中定义,但尚未在 SQL 导出文件中创建。以下 DDL 章节仅覆盖已导出的实际表。

2.1 ER 图


2.2 核心业务表 DDL

2.2.1 表:iot_user(IoT 用户/家属账号)

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive所属家庭ID
phoneVARCHAR(50)UNIQUE(加密存储)手机号(MyBatis AES-256 加密)
nicknameVARCHAR(100)昵称
avatarVARCHAR(500)头像URL
statusVARCHAR(20)DEFAULT 'active'状态:active / inactive
create_deptBIGINT创建部门(RuoYi框架)
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询成员
idx_phonephoneUNIQUE手机号登录查询

关联iot_useriot_family_group_member(多对多家庭成员)← iot_family_archive


2.2.2 表:iot_family_archive(家庭档案 / 被照护者)

需求中对应 FAMILY + ELDER 两个实体,在实现中合并为一张表。

字段名类型约束说明
idBIGSERIALPK主键
family_nameVARCHAR(100)家庭名称
elder_nameVARCHAR(100)被照护者姓名
elder_ageINT被照护者年龄
elder_genderVARCHAR(10)性别
health_profileJSONB健康档案JSON:疾病史/用药史/作息规律
baseline_hashVARCHAR(100)行为基线标识
privacy_consentJSONB隐私同意状态JSON
addressVARCHAR(500)家庭地址
statusVARCHAR(20)DEFAULT 'active'状态:active / pilot / formal
create_deptBIGINT创建部门
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_statusstatusNORMAL状态筛选(试点/正式)

DDL

CREATE TABLE iot_family_archive (
id BIGSERIAL PRIMARY KEY,
family_name VARCHAR(100),
elder_name VARCHAR(100),
elder_age INT,
elder_gender VARCHAR(10),
health_profile JSONB,
baseline_hash VARCHAR(100),
privacy_consent JSONB,
address VARCHAR(500),
status VARCHAR(20) DEFAULT 'active',
create_dept BIGINT,
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6),
INDEX idx_status (status)
);

2.2.3 表:iot_family_group_member(家庭组成员)

需求中对应 CAREGIVER 实体,实现为关联表支持多成员家庭。

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive, NOT NULL家庭ID
user_idBIGINTFK → iot_user, NOT NULL用户ID
roleVARCHAR(20)DEFAULT 'member'角色:admin / member
priorityINTDEFAULT 99紧急联系优先级(1最高)
nicknameVARCHAR(100)成员昵称
statusVARCHAR(20)DEFAULT 'active'状态
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询成员
idx_user_iduser_idNORMAL按用户查询家庭
uk_family_userfamily_id + user_idUNIQUE唯一约束

DDL

CREATE TABLE iot_family_group_member (
id BIGSERIAL PRIMARY KEY,
family_id BIGINT NOT NULL REFERENCES iot_family_archive(id),
user_id BIGINT NOT NULL REFERENCES iot_user(id),
role VARCHAR(20) DEFAULT 'member',
priority INT DEFAULT 99,
nickname VARCHAR(100),
status VARCHAR(20) DEFAULT 'active',
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
UNIQUE (family_id, user_id),
INDEX idx_family_id (family_id),
INDEX idx_user_id (user_id)
);

2.2.4 表:iot_device(设备)

需求中对应 DEVICE 实体,统一管理三类设备。

字段名类型约束说明
idBIGSERIALPK主键
serial_numberVARCHAR(100)UNIQUE, NOT NULL设备序列号
device_typeVARCHAR(20)NOT NULL类型:luma / radar / watch
family_idBIGINTFK → iot_family_archive绑定家庭ID
device_nameVARCHAR(100)设备名称(可自定义)
device_modelVARCHAR(100)设备型号
statusVARCHAR(20)DEFAULT 'pending'状态:online / offline / pending
configJSONB设备配置JSON
last_heartbeatTIMESTAMP(6)最后心跳时间
firmware_versionVARCHAR(50)固件版本
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_serial_numberserial_numberUNIQUE序列号精确查询
idx_family_idfamily_idNORMAL按家庭查询设备
idx_device_typedevice_typeNORMAL设备类型筛选
idx_statusstatusNORMAL状态筛选
idx_last_heartbeatlast_heartbeatNORMAL心跳超时检测

DDL

CREATE TABLE iot_device (
id BIGSERIAL PRIMARY KEY,
serial_number VARCHAR(100) NOT NULL UNIQUE,
device_type VARCHAR(20) NOT NULL,
family_id BIGINT REFERENCES iot_family_archive(id),
device_name VARCHAR(100),
device_model VARCHAR(100),
status VARCHAR(20) DEFAULT 'pending',
config JSONB,
last_heartbeat TIMESTAMP(6),
firmware_version VARCHAR(50),
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6),
INDEX idx_family_id (family_id),
INDEX idx_device_type (device_type),
INDEX idx_status (status),
INDEX idx_last_heartbeat (last_heartbeat)
);

2.2.5 表:iot_family_device(家庭设备绑定关系)

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive, NOT NULL家庭ID
device_idBIGINTFK → iot_device, NOT NULL设备ID
binding_statusVARCHAR(20)DEFAULT 'active'绑定状态
bind_timeTIMESTAMP(6)绑定时间
unbind_timeTIMESTAMP(6)解绑时间
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询设备
idx_device_iddevice_idNORMAL按设备查询家庭
uk_family_devicefamily_id + device_idUNIQUE唯一约束

2.2.6 表:iot_device_share(设备分享)

字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device, NOT NULL设备ID
owner_family_idBIGINTFK → iot_family_archive所有者家庭ID
shared_family_idBIGINTFK → iot_family_archive被分享家庭ID
share_typeVARCHAR(20)DEFAULT 'view'分享类型:view / control
statusVARCHAR(20)DEFAULT 'active'状态
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

2.2.7 表:iot_family_message(家庭消息)

需求中对应 NOTIFICATION 实体(消息通知)。

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive, NOT NULL家庭ID
sender_idBIGINTFK → iot_user发送者用户ID
sender_typeVARCHAR(20)发送者类型:user / elder
elder_idBIGINT老人ID(消息对象)
content_typeVARCHAR(20)NOT NULL内容类型:voice / text
contentTEXT文字内容
voice_urlVARCHAR(500)语音文件URL(S3)
durationINT语音时长(秒)
statusVARCHAR(20)DEFAULT 'pending'状态:pending / sent / delivered / played / failed
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询消息
idx_sender_idsender_idNORMAL按发送者查询
idx_create_timecreate_timeNORMAL时间倒序查询
idx_statusstatusNORMAL状态筛选

DDL

CREATE TABLE iot_family_message (
id BIGSERIAL PRIMARY KEY,
family_id BIGINT NOT NULL REFERENCES iot_family_archive(id),
sender_id BIGINT REFERENCES iot_user(id),
sender_type VARCHAR(20),
elder_id BIGINT,
content_type VARCHAR(20) NOT NULL,
content TEXT,
voice_url VARCHAR(500),
duration INT,
status VARCHAR(20) DEFAULT 'pending',
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6),
INDEX idx_family_id (family_id),
INDEX idx_create_time (create_time DESC),
INDEX idx_status (status)
);
-- 触发器:update_time 自动更新
CREATE TRIGGER update_family_message_modtime
BEFORE UPDATE ON iot_family_message
FOR EACH ROW EXECUTE FUNCTION update_family_message_modtime();

2.2.8 表:iot_family_reminder(提醒计划)

需求中对应 REMINDER 实体。

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive, NOT NULL家庭ID
elder_idBIGINT被提醒老人ID
creator_idBIGINTFK → iot_user创建人ID
content_typeVARCHAR(20)DEFAULT 'text'内容类型:text / voice
contentTEXT提醒文字内容
voice_urlVARCHAR(500)语音文件URL
scheduleVARCHAR(100)Cron 表达式
frequencyVARCHAR(20)频率:daily / weekly / custom
need_confirmBOOLEANDEFAULT false是否需老人确认
sharedBOOLEANDEFAULT true是否分享给家属
statusVARCHAR(20)DEFAULT 'active'状态:active / paused / deleted
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询提醒
idx_elder_idelder_idNORMAL按老人查询提醒
idx_statusstatusNORMAL状态筛选
idx_schedulescheduleNORMALCron 调度查询

2.2.9 表:iot_family_call(家庭通话记录)

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive家庭ID
initiator_idBIGINTFK → iot_user发起人用户ID
call_typeVARCHAR(20)DEFAULT 'audio'通话类型:audio / video
statusVARCHAR(20)DEFAULT 'pending'状态:pending / connected / cancelled / no_answer / ended
durationINTDEFAULT 0通话时长(秒)
start_timeTIMESTAMP(6)开始时间
end_timeTIMESTAMP(6)结束时间
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

DDL

CREATE TABLE iot_family_call (
id BIGSERIAL PRIMARY KEY,
family_id BIGINT REFERENCES iot_family_archive(id),
initiator_id BIGINT REFERENCES iot_user(id),
call_type VARCHAR(20) DEFAULT 'audio',
status VARCHAR(20) DEFAULT 'pending',
duration INT DEFAULT 0,
start_time TIMESTAMP(6),
end_time TIMESTAMP(6),
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6)
);
-- 触发器:update_time 自动更新
CREATE TRIGGER update_family_call_modtime
BEFORE UPDATE ON iot_family_call
FOR EACH ROW EXECUTE FUNCTION update_family_call_modtime();

2.2.10 表:iot_ai_session_memory(AI 记忆话题)

需求中对应 MEMORY 实体。家属提问 → Luma 收音 → 家属播放 → 完成闭环。

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive, NOT NULL家庭ID
elder_idBIGINT被提问老人ID
caregiver_idBIGINTFK → iot_user提问人用户ID
topicVARCHAR(500)话题内容
elder_response_textTEXT老人回答文字
elder_response_urlVARCHAR(500)老人回答语音URL(S3)
statusVARCHAR(20)DEFAULT 'pending'状态:pending / answered / listened / expired
asked_atTIMESTAMP(6)提问时间
answered_atTIMESTAMP(6)回答时间
listened_atTIMESTAMP(6)聆听时间
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询记忆
idx_statusstatusNORMAL状态筛选
idx_create_timecreate_timeNORMAL时间查询

DDL

CREATE TABLE iot_ai_session_memory (
id BIGSERIAL PRIMARY KEY,
family_id BIGINT NOT NULL REFERENCES iot_family_archive(id),
elder_id BIGINT,
caregiver_id BIGINT REFERENCES iot_user(id),
topic VARCHAR(500),
elder_response_text TEXT,
elder_response_url VARCHAR(500),
status VARCHAR(20) DEFAULT 'pending',
asked_at TIMESTAMP(6),
answered_at TIMESTAMP(6),
listened_at TIMESTAMP(6),
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6),
INDEX idx_family_id (family_id),
INDEX idx_status (status)
);
CREATE TRIGGER update_ai_memory_modtime
BEFORE UPDATE ON iot_ai_session_memory
FOR EACH ROW EXECUTE FUNCTION update_ai_memory_modtime();

2.2.11 表:iot_ai_session_message(AI 会话消息)

字段名类型约束说明
idBIGSERIALPK主键
session_idBIGINTFK → iot_ai_session_memory会话/记忆ID
roleVARCHAR(20)NOT NULL角色:user / assistant
contentTEXT消息内容
voice_urlVARCHAR(500)语音URL
modelVARCHAR(50)使用的AI模型
tokens_usedINT消耗token数
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_byBIGINT更新者
update_timeTIMESTAMP(6)更新时间

DDL

CREATE TABLE iot_ai_session_message (
id BIGSERIAL PRIMARY KEY,
session_id BIGINT REFERENCES iot_ai_session_memory(id),
role VARCHAR(20) NOT NULL,
content TEXT,
voice_url VARCHAR(500),
model VARCHAR(50),
tokens_used INT,
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
update_by BIGINT,
update_time TIMESTAMP(6),
INDEX idx_session_id (session_id)
);
CREATE TRIGGER update_ai_session_msg_modtime
BEFORE UPDATE ON iot_ai_session_message
FOR EACH ROW EXECUTE FUNCTION update_ai_session_msg_modtime();

2.2.12 表:ai_operation_log(AI 操作日志)

字段名类型约束说明
idBIGSERIALPK主键
operation_typeVARCHAR(50)NOT NULL操作类型:tts / asr / transcribe / session / gpt
family_idBIGINT关联家庭ID
device_idBIGINT关联设备ID
session_idBIGINT关联会话ID
request_payloadJSONB请求参数JSON
response_payloadJSONB响应结果JSON
statusVARCHAR(20)DEFAULT 'success'状态:success / failed
error_messageTEXT错误信息
duration_msBIGINT耗时(毫秒)
modelVARCHAR(50)AI模型
tokens_usedINTtoken消耗
create_timeTIMESTAMP(6)DEFAULT NOW()操作时间

索引设计

索引名字段类型说明
idx_family_idfamily_idNORMAL按家庭查询AI使用记录
idx_device_iddevice_idNORMAL按设备查询
idx_session_idsession_idNORMAL按会话查询
idx_operation_typeoperation_typeNORMAL操作类型筛选
idx_create_timecreate_timeNORMAL时间范围查询

2.2.13 表:mqtt_fall_event(雷达跌倒事件)

需求中对应 DEVICE_EVENT(event_type = fall)。

字段名类型约束说明
idBIGSERIALPK主键
serial_numberVARCHAR(100)NOT NULL设备序列号
device_idBIGINTFK → iot_device设备ID
family_idBIGINTFK → iot_family_archive家庭ID
elder_idBIGINT老人ID
fall_confidenceDECIMAL(5,4)跌倒置信度(0.0000-1.0000)
heart_rateINT当时心率
fall_typeVARCHAR(50)跌倒类型
presence_dataJSONB存在感数据
radar_paramsJSONB雷达参数JSON
ai_verdictVARCHAR(20)AI判断结果:escalate / dismiss
luma_responseVARCHAR(50)Luma询问结果:ok / timeout / help
process_statusVARCHAR(20)DEFAULT 'pending'处理状态:pending / processed / escalated / dismissed
event_timeTIMESTAMP(6)NOT NULL事件发生时间
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_serial_numberserial_numberNORMAL序列号查询
idx_family_idfamily_idNORMAL按家庭查询
idx_event_timeevent_timeNORMAL时间范围查询
idx_process_statusprocess_statusNORMAL处理状态筛选
idx_device_eventdevice_id + event_timeNORMAL设备事件时序查询

DDL

CREATE TABLE mqtt_fall_event (
id BIGSERIAL PRIMARY KEY,
serial_number VARCHAR(100) NOT NULL,
device_id BIGINT REFERENCES iot_device(id),
family_id BIGINT REFERENCES iot_family_archive(id),
elder_id BIGINT,
fall_confidence DECIMAL(5,4),
heart_rate INT,
fall_type VARCHAR(50),
presence_data JSONB,
radar_params JSONB,
ai_verdict VARCHAR(20),
luma_response VARCHAR(50),
process_status VARCHAR(20) DEFAULT 'pending',
event_time TIMESTAMP(6) NOT NULL,
create_by BIGINT,
create_time TIMESTAMP(6) DEFAULT NOW(),
INDEX idx_serial_number (serial_number),
INDEX idx_family_id (family_id),
INDEX idx_event_time (event_time DESC),
INDEX idx_process_status (process_status)
);

2.2.14 表:mqtt_subscription(MQTT 订阅管理)

字段名类型约束说明
idBIGSERIALPK主键
client_idVARCHAR(100)NOT NULLMQTT客户端ID
topicVARCHAR(255)NOT NULL订阅主题
qosINTDEFAULT 0QoS级别:0/1/2
statusVARCHAR(20)DEFAULT 'active'状态:active / disconnected
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_client_idclient_idNORMAL客户端查询
idx_topictopicNORMAL主题查询

2.2.15 表:mqtt_inbound_message(MQTT 入站消息)

字段名类型约束说明
idBIGSERIALPK主键
client_idVARCHAR(100)NOT NULL来源客户端ID
topicVARCHAR(255)NOT NULL消息主题
payloadTEXT消息内容
qosINTQoS级别
message_typeVARCHAR(50)消息类型
headersJSONB消息头JSON
device_idBIGINTFK → iot_device设备ID
received_atTIMESTAMP(6)NOT NULL接收时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_client_idclient_idNORMAL客户端查询
idx_topictopicNORMAL主题查询
idx_received_atreceived_atNORMAL时间范围查询

2.2.16 表:健康数据系列

iot_heart_rate(心率)
字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device设备ID
elder_idBIGINT老人ID
heart_rateINTNOT NULL心率值(bpm)
qualityVARCHAR(20)数据质量:good / poor
measured_atTIMESTAMP(6)NOT NULL测量时间
create_byBIGINT创建者
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

索引设计

索引名字段类型说明
idx_device_measureddevice_id + measured_atNORMAL设备时序查询
idx_elder_measuredelder_id + measured_atNORMAL老人时序查询
iot_spo(血氧)
字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device设备ID
elder_idBIGINT老人ID
spo2INTNOT NULL血氧值(%)
piINT灌注指数
qualityVARCHAR(20)数据质量
measured_atTIMESTAMP(6)NOT NULL测量时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
iot_pedo(步数)
字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device设备ID
elder_idBIGINT老人ID
step_countINT步数
calorieINT卡路里
distanceINT距离(米)
active_minutesJSONB活跃分钟数JSON
measured_dateDATENOT NULL测量日期
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
iot_sleep_raw(睡眠原始数据)
字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device设备ID
elder_idBIGINT老人ID
sleep_startTIMESTAMP(6)入睡时间
sleep_endTIMESTAMP(6)醒来时间
sleep_durationINT睡眠时长(分钟)
sleep_stagesJSONB睡眠分期JSON
sleep_scoreINT睡眠评分
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
iot_temperature(体温)
字段名类型约束说明
idBIGSERIALPK主键
device_idBIGINTFK → iot_device设备ID
elder_idBIGINT老人ID
temperatureDECIMAL(4,1)NOT NULL体温值(℃)
measurement_typeVARCHAR(20)测量类型:skin / ambient
measured_atTIMESTAMP(6)NOT NULL测量时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

2.3 待建告警相关表(需求定义,未在 SQL 导出中实现)

以下三表已在 business_architecture.md 需求文档中定义,但当前 SQL 导出中尚未创建。列出预期结构供参考实现。

2.3.1 表:ref_alert(告警事件 — 待建)

字段名类型约束说明
idBIGSERIALPK主键
family_idBIGINTFK → iot_family_archive家庭ID
elder_idBIGINT被照护者ID
device_event_idBIGINTFK → mqtt_fall_event触发事件ID
levelVARCHAR(20)NOT NULL级别:red / amber / normal
statusVARCHAR(20)DEFAULT 'firing'状态:firing / escalating / acknowledged / resolved / false_alarm
evidence_packJSONB证据包(雷达数据+Luma询问结果)
false_alarm_reasonVARCHAR(500)误报原因
fired_atTIMESTAMP(6)NOT NULL触发时间
acknowledged_atTIMESTAMP(6)确认时间
acknowledged_byBIGINT确认人用户ID
resolved_atTIMESTAMP(6)解决时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间
update_timeTIMESTAMP(6)更新时间

2.3.2 表:ref_escalation(升级链路 — 待建)

字段名类型约束说明
idBIGSERIALPK主键
alert_idBIGINTFK → ref_alert告警ID
escalation_levelINTNOT NULL升级阶梯(1-4)
caregiver_idBIGINTFK → iot_user通知对象
channelVARCHAR(20)NOT NULL通道:push / sms / voice
statusVARCHAR(20)DEFAULT 'pending'状态:pending / sent / delivered / acknowledged / timeout
scheduled_atTIMESTAMP(6)NOT NULL计划通知时间
sent_atTIMESTAMP(6)实际发送时间
acked_atTIMESTAMP(6)确认时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

2.3.3 表:ref_notification(通知记录 — 待建)

字段名类型约束说明
idBIGSERIALPK主键
alert_idBIGINTFK → ref_alert告警ID
escalation_idBIGINTFK → ref_escalation升级记录ID
caregiver_idBIGINTFK → iot_user接收人
channelVARCHAR(20)NOT NULL通道:push / sms / voice
titleVARCHAR(200)通知标题
bodyTEXT通知正文
statusVARCHAR(20)DEFAULT 'sent'状态:sent / delivered / failed
sent_atTIMESTAMP(6)发送时间
delivered_atTIMESTAMP(6)送达时间
create_timeTIMESTAMP(6)DEFAULT NOW()创建时间

2.4 框架表说明

表前缀所属框架说明
sys_*RuoYi-Vue-Plus 系统管理用户、角色、菜单、部门、字典、OSS、审计日志
gen_*RuoYi 代码生成代码生成配置表(表信息、字段信息)
sj_*分布式任务调度(saturn)定时任务、任务执行器、工作流、重试机制

框架表由 RuoYi-Vue-Plus 脚手架自动生成和维护,业务开发通常不直接操作。


第三部分:缓存结构设计(Redis)

基于 technical_architecture.md 5.4 章节定义。

3.1 缓存 Key 总览

Key 模式类型内容TTL服务说明
device:heartbeat:{deviceId}String心跳时间戳5 minD1 设备接入高频写入,Redis 提供毫秒级读写
family:status:{familyId}Hash家庭当前六状态30sD2/D4六态联动 Family App / Luma App,实时刷新
session:{token}Hash用户会话信息2h通用Sa-Token + JWT
alert:escalation:{alertId}String升级链路状态锁90sD5 通知告警Redisson 分布式锁
iot:device:online:{serialNumber}String设备在线状态5 minD1 设备接入与心跳 key 联动
iot:family:elder:{familyId}Hash老人实时状态30sD4 AI大脑心率/活动状态
ai:session:{sessionId}HashAI会话上下文1hD4 AI大脑GPT-4o 对话上下文缓存
tts:audio:{hash}StringTTS音频缓存24hD4 AI大脑相同内容不重复合成

3.2 缓存策略

  • 设备心跳device:heartbeat:*):高频写入 Redis,DB 异步批量落盘,避免频繁 IO
  • 家庭状态family:status:*):30s 过期,每次状态变化时主动刷新,支持 Family App / Luma App 实时感知
  • 告警升级锁alert:escalation:*):90s 锁,Redisson 分布式锁保证升级链路原子性
  • AI 会话ai:session:*):1h 过期,存储 GPT-4o 对话上下文,减少 token 消耗
  • 会话session:*):2h TTL,Sa-Token JWT 会话,续期机制

3.3 分布式锁用途

锁名称用途TTL实现
lock:device:heartbeat:{id}设备心跳并发写入10sRedisson
lock:family:alert:{id}告警升级链路原子性90sRedisson
lock:device:command:{id}设备指令下发幂等30sRedisson
lock:ai:tts:{content_hash}TTS 内容去重合成1hRedisson

第四部分:ORM 模型代码

以下为 MyBatis-Plus 实体类,对应 RuoYi-Vue-Plus 框架规范。包名 health.reflekt.domain

4.1 用户与家庭

package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotUser {
@TableId(type = IdType.AUTO)
private Long id;
private Long familyId;
/** 手机号(AES-256加密,MyBatis拦截器自动加解密) */
private String phone;
private String nickname;
private String avatar;
private String status; // active / inactive
@TableField(fill = FieldFill.INSERT)
private Long createDept;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;

@Data
public class IotFamilyArchive {
@TableId(type = IdType.AUTO)
private Long id;
private String familyName;
private String elderName;
private Integer elderAge;
private String elderGender;
/** 健康档案JSON:疾病史/用药史/作息 */
private Map<String, Object> healthProfile;
/** 行为基线标识 */
private String baselineHash;
/** 隐私同意状态JSON */
private Map<String, Object> privacyConsent;
private String address;
private String status; // active / pilot / formal
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotFamilyGroupMember {
@TableId(type = IdType.AUTO)
private Long id;
private Long familyId;
private Long userId;
/** 角色:admin / member */
private String role;
/** 紧急联系优先级(1最高) */
private Integer priority;
private String nickname;
private String status;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

4.2 设备

package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;

@Data
public class IotDevice {
@TableId(type = IdType.AUTO)
private Long id;
/** 设备序列号 */
private String serialNumber;
/** 设备类型:luma / radar / watch */
private String deviceType;
private Long familyId;
private String deviceName;
private String deviceModel;
/** 状态:online / offline / pending */
private String status;
/** 设备配置JSON */
private Map<String, Object> config;
private LocalDateTime lastHeartbeat;
private String firmwareVersion;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

4.3 消息与提醒

package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotFamilyMessage {
@TableId(type = IdType.AUTO)
private Long id;
private Long familyId;
private Long senderId;
/** 发送者类型:user / elder */
private String senderType;
private Long elderId;
/** 内容类型:voice / text */
private String contentType;
private String content;
/** 语音文件URL(S3) */
private String voiceUrl;
/** 语音时长(秒) */
private Integer duration;
/** 状态:pending / sent / delivered / played / failed */
private String status;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
@TableField(update = "%NOW%")
private LocalDateTime updateTime;
}
package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotFamilyReminder {
@TableId(type = IdType.AUTO)
private Long id;
private Long familyId;
private Long elderId;
private Long creatorId;
/** 内容类型:text / voice */
private String contentType;
private String content;
private String voiceUrl;
/** Cron表达式 */
private String schedule;
/** 频率:daily / weekly / custom */
private String frequency;
private Boolean needConfirm;
private Boolean shared;
/** 状态:active / paused / deleted */
private String status;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

4.4 AI 对话与记忆

package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotAiSessionMemory {
@TableId(type = IdType.AUTO)
private Long id;
private Long familyId;
private Long elderId;
private Long caregiverId;
private String topic;
private String elderResponseText;
/** 老人回答语音URL(S3) */
private String elderResponseUrl;
/** 状态:pending / answered / listened / expired */
private String status;
private LocalDateTime askedAt;
private LocalDateTime answeredAt;
private LocalDateTime listenedAt;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
@TableField(update = "%NOW%")
private LocalDateTime updateTime;
}
package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotAiSessionMessage {
@TableId(type = IdType.AUTO)
private Long id;
private Long sessionId;
/** 角色:user / assistant */
private String role;
private String content;
private String voiceUrl;
private String model;
private Integer tokensUsed;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
@TableField(update = "%NOW%")
private LocalDateTime updateTime;
}

4.5 雷达事件

package health.reflekt.domain.mqtt;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

@Data
public class MqttFallEvent {
@TableId(type = IdType.AUTO)
private Long id;
private String serialNumber;
private Long deviceId;
private Long familyId;
private Long elderId;
/** 跌倒置信度(0.0000-1.0000) */
private BigDecimal fallConfidence;
private Integer heartRate;
private String fallType;
/** 存在感数据JSON */
private Map<String, Object> presenceData;
/** 雷达参数JSON */
private Map<String, Object> radarParams;
/** AI判断:escalate / dismiss */
private String aiVerdict;
/** Luma询问结果:ok / timeout / help */
private String lumaResponse;
/** 处理状态:pending / processed / escalated / dismissed */
private String processStatus;
private LocalDateTime eventTime;
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

4.6 健康数据

package health.reflekt.domain.iot;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class IotHeartRate {
@TableId(type = IdType.AUTO)
private Long id;
private Long deviceId;
private Long elderId;
/** 心率值(bpm) */
private Integer heartRate;
private String quality; // good / poor
private LocalDateTime measuredAt;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

@Data
public class IotSpo {
@TableId(type = IdType.AUTO)
private Long id;
private Long deviceId;
private Long elderId;
/** 血氧值(%) */
private Integer spo2;
private Integer pi;
private String quality;
private LocalDateTime measuredAt;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

@Data
public class IotPedo {
@TableId(type = IdType.AUTO)
private Long id;
private Long deviceId;
private Long elderId;
private Integer stepCount;
private Integer calorie;
private Integer distance;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

@Data
public class IotSleepRaw {
@TableId(type = IdType.AUTO)
private Long id;
private Long deviceId;
private Long elderId;
private LocalDateTime sleepStart;
private LocalDateTime sleepEnd;
private Integer sleepDuration;
/** 睡眠分期JSON */
private String sleepStages;
private Integer sleepScore;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

@Data
public class IotTemperature {
@TableId(type = IdType.AUTO)
private Long id;
private Long deviceId;
private Long elderId;
/** 体温值(℃) */
private java.math.BigDecimal temperature;
/** 测量类型:skin / ambient */
private String measurementType;
private LocalDateTime measuredAt;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

本文档由 Reflekt Health 技术团队维护,最后更新于 2026-04-22。