rwadurian/backend/services/admin-service/src/api/controllers/system-config.controller.ts

203 lines
4.9 KiB
TypeScript

import {
Controller,
Get,
Put,
Body,
Param,
HttpCode,
HttpStatus,
Inject,
Query,
} from '@nestjs/common';
import {
SYSTEM_CONFIG_REPOSITORY,
ISystemConfigRepository,
} from '../../domain/repositories/system-config.repository';
/**
* 系统配置常量 - 热度展示设置
*/
export const CONFIG_KEYS = {
// 是否允许未认种用户查看各省认种热度
ALLOW_NON_ADOPTER_VIEW_HEAT: 'display.allowNonAdopterViewHeat',
// 热度展示方式: 'count' | 'level'
HEAT_DISPLAY_MODE: 'display.heatDisplayMode',
} as const;
/**
* 获取系统配置响应 DTO
*/
interface SystemConfigResponseDto {
key: string;
value: string;
description: string | null;
updatedAt: Date;
}
/**
* 前端展示设置响应 DTO
*/
interface DisplaySettingsResponseDto {
allowNonAdopterViewHeat: boolean;
heatDisplayMode: 'count' | 'level';
}
/**
* 前端展示设置请求 DTO
*/
interface UpdateDisplaySettingsDto {
allowNonAdopterViewHeat?: boolean;
heatDisplayMode?: 'count' | 'level';
}
/**
* 管理端系统配置控制器
*/
@Controller('admin/system-config')
export class AdminSystemConfigController {
constructor(
@Inject(SYSTEM_CONFIG_REPOSITORY)
private readonly configRepo: ISystemConfigRepository,
) {}
/**
* 获取所有系统配置
*/
@Get()
async getAll(): Promise<SystemConfigResponseDto[]> {
const configs = await this.configRepo.findAll();
return configs.map((c) => ({
key: c.key,
value: c.value,
description: c.description,
updatedAt: c.updatedAt,
}));
}
/**
* 获取单个配置
*/
@Get(':key')
async getByKey(@Param('key') key: string): Promise<SystemConfigResponseDto | null> {
const config = await this.configRepo.findByKey(key);
if (!config) {
return null;
}
return {
key: config.key,
value: config.value,
description: config.description,
updatedAt: config.updatedAt,
};
}
/**
* 获取前端展示设置
*/
@Get('display/settings')
async getDisplaySettings(): Promise<DisplaySettingsResponseDto> {
const configs = await this.configRepo.findByKeys([
CONFIG_KEYS.ALLOW_NON_ADOPTER_VIEW_HEAT,
CONFIG_KEYS.HEAT_DISPLAY_MODE,
]);
const configMap = new Map(configs.map((c) => [c.key, c.value]));
return {
allowNonAdopterViewHeat:
configMap.get(CONFIG_KEYS.ALLOW_NON_ADOPTER_VIEW_HEAT) === 'true',
heatDisplayMode:
(configMap.get(CONFIG_KEYS.HEAT_DISPLAY_MODE) as 'count' | 'level') || 'count',
};
}
/**
* 更新前端展示设置
*/
@Put('display/settings')
@HttpCode(HttpStatus.OK)
async updateDisplaySettings(
@Body() dto: UpdateDisplaySettingsDto,
): Promise<DisplaySettingsResponseDto> {
const updates: Array<{ key: string; value: string; description?: string }> = [];
if (dto.allowNonAdopterViewHeat !== undefined) {
updates.push({
key: CONFIG_KEYS.ALLOW_NON_ADOPTER_VIEW_HEAT,
value: String(dto.allowNonAdopterViewHeat),
description: '是否允许未认种用户查看各省认种热度',
});
}
if (dto.heatDisplayMode !== undefined) {
updates.push({
key: CONFIG_KEYS.HEAT_DISPLAY_MODE,
value: dto.heatDisplayMode,
description: '热度展示方式: count=显示具体数量, level=仅显示热度等级',
});
}
if (updates.length > 0) {
await this.configRepo.batchUpsert(updates, 'admin');
}
// 返回更新后的配置
return this.getDisplaySettings();
}
/**
* 更新单个配置
*/
@Put(':key')
@HttpCode(HttpStatus.OK)
async updateByKey(
@Param('key') key: string,
@Body() body: { value: string; description?: string },
): Promise<SystemConfigResponseDto> {
const config = await this.configRepo.upsert(
key,
body.value,
body.description,
'admin',
);
return {
key: config.key,
value: config.value,
description: config.description,
updatedAt: config.updatedAt,
};
}
}
/**
* 移动端/公开系统配置控制器
* 用于 mobile-app 获取展示相关的配置
*/
@Controller('system-config')
export class PublicSystemConfigController {
constructor(
@Inject(SYSTEM_CONFIG_REPOSITORY)
private readonly configRepo: ISystemConfigRepository,
) {}
/**
* 获取前端展示设置(公开接口)
*/
@Get('display/settings')
async getDisplaySettings(): Promise<DisplaySettingsResponseDto> {
const configs = await this.configRepo.findByKeys([
CONFIG_KEYS.ALLOW_NON_ADOPTER_VIEW_HEAT,
CONFIG_KEYS.HEAT_DISPLAY_MODE,
]);
const configMap = new Map(configs.map((c) => [c.key, c.value]));
return {
allowNonAdopterViewHeat:
configMap.get(CONFIG_KEYS.ALLOW_NON_ADOPTER_VIEW_HEAT) === 'true',
heatDisplayMode:
(configMap.get(CONFIG_KEYS.HEAT_DISPLAY_MODE) as 'count' | 'level') || 'count',
};
}
}