203 lines
4.9 KiB
TypeScript
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',
|
|
};
|
|
}
|
|
}
|