很多团队第一次做互联网医院系统时,都会低估一个模块的复杂度——在线问诊与视频会诊。
表面看只是:
患者发消息
医生回复
再加个视频通话
听起来像“IM聊天 + 视频SDK”就搞定。
但真正落地你会发现,远不止这么简单。
线上问诊本质是:
医疗业务流程 + 即时通讯 + 音视频 + 合规留痕 + 订单结算 + 病历沉淀
如果架构没设计好,后期一定推倒重来。
这篇我从「源码实现角度」,带你把:
- 表结构设计
- 问诊流程建模
- 图文IM实现
- 视频会诊接入
- 订单状态控制
- 医疗数据合规存储
一整套技术方案拆开讲清楚,并附核心代码示例。
技术栈示例:
SpringBoot + MySQL + Redis + WebSocket + WebRTC / 腾讯云TRTC
一、先理解真实业务流程
不要先写代码,先把流程理顺。
标准在线问诊流程:
患者下单 → 支付
→ 医生接诊
→ 图文/视频沟通
→ 开处方/建议
→ 结束问诊 → 生成病历
注意:
问诊 ≠ 聊天
而是:
有时效 + 有订单 + 有医疗记录 + 可追溯
所以系统必须是「订单驱动型会话」。
二、核心数据模型设计
这是系统稳定的关键。
1 问诊订单表 consultation_order
CREATE TABLE consultation_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
patient_id BIGINT,
doctor_id BIGINT,
type VARCHAR(20), -- TEXT/VIDEO
price DECIMAL(10,2),
status VARCHAR(20), -- WAITING/ONGOING/FINISHED/CANCEL
start_time DATETIME,
end_time DATETIME,
created_at DATETIME
);
作用:
控制整场问诊生命周期。
记住:
所有沟通必须绑定订单ID。
2 聊天消息表 consultation_message
CREATE TABLE consultation_message (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT,
sender_id BIGINT,
sender_role VARCHAR(20), -- DOCTOR/PATIENT
msg_type VARCHAR(20), -- TEXT/IMAGE/FILE
content TEXT,
created_at DATETIME
);
必须落库。
原因:
医疗场景必须可追溯、可审计。
不能只存在IM里。
3 视频会诊记录表
CREATE TABLE consultation_video (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT,
room_id VARCHAR(50),
duration INT,
record_url VARCHAR(255),
created_at DATETIME
);
用于:
- 视频回放
- 医疗留档
- 投诉取证

三、图文问诊实现(WebSocket实时通信)
图文问诊本质:
IM即时通讯
推荐:
WebSocket + Redis
不要用轮询。
后端 WebSocket 服务
@ServerEndpoint("/ws/{userId}")
@Component
public class ChatWebSocket {
private static ConcurrentHashMap<Long, Session> sessions = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(@PathParam("userId") Long userId, Session session) {
sessions.put(userId, session);
}
@OnMessage
public void onMessage(String message) {
ChatDTO dto = JSON.parseObject(message, ChatDTO.class);
// 1 存库
messageService.save(dto);
// 2 推送对方
Session target = sessions.get(dto.getTargetId());
if(target != null){
target.getAsyncRemote().sendText(message);
}
}
}
核心原则:
先存库,再发送。
否则断线会丢数据。
消息落库 Service
public void save(ChatDTO dto){
ConsultationMessage msg = new ConsultationMessage();
msg.setOrderId(dto.getOrderId());
msg.setContent(dto.getContent());
msg.setMsgType(dto.getType());
msg.setSenderId(dto.getSenderId());
messageMapper.insert(msg);
}
四、视频会诊实现(WebRTC / TRTC)
视频不要自己造轮子。
直接用:
- 腾讯TRTC
- 声网Agora
- 阿里RTC
否则你会踩死。
推荐模式:
后端只做:
生成 room + token
视频交给SDK。
创建视频房间接口
@PostMapping("/video/room/create")
public VideoRoomDTO createRoom(Long orderId){
String roomId = "room_" + orderId;
String token = trtcService.genUserSig(roomId);
return new VideoRoomDTO(roomId, token);
}
前端初始化(示例)
const client = TRTC.createClient({
sdkAppId,
userId,
userSig,
mode: "rtc"
});
await client.join({
roomId });
await client.publish(localStream);
就能实现:
- 音视频通话
- 屏幕共享
- 录制回放
五、订单状态机控制(非常关键)
很多系统崩溃不是技术问题,而是:
状态混乱。
必须用状态机。
状态设计
WAITING → ONGOING → FINISHED
→ CANCEL
Java实现
public void startConsult(Long orderId){
ConsultationOrder order = mapper.selectById(orderId);
if(!"WAITING".equals(order.getStatus())){
throw new RuntimeException("状态异常");
}
order.setStatus("ONGOING");
order.setStartTime(LocalDateTime.now());
mapper.update(order);
}
只允许合法流转。
杜绝:
重复接诊、重复结束。
六、高并发优化方案
医院高峰期:
- 同时几百医生在线
- 几千患者发消息
必须优化:
1 Redis在线状态缓存
redisTemplate.opsForSet().add("online_doctor", doctorId);
快速匹配医生。
2 消息异步写库
高并发时:
MQ异步:
mqProducer.send(chatMsg);
消费者批量落库。
3 聊天记录冷热分离
近7天 → MySQL
历史 → OSS/对象存储
否则表会爆。
七、医疗合规注意事项(必须重视)
很多团队只管功能,不管合规,最后项目直接过不了审。
必须做:
- 实名认证(身份证 + 人脸)
- 医生资质校验
- 聊天永久留痕
- 视频录制存档
- 数据加密存储
例如:
String encrypt = AESUtil.encrypt(content);
医疗数据一定要加密。
八、实战总结(关键经验)
说句行业实话:
在线问诊系统不是IM系统升级版。
而是:
订单系统 + IM + 音视频 + 病历 + 合规
五套系统的组合。
真正稳定的实现思路是:
订单驱动会话
数据库留痕优先
IM只是通道
视频交给成熟SDK
不要自己造轮子。
否则你80%的时间都在踩坑。