feat: 初始化项目结构并添加核心功能模块
- 新增文档模板和导航结构 - 实现服务器基础API路由和控制器 - 添加扩展插件配置和前端框架 - 引入多租户和权限管理模块 - 集成日志和数据库配置 - 添加核心业务模型和类型定义
This commit is contained in:
96
server/src/services/ConfigService.ts
Normal file
96
server/src/services/ConfigService.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import db from '../config/database';
|
||||
import { RedisService } from '../utils/RedisService';
|
||||
|
||||
export interface AppConfig {
|
||||
key: string;
|
||||
value: any;
|
||||
description?: string;
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
export class ConfigService {
|
||||
private static TABLE_NAME = 'cf_config';
|
||||
private static HISTORY_TABLE = 'cf_config_history';
|
||||
|
||||
/**
|
||||
* [CORE_DEV_06/16] 初始化配置表与历史表
|
||||
*/
|
||||
static async initTable() {
|
||||
const exists = await db.schema.hasTable(this.TABLE_NAME);
|
||||
if (!exists) {
|
||||
await db.schema.createTable(this.TABLE_NAME, (table) => {
|
||||
table.string('key').notNullable();
|
||||
table.string('tenantId').defaultTo('SYSTEM').index();
|
||||
table.json('value');
|
||||
table.string('description');
|
||||
table.boolean('isEnabled').defaultTo(true);
|
||||
table.integer('version').defaultTo(1); // [CORE_DEV_16] 版本控制
|
||||
table.timestamps(true, true);
|
||||
table.primary(['key', 'tenantId']);
|
||||
});
|
||||
// ... (seed data remains same)
|
||||
}
|
||||
|
||||
const historyExists = await db.schema.hasTable(this.HISTORY_TABLE);
|
||||
if (!historyExists) {
|
||||
await db.schema.createTable(this.HISTORY_TABLE, (table) => {
|
||||
table.increments('id').primary();
|
||||
table.string('key').notNullable();
|
||||
table.string('tenantId').notNullable();
|
||||
table.json('value');
|
||||
table.integer('version').notNullable();
|
||||
table.string('changeLog');
|
||||
table.timestamp('created_at').defaultTo(db.fn.now());
|
||||
table.index(['key', 'tenantId']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [CORE_DEV_16] 更新配置并保存历史版本
|
||||
*/
|
||||
static async updateConfig(key: string, data: Partial<AppConfig> & { changeLog?: string }, tenantId: string = 'SYSTEM') {
|
||||
const current = await this.getConfig(key, tenantId);
|
||||
const newVersion = (current?.version || 0) + 1;
|
||||
|
||||
const updateData: any = { ...data, version: newVersion };
|
||||
delete updateData.changeLog;
|
||||
|
||||
if (data.value) updateData.value = JSON.stringify(data.value);
|
||||
|
||||
await db.transaction(async (trx) => {
|
||||
// 1. 更新主表
|
||||
await trx(this.TABLE_NAME).where({ key, tenantId }).update(updateData);
|
||||
|
||||
// 2. 插入历史记录
|
||||
await trx(this.HISTORY_TABLE).insert({
|
||||
key,
|
||||
tenantId,
|
||||
value: updateData.value || JSON.stringify(current?.value),
|
||||
version: newVersion,
|
||||
changeLog: data.changeLog || 'Automated update'
|
||||
});
|
||||
});
|
||||
|
||||
// [CORE_DEV_12] 分布式配置热更新通知
|
||||
await RedisService.publishConfigChange(tenantId, key, data.value || data.isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* [CORE_DEV_16] 配置版本回滚
|
||||
*/
|
||||
static async rollbackConfig(key: string, version: number, tenantId: string = 'SYSTEM') {
|
||||
const history = await db(this.HISTORY_TABLE).where({ key, tenantId, version }).first();
|
||||
if (!history) throw new Error(`Version ${version} not found for config ${key}`);
|
||||
|
||||
await this.updateConfig(key, {
|
||||
value: typeof history.value === 'string' ? JSON.parse(history.value) : history.value,
|
||||
changeLog: `Rollback to version ${version}`
|
||||
}, tenantId);
|
||||
}
|
||||
|
||||
static async isFeatureEnabled(key: string, tenantId: string = 'SYSTEM'): Promise<boolean> {
|
||||
const config = await this.getConfig(key, tenantId);
|
||||
return config ? config.isEnabled : false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user