1. 项目背景与需求分析
牙科诊所预约系统是近年来医疗信息化领域的热门应用方向。随着移动互联网的普及和微信小程序的广泛应用,传统电话预约方式已经无法满足现代患者的需求。根据行业调研数据显示,采用线上预约系统的牙科诊所,其患者满意度提升约40%,医生工作效率提高35%。
本项目采用Python作为后端开发语言,结合微信小程序前端,旨在解决以下核心痛点:
- 患者预约难:传统方式需要电话沟通,经常占线或需要反复确认
- 诊所管理低效:手工记录预约信息易出错,难以统计和分析
- 资源分配不均:热门医生时段紧张,其他时段资源闲置
- 患者体验差:候诊时间长,无法提前规划就诊时间
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体架构方案
系统采用前后端分离的B/S架构:
code复制微信小程序前端 → HTTP/HTTPS → Python后端API → MySQL数据库
↑
(WebSocket)
↓
实时通知服务
2.2 核心技术选型
后端技术栈:
- Python 3.8+:选择Python因其丰富的Web开发生态和高效的开发效率
- Flask/Django:轻量级框架适合快速开发API接口
- MySQL 8.0:关系型数据库存储结构化数据
- Redis:缓存高频访问数据和实现分布式锁
前端技术栈:
- 微信小程序原生开发:最佳的性能和兼容性
- WXML/WXSS:小程序特有模板语言和样式表
- ECharts for WeChat:数据可视化展示
关键技术考量:
- 预约冲突处理:采用乐观锁机制防止超订
- 支付集成:微信支付原生支持
- 消息通知:模板消息+WebSocket实时提醒
3. 数据库设计
3.1 核心表结构
医生表(doctor)
sql复制CREATE TABLE `doctor` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '医生姓名',
`title` varchar(20) NOT NULL COMMENT '职称',
`specialty` varchar(100) DEFAULT NULL COMMENT '专长领域',
`introduction` text COMMENT '详细介绍',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',
`status` tinyint(1) DEFAULT '1' COMMENT '1-在职 0-离职',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
预约表(appointment)
sql复制CREATE TABLE `appointment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient_id` int(11) NOT NULL,
`doctor_id` int(11) NOT NULL,
`schedule_id` int(11) NOT NULL COMMENT '排班ID',
`appoint_time` datetime NOT NULL COMMENT '预约时间',
`status` tinyint(1) DEFAULT '0' COMMENT '0-待确认 1-已预约 2-已取消',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_doctor_time` (`doctor_id`,`appoint_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 关键业务表关系
code复制患者(patient) → 预约(appointment) ← 医生(doctor)
↑
排班(schedule) ←──┘
4. 核心功能实现
4.1 微信小程序端实现
预约流程页面跳转逻辑:
code复制首页 → 医生列表 → 医生详情 → 选择时段 → 确认预约 → 支付 → 预约成功
关键代码示例 - 预约时段选择
javascript复制// pages/booking/booking.js
Page({
data: {
timeSlots: [],
selectedSlot: null
},
onLoad: function(options) {
this.loadTimeSlots(options.doctorId);
},
loadTimeSlots: function(doctorId) {
wx.request({
url: 'https://yourdomain.com/api/timeslots',
data: { doctor_id: doctorId },
success: (res) => {
this.setData({ timeSlots: res.data });
}
});
},
selectSlot: function(e) {
this.setData({ selectedSlot: e.currentTarget.dataset.slot });
}
})
4.2 Python后端实现
使用Flask构建RESTful API
python复制# app.py
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:pass@localhost/clinic'
db = SQLAlchemy(app)
@app.route('/api/timeslots', methods=['GET'])
def get_time_slots():
doctor_id = request.args.get('doctor_id')
# 查询数据库获取可预约时段
slots = TimeSlot.query.filter_by(doctor_id=doctor_id).all()
return jsonify([s.to_dict() for s in slots])
@app.route('/api/appointments', methods=['POST'])
def create_appointment():
data = request.get_json()
# 处理预约逻辑
new_appoint = Appointment(**data)
db.session.add(new_appoint)
db.session.commit()
return jsonify({"status": "success"})
if __name__ == '__main__':
app.run(debug=True)
预约冲突处理逻辑
python复制def make_appointment(patient_id, doctor_id, slot_id):
with db.session.begin():
# 检查时段是否可用
slot = TimeSlot.query.filter_by(
id=slot_id,
status=0
).with_for_update().first()
if not slot:
raise ValueError("时段不可用")
# 创建预约记录
appointment = Appointment(
patient_id=patient_id,
doctor_id=doctor_id,
slot_id=slot_id,
status=1
)
db.session.add(appointment)
# 更新时段状态
slot.status = 1
db.session.add(slot)
return appointment
5. 关键问题解决方案
5.1 高并发预约处理
采用Redis实现分布式锁:
python复制import redis
from contextlib import contextmanager
redis_client = redis.StrictRedis()
@contextmanager
def redis_lock(lock_name, timeout=10):
lock = redis_client.lock(lock_name, timeout=timeout)
try:
acquired = lock.acquire(blocking=True)
if acquired:
yield
else:
raise Exception("获取锁失败")
finally:
lock.release()
5.2 微信支付集成
支付流程实现:
- 小程序端调用wx.requestPayment
- 后端生成预支付订单
- 微信支付回调处理
python复制@app.route('/api/payment/prepay', methods=['POST'])
def create_prepay():
# 获取用户openid
openid = get_openid_from_token()
# 创建支付订单
unified_order = {
'appid': APP_ID,
'mch_id': MCH_ID,
'nonce_str': generate_nonce_str(),
'body': '牙科预约费用',
'out_trade_no': generate_order_no(),
'total_fee': 100, # 单位:分
'spbill_create_ip': request.remote_addr,
'notify_url': PAYMENT_CALLBACK_URL,
'trade_type': 'JSAPI',
'openid': openid
}
# 调用微信支付统一下单接口
response = wechat_pay.unified_order(unified_order)
return jsonify({
'prepay_id': response['prepay_id'],
'nonceStr': response['nonce_str'],
'timeStamp': str(int(time.time()))
})
6. 部署与运维
6.1 服务器环境配置
推荐使用Nginx + uWSGI部署Python应用:
code复制server {
listen 80;
server_name yourdomain.com;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
}
location /static {
alias /path/to/static/files;
}
}
6.2 微信小程序配置要点
- 在微信公众平台配置合法域名
- 开通微信支付功能
- 配置消息模板
- 设置业务域名
7. 项目优化方向
- 智能推荐系统:基于历史数据推荐就诊时段
- 候诊队列实时更新:让患者了解当前就诊进度
- 医生端APP:方便医生管理预约
- 数据分析看板:为诊所提供经营决策支持
在实际开发中,我们遇到了微信支付回调验证的问题。解决方案是严格验证签名,并使用幂等设计处理重复通知:
python复制@app.route('/payment/callback', methods=['POST'])
def payment_callback():
# 验证签名
if not verify_signature(request.data):
return "FAIL"
# 处理业务逻辑
try:
result = handle_payment_result(request.data)
if result:
return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"
except Exception as e:
logger.error(f"Payment callback error: {str(e)}")
return "FAIL"
这个项目从设计到上线大约需要2-3个月时间,关键是要做好需求分析和数据库设计。在实际运营中,建议定期备份数据库,并监控系统性能指标。
