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;