
很多团队第一次做互联网医院系统时,都会低估一个模块的复杂度——在线问诊与视频会诊。
表面看只是:
患者发消息 医生回复 再加个视频通话
听起来像“IM聊天 + 视频SDK”就搞定。

但真正落地你会发现,远不止这么简单。
线上问诊本质是:
医疗业务流程 + 即时通讯 + 音视频 + 合规留痕 + 订单结算 + 病历沉淀
如果架构没设计好,后期一定推倒重来。
这篇我从「源码实现角度」,带你把:
一整套技术方案拆开讲清楚,并附核心代码示例。
技术栈示例:
SpringBoot + MySQL + Redis + WebSocket + WebRTC / 腾讯云TRTC
不要先写代码,先把流程理顺。
标准在线问诊流程:
患者下单 → 支付 → 医生接诊 → 图文/视频沟通 → 开处方/建议 → 结束问诊 → 生成病历
注意:
问诊 ≠ 聊天
而是:
有时效 + 有订单 + 有医疗记录 + 可追溯
所以系统必须是「订单驱动型会话」。
这是系统稳定的关键。
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。
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里。
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
);用于:

图文问诊本质:
IM即时通讯
推荐:
WebSocket + Redis
不要用轮询。
@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);
}
}
}核心原则:
先存库,再发送。
否则断线会丢数据。
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);
}视频不要自己造轮子。
直接用:
否则你会踩死。
推荐模式:
后端只做:
生成 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
→ CANCELpublic 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);
}只允许合法流转。
杜绝:
重复接诊、重复结束。
医院高峰期:
必须优化:
redisTemplate.opsForSet().add("online_doctor", doctorId);快速匹配医生。
高并发时:
MQ异步:
mqProducer.send(chatMsg);消费者批量落库。
近7天 → MySQL 历史 → OSS/对象存储
否则表会爆。
很多团队只管功能,不管合规,最后项目直接过不了审。
必须做:
例如:
String encrypt = AESUtil.encrypt(content);医疗数据一定要加密。

说句行业实话:
在线问诊系统不是IM系统升级版。
而是:
订单系统 + IM + 音视频 + 病历 + 合规
五套系统的组合。
真正稳定的实现思路是:
订单驱动会话 数据库留痕优先 IM只是通道 视频交给成熟SDK
不要自己造轮子。
否则你80%的时间都在踩坑。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。