diff --git a/app/api/routers/config.py b/app/api/routers/config.py index 87e3cb5..7bd75d8 100644 --- a/app/api/routers/config.py +++ b/app/api/routers/config.py @@ -62,6 +62,17 @@ async def update_remote_config(config: dict[str, Any] = Body(...)): return {"success": True, "message": "远程数据配置已更新", "update": state.config.update} +@router.post("/api/config/metrix-enabled") +async def update_metrix_enabled(enabled: bool = Body(..., embed=True)): + state.reload_config() + state.config.metrix_enabled = enabled + if not enabled: + state.config.source_type = "external" + state.config.warehouse_type = "mysql" + state.config.save() + return {"success": True, "message": "已更新", "update": state.config.update} + + @router.post("/api/config/backend") async def update_backend( source_type: str = Body(...), diff --git a/app/config.py b/app/config.py index 1a94dfb..3234001 100644 --- a/app/config.py +++ b/app/config.py @@ -72,8 +72,8 @@ class MySQLConfig: ).normalized() -# Source backends: direct FTP/SFTP, or Metrix storage platform. -SOURCE_TYPES = ("ftp", "sftp", "metrix") +# Source backends: external (FTP/SFTP), or Metrix storage platform. +SOURCE_TYPES = ("external", "metrix") # Warehouse backends: direct MySQL, or Metrix database platform. WAREHOUSE_TYPES = ("mysql", "metrix") @@ -537,8 +537,9 @@ def _normalize_source_type(value: Any, protocol: str = "sftp") -> str: text = str(value or "").strip().lower() if text in SOURCE_TYPES: return text - # Back-compat: no explicit source type means direct remote, pick its protocol. - return "ftp" if str(protocol).strip().lower() == "ftp" else "sftp" + if text in ("ftp", "sftp"): + return "external" + return "external" def _normalize_warehouse_type(value: Any) -> str: @@ -549,7 +550,8 @@ def _normalize_warehouse_type(value: Any) -> str: @dataclass class AppConfig: update: str = "" - source_type: str = "sftp" + metrix_enabled: bool = False + source_type: str = "external" warehouse_type: str = "mysql" mysql: MySQLConfig = field(default_factory=MySQLConfig) metrix: MetrixConfig = field(default_factory=MetrixConfig) @@ -578,6 +580,7 @@ class AppConfig: return cls( update=data.get("Update", ""), + metrix_enabled=bool(data.get("MetrixEnabled", False)), source_type=_normalize_source_type(data.get("SourceType"), remote_config.protocol), warehouse_type=_normalize_warehouse_type(data.get("WarehouseType")), mysql=mysql_config, @@ -602,6 +605,7 @@ class AppConfig: """转换为配置文件结构(包含敏感字段,用于保存和下载)""" return { "Update": self.update, + "MetrixEnabled": self.metrix_enabled, "SourceType": self.source_type, "WarehouseType": self.warehouse_type, "MySQL_DBInfo": self.mysql.normalized().to_dict(include_password=True), @@ -618,6 +622,7 @@ class AppConfig: """转换为字典(用于返回给前端,隐藏密码)""" return { "update": self.update, + "metrix_enabled": self.metrix_enabled, "source_type": self.source_type, "warehouse_type": self.warehouse_type, "mysql": self.mysql.normalized().to_dict(), @@ -634,6 +639,7 @@ class AppConfig: """转换为完整字典(包含密码,用于编辑时回显)""" return { "update": self.update, + "metrix_enabled": self.metrix_enabled, "source_type": self.source_type, "warehouse_type": self.warehouse_type, "mysql": self.mysql.normalized().to_dict(include_password=True), diff --git a/docs/project_context.md b/docs/project_context.md index d36fbe2..4b9b8e2 100644 --- a/docs/project_context.md +++ b/docs/project_context.md @@ -877,5 +877,14 @@ - 新增 `cell_data.py::copy_celldata_tables_to_capacity()`:列出 CellData 库所有表,逐表 `SHOW CREATE TABLE` → 目标库建表 → 分批 `SELECT * / INSERT INTO` 复制数据;两库相同时跳过。 - CellData 独立处理(远程 / 本地上传)完成后自动执行 CellData 脚本(不复制表)。 - 容量处理集成(`tasks.py` / `remote.py` 的 `_try_refresh_cell_data`):CellData 数据更新 → 执行 CellData 脚本 → 复制表到容量库 → 后续 ReportScript.sql 可直接引用 CellData 表。 -- 前端脚本编辑页(`ScriptPanel.vue`)编辑器上方新增 Naive UI segment tabs 切换「报表脚本」和「CellData 脚本」;切换时检查未保存状态、加载对应脚本内容;保存和运行按钮跟随当前脚本类型。 +- 前端脚本编辑页(`ScriptPanel.vue`)页头下拉按钮切换「容量报表脚本」和「CellData 脚本」;运行按钮文案统一为「运行」,跟随当前脚本类型执行对应库的 SQL。 +- 验证:`python -m compileall -q app` 通过;`frontend` `npm run build`(vue-tsc)通过;构建产物已清理。 + +## 2026-06-25:Metrix 平台模式按需启用 + 数据源合并为外部储存 + +- Metrix 平台开关:新增 `AppConfig.metrix_enabled`(默认 `false`),存储为 `Configure.json` 的 `MetrixEnabled`;关闭时 `source_type` 和 `warehouse_type` 自动回落为 `external` / `mysql`。 +- 开关入口:连点品牌图标 8 次打开的「授权延期」弹窗底部新增「启用 Metrix 平台」开关(`LicenseActivationModal.vue`),通过 `POST /api/config/metrix-enabled` 保存。 +- 条件显示:设置页「数据源 / 仓库」标签页仅在 `metrix_enabled=true` 时显示;未启用时该页不可见,系统默认走外部储存 + MySQL 直连。 +- 数据源合并:`source_type` 从 `ftp | sftp | metrix` 改为 `external | metrix`;FTP/SFTP 协议选择保留在远程数据源配置的 `RemoteData.protocol` 中,`external` 统一代表外部储存。旧值 `ftp`/`sftp` 自动规范化为 `external`。 +- 全局状态:`metrixEnabled` 通过 `composables/metrixEnabled.ts` 共享响应式状态,`AppShell` 登录后和激活弹窗切换时同步更新。 - 验证:`python -m compileall -q app` 通过;`frontend` `npm run build`(vue-tsc)通过;构建产物已清理。 diff --git a/frontend/src/AppShell.vue b/frontend/src/AppShell.vue index 5348a52..f37a932 100644 --- a/frontend/src/AppShell.vue +++ b/frontend/src/AppShell.vue @@ -112,7 +112,7 @@ - + + + diff --git a/frontend/src/components/SettingsPanel.vue b/frontend/src/components/SettingsPanel.vue index bf6a8b2..7366c6e 100644 --- a/frontend/src/components/SettingsPanel.vue +++ b/frontend/src/components/SettingsPanel.vue @@ -4,16 +4,15 @@ - + - SFTP - FTP - Metrix 存储平台 + 外部储存 + Metrix 储存平台 @@ -22,7 +21,7 @@ Metrix 数据库平台 - 主数据源和数据仓库可独立选择;CellData 单独配置。 + 数据源和数据仓库可独立选择;CellData 单独配置。 @@ -819,6 +818,7 @@ import type { RemoteSchedulerStatus } from '../types'; import { showDownloadCompleteDialog } from '../composables/downloadFeedback'; +import { metrixEnabled as metrixEnabledRef } from '../composables/metrixEnabled'; import { resetPageHeader, setPageHeader } from '../composables/pageHeader'; interface ExtractFieldConfig { @@ -882,7 +882,7 @@ const savingCellDataSettings = ref(false); const validatingCellDataSettings = ref(false); const savingBackend = ref(false); const savingMetrix = ref(false); -const sourceType = ref<'ftp' | 'sftp' | 'metrix'>('sftp'); +const sourceType = ref<'external' | 'metrix'>('external'); const warehouseType = ref<'mysql' | 'metrix'>('mysql'); const savingDirectoryMappings = ref(false); const savingHistoryRetention = ref(false); @@ -1120,7 +1120,7 @@ async function loadConfig() { try { const config = await apiGet('/api/config/full'); configUpdate.value = config.update; - sourceType.value = config.source_type || 'sftp'; + sourceType.value = (config.source_type === 'metrix' ? 'metrix' : 'external') as 'external' | 'metrix'; warehouseType.value = config.warehouse_type || 'mysql'; if (config.metrix) { metrixForm.base_url = config.metrix.base_url || ''; diff --git a/frontend/src/composables/metrixEnabled.ts b/frontend/src/composables/metrixEnabled.ts new file mode 100644 index 0000000..9934892 --- /dev/null +++ b/frontend/src/composables/metrixEnabled.ts @@ -0,0 +1,3 @@ +import { ref } from 'vue'; + +export const metrixEnabled = ref(false); diff --git a/frontend/src/types.ts b/frontend/src/types.ts index e3428ea..0879af7 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -96,7 +96,8 @@ export interface CacheSize { export interface AppConfig { update: string; - source_type: 'ftp' | 'sftp' | 'metrix'; + metrix_enabled: boolean; + source_type: 'external' | 'metrix'; warehouse_type: 'mysql' | 'metrix'; mysql: { host: string;
主数据源和数据仓库可独立选择;CellData 单独配置。
数据源和数据仓库可独立选择;CellData 单独配置。