作为一名长期从事校园信息化系统开发的工程师,我最近完成了一个基于Flask+Vue.js的校园帮任务系统。这个系统主要解决学生之间互助任务发布、接取和管理的需求,相比传统BBS或微信群更加结构化、可追踪。
在技术选型阶段,我们对比了几种主流方案:
Flask+Vue方案:
Django全栈方案:
Spring Boot+Vue方案:
最终选择Flask+Vue主要基于以下考虑:
提示:如果是需要快速上线验证的校园项目,建议优先考虑开发效率。当用户量达到一定规模后,再考虑迁移到Django或Spring Boot。
系统主要分为以下几个模块:
| 模块名称 | 功能描述 | 技术实现 |
|---|---|---|
| 用户模块 | 注册/登录/权限管理 | Flask-Login + JWT |
| 任务模块 | 任务发布/接取/管理 | Flask-SQLAlchemy |
| 通知模块 | 实时状态变更通知 | Socket.IO |
| 支付模块 | 任务报酬结算 | 支付宝沙箱环境 |
| 评价模块 | 双方互评系统 | 星级评分+评论 |
使用PyCharm作为主要开发工具,具体配置步骤如下:
创建Python虚拟环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
安装Flask及相关扩展:
bash复制pip install flask flask-sqlalchemy flask-login flask-cors flask-socketio
项目结构规划:
code复制/backend
├── app.py # 应用入口
├── config.py # 配置文件
├── models.py # 数据模型
├── routes/ # 路由模块
├── static/ # 静态文件
└── templates/ # 模板文件
Vue.js项目通过Vue CLI初始化:
安装Vue CLI:
bash复制npm install -g @vue/cli
创建Vue项目:
bash复制vue create frontend
cd frontend
npm install axios vue-socket.io --save
开发环境代理配置(vue.config.js):
javascript复制module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true
}
}
}
}
采用JWT(JSON Web Token)进行认证,后端实现:
python复制# auth.py
from flask_jwt_extended import create_access_token, jwt_required
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username')
password = request.json.get('password')
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
return jsonify({"msg": "Bad credentials"}), 401
前端调用示例:
javascript复制// Login.vue
axios.post('/login', {
username: this.username,
password: this.password
}).then(response => {
localStorage.setItem('token', response.data.access_token)
this.$router.push('/dashboard')
})
python复制@app.route('/tasks', methods=['POST'])
@jwt_required()
def create_task():
current_user = get_jwt_identity()
data = request.get_json()
new_task = Task(
title=data['title'],
description=data['description'],
reward=data['reward'],
publisher=current_user,
status='pending'
)
db.session.add(new_task)
db.session.commit()
return jsonify(new_task.to_dict()), 201
python复制@app.route('/tasks/<int:task_id>/accept', methods=['POST'])
@jwt_required()
def accept_task(task_id):
current_user = get_jwt_identity()
task = Task.query.get_or_404(task_id)
if task.status != 'pending':
return jsonify({"msg": "Task not available"}), 400
task.acceptor = current_user
task.status = 'accepted'
db.session.commit()
# 触发通知
emit('task_update', task.to_dict(), room=task.publisher)
return jsonify(task.to_dict())
python复制# app.py
from flask_socketio import SocketIO, emit
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('connect')
def handle_connect():
print('Client connected')
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
javascript复制// main.js
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
debug: true,
connection: 'http://localhost:5000',
options: { path: '/socket.io' }
}))
// 组件中使用
this.$socket.emit('join_room', {userId: this.currentUser.id})
this.sockets.subscribe('task_update', (data) => {
this.$notify({
title: '任务状态更新',
message: `任务"${data.title}"已被接取`,
type: 'success'
})
})
推荐使用Nginx+Gunicorn方案:
Gunicorn配置:
bash复制gunicorn -w 4 -b 0.0.0.0:5000 app:app
Nginx配置示例:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
root /path/to/frontend/dist;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
}
location /socket.io {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
索引优化:
python复制class Task(db.Model):
__tablename__ = 'tasks'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), index=True) # 添加索引
status = db.Column(db.String(20), index=True)
查询优化:
python复制# 不好的写法
tasks = Task.query.all() # 获取全部数据
# 优化写法
tasks = Task.query.filter_by(status='pending').paginate(page=1, per_page=10)
开发过程中遇到的主要挑战是跨域问题,最终采用以下方案:
Flask端配置CORS:
python复制from flask_cors import CORS
CORS(app, resources={r"/api/*": {"origins": "*"}})
生产环境通过Nginx反向代理解决
数据库连接泄露:
python复制@app.teardown_appcontext
def shutdown_session(exception=None):
db.session.remove()
JWT令牌失效:
python复制app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(hours=1)
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(days=30)
静态文件缓存:
javascript复制// vue.config.js
module.exports = {
filenameHashing: true
}
这个项目从技术选型到最终上线历时两个月,最大的体会是Flask+Vue的组合确实能带来很高的开发效率,特别适合校园场景的中小型应用开发。对于刚开始接触全栈开发的同学,建议先从核心功能入手,逐步完善周边模块,不要一开始就追求大而全的解决方案。