e-scooter-rental-system/server/routes/riders.js

110 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const rateLimit = require('express-rate-limit');
const Rider = require('../models/Rider');
const Order = require('../models/Order');
const { comparePassword } = require('../utils/password');
const { validate } = require('../middleware/validate');
const { schemas } = require('../middleware/validate');
// 登录限流(单独,更严格)
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 20,
standardHeaders: true,
legacyHeaders: false,
message: { success: false, message: '登录尝试过于频繁请15分钟后再试' }
});
// 骑手登录
router.post('/login', loginLimiter, validate(schemas.login), async (req, res) => {
try {
const { phone, password } = req.body;
// 用 select(false) 主动拉取 password 字段
const rider = await Rider.findOne({ phone }).select('+password');
if (!rider) {
return res.status(401).json({ success: false, message: '手机号或密码错误' });
}
// bcrypt 比对密码
const isMatch = await comparePassword(password, rider.password);
if (!isMatch) {
return res.status(401).json({ success: false, message: '手机号或密码错误' });
}
// 签发 JWT包含 id、role
const token = jwt.sign(
{ id: rider._id, role: rider.role, phone: rider.phone },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
);
res.json({
success: true,
data: {
id: rider._id,
riderId: rider.riderId,
name: rider.name,
phone: rider.phone,
status: rider.status,
role: rider.role,
rating: rider.rating,
totalOrders: rider.totalOrders,
totalIncome: rider.totalIncome,
token
}
});
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 获取骑手信息(需登录)
router.get('/:id', async (req, res) => {
try {
const rider = await Rider.findById(req.params.id);
if (!rider) {
return res.status(404).json({ success: false, message: '骑手不存在' });
}
res.json({ success: true, data: rider });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 更新骑手信息(如状态切换,需登录本人或管理员)
router.put('/:id', async (req, res) => {
try {
// 不允许通过 PUT 修改密码和 role
const { password, role, ...safeBody } = req.body;
const rider = await Rider.findByIdAndUpdate(
req.params.id,
safeBody,
{ new: true, runValidators: true }
);
if (!rider) {
return res.status(404).json({ success: false, message: '骑手不存在' });
}
res.json({ success: true, data: rider });
} catch (error) {
res.status(400).json({ success: false, message: error.message });
}
});
// 获取骑手的订单
router.get('/:id/orders', async (req, res) => {
try {
const orders = await Order.find({ rider: req.params.id })
.populate('customer', 'name phone')
.populate('vehicle', 'vehicleId model color')
.sort({ createdAt: -1 });
res.json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
module.exports = router;