import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { CurrentSessionUserId } from '../auth/current-session-user.decorator'; import { SendChainService } from '../send-chain/send-chain.service'; import { BatchReviewSmsTasksDto, CreateRiskRuleDto, ReviewSmsTaskDto, RiskReviewService, } from './risk-review.service'; import { CreatePhoneFrequencyWhitelistDto, PhoneFrequencyService, UpdatePhoneFrequencyWhitelistDto, } from './phone-frequency.service'; @ApiTags('risk-review') @Controller('admin/risk-review') export class AdminRiskReviewController { constructor( private readonly riskReview: RiskReviewService, private readonly sendChain: SendChainService, private readonly phoneFrequency: PhoneFrequencyService, ) {} @Get('rules') listRules(@Query('applicationId') applicationId?: string) { return this.riskReview.listRules(applicationId); } @Post('rules') createRule(@Body() body: CreateRiskRuleDto) { return this.riskReview.createRule(body); } @Put('rules/:id') updateRule(@Param('id') ruleId: string, @Body() body: Partial) { return this.riskReview.updateRule(ruleId, body); } @Get('hits') listHits(@Query('tenantId') tenantId?: string, @Query('taskId') taskId?: string) { return this.riskReview.listHits(tenantId, taskId); } @Get('phone-frequency-hits') listPhoneFrequencyHits( @Query('tenantId') tenantId?: string, @Query('applicationId') applicationId?: string, @Query('phoneNumber') phoneNumber?: string, @Query('status') status?: 'active' | 'expired' | 'released', @Query('createdAtFrom') createdAtFrom?: string, @Query('createdAtTo') createdAtTo?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { return this.phoneFrequency.listHits({ tenantId, applicationId, phoneNumber, status, createdAtFrom, createdAtTo, page: Number(page ?? 1), pageSize: Number(pageSize ?? 20), }); } @Post('phone-frequency-hits/:id/release') releasePhoneFrequencyHit( @Param('id') hitId: string, @Body() body: { reason?: string }, @CurrentSessionUserId() reviewerId?: string, ) { return this.phoneFrequency.releaseHit(hitId, reviewerId, body.reason); } @Get('phone-frequency-whitelist') listPhoneFrequencyWhitelist( @Query('phoneNumber') phoneNumber?: string, @Query('keyword') keyword?: string, @Query('status') status?: 'active' | 'inactive' | 'deleted', @Query('updatedAtFrom') updatedAtFrom?: string, @Query('updatedAtTo') updatedAtTo?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { return this.phoneFrequency.listWhitelist({ phoneNumber, keyword, status, updatedAtFrom, updatedAtTo, page: Number(page ?? 1), pageSize: Number(pageSize ?? 20), }); } @Post('phone-frequency-whitelist') createPhoneFrequencyWhitelist( @Body() body: CreatePhoneFrequencyWhitelistDto, @CurrentSessionUserId() operatorId?: string, ) { return this.phoneFrequency.createWhitelist(body, operatorId); } @Put('phone-frequency-whitelist/:id') updatePhoneFrequencyWhitelist( @Param('id') id: string, @Body() body: UpdatePhoneFrequencyWhitelistDto, @CurrentSessionUserId() operatorId?: string, ) { return this.phoneFrequency.updateWhitelist(id, body, operatorId); } @Delete('phone-frequency-whitelist/:id') deletePhoneFrequencyWhitelist( @Param('id') id: string, @Body() body: { reason?: string }, @CurrentSessionUserId() operatorId?: string, ) { return this.phoneFrequency.deleteWhitelist(id, operatorId, body.reason); } @Get('tasks') listTasks(@Query('tenantId') tenantId?: string, @Query('status') status?: string, @Query('submittedAtFrom') submittedAtFrom?: string, @Query('submittedAtTo') submittedAtTo?: string) { return this.riskReview.listTasks(tenantId, status, submittedAtFrom, submittedAtTo); } @Get('tasks/pending') listPendingTasks() { return this.riskReview.listPendingTasks(); } @Get('tasks/:id/messages') listTaskMessages( @Param('id') taskId: string, @Query('phone') phone?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { return this.riskReview.listTaskMessages(taskId, phone, Number(page ?? 1), Number(pageSize ?? 20)); } @Post('tasks/:id/approve') async approveTask(@Param('id') taskId: string, @Body() body: ReviewSmsTaskDto, @CurrentSessionUserId() reviewerId?: string) { const review = { ...body, reviewerId }; const task = await this.riskReview.approveTask(taskId, review); await this.sendChain.handleReviewDecision(taskId, 'approved', body.reason ?? '运营审核通过'); return task; } @Post('tasks/batch/reject') async rejectTasks(@Body() body: BatchReviewSmsTasksDto, @CurrentSessionUserId() reviewerId?: string) { const tasks = await this.riskReview.rejectTasks({ ...body, reviewerId }); const reason = body.reason?.trim() ?? ''; for (const task of tasks) { await this.sendChain.handleReviewDecision(task.id, 'rejected', reason); } return tasks; } @Post('tasks/:id/reject') async rejectTask(@Param('id') taskId: string, @Body() body: ReviewSmsTaskDto, @CurrentSessionUserId() reviewerId?: string) { const task = await this.riskReview.rejectTask(taskId, { ...body, reviewerId }); await this.sendChain.handleReviewDecision(taskId, 'rejected', body.reason ?? task.rejectReason ?? '运营审核驳回'); return task; } }