Files
company-celebration/packages/server/src/routes/admin.routes.ts
empty 66ca67c137 feat(server): 添加节目配置文件管理
- 新增 programs.json 配置文件
- 新增 ProgramConfigService 服务
- 新增节目配置 API 接口 (GET/PUT /api/admin/programs)
- 修改 AdminService 使用配置服务替代硬编码
- 添加单元测试
2026-01-28 13:55:03 +08:00

209 lines
4.5 KiB
TypeScript

import { Router, IRouter } from 'express';
import multer from 'multer';
import { participantService } from '../services/participant.service';
import { prizeConfigService } from '../services/prize-config.service';
import { programConfigService } from '../services/program-config.service';
const router: IRouter = Router();
const upload = multer({ storage: multer.memoryStorage() });
/**
* GET /api/admin/stats
* Get system statistics
*/
router.get('/stats', async (_req, res, next) => {
try {
// TODO: Implement admin stats
return res.json({
success: true,
data: {
totalUsers: participantService.getCount(),
totalVotes: 0,
activeConnections: 0,
},
});
} catch (error) {
next(error);
}
});
/**
* GET /api/admin/prizes
* Get prize configuration
*/
router.get('/prizes', async (_req, res, next) => {
try {
const config = prizeConfigService.getFullConfig();
return res.json({
success: true,
data: config,
});
} catch (error) {
next(error);
}
});
/**
* PUT /api/admin/prizes
* Update prize configuration
*/
router.put('/prizes', async (req, res, next) => {
try {
const { prizes, settings } = req.body;
if (prizes) {
const result = await prizeConfigService.updatePrizes(prizes);
if (!result.success) {
return res.status(400).json({ success: false, error: result.error });
}
}
if (settings) {
const result = await prizeConfigService.updateSettings(settings);
if (!result.success) {
return res.status(400).json({ success: false, error: result.error });
}
}
return res.json({
success: true,
data: prizeConfigService.getFullConfig(),
});
} catch (error) {
next(error);
}
});
/**
* GET /api/admin/programs
* Get program configuration
*/
router.get('/programs', async (_req, res, next) => {
try {
const config = programConfigService.getFullConfig();
return res.json({
success: true,
data: config,
});
} catch (error) {
next(error);
}
});
/**
* PUT /api/admin/programs
* Update program configuration
*/
router.put('/programs', async (req, res, next) => {
try {
const { programs, settings } = req.body;
if (programs) {
const result = await programConfigService.updatePrograms(programs);
if (!result.success) {
return res.status(400).json({ success: false, error: result.error });
}
}
if (settings) {
const result = await programConfigService.updateSettings(settings);
if (!result.success) {
return res.status(400).json({ success: false, error: result.error });
}
}
return res.json({
success: true,
data: programConfigService.getFullConfig(),
});
} catch (error) {
next(error);
}
});
/**
* POST /api/admin/draw/start
* Start a lucky draw
*/
router.post('/draw/start', async (_req, res, next) => {
try {
// TODO: Implement draw start
return res.json({
success: true,
message: 'Draw started',
});
} catch (error) {
next(error);
}
});
/**
* POST /api/admin/draw/stop
* Stop the current draw
*/
router.post('/draw/stop', async (_req, res, next) => {
try {
// TODO: Implement draw stop
return res.json({
success: true,
message: 'Draw stopped',
});
} catch (error) {
next(error);
}
});
/**
* POST /api/admin/participants/import
* Import participants from Excel file
* Expected columns: 岗位, 姓名, 年份
*/
router.post('/participants/import', upload.single('file'), async (req, res, next) => {
try {
if (!req.file) {
return res.status(400).json({
success: false,
error: '请上传 Excel 文件',
});
}
const result = await participantService.importFromExcel(req.file.buffer);
return res.json({
success: result.success,
data: {
totalCount: result.totalCount,
importedCount: result.importedCount,
tagDistribution: result.tagDistribution,
errors: result.errors,
},
});
} catch (error) {
next(error);
}
});
/**
* GET /api/admin/participants
* Get all participants with statistics
*/
router.get('/participants', async (_req, res, next) => {
try {
const participants = participantService.getAll();
const stats = participantService.getStats();
return res.json({
success: true,
data: {
count: participants.length,
tagDistribution: stats.tagDistribution,
participants,
},
});
} catch (error) {
next(error);
}
});
export default router;