酒店服务管理系统是传统服务业数字化转型的典型场景。过去前台办理入住、人工记录客房状态、纸质化服务请求的方式,不仅效率低下,还容易出错。我去年帮一家本地连锁酒店做系统升级时,经理告诉我他们平均每天要处理30次以上的房态核对错误,旺季时客户等待时间经常超过20分钟。
这个基于Flask+Vue的全栈系统正是为了解决这些痛点而生。前端采用Vue构建响应式管理界面,后端用Flask轻量化处理业务逻辑,配合PyCharm的专业开发环境和Django生态的部分组件,实现了:
虽然项目标题出现了Django,但核心后端我们选择了Flask,这是经过实际业务验证的决策:
python复制# 典型API服务实现示例
@app.route('/api/checkin', methods=['POST'])
@token_required
def check_in():
data = request.get_json()
room = Room.query.filter_by(number=data['room_no']).first()
if room.status != 'vacant':
return jsonify({'error': 'Room not available'}), 400
# 原子化操作保证数据一致性
db.session.begin()
try:
room.status = 'occupied'
guest = Guest(**data['guest_info'])
db.session.add(guest)
db.session.commit()
except:
db.session.rollback()
return jsonify({'error': 'Database operation failed'}), 500
return jsonify({'success': True}), 201
采用Vue CLI 4.x搭建的SPA前端包含三个关键设计:
重要提示:一定要在vue.config.js中配置proxyTable解决跨域,实测直接使用CORS在部分安卓设备上会出现预检请求失败。
数据库设计采用"房间状态分离"策略:
sql复制CREATE TABLE rooms (
id INT PRIMARY KEY,
number VARCHAR(10) UNIQUE,
type_id INT REFERENCES room_types,
physical_status ENUM('clean','dirty','maintenance'), -- 物理状态
business_status ENUM('vacant','occupied','reserved') -- 业务状态
);
前端通过长轮询(初期)升级为WebSocket(正式环境)实现实时更新:
javascript复制// WebSocket连接管理
const socket = new WebSocket(`wss://${location.host}/ws/room-status`)
socket.onmessage = (event) => {
const data = JSON.parse(event.data)
store.commit('updateRoomStatus', data) // 更新Vuex状态
}
采用"状态机+优先级队列"的设计模式:
python复制# 工单分配算法核心逻辑
def assign_ticket(ticket):
staff = Staff.query.filter_by(
department=ticket.department,
on_duty=True
).order_by(
func.count(Ticket.id) # 当前负责工单数
).first()
if staff:
ticket.assignee = staff
ticket.status = 'assigned'
send_push_notification(staff.device_token, ticket)
运行配置:
数据库工具:
Vue插件:
后端使用requirements分层:
code复制requirements/
├── base.txt # 核心依赖
├── dev.txt # 开发工具
└── prod.txt # 生产环境扩展
前端采用package.json的resolutions字段解决依赖冲突:
json复制"resolutions": {
"lodash": "4.17.21",
"vue-router": "3.5.3"
}
现象:高峰时段出现"TimeoutError: QueuePool limit"错误
解决方案:
python复制SQLALCHEMY_ENGINE_OPTIONS = {
'pool_size': 20,
'max_overflow': 10,
'pool_pre_ping': True # 自动检测失效连接
}
python复制from prometheus_flask_exporter import PrometheusMetrics
metrics = PrometheusMetrics(app)
metrics.info('app_info', 'Application info', version='1.0.3')
常见问题及修复方法:
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 日期选择器错位 | 视口单位计算误差 | 改用px配合transform缩放 |
| 按钮点击无响应 | FastClick冲突 | 在main.js中添加特定class排除 |
| 图片加载缓慢 | 未启用WebP格式 | 配置vue-image-loader |
缓存策略:
SQL优化:
python复制# 反例:N+1查询问题
rooms = Room.query.all()
for room in rooms:
print(room.type.name) # 每次循环都查询type表
# 正例:使用join提前加载
rooms = Room.query.options(joinedload(Room.type)).all()
javascript复制// 动态导入工单模块
const ServiceModule = () => import('./views/Service.vue')
JWT实现要点:
python复制# 令牌验证装饰器
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.cookies.get('access_token')
if not token:
return jsonify({'error': 'Token missing'}), 401
try:
data = jwt.decode(token, current_app.config['PUBLIC_KEY'], algorithms=['RS256'])
g.current_user = User.query.get(data['sub'])
except jwt.ExpiredSignatureError:
return jsonify({'error': 'Token expired'}), 403
except:
return jsonify({'error': 'Invalid token'}), 403
return f(*args, **kwargs)
return decorated
SQL注入防护:
XSS防护:
Docker-compose典型配置:
yaml复制version: '3.8'
services:
web:
build: ./backend
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/hotel
depends_on:
- db
- redis
frontend:
build: ./frontend
ports:
- "8080:80"
db:
image: postgres:13
volumes:
- pg_data:/var/lib/postgresql/data
GitLab Runner配置要点:
yaml复制stages:
- test
- build
- deploy
backend-test:
stage: test
script:
- pip install -r requirements/dev.txt
- pytest --cov=app tests/
frontend-build:
stage: build
image: node:14
script:
- npm install
- npm run build
artifacts:
paths:
- dist/
智能房态预测:
语音控制集成:
能耗监控:
这个项目最让我有成就感的,是看到前台员工从最初抗拒系统到后来主动提出优化建议的转变。技术负责人特别提到,系统上线后他们的OTA渠道差评率下降了43%。如果你也准备开发类似系统,我的建议是:一定要在前两周安排开发人员现场驻点,真实场景下的用户反馈比任何需求文档都有价值。