feat:实现通知系统核心功能

- 添加通知实体和数据传输对象
- 实现通知服务层逻辑,支持创建、查询、标记已读
- 添加通知REST API控制器
- 实现WebSocket网关,支持实时通知推送
- 支持系统通知、用户通知、广播通知三种类型
- 支持定时通知功能,每分钟自动检查待发送通知
- 添加通知模块导出
This commit is contained in:
moyin
2026-01-10 21:51:29 +08:00
parent 23c54215e1
commit a2d630d864
8 changed files with 521 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
import {
Controller,
Get,
Post,
Body,
Param,
Patch,
Query,
ParseIntPipe,
UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { NoticeService } from './notice.service';
import { CreateNoticeDto } from './dto/create-notice.dto';
import { NoticeResponseDto } from './dto/notice-response.dto';
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { CurrentUser } from '../auth/current_user.decorator';
@ApiTags('通知管理')
@Controller('api/notices')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class NoticeController {
constructor(private readonly noticeService: NoticeService) {}
@Post()
@ApiOperation({ summary: '创建通知' })
@ApiResponse({ status: 201, description: '通知创建成功', type: NoticeResponseDto })
async create(@Body() createNoticeDto: CreateNoticeDto): Promise<NoticeResponseDto> {
return this.noticeService.create(createNoticeDto);
}
@Get()
@ApiOperation({ summary: '获取通知列表' })
@ApiResponse({ status: 200, description: '获取成功', type: [NoticeResponseDto] })
async findAll(
@CurrentUser() user: any,
@Query('all') all?: string,
): Promise<NoticeResponseDto[]> {
// 如果是管理员且指定了all参数返回所有通知
const userId = all === 'true' && user.isAdmin ? undefined : user.id;
return this.noticeService.findAll(userId);
}
@Get('unread-count')
@ApiOperation({ summary: '获取未读通知数量' })
@ApiResponse({ status: 200, description: '获取成功' })
async getUnreadCount(@CurrentUser() user: any): Promise<{ count: number }> {
const count = await this.noticeService.getUserUnreadCount(user.id);
return { count };
}
@Get(':id')
@ApiOperation({ summary: '获取通知详情' })
@ApiResponse({ status: 200, description: '获取成功', type: NoticeResponseDto })
async findOne(@Param('id', ParseIntPipe) id: number): Promise<NoticeResponseDto> {
return this.noticeService.findById(id);
}
@Patch(':id/read')
@ApiOperation({ summary: '标记通知为已读' })
@ApiResponse({ status: 200, description: '标记成功', type: NoticeResponseDto })
async markAsRead(
@Param('id', ParseIntPipe) id: number,
@CurrentUser() user: any,
): Promise<NoticeResponseDto> {
return this.noticeService.markAsRead(id, user.id);
}
@Post('system')
@ApiOperation({ summary: '发送系统通知' })
@ApiResponse({ status: 201, description: '发送成功', type: NoticeResponseDto })
async sendSystemNotice(
@Body() body: { title: string; content: string; userId?: number },
): Promise<NoticeResponseDto> {
return this.noticeService.sendSystemNotice(body.title, body.content, body.userId);
}
@Post('broadcast')
@ApiOperation({ summary: '发送广播通知' })
@ApiResponse({ status: 201, description: '发送成功', type: NoticeResponseDto })
async sendBroadcast(
@Body() body: { title: string; content: string },
): Promise<NoticeResponseDto> {
return this.noticeService.sendBroadcast(body.title, body.content);
}
}