取代纸质排队号码和手动登记,自动化诊所排队、挂号、叫号全流程
* Preview is for reference only. Actual results may vary depending on the AI model, variable values, and tools used.
你是一位资深全栈开发者,擅长医疗系统和实时应用开发。请为 {clinic_name} 构建一个完整的患者排队与挂号系统。
## 项目概述
这是一个取代纸质排队号码的现代化诊所排队管理系统,服务于马来西亚 {clinic_type}。系统需支持患者自助挂号、实时排队显示、医生叫号、SMS 通知(模拟)等功能。
## 技术栈
- 框架:Next.js 16(App Router)
- 样式:Tailwind CSS 4
- 后端:Supabase(Postgres + Auth + Realtime)
- 部署:Vercel
- 语言:TypeScript
## 数据模型(Supabase Postgres)
### departments 科室表
- id: uuid primary key default gen_random_uuid()
- name_zh: text not null(如『普通门诊』『牙科』『药房』)
- name_en: text not null
- code: text unique not null(如 GP, DENTAL, PHARMA)
- icon: text(lucide icon 名称)
- is_active: boolean default true
- sort_order: integer default 0
- created_at: timestamptz default now()
### doctors 医生表
- id: uuid primary key default gen_random_uuid()
- name: text not null
- title: text(如『Dr.』『牙医』)
- department_id: uuid references departments(id)
- room_number: text(诊室编号)
- is_available: boolean default true
- max_patients_per_day: integer default 40
- avg_consultation_minutes: integer default 15
- created_at: timestamptz default now()
- 索引:department_id
### patients 患者表
- id: uuid primary key default gen_random_uuid()
- ic_number: text unique(MyKad IC 号码,格式 XXXXXX-XX-XXXX)
- name: text not null
- phone: text(马来西亚手机号 +60XX-XXXXXXX)
- email: text
- date_of_birth: date
- gender: text check (gender in (M, F))
- address: text
- emergency_contact: text
- blood_type: text
- allergies: text
- is_panel: boolean default false(是否 panel 病人)
- created_at: timestamptz default now()
- updated_at: timestamptz default now()
- 索引:ic_number, phone
### queue_entries 排队记录表
- id: uuid primary key default gen_random_uuid()
- queue_number: text not null(格式:科室代码+序号,如 GP-001, DENTAL-015)
- patient_id: uuid references patients(id)
- department_id: uuid references departments(id)
- doctor_id: uuid references doctors(id)(可空,后续分配)
- queue_type: text check (queue_type in (walk_in, appointment)) default walk_in
- priority: integer default 0(0=普通, 1=预约优先, 2=紧急)
- status: text check (status in (waiting, called, in_consultation, completed, no_show, cancelled)) default waiting
- check_in_time: timestamptz default now()
- called_time: timestamptz
- start_time: timestamptz(开始就诊时间)
- end_time: timestamptz(结束就诊时间)
- estimated_wait_minutes: integer
- notes: text
- sms_sent: boolean default false
- sms_sent_at: timestamptz
- queue_date: date default current_date
- created_at: timestamptz default now()
- 索引:department_id, doctor_id, patient_id, queue_date, status
- 唯一约束:(queue_number, queue_date)
### visit_records 就诊记录表
- id: uuid primary key default gen_random_uuid()
- queue_entry_id: uuid references queue_entries(id)
- patient_id: uuid references patients(id)
- doctor_id: uuid references doctors(id)
- department_id: uuid references departments(id)
- diagnosis: text
- prescription: text
- notes: text
- follow_up_date: date
- visit_date: date default current_date
- created_at: timestamptz default now()
- 索引:patient_id, doctor_id, visit_date
### daily_counters 每日计数器表
- id: uuid primary key default gen_random_uuid()
- department_id: uuid references departments(id)
- counter_date: date default current_date
- last_number: integer default 0
- 唯一约束:(department_id, counter_date)
## RLS 安全策略
- patients: anon 可 INSERT(自助挂号);authenticated 可 SELECT/UPDATE/DELETE
- queue_entries: anon 可 INSERT 和 SELECT(显示屏需要读取);authenticated 可 UPDATE/DELETE
- doctors/departments: anon 可 SELECT;authenticated 可全部操作
- visit_records: 仅 authenticated 可操作
- daily_counters: anon 可 SELECT;authenticated 可 UPDATE
## Supabase Realtime 配置
对 queue_entries 表启用 Realtime,让叫号屏和前台仪表盘实时更新:
- 监听 INSERT(新患者排队)
- 监听 UPDATE(状态变更:叫号、就诊、完成)
## 核心业务逻辑
### 1. 排队号码生成
- 格式:{科室代码}-{三位序号},如 GP-001, DENTAL-015
- 每日自动重置,从 001 开始
- 使用 daily_counters 表 + Postgres 事务确保并发安全
- 预约患者号码前缀加 A,如 A-GP-003
### 2. 排队优先级
- priority 0:普通 walk-in,先到先服务
- priority 1:预约患者,在当前等候队列中插入(排在同优先级最后)
- priority 2:紧急/VIP,排在队列最前
- 排序规则:ORDER BY priority DESC, check_in_time ASC
### 3. 预计等待时间计算
- 公式:前面等候人数 x 该科室平均就诊时长
- 从 doctors 表获取 avg_consultation_minutes
- 考虑该科室当前可用医生数量
- 每次状态变更时重新计算队列中所有人的等待时间
### 4. SMS 通知(模拟)
- 当患者前面只剩 3 人时触发
- 在 queue_entries 表标记 sms_sent = true
- 前端用 toast 通知模拟 SMS 发送效果
- 通知内容模板:【{clinic_name}】您的号码 {queue_number} 即将到号,前面还有 {remaining} 位,请到 {department} 候诊区准备。
### 5. 医生分配
- 自动分配:选择该科室当前排队最少的可用医生
- 手动分配:前台可指定医生
- 医生请假/暂停接诊时,自动重新分配其队列
### 6. 叫号流程
- 医生点击『叫下一位』→ 状态从 waiting 变为 called
- 叫号屏播放提示音 + 显示号码和诊室
- 如果 3 分钟未到诊,标记为过号(no_show),可选择重新排队
- 医生点击『开始就诊』→ 状态变为 in_consultation
- 医生点击『完成就诊』→ 状态变为 completed,自动叫下一位
## 页面结构与 UI/UX 规范
### 全局设计
- 主色调:{primary_color}
- 字体:Inter + Noto Sans SC
- 大量使用大号字体(叫号屏和挂号机需远距离可读)
- 按钮最小高度 48px(触屏友好)
- 所有界面支持中英文双语显示
### 页面 1:自助挂号 Kiosk /kiosk
全屏界面,为触摸屏优化,大按钮大字体。
流程:
1. 欢迎页 — 显示诊所名称 logo,两个大按钮:『扫描 IC 卡』和『手动输入』
2. 输入 IC 号 — 大数字键盘(类似 ATM),支持 MyKad 格式 XXXXXX-XX-XXXX
3. 确认/补充信息 — 如果是回访患者,显示已有信息确认;新患者填写姓名、电话、性别
4. 选择科室 — 大卡片网格显示 {departments},每个卡片显示科室名称、图标、当前等候人数
5. 选择类型 — Walk-in(普通挂号)或 Appointment(预约到诊)
6. 确认并取号 — 显示排队号码(超大字体)、预计等待时间、前面等候人数
7. 完成 — 5 秒后自动返回欢迎页
设计要点:
- 背景白色,卡片圆角 16px
- 排队号码显示用 96px+ 超大字体,加粗
- 科室选择卡片 min-height 120px
- 每个步骤有返回按钮
- 触摸区域最小 64x64px
- 闲置 60 秒自动返回欢迎页
### 页面 2:叫号显示屏 /display
全屏,为大电视/显示器优化,无需交互。
布局:
- 顶部横栏:诊所名称 + 当前时间 + 日期
- 主区域分栏显示各科室({departments})
- 每个科室栏显示:
- 科室名称 + 图标
- 『当前叫号』大号显示(闪烁动画吸引注意)
- 医生姓名 + 诊室号
- 『等候中』号码列表(最近 5 个)
- 等候总人数
- 底部滚动通知栏:显示最近叫号信息(如『GP-015 请到 诊室 2 就诊』)
设计要点:
- 深色背景(#0F172A)配高对比文字
- 当前叫号用 {primary_color} 高亮,字号 72px+
- 等候号码字号 32px
- 新叫号时有弹入动画 + 提示音
- 使用 Supabase Realtime 订阅实时更新
- 自动全屏(F11 提示)
- 支持多屏:URL 参数 ?department=GP 可只显示单科室
### 页面 3:前台管理仪表盘 /dashboard
前台护士/接待员使用的管理界面。
布局:
- 左侧边栏:科室筛选、快速操作按钮
- 主区域:
- 顶部统计卡片:今日总挂号数、当前等候人数、平均等待时间、已完成就诊数
- 排队列表表格:号码、患者姓名、IC 号(脱敏)、科室、医生、状态、等待时间、操作按钮
- 操作:叫号、跳过、取消、重新排队、分配医生
- 右侧面板(Sheet):点击患者显示详细资料和历史记录
功能:
- 手动新增挂号(为不会操作 Kiosk 的老人家代办)
- 批量叫号(一次叫多个科室的下一位)
- 搜索患者(按 IC 号、姓名、电话)
- 查看/编辑患者资料
- 今日排队总览(按科室分标签页 Tabs)
- 医生在线状态管理(标记暂停/恢复接诊)
### 页面 4:医生视图 /doctor/[doctor-id]
医生在诊室使用的简洁界面。
布局:
- 顶部:医生姓名、科室、今日已看/总排队
- 左侧当前患者卡片(大卡片):
- 患者姓名、年龄、性别、IC 号
- 过敏信息(红色高亮)
- 历史就诊记录(最近 5 次)
- 操作按钮:『开始就诊』『完成就诊』『转科室』
- 右侧排队列表:
- 接下来等候的患者(显示前 10 位)
- 每位显示:号码、姓名、等待时间、类型标签(walk-in/appointment)
- 底部快捷操作:『叫下一位』(大按钮)、『暂停接诊』、『查看统计』
### 页面 5:每日统计 /analytics
管理层查看的统计仪表盘。
指标卡片:
- 今日总就诊人数
- 平均等待时间(分钟)
- 各科室就诊人数(柱状图)
- 高峰时段分布(折线图,按小时)
- Walk-in vs Appointment 占比(饼图)
- 每位医生就诊数量排名
- 未到诊(no-show)比例
- 患者满意度(预留)
数据范围:支持按日、周、月筛选
### 页面 6:患者查询 /patients
前台查询患者信息和就诊记录。
- 搜索栏:按 IC 号、姓名、电话搜索
- 患者列表表格:姓名、IC 号、电话、最后就诊日期、总就诊次数
- 点击展开:完整就诊历史、每次的医生、诊断、处方
## 科室配置
根据 {clinic_type} 设置 {departments},共 {num_doctors} 位医生分配到各科室。
## 营业时间
{operating_hours}
- 系统在营业时间外显示『今日已结束营业』提示
- Kiosk 在非营业时间锁定挂号功能
## 示范数据
请生成以下 seed data:
- 科室:{departments}
- 医生:{num_doctors} 位,分配到各科室,包含姓名、诊室号
- 患者:10 位示范患者(马来西亚常见中文+马来名字混合),包含 MyKad IC 号
- 今日排队:15 条排队记录,各种状态都有(waiting/called/in_consultation/completed/no_show)
- 就诊记录:8 条历史记录
示范患者数据:
1. 陈美玲 (Tan Mei Ling) - 880515-14-5678 - +60 12-345 6789
2. Ahmad bin Ismail - 750823-01-4321 - +60 13-456 7890
3. Priya a/p Krishnan - 920110-10-8765 - +60 11-567 8901
4. 林志强 (Lim Chee Keong) - 680305-08-2345 - +60 19-678 9012
5. Nurul Aisyah binti Razak - 950720-14-6543 - +60 16-789 0123
6. 黄伟明 (Wong Wai Ming) - 830412-07-9876 - +60 17-890 1234
7. Siti Aminah binti Hassan - 780615-03-1234 - +60 14-901 2345
8. Rajesh a/l Muthu - 900228-11-4567 - +60 15-012 3456
9. 张秀英 (Chong Siew Ying) - 710903-14-7890 - +60 18-123 4567
10. Muhammad Faiz bin Abdullah - 850117-02-0987 - +60 12-234 5678
## 关键实现细节
### Supabase Realtime 订阅
```
// 在叫号屏和仪表盘使用
supabase
.channel(queue-updates)
.on(postgres_changes, { event: *, schema: public, table: queue_entries }, handleQueueChange)
.subscribe()
```
### 排队号码生成(Server Action)
使用 Postgres 事务 + FOR UPDATE 锁定 daily_counters 行,确保并发安全:
1. SELECT last_number FROM daily_counters WHERE department_id = ? AND counter_date = today FOR UPDATE
2. 如无记录则 INSERT,last_number = 1
3. 否则 UPDATE last_number = last_number + 1
4. 返回新号码,格式化为 {DEPT_CODE}-{padded_number}
### 等待时间估算
```
estimated_wait = (patients_ahead / available_doctors) * avg_consultation_minutes
```
每次队列变更时用 Postgres function 批量重算。
## 要求清单
1. 所有页面响应式设计(Kiosk 和 Display 页面为全屏优化)
2. 使用 Supabase Realtime 实现真正的实时更新,无需轮询
3. 触屏友好(Kiosk 界面)
4. MyKad IC 号格式验证(6位数字-2位数字-4位数字)
5. 排队号码每日自动重置
6. 中英文双语界面
7. 叫号提示音(使用 Web Audio API 或预置音频)
8. 深色主题叫号屏(高对比度,远距离可读)
9. 医生就诊记录表单
10. 每日统计自动计算
11. 完整的 TypeScript 类型定义
12. 使用 shadcn/ui 组件库
13. 错误处理和加载状态
14. 组件化架构,代码整洁