1. 项目背景与需求分析
包头师范学院内部订餐系统是一个面向校园师生的餐饮服务平台。在高校环境中,传统的食堂就餐模式存在几个痛点:用餐高峰期排队拥挤、人工统计效率低下、支付方式单一、餐品信息不透明等。我们设计的系统需要解决以下核心问题:
- 分流就餐压力:通过线上预订实现错峰取餐
- 提升管理效率:自动统计各档口订单数据
- 支付方式整合:支持校园卡对接和沙箱支付测试
- 信息透明化:实时展示菜品库存和营养信息
技术选型上采用前后端分离架构:
- 前端:Vue3 + Element Plus(管理后台)+ Vant(移动端)
- 后端:Python Flask框架
- 数据库:MySQL 8.0
- 支付对接:支付宝沙箱环境
提示:高校系统开发需特别注意并发性能,中午11:30-12:30的订单量通常是平时的10-15倍
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈深度解析
前端架构选择Vue3的原因:
- Composition API更适合复杂业务逻辑组织
- 更小的打包体积(相比Vue2减少约40%)
- 更好的TypeScript支持
- 实测Vant3组件库在校园网环境下加载速度快(平均1.2s)
后端选择Flask而非Django的考量:
- 微服务架构更适合后续扩展外卖配送模块
- 更轻量级的ORM适合高校相对简单的数据关系
- 开发团队已有Python基础但无Django经验
2.2 数据库ER图关键设计
主要实体关系:
code复制用户(学生/教职工) 1:n 订单 n:1 档口
档口 1:n 菜品 1:n 营养信息
特别注意的字段设计:
- 用户表增加
balance字段存储校园卡余额 - 订单表设置
expect_time字段(期望取餐时间段) - 菜品表包含
daily_limit(每日限量)和sold_count
3. 核心功能实现
3.1 订餐业务流程实现
python复制# 订单创建API核心逻辑
@app.route('/api/order', methods=['POST'])
@auth_required
def create_order():
# 参数校验
items = request.json.get('items')
if not items or len(items) > 10: # 单次最多10个菜品
abort(400)
# 库存检查
for item in items:
dish = Dish.query.get(item['dish_id'])
if dish.stock < item['quantity']:
return {'code': 400, 'msg': f'{dish.name}库存不足'}
# 创建订单
new_order = Order(
user_id=g.current_user.id,
stall_id=items[0]['stall_id'], # 同一档口的菜品
total=sum(item['price']*item['quantity'] for item in items),
status=0 # 待支付
)
# 扣减库存
for item in items:
dish = Dish.query.get(item['dish_id'])
dish.stock -= item['quantity']
OrderItem(
order=new_order,
dish_id=item['dish_id'],
quantity=item['quantity']
)
db.session.commit()
return {'code': 200, 'data': {'order_id': new_order.id}}
3.2 沙箱支付集成要点
支付宝沙箱环境配置关键步骤:
-
申请沙箱账号:
- 登录支付宝开放平台 → 研发服务 → 沙箱应用
- 获取APPID和网关地址
-
后端接口实现:
python复制from alipay import AliPay
alipay = AliPay(
appid="202100xxxxxx",
app_notify_url=None,
app_private_key_string=open("app_private_key.pem").read(),
alipay_public_key_string=open("alipay_public_key.pem").read(),
sign_type="RSA2",
debug=True # 沙箱模式
)
# 生成支付链接
def generate_pay_url(order_id, total):
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order_id,
total_amount=str(total),
subject="校园订餐",
return_url="https://yourdomain.com/pay/return",
notify_url="https://yourdomain.com/pay/notify"
)
return f"https://openapi.alipaydev.com/gateway.do?{order_string}"
- 前端对接注意事项:
- 在vue.config.js中配置代理解决跨域
- 支付成功后轮询查询订单状态(建议3秒间隔)
- 处理移动端返回按钮的特殊逻辑
4. 性能优化实践
4.1 高并发场景应对方案
实测中午高峰期的QPS可达120-150,我们采取以下措施:
-
缓存策略:
- Redis缓存热门档口信息(TTL 5分钟)
- 菜品详情使用@cache装饰器
python复制from functools import wraps def cache(ttl=300): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): key = f"{func.__name__}:{str(args)}:{str(kwargs)}" value = redis_client.get(key) if value: return json.loads(value) result = func(*args, **kwargs) redis_client.setex(key, ttl, json.dumps(result)) return result return wrapper return decorator -
数据库优化:
- 订单表按学期分表(order_2023_spring)
- 建立复合索引:
sql复制CREATE INDEX idx_order_user_time ON order_2023_autumn (user_id, create_time); -
异步处理:
- 使用Celery处理支付结果通知
- 短信提醒使用消息队列削峰
4.2 移动端适配技巧
Vue3+Vant的移动端适配方案:
- 使用vw单位+postcss-px-to-viewport插件
- 针对iOS的优化:
css复制/* 解决Safari的100vh问题 */ .page-container { height: 100vh; height: -webkit-fill-available; } - 图片懒加载策略:
vue复制<img v-lazy="dish.image" alt="菜品图片" />
5. 安全防护措施
5.1 常见攻击防护
-
XSS防护:
- 前端使用DOMPurify过滤富文本
javascript复制import DOMPurify from 'dompurify' const clean = DOMPurify.sanitize(dirtyHtml) -
CSRF防护:
- Flask启用CSRFProtect扩展
- 自定义请求头校验
-
SQL注入防护:
- 坚持使用ORM或参数化查询
- 禁用字符串拼接SQL
5.2 支付安全特别处理
-
金额校验:
- 后端校验前端传参金额与订单实际金额
- 使用Decimal类型处理金额计算
-
幂等性设计:
python复制@app.route('/pay/notify', methods=['POST']) def pay_notify(): # 验证签名 if not alipay.verify(request.data): abort(403) # 处理重复通知 if PaymentLog.query.filter_by(trade_no=request.data['trade_no']).first(): return 'success' # 业务逻辑...
6. 部署与监控
6.1 生产环境部署
采用Docker Compose方案:
yaml复制version: '3'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
depends_on:
- redis
- mysql
redis:
image: redis:6
volumes:
- redis_data:/data
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=yourpassword
volumes:
- mysql_data:/var/lib/mysql
volumes:
redis_data:
mysql_data:
6.2 监控方案
-
使用Prometheus+Grafana监控:
- 关键指标:订单创建成功率、支付成功率、API响应时间
- 自定义指标示例:
python复制from prometheus_client import Counter ORDER_COUNTER = Counter('canteen_orders', 'Total meal orders') @app.route('/api/order') def create_order(): ORDER_COUNTER.inc() # ... -
错误日志收集:
- 使用Sentry捕获前端错误
- ELK收集后端日志
在系统上线后,我们观察到一些有趣的数据:周三的订单量比其他工作日高18%,而最受欢迎的菜品"红烧肉"在冬季销量比夏季高出63%。这些数据帮助食堂优化了采购计划和菜品安排
