import express from 'express'; import User from '../models/User.js'; import Analysis from '../models/Analysis.js'; import AuditLog from '../models/AuditLog.js'; import { asyncHandler } from '../middleware/errorHandler.js'; import { requireAdmin, requireSuperAdmin } from '../middleware/auth.js'; const router = express.Router(); /** * GET /api/admin/dashboard * 管理者儀表板統計 */ router.get('/dashboard', requireAdmin, asyncHandler(async (req, res) => { const stats = await Analysis.getStatistics(); const userStats = await User.getAll(1, 1000); // 取得所有使用者 const totalUsers = userStats.pagination.total; const activeUsers = userStats.data.filter(u => u.is_active).length; res.json({ success: true, data: { totalUsers, activeUsers, totalAnalyses: stats.total, completedAnalyses: stats.completed, failedAnalyses: stats.failed, processingAnalyses: stats.processing, avgProcessingTime: Math.round(stats.avg_processing_time) || 0, successRate: stats.total > 0 ? ((stats.completed / stats.total) * 100).toFixed(1) : 0 } }); })); /** * GET /api/admin/users * 取得所有使用者 */ router.get('/users', requireAdmin, asyncHandler(async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const filters = { role: req.query.role, is_active: req.query.is_active !== undefined ? req.query.is_active === 'true' : undefined, search: req.query.search }; const result = await User.getAll(page, limit, filters); res.json({ success: true, ...result }); })); /** * POST /api/admin/users * 建立新使用者 */ router.post('/users', requireAdmin, asyncHandler(async (req, res) => { const { employee_id, username, email, password, role, department, position } = req.body; // 驗證必填欄位 if (!employee_id || !username || !email || !password) { return res.status(400).json({ success: false, error: '請填寫所有必填欄位' }); } // 驗證 role const validRoles = ['user', 'admin', 'super_admin']; if (role && !validRoles.includes(role)) { return res.status(400).json({ success: false, error: '無效的權限等級' }); } const newUser = await User.create({ employee_id, username, email, password, role: role || 'user', department, position }); // 記錄稽核日誌 await AuditLog.logCreate( req.session.userId, 'user', newUser.id, { username, email, role: newUser.role }, req.ip, req.get('user-agent') ); res.status(201).json({ success: true, message: '使用者已建立', data: newUser }); })); /** * PUT /api/admin/users/:id * 更新使用者 */ router.put('/users/:id', requireAdmin, asyncHandler(async (req, res) => { const userId = parseInt(req.params.id); const { username, email, role, department, position, is_active } = req.body; const oldUser = await User.findById(userId); if (!oldUser) { return res.status(404).json({ success: false, error: '使用者不存在' }); } const updatedUser = await User.update(userId, { username, email, role, department, position, is_active }); // 記錄稽核日誌 await AuditLog.logUpdate( req.session.userId, 'user', userId, { username: oldUser.username, role: oldUser.role }, { username, role }, req.ip, req.get('user-agent') ); res.json({ success: true, message: '使用者已更新', data: updatedUser }); })); /** * DELETE /api/admin/users/:id * 停用/刪除使用者 */ router.delete('/users/:id', requireSuperAdmin, asyncHandler(async (req, res) => { const userId = parseInt(req.params.id); const hard = req.query.hard === 'true'; const user = await User.findById(userId); if (!user) { return res.status(404).json({ success: false, error: '使用者不存在' }); } // 不能刪除自己 if (userId === req.session.userId) { return res.status(400).json({ success: false, error: '無法刪除自己的帳號' }); } if (hard) { await User.hardDelete(userId); } else { await User.delete(userId); } // 記錄稽核日誌 await AuditLog.logDelete( req.session.userId, 'user', userId, { username: user.username, email: user.email }, req.ip, req.get('user-agent') ); res.json({ success: true, message: hard ? '使用者已刪除' : '使用者已停用' }); })); /** * GET /api/admin/analyses * 取得所有分析記錄 */ router.get('/analyses', requireAdmin, asyncHandler(async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const filters = { status: req.query.status, user_id: req.query.user_id, search: req.query.search }; const result = await Analysis.getAll(page, limit, filters); res.json({ success: true, ...result }); })); /** * GET /api/admin/audit-logs * 取得稽核日誌 */ router.get('/audit-logs', requireSuperAdmin, asyncHandler(async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 50; const filters = { user_id: req.query.user_id, action: req.query.action, entity_type: req.query.entity_type, status: req.query.status, date_from: req.query.date_from, date_to: req.query.date_to }; const result = await AuditLog.getAll(page, limit, filters); res.json({ success: true, ...result }); })); /** * GET /api/admin/statistics * 取得完整統計資料 */ router.get('/statistics', requireSuperAdmin, asyncHandler(async (req, res) => { const overallStats = await Analysis.getStatistics(); const users = await User.getAll(1, 1000); // 計算各部門統計 const departmentStats = users.data.reduce((acc, user) => { const dept = user.department || '未分類'; if (!acc[dept]) { acc[dept] = { total: 0, active: 0 }; } acc[dept].total++; if (user.is_active) acc[dept].active++; return acc; }, {}); // 計算權限統計 const roleStats = users.data.reduce((acc, user) => { const role = user.role || 'user'; acc[role] = (acc[role] || 0) + 1; return acc; }, {}); res.json({ success: true, data: { overall: overallStats, users: { total: users.pagination.total, byDepartment: departmentStats, byRole: roleStats } } }); })); export default router;