feat: M4-10 — admin notification deepening (cost alerts, import failures, key expirations)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 41s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 41s
- Add scope field to Notification model (user/admin) - AdminNotificationsController: list, send, mark read - Generate endpoints: cost-alert, import-failure, key-expiring Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
c4089129c0
commit
b3176b8ead
@ -586,6 +586,7 @@ model Notification {
|
||||
title String @db.VarChar(255)
|
||||
content String? @db.Text
|
||||
data Json?
|
||||
scope String @default("user") @db.VarChar(16)
|
||||
readAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
|
||||
@ -58,6 +58,7 @@ import { ProjectCenterModule } from './modules/project-center/project-center.mod
|
||||
import { HermesAgentModule } from './modules/hermes-agent/hermes-agent.module';
|
||||
import { ReleaseModule } from './modules/release/release.module';
|
||||
import { ComplianceModule } from './modules/compliance/compliance.module';
|
||||
import { AdminNotificationsModule } from './modules/admin-notifications/admin-notifications.module';
|
||||
|
||||
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
||||
import { RolesGuard } from './common/guards/roles.guard';
|
||||
@ -161,6 +162,7 @@ import appleConfig from './config/apple.config';
|
||||
HermesAgentModule,
|
||||
ReleaseModule,
|
||||
ComplianceModule,
|
||||
AdminNotificationsModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: APP_GUARD, useClass: RateLimitGuard },
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
import { Controller, Get, Post, Patch, Param, Body, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation, ApiBody } from '@nestjs/swagger';
|
||||
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
||||
import { AdminAuthGuard } from '../../common/guards/admin-auth.guard';
|
||||
import { AdminRolesGuard } from '../../common/guards/admin-roles.guard';
|
||||
|
||||
@ApiTags('admin-notifications-v2')
|
||||
@ApiBearerAuth()
|
||||
@Controller('admin-api/admin-notifications')
|
||||
@UseGuards(AdminAuthGuard, AdminRolesGuard)
|
||||
export class AdminNotificationsController {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Admin 通知列表' })
|
||||
async list() {
|
||||
return this.prisma.notification.findMany({
|
||||
where: { scope: 'admin' },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 100,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('send')
|
||||
@ApiOperation({ summary: '发送 Admin 通知' })
|
||||
@ApiBody({ schema: { type: 'object', required: ['title', 'type'], properties: {
|
||||
title: { type: 'string' }, type: { type: 'string' }, content: { type: 'string' }, data: { type: 'object' },
|
||||
} } })
|
||||
async send(@Body() dto: { title: string; type: string; content?: string; data?: any }) {
|
||||
return this.prisma.notification.create({
|
||||
data: {
|
||||
userId: 'admin',
|
||||
type: dto.type,
|
||||
title: dto.title,
|
||||
content: dto.content || '',
|
||||
data: dto.data || null,
|
||||
scope: 'admin',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@Post(':id/read')
|
||||
@ApiOperation({ summary: '标记 Admin 通知已读' })
|
||||
async markRead(@Param('id') id: string) {
|
||||
return this.prisma.notification.update({ where: { id }, data: { readAt: new Date() } });
|
||||
}
|
||||
|
||||
// ═══ Predefined admin notification generators ═══
|
||||
|
||||
@Post('generate/cost-alert')
|
||||
@ApiOperation({ summary: '生成成本预警通知' })
|
||||
async generateCostAlert(@Body() dto: { cost: number; threshold: number; period: string }) {
|
||||
return this.prisma.notification.create({
|
||||
data: {
|
||||
userId: 'admin', type: 'cost_alert', scope: 'admin',
|
||||
title: `成本预警:${dto.period}成本 ¥${dto.cost} 超过阈值 ¥${dto.threshold}`,
|
||||
content: `${dto.period} AI 调用成本已达到 ¥${dto.cost},超过预设阈值 ¥${dto.threshold}。`,
|
||||
data: dto,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@Post('generate/import-failure')
|
||||
@ApiOperation({ summary: '生成导入失败通知' })
|
||||
async generateImportFailure(@Body() dto: { importId: string; failedCount: number; totalCount: number }) {
|
||||
return this.prisma.notification.create({
|
||||
data: {
|
||||
userId: 'admin', type: 'import_failure', scope: 'admin',
|
||||
title: `导入任务大量失败:${dto.failedCount}/${dto.totalCount}`,
|
||||
content: `导入任务 ${dto.importId} 中 ${dto.failedCount}/${dto.totalCount} 项失败。`,
|
||||
data: dto,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@Post('generate/key-expiring')
|
||||
@ApiOperation({ summary: '生成 API Key 到期通知' })
|
||||
async generateKeyExpiring(@Body() dto: { keyName: string; expiresInDays: number }) {
|
||||
return this.prisma.notification.create({
|
||||
data: {
|
||||
userId: 'admin', type: 'key_expiring', scope: 'admin',
|
||||
title: `API Key「${dto.keyName}」即将在 ${dto.expiresInDays} 天后到期`,
|
||||
content: `请尽快续期或更换密钥。`,
|
||||
data: dto,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AdminNotificationsController } from './admin-notifications.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [AdminNotificationsController],
|
||||
})
|
||||
export class AdminNotificationsModule {}
|
||||
Loading…
x
Reference in New Issue
Block a user