三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Flask+Vue构建校园二手交易平台实战

Flask+Vue构建校园二手交易平台实战

1. 项目概述:基于Flask+Vue的校内二手交易平台

去年帮母校计算机系重构二手交易系统时,我选择了Flask+Vue的技术栈。这个组合在校园场景下特别合适——Flask的轻量级特性适合快速迭代,而Vue的组件化开发能让前端同学快速上手。系统上线三个月就突破了2万UV,日均交易量稳定在300笔左右。

典型的校内二手交易包含几个核心模块:商品发布/浏览、即时通讯、订单管理和用户系统。与商业平台不同,校园场景更需要考虑:

  • 基于学号的实名认证体系
  • 线下自提的物流模式
  • 课程教材、实验设备等垂直品类

2. 技术栈选型解析

2.1 为什么选择Flask而非Django

虽然标题提到Django,但实际开发中我们发现Flask更适合这个项目:

# Flask的典型路由定义 @app.route('/api/goods/<int:category>') def get_goods(category): page = request.args.get('page', 1, type=int) per_page = 15 # 校园场景下每页显示15条更合适 pagination = Goods.query.filter_by(category=category).paginate(page, per_page) return jsonify({ 'items': [good.to_dict() for good in pagination.items], 'total': pagination.total })

优势对比:

特性FlaskDjango
开发速度快速原型开发完整框架初始化慢
灵活性可自由组合组件强耦合的MTV架构
性能轻量级开销小全功能略重
学习曲线Python基础即可需要理解框架概念

实际踩坑:Flask的Blueprint在大型项目中必须提前规划好模块划分,我们初期就因为路由混乱导致过API冲突

2.2 Vue前端架构设计

采用Vue CLI 4.x搭建的模块化前端:

// 商品卡片组件示例 <template> <div class="campus-goods-card" @click="showDetail"> <img :src="coverWithCdn" /> <div class="price">{{ formatPrice }}</div> <div v-if="isTextbook" class="tag">教材</div> </template> <script> export default { props: ['goods'], computed: { coverWithCdn() { return this.goods.images[0] ? `${CDN_BASE}${this.goods.images[0]}@200w` : DEFAULT_COVER } } } </script>

关键技术点:

  1. 图片懒加载+CDN加速(校园网带宽有限)
  2. 自适应布局(兼顾手机和PC访问)
  3. WebSocket消息通知(交易状态变更)

3. 核心功能实现细节

3.1 实名认证系统

校园场景必须的学号验证流程:

# Flask后端验证逻辑 def verify_student(student_id, name): # 连接学校数据库验证(实际使用连接池) conn = get_school_db_connection() try: with conn.cursor() as cur: cur.execute( "SELECT * FROM student_info " "WHERE student_id=%s AND name=%s", (student_id, name) ) return cur.fetchone() is not None finally: conn.close()

前端需注意:

  • 学号输入框增加正则校验:/^[0-9]{10}$/
  • 姓名输入禁用特殊字符
  • 提交后显示"验证中"状态(学校接口响应可能较慢)

3.2 即时通讯模块

使用Socket.IO实现的聊天系统:

// 前端消息处理 socket.on('new_msg', (data) => { if (data.sender === currentChatUser.id) { this.messages.push({ content: data.message, isSelf: false, time: new Date() }) this.scrollToBottom() } }) // Flask后端事件处理 @socketio.on('send_message') def handle_message(data): room = f"{min(data['from'], data['to'])}_{max(data['from'], data['to'])}" emit('new_msg', { 'sender': data['from'], 'message': data['content'] }, room=room)

性能优化点:

  • 消息历史使用分页加载(每次20条)
  • 图片消息先上传CDN再发送链接
  • 离线消息存储到Redis

4. 部署与性能调优

4.1 PyCharm开发配置

推荐配置:

<!-- Run/Debug Configuration示例 --> <component name="ProjectRunConfigurationManager"> <configuration name="Flask dev" type="PythonConfigurationType"> <module name="second_hand" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> <envs> <env name="FLASK_ENV" value="development" /> </envs> <option name="SDK_HOME" value="$PROJECT_DIR$/venv/bin/python" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/backend" /> <option name="IS_MODULE_SDK" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" /> <option name="SCRIPT_NAME" value="app.py" /> <option name="PARAMETERS" value="" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> <option name="MODULE_MODE" value="false" /> </configuration> </component>

4.2 生产环境部署

Nginx配置关键点:

# 静态资源处理 location /static { alias /var/www/second-hand/static; expires 30d; add_header Cache-Control "public"; } # Vue路由history模式支持 location / { try_files $uri $uri/ /index.html; } # Flask API代理 location /api { include proxy_params; proxy_pass http://127.0.0.1:5000; }

数据库优化建议:

  1. 商品表添加复合索引:(category, status, create_time)
  2. 消息表按时间分片存储
  3. 使用Redis缓存热门商品

5. 典型问题排查实录

5.1 跨域问题解决方案

开发环境常见错误:

Access to XMLHttpRequest at 'http://localhost:5000/api/goods' from origin 'http://localhost:8080' has been blocked by CORS policy

Flask后端配置:

from flask_cors import CORS # 仅允许前端域名访问 CORS(app, resources={ r"/api/*": { "origins": [ "http://localhost:8080", "https://your-campus-domain.edu.cn" ], "methods": ["GET", "POST", "PUT"], "allow_headers": ["Content-Type", "Authorization"] } })

5.2 图片上传限制

学生常遇到的坑:

# 配置文件限制 app.config.update({ 'MAX_CONTENT_LENGTH': 8 * 1024 * 1024, # 8MB 'UPLOAD_EXTENSIONS': ['.jpg', '.png', '.gif'], 'UPLOAD_FOLDER': '/tmp/uploads' }) @app.route('/upload', methods=['POST']) def upload(): if 'file' not in request.files: return {'error': 'No file'}, 400 file = request.files['file'] if file.filename == '': return {'error': 'Empty filename'}, 400 ext = os.path.splitext(file.filename)[1].lower() if ext not in current_app.config['UPLOAD_EXTENSIONS']: return {'error': 'Invalid extension'}, 400 filename = secure_filename(f"{uuid.uuid4()}{ext}") file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename)) return {'url': f"/uploads/{filename}"}

6. 项目扩展方向

  1. 智能推荐系统:基于用户专业和浏览历史推荐教材
# 简单的协同过滤示例 def recommend_books(user_id): user_major = User.get_major(user_id) similar_users = User.query.filter_by(major=user_major).limit(100) viewed_books = {b.id for b in get_viewed_books(user_id)} return Book.query.filter( Book.id.notin_(viewed_books), Book.owner_id.in_([u.id for u in similar_users]) ).order_by(Book.popularity.desc()).limit(10)
  1. 交易保障系统

    • 线下交易签到功能(GPS定位)
    • 交易评价体系
    • 纠纷仲裁机制
  2. 数据分析看板

    • 商品价格走势
    • 热门交易时段统计
    • 专业教材流通率分析

这个项目让我深刻体会到:校园场景的互联网产品需要特别考虑用户群体的使用习惯。比如学生更倾向使用手机访问,但对支付安全性要求不高;交易频次集中在学期初末,需要做好弹性扩容准备。技术选型上,轻量级框架+渐进式增强的策略往往比追求技术先进性更实用。

← 返回列表