1. 项目概述
校园二手交易平台是每个大学生都需要的实用工具。记得我大三那年搬家时,面对堆积如山的教材和电器,才深刻体会到校园里缺少一个靠谱的二手交易渠道。这个基于Node.js+Vue.js的全栈项目,正是为了解决这个痛点而生。
这个系统本质上是一个校园版的"闲鱼",但针对学生群体做了特殊优化。核心功能包括商品发布、搜索、在线沟通、订单管理等模块。与市面上通用二手平台相比,它有三个独特优势:一是通过学号认证确保用户真实性;二是基于校区地理位置的智能排序;三是针对教材、电子设备等校园常见物品的专用分类。
技术选型方面,我们采用Vue.js+ElementUI构建前端界面,Node.js(Express框架)处理后端逻辑,MySQL存储数据。这套技术栈特别适合学生开发者:学习曲线平缓、社区资源丰富,而且完全免费开源。我在开发过程中踩过的坑,都会在后续章节详细说明。
2. 技术架构详解
2.1 前端架构设计
前端采用Vue 2.x版本(考虑到校园网环境兼容性),配合ElementUI组件库快速搭建界面。这里特别说明几个关键设计点:
-
响应式布局方案:
- 使用flex+rem布局适配不同设备
- 临界点设置为768px(平板)和992px(桌面)
- 商品卡片采用CSS Grid实现瀑布流展示
-
状态管理:
javascript复制// store/modules/goods.js const state = { searchParams: { category: '', keyword: '', campus: '' }, goodsList: [] } -
性能优化技巧:
- 图片懒加载:使用vue-lazyload插件
- 路由懒加载:component: () => import('./views/Goods.vue')
- 防抖搜索:lodash的debounce方法
注意:校园网环境下要特别注意包体积,最终打包的js文件应控制在500KB以内
2.2 后端服务搭建
Express框架虽然轻量,但需要合理组织代码结构。我的项目目录如下:
code复制/src
/config # 数据库等配置
/middleware # 中间件
/models # 数据模型
/routes # 路由文件
/utils # 工具函数
app.js # 主入口
关键中间件配置示例:
javascript复制// 处理跨域
app.use(cors({
origin: ['http://localhost:8080', 'https://yourcampus.edu.cn']
}))
// 身份验证中间件
const auth = (req, res, next) => {
const token = req.header('Authorization')
try {
req.user = jwt.verify(token, process.env.JWT_SECRET)
next()
} catch (err) {
res.status(401).send('无效token')
}
}
数据库连接池配置(重要!):
javascript复制const pool = mysql.createPool({
connectionLimit: 10, // 根据校园服务器配置调整
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: 'campus_trade'
})
3. 核心功能实现
3.1 用户认证系统
校园场景下的认证需要特殊处理:
- 注册时要求填写学号和校园邮箱
- 通过学校API验证用户身份真实性
- JWT token设计包含院系信息:
javascript复制{ userId: 123, studentId: '20203000', department: '计算机学院', exp: 1625097600 }
密码存储务必加盐哈希:
javascript复制const salt = bcrypt.genSaltSync(10)
const hashedPassword = bcrypt.hashSync(password, salt)
3.2 商品发布流程
商品表设计关键字段:
sql复制CREATE TABLE goods (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(100) NOT NULL,
category ENUM('教材','电子','服饰','其他') NOT NULL,
price DECIMAL(10,2) NOT NULL,
images JSON NOT NULL, -- 存储图片URL数组
campus ENUM('主校区','东校区','西校区') NOT NULL,
status TINYINT DEFAULT 1 -- 1上架 0下架
);
图片上传处理要点:
- 使用multer中间件处理文件上传
- 图片压缩:sharp库将图片限制在800px宽度
- 存储方案:开发环境本地存储,生产环境使用七牛云
3.3 搜索与推荐
Elasticsearch在校园环境下可能太重,我们采用MySQL全文检索+缓存方案:
sql复制ALTER TABLE goods ADD FULLTEXT INDEX ft_index (title, description);
SELECT * FROM goods WHERE MATCH(title,description) AGAINST('二手笔记本');
简易推荐算法实现:
javascript复制// 基于用户浏览历史推荐
const getRecommendations = (userId) => {
const history = await getBrowseHistory(userId)
const categories = [...new Set(history.map(item => item.category))]
return db.query(
'SELECT * FROM goods WHERE category IN (?) ORDER BY RAND() LIMIT 8',
[categories]
)
}
4. 部署与运维实战
4.1 校园服务器部署
推荐使用学校提供的Linux服务器,Nginx配置示例:
nginx复制server {
listen 80;
server_name trade.yourschool.edu.cn;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
location /static {
alias /var/www/static;
expires 30d;
}
}
PM2进程管理配置:
bash复制pm2 start ecosystem.config.js --env production
4.2 性能优化记录
在200人同时使用的压力测试中,我们发现并解决了以下问题:
-
数据库连接泄漏:
- 现象:运行一段时间后响应变慢
- 解决方案:确保每个查询都释放连接
javascript复制// 错误示例 const result = await db.query('SELECT...') // 正确做法 let conn try { conn = await db.getConnection() const result = await conn.query('SELECT...') } finally { if(conn) conn.release() } -
图片加载慢:
- 采用WebP格式替代JPEG
- 配置CDN加速静态资源
5. 开发经验与避坑指南
5.1 校园环境特殊问题
-
网络波动:
- 添加请求重试机制
javascript复制axios.interceptors.response.use(null, (error) => { if(error.config && error.response?.status >= 500) { return new Promise(resolve => { setTimeout(() => resolve(axios(error.config)), 1000) }) } return Promise.reject(error) }) -
用户行为特点:
- 学期初/末交易高峰,需要自动扩容
- 考试周活跃度下降,可进行维护
5.2 安全防护措施
-
防XSS攻击:
javascript复制// 前端过滤 import DOMPurify from 'dompurify' const clean = DOMPurify.sanitize(userInput) // 后端双重验证 app.use(express.json({ limit: '10kb' })) // 防止JSON炸弹 -
交易安全:
- 强制使用校园支付平台
- 敏感操作需要二次验证
这个项目从技术角度看不算复杂,但真正在校园环境中落地需要考虑很多细节问题。比如我们发现晚上11点后系统访问量会突然增加(宿舍熄灯前),这就需要针对性地优化服务器资源分配。另外,学生用户更倾向于使用手机操作,但校园APP分发又很麻烦,所以我们特别强化了PWA特性,支持添加到手机桌面。