docs: 更新项目文档,完善需求和技术细节

This commit is contained in:
ylweng
2025-08-31 23:29:26 +08:00
parent fcce470415
commit 028a458283
35 changed files with 13517 additions and 0 deletions

218
backend/routes/auth.js Normal file
View File

@@ -0,0 +1,218 @@
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const validator = require('validator');
const dbConnector = require('../utils/dbConnector');
const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
/**
* 用户注册
*/
router.post('/register', async (req, res, next) => {
try {
const { username, password, phone, email, user_type = 'farmer' } = req.body;
// 参数验证
if (!username || !password || !phone) {
return res.status(400).json({
code: 400,
message: '用户名、密码和手机号为必填项',
data: null
});
}
if (password.length < 6) {
return res.status(400).json({
code: 400,
message: '密码长度不能少于6位',
data: null
});
}
if (!validator.isMobilePhone(phone, 'zh-CN')) {
return res.status(400).json({
code: 400,
message: '手机号格式不正确',
data: null
});
}
if (email && !validator.isEmail(email)) {
return res.status(400).json({
code: 400,
message: '邮箱格式不正确',
data: null
});
}
// 检查用户是否已存在
const existingUser = await dbConnector.query(
'SELECT id FROM users WHERE username = ? OR phone = ? OR email = ?',
[username, phone, email]
);
if (existingUser.length > 0) {
return res.status(409).json({
code: 409,
message: '用户名、手机号或邮箱已存在',
data: null
});
}
// 加密密码
const hashedPassword = await bcrypt.hash(password, 12);
// 创建用户
const result = await dbConnector.query(
'INSERT INTO users (username, password_hash, phone, email, user_type) VALUES (?, ?, ?, ?, ?)',
[username, hashedPassword, phone, email, user_type]
);
// 生成JWT token
const token = jwt.sign(
{ userId: result.insertId, username, user_type },
JWT_SECRET,
{ expiresIn: '7d' }
);
res.status(201).json({
code: 201,
message: '注册成功',
data: {
user_id: result.insertId,
username,
phone,
email,
user_type,
token
}
});
} catch (error) {
next(error);
}
});
/**
* 用户登录
*/
router.post('/login', async (req, res, next) => {
try {
const { login, password } = req.body;
if (!login || !password) {
return res.status(400).json({
code: 400,
message: '登录账号和密码为必填项',
data: null
});
}
// 查询用户(支持用户名、手机号、邮箱登录)
const user = await dbConnector.query(
'SELECT * FROM users WHERE (username = ? OR phone = ? OR email = ?) AND status = 1',
[login, login, login]
);
if (user.length === 0) {
return res.status(401).json({
code: 401,
message: '用户不存在或已被禁用',
data: null
});
}
const userData = user[0];
// 验证密码
const isValidPassword = await bcrypt.compare(password, userData.password_hash);
if (!isValidPassword) {
return res.status(401).json({
code: 401,
message: '密码不正确',
data: null
});
}
// 更新最后登录时间
await dbConnector.query(
'UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?',
[userData.id]
);
// 生成JWT token
const token = jwt.sign(
{ userId: userData.id, username: userData.username, user_type: userData.user_type },
JWT_SECRET,
{ expiresIn: '7d' }
);
res.json({
code: 200,
message: '登录成功',
data: {
user_id: userData.id,
username: userData.username,
phone: userData.phone,
email: userData.email,
user_type: userData.user_type,
avatar_url: userData.avatar_url,
token
}
});
} catch (error) {
next(error);
}
});
/**
* 获取当前用户信息
*/
router.get('/me', async (req, res, next) => {
try {
// 从token中获取用户ID
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
code: 401,
message: '未提供认证token',
data: null
});
}
const decoded = jwt.verify(token, JWT_SECRET);
const user = await dbConnector.query(
'SELECT id, username, phone, email, user_type, avatar_url, created_at, last_login FROM users WHERE id = ? AND status = 1',
[decoded.userId]
);
if (user.length === 0) {
return res.status(404).json({
code: 404,
message: '用户不存在',
data: null
});
}
res.json({
code: 200,
message: '获取成功',
data: user[0]
});
} catch (error) {
if (error.name === 'JsonWebTokenError') {
return res.status(401).json({
code: 401,
message: '无效的token',
data: null
});
}
next(error);
}
});
module.exports = router;