From 23f8d42818ce68551e98addc869c953757924f1c Mon Sep 17 00:00:00 2001 From: feie9456 Date: Sat, 18 Apr 2026 11:42:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 547 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 525 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index e215bc4..00f74b3 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,539 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# 安智伴 · 家人连线台(Web 监护端) -## Getting Started +> 本项目与 [dh_aigc_android](https://github.com/user/dh_aigc_android)(Android AI 数字人陪护终端)配合使用,共同构成完整的"AI 数字人 + 家庭远程关怀"解决方案。 -First, run the development server: +--- -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +## 目录 + +- [需求分析](#需求分析) +- [设计思路](#设计思路) +- [技术架构](#技术架构) +- [数据库设计](#数据库设计) +- [页面与功能](#页面与功能) +- [API 接口](#api-接口) +- [全链路数据流](#全链路数据流) +- [推送通知系统](#推送通知系统) +- [身份验证](#身份验证) +- [开发与部署](#开发与部署) + +--- + +## 需求分析 + +### 背景 + +配合 Android 端 AI 数字人陪护应用,家属需要一个便捷的远程监护面板来: +- 了解老人是否在使用设备、与 AI 聊了什么 +- 主动发送关怀留言,由数字人口播转达 +- 接收老人通过 AI 口述的回复留言 +- 获得实时推送通知,不遗漏重要消息 + +### 核心需求 + +| 需求维度 | 描述 | +|---------|------| +| **双向留言** | 家属发送留言 → 数字人口播给老人;老人口述 → AI 转录 → 家属在此查看 | +| **使用监测** | 查看老人设备的使用频率、AI 对话次数、最后在线时间 | +| **设备绑定** | 支持扫码或手动输入设备码绑定老人设备,一个家属可绑定多台设备 | +| **推送提醒** | 收到新留言时浏览器推送通知(PWA + Web Push) | +| **多端登录** | 同一家属账号可在多个浏览器/设备登录 | +| **面向家属的友好界面** | 暖色调、生活化文案,避免技术化的配置面板 | + +### 用户角色 + +| 角色 | 使用场景 | +|------|---------| +| **家属**(本 Web 端) | 登录后查看老人动态、发送留言、管理设备绑定、接收推送 | +| **老人**(Android 端) | 不直接使用本系统,通过 AI 数字人间接交互 | +| **设备**(Android 端自动上报) | 自动注册、上报使用事件和对话数据 | + +--- + +## 设计思路 + +### 1. 以留言为核心的关怀模式 + +不同于即时通讯工具,本系统采用"留言板"模式: +- 家属写留言 → 等老人下次与 AI 对话时口播转达 +- 老人对 AI 说"帮我给儿子捎个话" → AI 通过工具调用存入数据库 → 家属收到推送 + +这种异步模式契合老人的使用习惯,无需老人学习操作手机。 + +### 2. 设备即桥梁 + +- Android 设备是唯一的数据桥梁,通过 UUID 标识 +- 家属通过扫码或输入设备码绑定设备 +- 所有消息和事件都关联到设备维度 + +### 3. PWA 优先 + +- 支持"安装到桌面",像原生 App 一样使用 +- Service Worker 处理推送通知 +- 即使浏览器关闭也能收到消息提醒 + +### 4. 温暖的视觉语言 + +- 暖色系纸质质感(`--paper: #f4ece0`、`--copper: #c76733`、`--olive: #76845e`) +- 生活化文案("写好并送出"而非"提交") +- 面向不一定技术精通的家属用户 + +--- + +## 技术架构 + +### 技术栈 + +| 层级 | 技术 | +|------|------| +| **框架** | Next.js 16 (App Router, Server Components) | +| **前端** | React 19 + TypeScript 5 | +| **样式** | Tailwind CSS 4 + CSS 变量暖色系统 | +| **ORM** | Prisma 7 + PrismaPg 适配器 | +| **数据库** | PostgreSQL | +| **推送** | Web Push API + VAPID 密钥 | +| **认证** | Session-based (HttpOnly Cookie + bcryptjs) | +| **PWA** | Service Worker + Web App Manifest | +| **扫码** | qr-scanner (浏览器端摄像头扫码) | + +### 系统架构图 + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ 家属浏览器 (PWA) │ +│ │ +│ ┌─────────────────┐ ┌─────────────┐ ┌────────────────────┐ │ +│ │ 设备管理 │ │ 留言板 │ │ 陪伴动态 │ │ +│ │ (扫码绑定/列表) │ │ (双向消息) │ │ (使用/对话/工具) │ │ +│ └────────┬────────┘ └──────┬──────┘ └─────────┬──────────┘ │ +│ │ │ │ │ +│ ┌────────▼──────────────────▼────────────────────▼──────────┐ │ +│ │ Service Worker (Web Push) │ │ +│ └───────────────────────────┬───────────────────────────────┘ │ +└──────────────────────────────┼───────────────────────────────────┘ + │ HTTPS + ▼ +┌──────────────────────────────────────────────────────────────────┐ +│ Next.js Server │ +│ │ +│ ┌────────────────────────────────────────────────────────────┐ │ +│ │ API Routes │ │ +│ │ /api/account/* 认证 (登录/注册/登出) │ │ +│ │ /api/family/* 家属操作 (发留言/绑定/别名/解绑) │ │ +│ │ /api/device/* 设备上报 (注册/消息/事件/对话/工具) │ │ +│ │ /api/push/* 推送管理 (订阅/退订/测试) │ │ +│ └────────────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────▼───────────────────────────────┐ │ +│ │ Prisma ORM │ │ +│ └────────────────────────────┬───────────────────────────────┘ │ +└───────────────────────────────┼──────────────────────────────────┘ + │ + ┌───────────▼───────────┐ + │ PostgreSQL │ + │ │ + │ CaregiverAccount │ + │ CaregiverSession │ + │ ElderDevice │ + │ DeviceBinding │ + │ FamilyMessage │ + │ ConversationTurn │ + │ UsageEvent │ + │ ToolCallLog │ + │ PushSubscription │ + └───────────────────────┘ ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +### 与 Android 端的通信 -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +``` +┌──────────────────┐ ┌──────────────────┐ +│ Android 设备端 │ │ Next.js 云端 │ +│ │ │ │ +│ FamilyBridge │ ──────→ │ /api/device/* │ +│ Service │ HTTPS │ │ +│ │ │ • register │ +│ • 设备注册 │ ──────→ │ • messages │ +│ • 拉取留言 │ ←────── │ • messages/read │ +│ • 标记已读 │ ──────→ │ • usage │ +│ • 上报事件 │ ──────→ │ • conversations │ +│ • 上传对话 │ ──────→ │ • tool-call │ +│ • 工具调用记录 │ ──────→ │ │ +└──────────────────┘ └──────────────────┘ +``` -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +--- -## Learn More +## 数据库设计 -To learn more about Next.js, take a look at the following resources: +### ER 关系 -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +``` +CaregiverAccount ──1:N──→ CaregiverSession (多设备登录) +CaregiverAccount ──1:N──→ DeviceBinding (绑定多台设备) +CaregiverAccount ──1:N──→ FamilyMessage (发出的留言) +CaregiverAccount ──1:N──→ PushSubscription (推送端点) -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +ElderDevice ──1:N──→ DeviceBinding (被多个家属绑定) +ElderDevice ──1:N──→ FamilyMessage (关联的留言) +ElderDevice ──1:N──→ ConversationTurn (对话记录) +ElderDevice ──1:N──→ UsageEvent (使用事件) +ElderDevice ──1:N──→ ToolCallLog (工具调用日志) +``` -## Deploy on Vercel +### 核心数据模型 -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +#### CaregiverAccount(家属账号) -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +| 字段 | 类型 | 说明 | +|------|------|------| +| id | Int (PK) | 自增主键 | +| username | String (unique) | 账户名,3-24 位 | +| passwordHash | String | bcrypt 密码哈希 | +| nickname | String? | 昵称 | + +#### ElderDevice(老人设备) + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | Int (PK) | 自增主键 | +| deviceUuid | String (unique) | UUID 格式设备号 | +| displayName | String? | 设备显示名 | +| appVersion | String? | 应用版本号 | +| lastSeenAt | DateTime | 最后在线时间 | + +#### DeviceBinding(设备绑定) + +| 字段 | 类型 | 说明 | +|------|------|------| +| caregiverId + elderDeviceId | 复合唯一键 | 多对多桥接 | +| alias | String? | 自定义别名(≤24 字) | + +#### FamilyMessage(双向留言) + +| 字段 | 类型 | 说明 | +|------|------|------| +| publicId | Int (auto-increment) | 公开 ID,用于 URL | +| content | String | 留言内容 | +| direction | Enum | `ELDER_TO_FAMILY` / `FAMILY_TO_ELDER` | +| importance | Enum | `LOW` / `NORMAL` / `HIGH` / `URGENT` | +| status | Enum | `PENDING` / `DELIVERED` / `READ` | + +#### UsageEvent(使用事件) + +事件类型:`APP_OPEN` · `SETTINGS_OPENED` · `AI_SESSION_STARTED` · `AI_SESSION_ENDED` · `CAMERA_ENABLED` · `CAMERA_DISABLED` · `TOOL_CALLED` + +#### ConversationTurn(对话轮次) + +角色:`USER`(老人语音)· `ASSISTANT`(AI 回复)· `TOOL`(工具调用) + +#### ToolCallLog(工具调用日志) + +记录 AI 对话中触发的工具调用,包括工具名、参数 JSON、执行结果、状态。 + +### 迁移历史 + +| 版本 | 时间 | 内容 | +|------|------|------| +| v1 | 2026-04-17 01:50 | 初始表结构 + 枚举类型 | +| v2 | 2026-04-17 04:09 | 添加 publicId + PushSubscription 表 | +| v3 | 2026-04-17 04:51 | 账号认证系统 + 多设备会话 | +| v4 | 2026-04-17 07:00 | 设备绑定别名功能 | + +--- + +## 页面与功能 + +### 页面结构 + +``` +/login → 登录 / 注册 +/ → 首页概览 (KPI 卡片 + 导航) +/devices → 设备列表 (绑定新设备 + 快速统计) +/devices/[uuid] → 设备详情 (发送留言 + 收到留言 + 活动记录) +/messages → 留言板 (双列:老人留言 / 我的问候) +/messages/[id] → 留言详情 +/activity → 陪伴动态 (使用记录 + 聊天记录 + 智能服务) +/scan → 扫码绑定 (QR Scanner) +/settings → 设置 (PWA 安装 + 推送管理) +/bind → 绑定结果页 +``` + +### 首页 `/` + +- 4 个 KPI 卡片:已绑设备数、新留言数、待查看数、对话总数 +- 4 个功能导航卡片:留言板、设备管理、陪伴动态、设置 +- 无设备时显示引导流程 +- 最近消息预览 + +### 设备管理 `/devices` + +- 手动粘贴设备码绑定 +- 设备卡片:在线状态、留言数、对话数、智能服务调用数 +- 最新动态预览 + +### 设备详情 `/devices/[uuid]` + +- KPI 指标(新留言、待查看、最后在线、绑定链接) +- 设备管理(别名修改、解绑) +- 发送留言表单(4 个优先级) +- 最近收到的留言列表 +- 最近活动记录 +- 已发送的问候 +- 最近对话片段 + +### 留言板 `/messages` + +- 双列分组:左侧"长辈的留言"(含未读计数)、右侧"我发出的问候"(含待查看计数) +- 每条显示:公开 ID、方向标签、设备名、优先级、状态、时间戳 + +### 陪伴动态 `/activity` + +- 三列展示:使用记录、聊天记录、智能服务 +- 趋势可视化图表 + +### 扫码绑定 `/scan` + +- 浏览器摄像头 QR 扫描 +- 自动摄像头授权检测 +- 失败降级提示手动输入 + +--- + +## API 接口 + +### 账号管理 `/api/account/` + +| 路由 | 方法 | 功能 | +|------|------|------| +| `/login` | POST | 登录(username + password → 设置 Session Cookie) | +| `/register` | POST | 注册(创建账号 + 自动登录) | +| `/logout` | POST | 登出(清除 Cookie + 删除 Session) | + +### 家属操作 `/api/family/` + +| 路由 | 方法 | 功能 | +|------|------|------| +| `/messages` | POST | 发送留言给老人(创建 FamilyMessage + 触发 Web Push) | +| `/device-binding` | PATCH | 修改设备别名 | +| `/device-binding` | DELETE | 解绑设备 | +| `/bind` | POST | 绑定新设备 | +| `/session` | GET | 会话验证 + 重定向 | + +### 设备上报 `/api/device/` + +| 路由 | 方法 | 功能 | 认证方式 | +|------|------|------|---------| +| `/register` | POST | 设备注册/更新 | deviceUuid 验证 | +| `/messages` | GET | 拉取待发送消息 | deviceUuid 查询参数 | +| `/messages/read` | POST | 标记消息已读 | deviceUuid 验证 | +| `/conversations` | POST | 记录对话内容 | deviceUuid 验证 | +| `/usage` | POST | 上报使用事件 | deviceUuid 验证 | +| `/tool-call` | POST | 记录工具调用 | deviceUuid 验证 | + +### 推送管理 `/api/push/` + +| 路由 | 方法 | 功能 | +|------|------|------| +| `/subscribe` | POST | 订阅推送通知(需登录) | +| `/unsubscribe` | POST | 取消订阅 | +| `/test` | POST | 发送测试推送 | + +--- + +## 全链路数据流 + +### 1. 设备绑定流程 + +``` +老人设备首次启动 → POST /api/device/register → 获得 deviceUuid + bindUrl +→ 设备屏幕展示二维码(编码 bindUrl) +→ 家属打开 /scan 页面 → 浏览器摄像头扫码 +→ 解析出 /bind?deviceUuid=xxx +→ 未登录 → 重定向 /login?redirectTo=/bind?deviceUuid=xxx +→ 已登录 → 调用 POST /api/family/bind +→ 检查/创建 ElderDevice → 创建 DeviceBinding → 迁移遗留数据 +→ 绑定成功页 +``` + +### 2. 家属发送留言 → 老人收到 + +``` +家属在 /devices/[uuid] 填写留言 → POST /api/family/messages +→ 创建 FamilyMessage (FAMILY_TO_ELDER, PENDING) +→ 触发 sendIncomingMessagePush() → 向所有订阅端点发送 Web Push +→ 家属收到浏览器通知确认 + +→ (稍后) 老人设备启动 AI 对话 +→ FamilyBridgeService → GET /api/device/messages +→ 返回未读消息 (summaryText + messages[]) +→ 注入 AI 系统 Prompt → AI 在第一轮回复中主动口播转达 +→ 设备端 → POST /api/device/messages/read → 标记已读 +``` + +### 3. 老人口述留言 → 家属收到 + +``` +老人对 AI 说 "帮我给女儿说一声我今天去公园了" +→ Qwen 识别意图 → 触发 leave_message_for_family 工具 +→ FamilyBridgeService → POST /api/device/conversations +→ 创建 FamilyMessage (ELDER_TO_FAMILY) +→ 触发 Web Push → 家属浏览器通知 +→ 家属打开 /messages 查看 +``` + +### 4. 使用监测 + +``` +设备事件 (APP_OPEN / AI_SESSION_STARTED / ...) +→ POST /api/device/usage → 存入 UsageEvent +→ 家属访问 /activity → Server Component 查询最近事件 +→ 渲染使用趋势图 + 对话记录 + 工具调用日志 +``` + +--- + +## 推送通知系统 + +### 架构 + +``` +家属浏览器 +├── 注册 Service Worker (/sw.js) +├── PushManager.subscribe(VAPID 公钥) → 获取 PushSubscription +├── POST /api/push/subscribe → 存入数据库 +└── 收到推送 → showNotification() → 点击 → 打开对应页面 + +服务端 (新消息触发时) +├── 查询目标设备所有已绑定家属的 PushSubscription +├── 循环调用 webpush.sendNotification() +└── 处理 410 Gone → 清理失效端点 +``` + +### Service Worker 功能 + +- **push 事件**:解析 JSON → 调用 `showNotification()`,显示标题、内容、图标 +- **notificationclick 事件**:打开或聚焦到目标 URL,支持已打开窗口的导航 +- **去重**:使用 `tag: "digital-human-message"` 合并同类通知 + +--- + +## 身份验证 + +### 家属端(Session-based) + +| 项目 | 说明 | +|------|------| +| Cookie 名 | `dh-caregiver-session` | +| 属性 | HttpOnly + Secure (生产) + SameSite=Lax | +| 有效期 | 365 天 | +| 密码哈希 | bcryptjs | +| 多设备 | 每次登录创建独立 Session,支持多端在线 | + +### 设备端(UUID 隐式验证) + +设备通过 `deviceUuid` 参数标识身份,依赖 UUID 的不可猜测性。无需额外认证令牌。 + +--- + +## 开发与部署 + +### 环境变量 + +```env +DATABASE_URL=postgresql://... # PostgreSQL 连接串 +NEXT_PUBLIC_VAPID_PUBLIC_KEY=... # Web Push 公钥(客户端) +VAPID_PRIVATE_KEY=... # Web Push 私钥(服务端) +VAPID_SUBJECT=mailto:admin@example.com # 推送发送者标识 +``` + +### 本地开发 + +```bash +# 安装依赖 +npm install + +# 数据库迁移 +npx prisma migrate dev + +# 启动开发服务器 +npm run dev +``` + +访问 [http://localhost:3000](http://localhost:3000) 。 + +### 数据库管理 + +```bash +# 查看数据库 +npx prisma studio + +# 生成 Prisma Client +npx prisma generate + +# 创建新迁移 +npx prisma migrate dev --name +``` + +### 生产部署 + +```bash +# 构建 +npm run build + +# 启动 +npm start +``` + +支持部署到 Vercel、Docker 或任何 Node.js 环境。 + +### 项目结构 + +``` +digital-human-monitor-v2/ +├── app/ # Next.js App Router +│ ├── layout.tsx # 根布局 (认证状态 + 导航) +│ ├── page.tsx # 首页概览 +│ ├── globals.css # 全局样式 (暖色系变量) +│ ├── manifest.ts # PWA Manifest +│ ├── api/ # API 路由 +│ │ ├── account/ # 登录/注册/登出 +│ │ ├── device/ # 设备上报接口 +│ │ ├── family/ # 家属操作接口 +│ │ └── push/ # 推送管理 +│ ├── activity/ # 陪伴动态页 +│ ├── bind/ # 绑定结果页 +│ ├── devices/ # 设备管理 +│ │ └── [deviceUuid]/ # 设备详情 +│ ├── login/ # 登录/注册页 +│ ├── messages/ # 留言板 +│ │ └── [messageId]/ # 留言详情 +│ ├── scan/ # 扫码绑定 +│ └── settings/ # 设置页 +├── components/ # 可复用 UI 组件 +├── lib/ # 业务逻辑库 +│ ├── prisma.ts # Prisma 客户端单例 +│ ├── session.ts # Session 管理 +│ ├── page-auth.ts # 页面级认证守卫 +│ ├── push.ts # Web Push 发送逻辑 +│ ├── caregiver-panel.ts # 家属面板数据聚合 +│ ├── monitor-data.ts # 监测数据查询 +│ └── panel-format.ts # 面板格式化工具 +├── prisma/ +│ ├── schema.prisma # 数据库 Schema +│ └── migrations/ # 迁移文件 +├── public/ +│ ├── sw.js # Service Worker +│ └── pwa/ # PWA 图标资源 +└── scripts/ + └── generate-icons.mjs # 图标生成脚本 +``` + +--- + +## 关联项目 + +| 项目 | 角色 | 仓库 | +|------|------|------| +| **digital-human-monitor-v2**(本项目) | 家属端:远程监护 Web 面板 + 消息管理 + 推送通知 | 当前仓库 | +| **dh_aigc_android** | 老人端:AI 数字人陪护 + 设备行为上报 | [dh_aigc_android](../dh_aigc_android/) |