- 移除未使用的TabPane组件 - 修复类型定义和导入方式 - 优化mock数据源的环境变量判断逻辑 - 更新文档结构并归档旧文件 - 添加新的UI组件和Memo组件 - 调整API路径和响应处理
402 lines
9.4 KiB
Markdown
402 lines
9.4 KiB
Markdown
# 配置驱动文档 (Crawlful Hub)
|
||
|
||
> **定位**:Crawlful Hub 配置驱动设计文档 - 说明如何实现可配置的系统参数,避免硬编码。
|
||
> **更新日期**: 2026-03-18
|
||
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
|
||
|
||
---
|
||
|
||
## 1. 配置驱动概述
|
||
|
||
### 1.1 定义
|
||
|
||
配置驱动是指将系统参数(如 ROI 阈值、库存预警值等)从代码中分离出来,通过配置文件或数据库进行管理,实现系统的灵活性和可维护性。
|
||
|
||
### 1.2 重要性
|
||
|
||
配置驱动的好处:
|
||
- **灵活性**:无需修改代码即可调整系统行为
|
||
- **可维护性**:集中管理配置,便于维护
|
||
- **安全性**:敏感配置可以单独管理
|
||
- **可扩展性**:易于添加新的配置项
|
||
- **可监控性**:可以监控配置的使用情况
|
||
|
||
---
|
||
|
||
## 2. 配置管理
|
||
|
||
### 2.1 配置存储
|
||
|
||
#### 2.1.1 配置文件
|
||
|
||
**适用场景**:静态配置,如数据库连接信息、API 密钥等
|
||
|
||
**实现**:
|
||
- 使用 YAML、JSON、ENV 等格式
|
||
- 按环境分离配置文件(开发、测试、生产)
|
||
- 使用配置文件加载工具
|
||
|
||
**示例**:
|
||
```yaml
|
||
# config.yaml
|
||
database:
|
||
host: localhost
|
||
port: 3306
|
||
username: root
|
||
password: password
|
||
database: crawlful_hub
|
||
|
||
api:
|
||
timeout: 30000
|
||
retry: 3
|
||
|
||
business:
|
||
roi_threshold: 1.5
|
||
inventory_alert: 10
|
||
max_order_quantity: 100
|
||
```
|
||
|
||
#### 2.1.2 数据库
|
||
|
||
**适用场景**:动态配置,如业务规则、阈值等
|
||
|
||
**实现**:
|
||
- 创建配置表
|
||
- 支持配置的版本管理
|
||
- 支持配置的生效时间
|
||
|
||
**示例**:
|
||
```sql
|
||
CREATE TABLE cf_config (
|
||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||
key VARCHAR(100) NOT NULL UNIQUE,
|
||
value JSON NOT NULL,
|
||
description VARCHAR(255),
|
||
tenant_id VARCHAR(50),
|
||
shop_id VARCHAR(50),
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 插入配置
|
||
INSERT INTO cf_config (key, value, description) VALUES
|
||
('roi_threshold', '1.5', 'ROI 阈值'),
|
||
('inventory_alert', '10', '库存预警值'),
|
||
('max_order_quantity', '100', '最大订单数量');
|
||
```
|
||
|
||
#### 2.1.3 缓存
|
||
|
||
**适用场景**:频繁访问的配置
|
||
|
||
**实现**:
|
||
- 使用 Redis 等缓存工具
|
||
- 配置变更时自动更新缓存
|
||
- 设置合理的缓存过期时间
|
||
|
||
**示例**:
|
||
```typescript
|
||
// 配置服务
|
||
class ConfigService {
|
||
private cache: Map<string, any> = new Map();
|
||
|
||
async getConfig(key: string): Promise<any> {
|
||
// 先从缓存获取
|
||
if (this.cache.has(key)) {
|
||
return this.cache.get(key);
|
||
}
|
||
|
||
// 从数据库获取
|
||
const config = await this.configRepository.findByKey(key);
|
||
if (config) {
|
||
this.cache.set(key, config.value);
|
||
return config.value;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
async updateConfig(key: string, value: any): Promise<void> {
|
||
// 更新数据库
|
||
await this.configRepository.update(key, value);
|
||
|
||
// 更新缓存
|
||
this.cache.set(key, value);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 配置加载
|
||
|
||
#### 2.2.1 启动时加载
|
||
|
||
**实现**:
|
||
- 在应用启动时加载所有配置
|
||
- 缓存到内存中
|
||
- 提供配置访问接口
|
||
|
||
**示例**:
|
||
```typescript
|
||
// 配置加载
|
||
class ConfigLoader {
|
||
private config: any = {};
|
||
|
||
async load(): Promise<void> {
|
||
// 加载配置文件
|
||
const fileConfig = await this.loadFromFile();
|
||
|
||
// 加载数据库配置
|
||
const dbConfig = await this.loadFromDatabase();
|
||
|
||
// 合并配置
|
||
this.config = { ...fileConfig, ...dbConfig };
|
||
}
|
||
|
||
get(key: string, defaultValue?: any): any {
|
||
const keys = key.split('.');
|
||
let value = this.config;
|
||
|
||
for (const k of keys) {
|
||
if (value[k] === undefined) {
|
||
return defaultValue;
|
||
}
|
||
value = value[k];
|
||
}
|
||
|
||
return value;
|
||
}
|
||
}
|
||
|
||
// 使用
|
||
const configLoader = new ConfigLoader();
|
||
await configLoader.load();
|
||
const roiThreshold = configLoader.get('business.roi_threshold', 1.5);
|
||
```
|
||
|
||
#### 2.2.2 动态加载
|
||
|
||
**实现**:
|
||
- 配置变更时自动加载
|
||
- 支持热更新
|
||
- 无需重启应用
|
||
|
||
**示例**:
|
||
```typescript
|
||
// 配置监听器
|
||
class ConfigListener {
|
||
constructor(private configService: ConfigService) {
|
||
// 监听配置变更
|
||
this.listenForChanges();
|
||
}
|
||
|
||
private listenForChanges(): void {
|
||
// 监听数据库变更
|
||
this.configService.on('configChanged', (key: string, value: any) => {
|
||
console.log(`Config changed: ${key} = ${value}`);
|
||
// 处理配置变更
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 配置分类
|
||
|
||
### 3.1 系统配置
|
||
|
||
- **数据库配置**:连接信息、池大小等
|
||
- **API 配置**:超时时间、重试次数等
|
||
- **缓存配置**:缓存大小、过期时间等
|
||
- **安全配置**:密钥、加密算法等
|
||
|
||
### 3.2 业务配置
|
||
|
||
- **定价配置**:ROI 阈值、定价策略等
|
||
- **库存配置**:预警值、安全库存等
|
||
- **订单配置**:最大数量、处理规则等
|
||
- **物流配置**:物流渠道、运费规则等
|
||
|
||
### 3.3 租户配置
|
||
|
||
- **租户特定配置**:每个租户的个性化配置
|
||
- **店铺配置**:每个店铺的特定配置
|
||
|
||
---
|
||
|
||
## 4. 配置管理界面
|
||
|
||
### 4.1 配置列表
|
||
|
||
- **展示所有配置**:按分类展示配置项
|
||
- **搜索配置**:支持按关键字搜索
|
||
- **过滤配置**:按类型、租户、店铺等过滤
|
||
|
||
### 4.2 配置编辑
|
||
|
||
- **编辑配置值**:修改配置的当前值
|
||
- **配置历史**:查看配置的修改历史
|
||
- **配置生效**:设置配置的生效时间
|
||
|
||
### 4.3 配置验证
|
||
|
||
- **格式验证**:验证配置值的格式
|
||
- **范围验证**:验证配置值的范围
|
||
- **依赖验证**:验证配置之间的依赖关系
|
||
|
||
---
|
||
|
||
## 5. 最佳实践
|
||
|
||
### 5.1 配置命名规范
|
||
|
||
- **使用点号分隔**:如 `business.roi_threshold`
|
||
- **使用小写字母**:避免大小写混淆
|
||
- **使用下划线**:代替空格
|
||
- **语义清晰**:配置名称应清晰表达其用途
|
||
|
||
### 5.2 配置默认值
|
||
|
||
- **设置合理的默认值**:确保系统在没有配置时也能正常运行
|
||
- **文档化默认值**:在文档中说明默认值的含义
|
||
- **环境特定默认值**:为不同环境设置不同的默认值
|
||
|
||
### 5.3 配置安全
|
||
|
||
- **敏感配置加密**:加密存储敏感配置
|
||
- **配置访问控制**:限制配置的访问权限
|
||
- **配置审计**:记录配置的修改历史
|
||
|
||
### 5.4 配置版本管理
|
||
|
||
- **版本控制**:记录配置的版本
|
||
- **回滚机制**:支持配置的回滚
|
||
- **变更通知**:通知相关人员配置变更
|
||
|
||
---
|
||
|
||
## 6. 实现示例
|
||
|
||
### 6.1 配置服务
|
||
|
||
```typescript
|
||
// 配置服务
|
||
class ConfigService {
|
||
private config: Map<string, any> = new Map();
|
||
private listeners: Map<string, Function[]> = new Map();
|
||
|
||
constructor(private configRepository: ConfigRepository) {
|
||
this.loadConfig();
|
||
}
|
||
|
||
private async loadConfig(): Promise<void> {
|
||
const configs = await this.configRepository.findAll();
|
||
configs.forEach(config => {
|
||
this.config.set(config.key, config.value);
|
||
});
|
||
}
|
||
|
||
async get(key: string, defaultValue?: any): Promise<any> {
|
||
if (this.config.has(key)) {
|
||
return this.config.get(key);
|
||
}
|
||
return defaultValue;
|
||
}
|
||
|
||
async set(key: string, value: any): Promise<void> {
|
||
await this.configRepository.upsert(key, value);
|
||
this.config.set(key, value);
|
||
this.notifyListeners(key, value);
|
||
}
|
||
|
||
private notifyListeners(key: string, value: any): void {
|
||
if (this.listeners.has(key)) {
|
||
this.listeners.get(key)?.forEach(listener => {
|
||
listener(value);
|
||
});
|
||
}
|
||
}
|
||
|
||
on(key: string, listener: Function): void {
|
||
if (!this.listeners.has(key)) {
|
||
this.listeners.set(key, []);
|
||
}
|
||
this.listeners.get(key)?.push(listener);
|
||
}
|
||
|
||
off(key: string, listener: Function): void {
|
||
if (this.listeners.has(key)) {
|
||
const listeners = this.listeners.get(key)?.filter(l => l !== listener);
|
||
this.listeners.set(key, listeners || []);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.2 配置使用示例
|
||
|
||
```typescript
|
||
// 定价服务
|
||
class PricingService {
|
||
constructor(private configService: ConfigService) {}
|
||
|
||
async calculateROI(product: Product, price: number): Promise<number> {
|
||
// 获取 ROI 阈值配置
|
||
const roiThreshold = await this.configService.get('business.roi_threshold', 1.5);
|
||
|
||
// 计算成本
|
||
const cost = await this.calculateCost(product);
|
||
|
||
// 计算 ROI
|
||
const roi = (price - cost) / cost;
|
||
|
||
// 检查是否达到阈值
|
||
if (roi < roiThreshold) {
|
||
this.logger.warn(`ROI below threshold: ${roi} < ${roiThreshold}`, {
|
||
productId: product.id,
|
||
price,
|
||
cost
|
||
});
|
||
}
|
||
|
||
return roi;
|
||
}
|
||
}
|
||
|
||
// 库存服务
|
||
class InventoryService {
|
||
constructor(private configService: ConfigService) {}
|
||
|
||
async checkInventory(productId: string): Promise<void> {
|
||
// 获取库存预警配置
|
||
const inventoryAlert = await this.configService.get('business.inventory_alert', 10);
|
||
|
||
// 获取库存
|
||
const inventory = await this.inventoryRepository.findByProductId(productId);
|
||
|
||
// 检查库存是否低于预警值
|
||
if (inventory.quantity < inventoryAlert) {
|
||
this.logger.warn(`Inventory below alert level: ${inventory.quantity} < ${inventoryAlert}`, {
|
||
productId,
|
||
quantity: inventory.quantity,
|
||
alert: inventoryAlert
|
||
});
|
||
|
||
// 发送库存预警
|
||
await this.notificationService.sendInventoryAlert(productId, inventory.quantity);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 相关文档
|
||
|
||
- [Service_Design.md](./Service_Design.md)
|
||
- [Data_Consistency.md](./Data_Consistency.md)
|
||
- [Observability.md](./Observability.md)
|
||
|
||
---
|
||
|
||
*本文档基于服务设计文档,最后更新: 2026-03-18* |