forked from wangziqi/gongxue-base
101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
Put,
|
|
Post,
|
|
Body,
|
|
UseGuards,
|
|
Req,
|
|
} from '@nestjs/common';
|
|
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
|
import { RequirePermission } from '../auth/decorators/permission.decorator';
|
|
import { OperationLogsService } from '../operation-logs/operation-logs.service';
|
|
import { extractRequestInfo } from '../common/request-utils';
|
|
import { AiConfigService } from './ai-config.service';
|
|
import { SaveAiConfigDto, TestAiConfigDto, FetchModelsDto } from './dto/ai-config.dto';
|
|
|
|
interface AuthenticatedRequest {
|
|
user?: { id: number; username: string };
|
|
headers: Record<string, string | string[] | undefined>;
|
|
connection?: { remoteAddress?: string };
|
|
}
|
|
|
|
@Controller('ai/config')
|
|
@UseGuards(JwtAuthGuard)
|
|
export class AiConfigController {
|
|
constructor(
|
|
private readonly service: AiConfigService,
|
|
private readonly opLog: OperationLogsService,
|
|
) {}
|
|
|
|
@Get()
|
|
@RequirePermission('ai:config:read')
|
|
async getConfig() {
|
|
const data = await this.service.getConfig();
|
|
return { success: true, data };
|
|
}
|
|
|
|
@Put()
|
|
@RequirePermission('ai:config:write')
|
|
async saveConfig(@Body() body: SaveAiConfigDto, @Req() req: AuthenticatedRequest) {
|
|
const config = await this.service.saveConfig(body);
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.opLog.log({
|
|
userId: req.user?.id,
|
|
username: req.user?.username,
|
|
module: 'ai-config',
|
|
action: 'save',
|
|
targetId: config.id,
|
|
targetType: 'AiConfig',
|
|
detail: `provider=${body.provider} host=${new URL(config.baseUrl).hostname} model=${body.defaultModel ? 'configured' : 'not-set'}`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return { success: true, message: '配置已保存' };
|
|
}
|
|
|
|
@Post('test')
|
|
@RequirePermission('ai:config:test')
|
|
async testConnection(@Body() body: TestAiConfigDto, @Req() req: AuthenticatedRequest) {
|
|
const result = await this.service.testConnection(body);
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.opLog.log({
|
|
userId: req.user?.id,
|
|
username: req.user?.username,
|
|
module: 'ai-config',
|
|
action: 'test',
|
|
targetType: 'AiConfig',
|
|
detail: `provider=${body.provider ?? '-'} success=${result.success} latency=${result.latencyMs ?? '-'}`,
|
|
ipAddress,
|
|
userAgent,
|
|
status: result.success ? 'success' : 'failure',
|
|
});
|
|
return result;
|
|
}
|
|
|
|
@Post('models')
|
|
@RequirePermission('ai:config:read')
|
|
async fetchModels(@Body() body: FetchModelsDto) {
|
|
const result = await this.service.fetchModels(body);
|
|
return result;
|
|
}
|
|
|
|
@Post('clear-key')
|
|
@RequirePermission('ai:config:write')
|
|
async clearKey(@Req() req: AuthenticatedRequest) {
|
|
const data = await this.service.clearKey();
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.opLog.log({
|
|
userId: req.user?.id,
|
|
username: req.user?.username,
|
|
module: 'ai-config',
|
|
action: 'clear-key',
|
|
targetType: 'AiConfig',
|
|
detail: `keySource=${data.keySource}`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return { success: true, message: '密钥已清除', data };
|
|
}
|
|
}
|