/** * Stats Controller - 运营统计控制器 * * 提供运营看板数据接口 * * @version 1.0.0 * @date 2026-01-25 */ import type { FastifyRequest, FastifyReply } from 'fastify'; import { activityService } from '../../../common/services/activity.service.js'; import { logger } from '../../../common/logging/index.js'; /** * 获取今日大盘数据 * GET /api/admin/stats/overview */ export async function getOverview( request: FastifyRequest, reply: FastifyReply ) { try { const data = await activityService.getTodayOverview(); return reply.send({ success: true, data, }); } catch (error: any) { logger.error('[StatsController] 获取大盘数据失败', { error: error.message }); return reply.status(500).send({ success: false, message: error.message || '获取大盘数据失败', }); } } /** * 获取实时流水账 * GET /api/admin/stats/live-feed?limit=100 */ export async function getLiveFeed( request: FastifyRequest<{ Querystring: { limit?: string } }>, reply: FastifyReply ) { try { const limit = Math.min(Number(request.query.limit) || 100, 500); // 最大500条 const data = await activityService.getLiveFeed(limit); return reply.send({ success: true, data, }); } catch (error: any) { logger.error('[StatsController] 获取流水账失败', { error: error.message }); return reply.status(500).send({ success: false, message: error.message || '获取流水账失败', }); } } /** * 获取用户360画像 * GET /api/admin/users/:id/overview */ export async function getUserOverview( request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply ) { try { const { id } = request.params; if (!id) { return reply.status(400).send({ success: false, message: '用户ID不能为空', }); } const data = await activityService.getUserOverview(id); if (!data.profile) { return reply.status(404).send({ success: false, message: '用户不存在', }); } return reply.send({ success: true, data, }); } catch (error: any) { logger.error('[StatsController] 获取用户画像失败', { error: error.message }); return reply.status(500).send({ success: false, message: error.message || '获取用户画像失败', }); } } /** * 分页查询运营日志 * GET /api/admin/stats/logs * * 查询参数: * - page: 页码 (默认1) * - pageSize: 每页条数 (默认20, 最大100) * - startDate: 开始日期 (YYYY-MM-DD) * - endDate: 结束日期 (YYYY-MM-DD) * - module: 模块筛选 * - action: 动作筛选 * - keyword: 关键词搜索 (用户名/租户名) */ export async function getActivityLogs( request: FastifyRequest<{ Querystring: { page?: string; pageSize?: string; startDate?: string; endDate?: string; module?: string; action?: string; keyword?: string; } }>, reply: FastifyReply ) { try { const { page: pageStr, pageSize: pageSizeStr, startDate: startDateStr, endDate: endDateStr, module, action, keyword, } = request.query; // 解析分页参数 const page = Math.max(1, Number(pageStr) || 1); const pageSize = Math.min(100, Math.max(1, Number(pageSizeStr) || 20)); // 解析日期参数 const startDate = startDateStr ? new Date(startDateStr) : undefined; const endDate = endDateStr ? new Date(endDateStr) : undefined; const result = await activityService.getActivityLogs({ page, pageSize, startDate, endDate, module, action, keyword, }); return reply.send({ success: true, data: result.data, pagination: { page: result.page, pageSize: result.pageSize, total: result.total, totalPages: Math.ceil(result.total / result.pageSize), }, }); } catch (error: any) { logger.error('[StatsController] 获取运营日志失败', { error: error.message }); return reply.status(500).send({ success: false, message: error.message || '获取运营日志失败', }); } } /** * 清理过期日志(管理接口) * POST /api/admin/stats/cleanup */ export async function cleanupLogs( request: FastifyRequest, reply: FastifyReply ) { try { const deletedCount = await activityService.cleanupOldLogs(); return reply.send({ success: true, data: { deletedCount, message: `已清理 ${deletedCount} 条过期日志`, }, }); } catch (error: any) { logger.error('[StatsController] 清理日志失败', { error: error.message }); return reply.status(500).send({ success: false, message: error.message || '清理日志失败', }); } }