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

228 lines
7.6 KiB
JavaScript

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 { authMiddleware, requireRole } = require('../middleware/auth');
const { validate } = require('../middleware/validate');
const { schemas } = require('../middleware/validate');
// 登录限流
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false,
message: { success: false, message: '登录尝试过于频繁,请稍后再试' }
});
// 骑手登录
router.post('/login', loginLimiter, validate(schemas.login), async (req, res) => {
try {
const { phone, password } = req.body;
const trimmedPhone = phone ? phone.trim() : '';
const trimmedPassword = password ? password.trim() : '';
const rider = await Rider.findOne({ phone: trimmedPhone }).select('+password');
if (!rider) {
return res.status(401).json({ success: false, message: '手机号或密码错误' });
}
const isMatch = await comparePassword(trimmedPassword, rider.password);
if (!isMatch) {
return res.status(401).json({ success: false, message: '手机号或密码错误' });
}
const token = jwt.sign(
{ id: rider._id, role: rider.role, type: 'rider', phone: rider.phone, jti: Math.random().toString(36) },
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: "服务器内部错误" });
}
});
// ===== 固定路由(必须放在 /:id 之前) =====
// 获取骑手统计
router.get('/stats', authMiddleware, requireRole('rider'), async (req, res) => {
try {
const rider = await Rider.findById(req.user.id);
if (!rider) {
return res.status(404).json({ success: false, message: '骑手不存在' });
}
const today = new Date();
today.setHours(0, 0, 0, 0);
const todayOrders = await Order.countDocuments({
rider: req.user.id,
status: '已完成',
actualEndDate: { $gte: today }
});
res.json({
success: true,
data: {
todayOrders,
monthIncome: rider.totalIncome || 0,
completedOrders: rider.totalOrders || 0
}
});
} catch (error) {
res.status(500).json({ success: false, message: "服务器内部错误" });
}
});
// 获取可接订单
router.get('/orders/available', authMiddleware, requireRole('rider'), async (req, res) => {
try {
const orders = await Order.find({ rider: { $exists: false }, status: '待支付' })
.populate('customer', 'name phone')
.populate('vehicle', 'vehicleId model color')
.sort({ createdAt: -1 })
.limit(50);
res.json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, message: "服务器内部错误" });
}
});
// 骑手接单
router.post('/orders/:id/accept', authMiddleware, requireRole('rider'), async (req, res) => {
try {
const order = await Order.findById(req.params.id);
if (!order) {
return res.status(404).json({ success: false, message: '订单不存在' });
}
if (order.rider) {
return res.status(400).json({ success: false, message: '该订单已被接单' });
}
order.rider = req.user.id;
order.status = '进行中';
await order.save();
await Rider.findByIdAndUpdate(req.user.id, { $inc: { totalOrders: 1 } });
res.json({ success: true, data: order });
} catch (error) {
res.status(500).json({ success: false, message: "服务器内部错误" });
}
});
// 骑手完成配送
router.post('/orders/:id/complete', authMiddleware, requireRole('rider'), async (req, res) => {
try {
const order = await Order.findOne({ _id: req.params.id, rider: req.user.id });
if (!order) {
return res.status(404).json({ success: false, message: '订单不存在或无权操作' });
}
order.status = '已完成';
order.actualEndDate = new Date();
await order.save();
await Rider.findByIdAndUpdate(req.user.id, { $inc: { totalIncome: order.totalAmount } });
res.json({ success: true, data: order });
} catch (error) {
res.status(500).json({ success: false, message: "服务器内部错误" });
}
});
// 骑手取消接单
router.post('/orders/:id/cancel', authMiddleware, requireRole('rider'), async (req, res) => {
try {
const order = await Order.findOne({ _id: req.params.id, rider: req.user.id });
if (!order) {
return res.status(404).json({ success: false, message: '订单不存在或无权操作' });
}
order.rider = null;
order.status = '待支付';
await order.save();
res.json({ success: true });
} catch (error) {
res.status(500).json({ success: false, message: "服务器内部错误" });
}
});
// ===== 参数路由(放在最后) =====
// 获取骑手信息
router.get('/:id', authMiddleware, async (req, res) => {
try {
const isSelf = req.params.id === req.user.id;
const isPrivileged = ['admin', 'store'].includes(req.user.role);
if (!isSelf && !isPrivileged) {
return res.status(403).json({ success: false, message: '无权查看该骑手信息' });
}
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: "服务器内部错误" });
}
});
// 更新骑手信息
router.put('/:id', authMiddleware, async (req, res) => {
try {
const isSelf = req.params.id === req.user.id;
const isPrivileged = ['admin', 'store'].includes(req.user.role);
if (!isSelf && !isPrivileged) {
return res.status(403).json({ success: false, message: '无权修改该骑手信息' });
}
const { password, ...safeBody } = req.body;
if (req.body.role && !isPrivileged) {
return res.status(403).json({ success: false, message: '无权修改角色' });
}
const updateData = isPrivileged ? req.body : safeBody;
const rider = await Rider.findByIdAndUpdate(req.params.id, updateData, { 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: "服务器内部错误" });
}
});
// 获取骑手的订单
router.get('/:id/orders', authMiddleware, async (req, res) => {
try {
const isSelf = req.params.id === req.user.id;
const isPrivileged = ['admin', 'store'].includes(req.user.role);
if (!isSelf && !isPrivileged) {
return res.status(403).json({ success: false, message: '无权查看该骑手的订单' });
}
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: "服务器内部错误" });
}
});
module.exports = router;