## Context 当前 `ui/app.py`(1369 行)在 `gr.Blocks` 顶部放了一个巨型 `gr.Accordion("⚙️ 全局设置")`,包含 LLM / SD / 换脸 / 系统设置约 100+ 行组件声明。`gr.Tabs()` 紧随其后,首 Tab 实际是「内容创作」(`build_tab` 返回组件字典),后续依次是热点探测、评论管家、账号登录、数据看板、智能学习、自动运营、内容排期。 核心约束: 1. `build_tab()` 在 `ui/tab_create.py` 中定义,返回一个组件字典(`res_title`, `res_content`, `res_prompt`, `res_tags`, `quality_mode`, `steps`, `cfg_scale`, `neg_prompt` 等)。字典 **key 不得变更**,否则 `app.py` 中所有 click 绑定会断开。 2. Gradio 组件对象一旦被创建,其引用必须在 `gr.Blocks` 上下文内,不能跨上下文移动。因此「全局组件」(`llm_model`, `sd_model`, `persona`, `status_bar`, `face_swap_toggle`, `face_image_preview`, `sd_url`, `mcp_url`)如需迁移到单独的配置 Tab,需在配置 Tab 内创建,然后作为参数传递给 `build_tab()` ——现有接口已这样设计,无需修改函数签名。 3. 自定义 CSS 需注入到 `gr.Blocks(css=...)` 参数,Gradio 4.x 支持 `elem_id` / `elem_classes` 定位。 ## Goals / Non-Goals **Goals:** - 移除顶部全局折叠块,将 LLM / SD / 账号 / 系统设置组件迁移进一个新的「⚙️ 配置」Tab - Tab 顺序调整为:✍️ 内容创作 → 📅 内容排期 → 🔥 热点探测 → 💬 评论管家 → 📊 数据看板 → 🧠 智能学习 → 🤖 自动运营 → 🔐 账号登录 → ⚙️ 配置 - 内容创作 Tab 内部重构为三栏布局(已在 `tab_create.py` 中实现,补充对齐) - 自动运营 Tab 改为 2 列卡片式网格 - 注入自定义 CSS:字体层级、按钮圆角、卡片阴影、Section 标题线 - 按钮 `variant` 分级统一 **Non-Goals:** - 不修改任何业务逻辑、事件处理函数或 `services/` 层代码 - 不修改 `build_tab()` 返回的字典 key - 不引入新的 Python 依赖 - 不重构内容创作 Tab 的内部逻辑(仅布局调整) ## Decisions ### D1:全局组件保留在 Blocks 顶层,配置 Tab 仅做视觉容器 **决策**:在 `gr.Tabs()` 内新建「⚙️ 配置」Tab,将原折叠块内的所有组件声明 **整体移动** 进该 Tab(保持变量名不变)。 **原因**:Gradio 组件必须在声明处确定其 `Block` 归属,无法在声明后再"移动"到别的上下文。将声明移进 Tab 与移进 Accordion 在 Python 语义上等价,所有后续 `.change()` / `.click()` 绑定仍可访问同名变量。 **备选方案**:保留折叠块但折叠状态改为始终折叠(`open=False`)——被否,未从根本上减少首屏干扰。 ### D2:Tab 顺序重排策略 **决策**:按"使用频率"重排,高频在前: ``` 0 ✍️ 内容创作 (主工作流起点) 1 📅 内容排期 (发布管理) 2 🔥 热点探测 (灵感来源) 3 💬 评论管家 (互动运营) 4 📊 数据看板 (查看结果) 5 🧠 智能学习 (后台任务) 6 🤖 自动运营 (定时任务) 7 🔐 账号登录 (一次性操作) 8 ⚙️ 配置 (初始化/低频) ``` **原因**:账号登录和配置均属初始设置,完成后几乎不再访问,放末尾减少对核心工作流的干扰。 ### D3:自动运营 Tab — 2 列 Group 卡片而非 CSS Grid **决策**:用 `gr.Row()` + `with gr.Column(scale=1)` 实现等宽两列,每个任务块用 `gr.Group()` 包裹(Gradio 原生组合组件,有边框/背景色),而非依赖纯 CSS grid。 **原因**:Gradio 4.x 的 `gr.Group` 提供开箱即用的视觉分组,无需 `elem_id` + CSS 精确定位,可靠性更高。CSS 仅用于微调阴影/圆角,不承担主布局责任。 **备选方案**:全用 CSS grid + `elem_classes` ——被否,Gradio 的 CSS 隔离机制容易与内部 shadow DOM 冲突,维护成本高。 ### D4:CSS 注入范围——最小化 **决策**:CSS 只覆盖: 1. `body` 字体 (Inter / 系统字体栈) 2. `.btn-primary` 圆角和阴影 3. `.gr-group` 卡片阴影 4. Section 分隔标题(`hr` + `.section-title` class) 不覆盖 Gradio 内部组件(如 `textarea`, `input`),避免版本升级破坏样式。 ### D5:内容创作 Tab 三栏布局 — 在 tab_create.py 中调整 **决策**:在 `build_tab()` 内部,将现有的垂直堆叠改为 `gr.Row()` 包裹三个 `gr.Column(scale=3/4/3)`: - 左栏:人设选择、话题/风格、生成参数 - 中栏:文案输出(title/content/tags)+ 文案操作按钮 - 右栏:图片预览 gallery + 图片操作按钮(含美化强度滑块) **原因**:`build_tab()` 自包含,且组件字典 key 不变,`app.py` 侧零改动。 ## Risks / Trade-offs | 风险 | 缓解措施 | |------|----------| | 全局组件迁入 Tab 后,首次切换到配置 Tab 时才初始化(Gradio lazy render) | Gradio 4.x 默认会在页面加载时渲染所有 Tab,非 lazy,风险低 | | CSS 注入与 Gradio 主题冲突 | 仅用 `:root` 变量覆盖和有命名空间的选择器,避免直接覆盖 Gradio 内部类 | | `build_tab()` 三栏改造后在窄屏(<1200px)下挤压 | Row 内设置 `wrap=True`(Gradio 支持)或通过 CSS media query 处理 | | 自动运营 Tab 两列卡片在小屏幕下折叠 | 同上,添加 `@media` 断点 CSS | ## Migration Plan 1. **不需要数据迁移**——纯 UI 代码变更 2. **部署步骤**:替换 `ui/app.py` 和 `ui/tab_create.py` 后重启应用即生效 3. **回滚**:git revert 即可,无状态变更 ## Open Questions - **无**——所有技术决策已确定,可直接进入任务拆解