- 管理台:活动设置、时长登记、用户管理、数据导出(Excel/PNG) - 用户端:姓名查询个人义工时长与活动记录 - 技术栈:React + Vite + TailwindCSS / Node.js + Express + sql.js (SQLite) - 支持 Docker 部署,附带 Gitea Actions 自动部署工作流 - 响应式界面,兼容移动端与 PC 端 - 默认管理员账号:admin / admin123
43 lines
1.8 KiB
TypeScript
43 lines
1.8 KiB
TypeScript
import { Router, Request, Response } from 'express';
|
|
import bcrypt from 'bcryptjs';
|
|
import jwt from 'jsonwebtoken';
|
|
import { getDb } from '../db';
|
|
import { JWT_SECRET, JWT_EXPIRES_IN } from '../config';
|
|
import { authMiddleware, AuthRequest } from '../middleware/auth';
|
|
|
|
const router = Router();
|
|
|
|
router.post('/login', (req: Request, res: Response) => {
|
|
const { username, password } = req.body || {};
|
|
if (!username || !password) {
|
|
return res.status(400).json({ error: '请输入用户名和密码' });
|
|
}
|
|
const db = getDb();
|
|
const admin = db.prepareCompat('SELECT * FROM admins WHERE username = ?').get(username) as any;
|
|
if (!admin) return res.status(401).json({ error: '用户名或密码错误' });
|
|
const ok = bcrypt.compareSync(password, admin.password_hash);
|
|
if (!ok) return res.status(401).json({ error: '用户名或密码错误' });
|
|
const token = jwt.sign({ id: admin.id, username: admin.username }, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
|
|
res.json({ token, username: admin.username });
|
|
});
|
|
|
|
router.post('/change-password', authMiddleware, (req: AuthRequest, res: Response) => {
|
|
const { oldPassword, newPassword } = req.body || {};
|
|
if (!oldPassword || !newPassword) {
|
|
return res.status(400).json({ error: '缺少参数' });
|
|
}
|
|
if (newPassword.length < 6) {
|
|
return res.status(400).json({ error: '新密码至少 6 位' });
|
|
}
|
|
const db = getDb();
|
|
const admin = db.prepareCompat('SELECT * FROM admins WHERE id = ?').get(req.adminId) as any;
|
|
const ok = bcrypt.compareSync(oldPassword, admin.password_hash);
|
|
if (!ok) return res.status(400).json({ error: '原密码错误' });
|
|
const hash = bcrypt.hashSync(newPassword, 10);
|
|
db.prepareCompat('UPDATE admins SET password_hash = ? WHERE id = ?').run(hash, req.adminId);
|
|
db.save();
|
|
res.json({ ok: true });
|
|
});
|
|
|
|
export default router;
|