# 重构任务：动态数据提供商配置架构 (Dynamic Data Provider Configuration)

## 1. 背景与目标 (Background & Objective)

目前系统的前端页面 (`DataSourceTab`) 硬编码了支持的数据源列表（Tushare, Finnhub 等）及其配置表单。这导致每增加一个新的数据源，都需要修改前端代码，违反了“单一来源”和“开闭原则”。

本次重构的目标是实现 **“前端无知 (Frontend Agnostic)”** 的架构：
1.  **后端驱动**：各 Provider 服务在启动注册时，声明自己的元数据（名称、描述）和配置规范（需要哪些字段）。
2.  **动态渲染**：前端通过 Gateway 获取所有已注册服务的元数据，动态生成配置表单。
3.  **通用交互**：测试连接、保存配置等操作通过统一的接口进行，不再针对特定 Provider 编写逻辑。

## 2. 核心数据结构设计 (Core Data Structures)

我们在 `common-contracts` 中扩展了服务注册的定义。

### 2.1 配置字段定义 (Config Field Definition)

不使用复杂的通用 JSON Schema，而是定义一套符合我们 UI 需求的强类型 Schema。

```rust
/// 字段类型枚举
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum FieldType {
    Text,       // 普通文本
    Password,   // 密码/Token (前端掩码显示)
    Url,        // URL 地址
    Boolean,    // 开关
    Select,     // 下拉选框 (需要 options)
}

/// 单个配置字段的定义
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ConfigFieldSchema {
    pub key: String,          // 字段键名 (如 "api_key")
    pub label: String,        // 显示名称 (如 "API Token")
    pub field_type: FieldType,// 字段类型
    pub required: bool,       // 是否必填
    pub placeholder: Option<String>, // 占位符
    pub default_value: Option<String>, // 默认值
    pub description: Option<String>,   // 字段说明
}
```

### 2.2 服务元数据扩展 (Service Metadata Extension)

修改 `ServiceRegistration` 并增加了 `ProviderMetadata` 结构。

```rust
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ProviderMetadata {
    pub id: String,           // 服务ID (如 "tushare")
    pub name_en: String,      // 英文名 (如 "Tushare Pro")
    pub name_cn: String,      // 中文名 (如 "Tushare Pro (中国股市)")
    pub description: String,  // 描述
    pub icon_url: Option<String>, // 图标 (可选)
    
    /// 该服务需要的配置字段列表
    pub config_schema: Vec<ConfigFieldSchema>,
    
    /// 是否支持“测试连接”功能
    pub supports_test_connection: bool,
}
```

## 3. 架构交互流程 (Architecture Flow)

### 3.1 服务注册 (Registration Phase)
1.  **Provider 启动** (如 `tushare-provider-service`):
    *   构建 `ProviderMetadata`，声明自己需要 `api_key` (必填, Password) 和 `api_url` (选填, Url, 默认值...)。
    *   调用 API Gateway 的 `/register` 接口，将 Metadata 发送给 Gateway。
    
2.  **API Gateway**:
    *   在内存 Registry 中存储这些 Metadata。

### 3.2 前端渲染 (Rendering Phase)
1.  **前端请求**: `GET /v1/registry/providers` (网关聚合接口)。
2.  **网关响应**: 返回所有活跃 Provider 的 `ProviderMetadata` 列表。
3.  **前端请求**: `GET /v1/configs/data_sources` (获取用户已保存的配置值)。
4.  **UI 生成**:
    *   前端遍历 Metadata 列表。
    *   对每个 Provider，根据 `config_schema` 动态生成 Input/Switch 组件。
    *   将已保存的配置值填充到表单中。

### 3.3 动作执行 (Action Phase)
1.  **保存 (Save)**:
    *   前端收集表单数据，发送标准 JSON 到 `POST /v1/configs/data_sources`。
    *   后端持久化服务保存数据。

2.  **测试连接 (Test Connection)**:
    *   前端发送 `POST /v1/configs/test` (注意：Gateway已有通用接口)。
    *   Payload: `{ type: "tushare", data: { "api_key": "..." } }`。
    *   网关将请求路由到对应的 Provider 微服务进行自我检查。

## 4. 任务拆解 (Task Breakdown)

### 4.1 后端开发 (Backend Development) - [已完成/Completed]
1.  **Common Contracts**: 更新 `registry.rs`，添加 `ProviderMetadata` 和 `ConfigFieldSchema` 定义。 (Done)
2.  **API Gateway**:
    *   更新注册逻辑，接收并存储 Metadata。 (Done)
    *   新增接口 `GET /v1/registry/providers` 供前端获取元数据。 (Done)
    *   **移除旧版接口**: 已删除 Legacy 的静态 schema 接口，强制转向动态机制。 (Done)
    *   **单元测试**: 实现了 `ServiceRegistry` 的单元测试 (`registry_unit_test.rs`)，覆盖注册、心跳、发现、注销等核心逻辑。 (Done)
3.  **Provider Services** (Tushare, Finnhub, etc.):
    *   实现 `ConfigSchema` 的构建逻辑。 (Done)
    *   更新注册调用，发送 Schema。 (Done for Tushare, Finnhub, AlphaVantage, YFinance)

### 4.2 后端验证测试 (Backend Verification) - [已完成/Completed]
在开始前端重构前，已进行一次集成测试，确保后端服务启动后能正确交互。

1.  **启动服务**: 使用 `tests/api-e2e/run_registry_test.sh` 启动最小化服务集。
2.  **API 验证**:
    *   调用 `GET /v1/registry/providers`，验证返回的 JSON 是否包含所有 Provider 的 Metadata 和 Schema。
    *   使用 `tests/api-e2e/registry_verifier.py` 脚本验证了 Tushare 的 Schema 字段正确性。
3.  **结果确认**:
    *   ✅ Tushare 服务成功注册。
    *   ✅ Schema 正确包含 `api_token` (Password, Required)。
    *   ✅ E2E 测试集 (`tests/end-to-end`) 也已更新并验证通过。

### 4.3 前端重构 (Frontend Refactor) - [待办/Pending]
1.  **API Client**: 更新 Client SDK 以支持新的元数据接口。
    *   **自动化更新脚本**: `scripts/update_api_spec.sh`
    *   **执行逻辑**: 
        1.  调用 `cargo test ... generate_openapi_json` 生成 `openapi.json`。
        2.  调用 `npm run gen:api` 重新生成前端 TypeScript 类型定义。
    *   **输出位置**: `frontend/src/api/schema.gen.ts`
2.  **State Management**: 修改 `useConfig` hook，增加获取 Provider Metadata 的逻辑。
3.  **UI Refactor**:
    *   废弃 `supportedProviders` 硬编码。
    *   创建 `DynamicConfigForm` 组件，根据 `ConfigFieldSchema` 渲染界面。
    *   对接新的测试连接和保存逻辑。
