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 & { 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 { const config = await this.getConfig(key, tenantId); return config ? config.isEnabled : false; } }