chore: add project configs, backend repair services, docs, and code quality tooling
- Add pre-commit hooks (ruff, black, prettier) and ESLint/Prettier configs - Add backend repair services (execution, orchestration, preview) with tests - Add project documentation (CLAUDE.md, README.md, design specs and plans) - Add MissingTagsInlinePanel component for exception handling - Add pyproject.toml with ruff/black configuration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,250 @@
|
||||
# 异常中心页面优化 — 设计规格
|
||||
|
||||
> 创建日期: 2026-05-07
|
||||
> 状态: 设计中
|
||||
|
||||
## 概述
|
||||
|
||||
对 MusicWorkshop 异常中心页面(`ExceptionPage.jsx`)进行全面的视觉、交互、流程和代码结构优化。
|
||||
|
||||
### 核心痛点
|
||||
|
||||
- 页面不够美观(首要痛点)
|
||||
- 操作太繁琐
|
||||
- 向导流程太长(保留 5 步但优化界面)
|
||||
- 代码维护困难(800+ 行单文件)
|
||||
|
||||
## 设计决策
|
||||
|
||||
| 维度 | 决策 |
|
||||
|------|------|
|
||||
| 视觉风格 | 深色专业(Dark Professional)— 暗色主题 + 靛蓝高亮 + 微弱边框 |
|
||||
| 页面布局 | 向导聚焦布局(Wizard Focus)— 顶部步骤条 + 左侧队列 + 右侧操作区 |
|
||||
| 向导步骤 | 保持 5 步(确保入库数据精准性) |
|
||||
| 代码重构 | 按功能区拆分组件 + 提取自定义 hooks |
|
||||
| 后端改动 | 无需改动(API 和数据结构不变) |
|
||||
|
||||
## 视觉设计
|
||||
|
||||
### 配色方案
|
||||
|
||||
```
|
||||
背景: #0f172a (slate-900) — 主背景
|
||||
卡片: #1e293b (slate-800) — 面板/卡片背景
|
||||
边框: #334155 (slate-700) — 微弱的组件边框
|
||||
文字: #e2e8f0 (slate-200) — 主文字
|
||||
次要: #94a3b8 (slate-400) — 辅助文字/标签
|
||||
高亮: #6366f1 (indigo-500) — 主要操作/选中状态
|
||||
成功: #22c55e (green-500) — 完成/入库操作
|
||||
警告: #f59e0b (amber-500) — 需注意的异常
|
||||
错误: #ef4444 (red-500) — 失败状态
|
||||
```
|
||||
|
||||
### 异常类型标签色
|
||||
|
||||
```
|
||||
元数据缺失: amber (amber-700 背景, amber-400 文字)
|
||||
匹配失败: red (red-900 背景, red-400 文字)
|
||||
匹配分过低: amber
|
||||
转码失败: red
|
||||
文件重复: slate
|
||||
入库失败: red
|
||||
```
|
||||
|
||||
### 排版
|
||||
|
||||
- 字体: 继承项目现有 Tailwind 配置(系统字体栈)
|
||||
- 步骤标题: text-lg font-semibold
|
||||
- 歌曲名称: text-sm font-medium
|
||||
- 元数据标签: text-xs text-slate-400
|
||||
- 按钮: text-sm font-medium rounded-lg
|
||||
|
||||
## 页面布局
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ 🏠 异常中心 [高级视图] │
|
||||
├──────────────────────────────────────────────────┤
|
||||
│ ①选择歌曲 ── ②试听确认 ── ③推荐匹配 ── ④手动编│
|
||||
│ 辑 ── ⑤入库确认 │
|
||||
├────────────┬─────────────────────────────────────┤
|
||||
│ 队列 (12) │ 🎵 01 - 夜曲.mp3 │
|
||||
│ │ ┌─────────────────────────────────┐│
|
||||
│ ▸ 01-夜曲 │ │ 匹配候选: ││
|
||||
│ track_02 │ │ ▸ 夜曲 / 周杰伦 · 十一月的萧邦 ││
|
||||
│ unknown │ │ 95% · MusicBrainz ││
|
||||
│ │ │ Nocturne / Jay Chou ││
|
||||
│ │ │ 78% · Spotify ││
|
||||
│ │ └─────────────────────────────────┘│
|
||||
│ │ [确认选择] [手动编辑] [跳过 →] │
|
||||
├────────────┴─────────────────────────────────────┤
|
||||
│ ⚡ 修复任务: 3/12 完成 · running │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 组件架构
|
||||
|
||||
```
|
||||
src/
|
||||
├── pages/
|
||||
│ └── ExceptionPage.jsx # 页面容器(路由入口 + 顶层状态协调)
|
||||
├── components/exceptions/
|
||||
│ ├── ExceptionStatsBar.jsx # 顶部统计概览条
|
||||
│ ├── ExceptionTypeNav.jsx # 异常类型筛选标签
|
||||
│ ├── ExceptionWizard.jsx # 5步向导主控制器
|
||||
│ ├── ExceptionListView.jsx # 高级列表视图(备用,对应高级模式)
|
||||
│ ├── steps/
|
||||
│ │ ├── StepSelect.jsx # 步骤1:选择歌曲
|
||||
│ │ ├── StepListen.jsx # 步骤2:试听确认
|
||||
│ │ ├── StepMatch.jsx # 步骤3:推荐匹配
|
||||
│ │ ├── StepEdit.jsx # 步骤4:手动编辑
|
||||
│ │ └── StepConfirm.jsx # 步骤5:入库确认
|
||||
│ ├── RepairTaskPanel.jsx # 修复任务实时状态面板
|
||||
│ └── ActionPreviewModal.jsx # 操作预览/确认弹窗
|
||||
├── hooks/
|
||||
│ ├── useExceptionSummary.js # 异常概览数据获取
|
||||
│ ├── useExceptionList.js # 异常列表(分页/筛选/队列)
|
||||
│ ├── useExceptionDetail.js # 单条异常详情
|
||||
│ ├── useRepairTask.js # WebSocket 修复任务跟踪
|
||||
│ └── useWizardState.js # 向导步骤状态管理
|
||||
```
|
||||
|
||||
### 组件职责
|
||||
|
||||
**ExceptionPage** — 页面容器,轻量级
|
||||
- 仅持有顶层路由和视图模式切换(wizard / advanced)
|
||||
- 通过 props 传递共享状态
|
||||
- 不包含任何步骤逻辑或 UI 细节
|
||||
|
||||
**ExceptionStatsBar** — 顶部统计概览
|
||||
- Props: summary (总数/分类统计)
|
||||
- 显示:开放中 / 处理中 / 已解决 三个统计卡片
|
||||
- 深色主题:渐变靛蓝背景卡片
|
||||
|
||||
**ExceptionTypeNav** — 类型筛选标签
|
||||
- Props: activeFilter, onFilterChange, counts
|
||||
- 水平滚动的胶囊标签,显示各类型数量
|
||||
- 深色主题:选中靛蓝填充,未选中 slate 边框
|
||||
|
||||
**ExceptionWizard** — 5步向导控制器
|
||||
- 管理 5 个步骤的切换(由 useWizardState hook 驱动)
|
||||
- 渲染当前步骤组件,传递必要的 props
|
||||
- 步骤条 UI:圆形步骤编号 + 连接线,已完成绿色/当前靛蓝/待完成 slate
|
||||
|
||||
**步骤组件 (StepSelect, StepListen, StepMatch, StepEdit, StepConfirm)**
|
||||
- 每个步骤是独立组件
|
||||
- 通过 props 接收:detailRecord, action, params, previewState
|
||||
- 通过回调通知:onActionChange, onParamsChange, onPreview, onExecute
|
||||
|
||||
**RepairTaskPanel** — 修复任务面板
|
||||
- 显示当前修复任务的进度
|
||||
- WebSocket 实时日志流
|
||||
- 可折叠设计
|
||||
|
||||
**ActionPreviewModal** — 操作预览弹窗
|
||||
- 显示批量操作的预览结果
|
||||
- 风险等级标识(低/中/高)
|
||||
- 确认/取消操作
|
||||
|
||||
### 自定义 Hooks
|
||||
|
||||
**useExceptionSummary**
|
||||
- 封装 fetchExceptionSummary API 调用
|
||||
- 返回 { summary, error, refresh }
|
||||
|
||||
**useExceptionList**
|
||||
- 封装 fetchExceptionItems API(分页/筛选/队列模式)
|
||||
- 管理 items, total, page, filter 状态
|
||||
- 返回 { items, total, page, filter, setFilter, setPage, refresh, loading, error }
|
||||
|
||||
**useExceptionDetail**
|
||||
- 封装 fetchExceptionItem API
|
||||
- 由 selectedExceptionId 驱动自动获取
|
||||
- 返回 { detail, loading, error, refresh }
|
||||
|
||||
**useRepairTask**
|
||||
- 封装 WebSocket 连接 + repair task 状态
|
||||
- 管理 repairTask, repairLogs
|
||||
- 自动处理重连
|
||||
|
||||
**useWizardState**
|
||||
- 管理:wizardStep, selectedAction, actionParams, previewState, executeError
|
||||
- 步骤切换逻辑:inferDefaultAction, buildDefaultParams
|
||||
- 返回 { wizardStep, setWizardStep, selectedAction, setSelectedAction, ... }
|
||||
|
||||
### 数据流
|
||||
|
||||
```
|
||||
ExceptionPage (顶层)
|
||||
│
|
||||
├─ useExceptionSummary() ──→ ExceptionStatsBar
|
||||
├─ useExceptionList() ──→ 左侧歌曲队列
|
||||
├─ useExceptionDetail() ──→ 当前选中歌曲详情
|
||||
├─ useWizardState() ──→ ExceptionWizard → 5 步骤组件
|
||||
└─ useRepairTask() ──→ RepairTaskPanel
|
||||
```
|
||||
|
||||
数据通过 props 向下流动,回调通过 props 向上通知。不使用 Context(避免不必要的心智负担)。
|
||||
|
||||
## 交互优化
|
||||
|
||||
### 平滑过渡
|
||||
- 步骤切换:CSS transition 淡入淡出(150ms)
|
||||
- 列表项选择:背景色过渡(150ms)
|
||||
- 弹窗:fade + scale 动画(200ms)
|
||||
|
||||
### 微交互
|
||||
- 悬停状态:列表项 hover 时背景微亮(slate-700)
|
||||
- 操作按钮:hover 时颜色加深 10%
|
||||
- 统计卡片:hover 时轻微上浮 (translateY -2px)
|
||||
- 加载状态:骨架屏替代纯 spinner
|
||||
|
||||
### 键盘导航
|
||||
- ← → 键切换向导步骤
|
||||
- ↑ ↓ 键在歌曲队列中导航
|
||||
- Enter 确认当前操作
|
||||
- Escape 关闭弹窗
|
||||
|
||||
## 5步向导流程(保持现有逻辑)
|
||||
|
||||
| 步骤 | 名称 | 功能 | 可操作 |
|
||||
|------|------|------|--------|
|
||||
| 1 | 选择歌曲 | 从异常队列选择歌曲 | 点击选中 |
|
||||
| 2 | 试听确认 | 播放音频确认文件正确 | 播放/暂停 |
|
||||
| 3 | 推荐匹配 | 查看元数据候选列表 | 选择候选/确认 |
|
||||
| 4 | 手动编辑 | 编辑元数据字段 | 修改字段值 |
|
||||
| 5 | 入库确认 | 确认目标路径并入库 | 预览/执行 |
|
||||
|
||||
步骤可自由前进后退(已确认的操作不丢失)。
|
||||
|
||||
## 兼容性
|
||||
|
||||
### 保留功能
|
||||
- 高级列表视图模式(通过右上角切换入口)
|
||||
- 批量操作(在高级列表模式下)
|
||||
- 所有现有 API 端点不变
|
||||
- 所有现有异常类型和操作动作
|
||||
|
||||
### 浏览器支持
|
||||
- Chrome, Firefox, Safari, Edge 最近 2 个主版本
|
||||
- 不需要 IE 支持
|
||||
|
||||
## 非目标(不在本次范围)
|
||||
|
||||
- 后端 API 修改
|
||||
- 新增异常类型
|
||||
- 新增修复操作类型
|
||||
- 国际化(i18n)
|
||||
- 移动端适配(保持桌面端优先,响应式布局兜底)
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. **Phase 1**: 提取自定义 hooks(纯逻辑层,不改变 UI)
|
||||
2. **Phase 2**: 拆分步骤组件(保持原有 5 步逻辑)
|
||||
3. **Phase 3**: 重构 ExceptionPage 容器(集成 hooks + 组件)
|
||||
4. **Phase 4**: 应用深色专业主题样式
|
||||
5. **Phase 5**: 添加过渡动画和微交互
|
||||
6. **Phase 6**: 更新高级列表视图样式
|
||||
7. **Phase 7**: 测试与验证
|
||||
|
||||
每个 Phase 完成后进行功能验证,确保不引入回归。
|
||||
@@ -0,0 +1,157 @@
|
||||
# WorkbenchPage 重构 — 设计规格
|
||||
|
||||
> 创建日期: 2026-05-07
|
||||
> 状态: 设计中
|
||||
|
||||
## 概述
|
||||
|
||||
将 WorkbenchPage.jsx 从 ~800 行单体组件重构为 5 个聚焦组件 + 2 个自定义 hooks 的模块化架构,继承深色专业主题风格。
|
||||
|
||||
### 核心痛点
|
||||
|
||||
- 所有逻辑在一个文件(任务加载、WebSocket、配置展示、进度可视化、5阶段统计、文件列表、日志流)
|
||||
- 事件处理爆炸(handleStreamEvent 处理 10+ 种 WebSocket 事件类型)
|
||||
- 统计展示冗余(5 个阶段 40+ 个 StatCard 重复渲染)
|
||||
- 配置和控制耦合(目录配置展示和任务启动/监控逻辑混在一起)
|
||||
|
||||
## 设计决策
|
||||
|
||||
| 维度 | 决策 |
|
||||
|------|------|
|
||||
| 视觉风格 | 继承深色专业主题(indigo/slate,与异常中心一致) |
|
||||
| 组件拆分 | 6 个功能组件 + 2 个自定义 hooks |
|
||||
| 事件处理 | `useTaskStream` hook 封装 WebSocket 事件处理 |
|
||||
| 统计面板 | `StageStatsPanel` 通过 stage/stats props 消除 40+ 重复 StatCard |
|
||||
| 后端改动 | 无需改动 |
|
||||
|
||||
## 组件架构
|
||||
|
||||
```
|
||||
src/
|
||||
├── pages/
|
||||
│ └── WorkbenchPage.jsx # ~120行容器(从~800行精简)
|
||||
├── components/workbench/
|
||||
│ ├── TaskControlPanel.jsx # 目录配置展示 + 启动/重试按钮
|
||||
│ ├── TaskProgressBar.jsx # 5阶段进度条(Scan→Preprocess→Match→Dedupe→Organize)
|
||||
│ ├── StageStatsPanel.jsx # 5阶段统计面板(消除40+重复StatCard)
|
||||
│ ├── TaskInfoPanel.jsx # 当前任务基本信息
|
||||
│ ├── TaskFileList.jsx # 任务文件列表
|
||||
│ └── TaskLogStream.jsx # 实时日志流
|
||||
├── hooks/
|
||||
│ ├── useTaskStream.js # WebSocket 连接 + 10+ 事件类型处理
|
||||
│ └── useTaskRunner.js # 任务启动/状态管理
|
||||
└── utils/
|
||||
└── workbench.js # 阶段定义、空统计模板等共享常量
|
||||
```
|
||||
|
||||
### 组件职责
|
||||
|
||||
**WorkbenchPage** — 页面容器(~120行)
|
||||
- 通过 useTaskStream 和 useTaskRunner 管理顶层状态
|
||||
- 将 task/items/logs/config 通过 props 分发给子组件
|
||||
- 不包含任何渲染细节
|
||||
|
||||
**TaskControlPanel** — 任务控制面板
|
||||
- Props: config, canStart, isRunning, isCompleted, isFailed, onStart, isStarting, errorMessage
|
||||
- 显示三个目录配置(输入/输出/回收站)
|
||||
- 根据状态显示不同的启动按钮和提示
|
||||
|
||||
**TaskProgressBar** — 5阶段进度条
|
||||
- Props: task, isRunning, isCompleted, isFailed, progressWidth, progressLabel, latestFile
|
||||
- 5个圆形步骤节点 + 连接线 + 进度条
|
||||
- 状态颜色:running=emerald/active=emerald/completed=emerald/failed=rose
|
||||
|
||||
**StageStatsPanel** — 阶段统计面板
|
||||
- Props: stageName, stats, stageConfig
|
||||
- 通过 STAGE_STATS_CONFIG 自动渲染该阶段的所有统计卡片
|
||||
- 消除原来 5 个阶段的重复 StatCard 排列
|
||||
|
||||
**TaskInfoPanel** — 任务信息面板
|
||||
- Props: task, latestLogId, hasMoreLogs
|
||||
- 显示任务状态、当前阶段、开始/完成时间等基本信息
|
||||
|
||||
**TaskFileList** — 任务文件列表
|
||||
- Props: items, isLoading
|
||||
- 文件项展示:路径、封面/歌词状态、各阶段状态徽章
|
||||
|
||||
**TaskLogStream** — 实时日志流
|
||||
- Props: logs, logsEndRef
|
||||
- 分色日志行(error=rose/success=emerald/warning=amber/info=blue)
|
||||
|
||||
### 自定义 Hooks
|
||||
|
||||
**useTaskStream**
|
||||
- 封装 WebSocket 连接(createTaskStream)
|
||||
- 处理 10+ 事件类型:task.snapshot, task.started, stage.started, *.progress, stage.completed, task.completed, task.failed, log.appended
|
||||
- 管理 task, items, logs 状态
|
||||
- 返回 { task, items, logs, latestFile, hasMoreLogs, latestLogId, loadCurrentTask, startTask, ... }
|
||||
|
||||
**useTaskRunner**
|
||||
- 封装任务启动/停止逻辑
|
||||
- runTask API 调用 + 409 冲突处理(已有运行中任务)
|
||||
- 返回 { isStarting, errorMessage, handleStart }
|
||||
|
||||
### 数据流
|
||||
|
||||
```
|
||||
WorkbenchPage (顶层 ~120行)
|
||||
│
|
||||
├─ useTaskStream() ──→ WebSocket → task/items/logs 状态
|
||||
├─ useTaskRunner() ──→ 启动/停止逻辑
|
||||
│
|
||||
├─ TaskControlPanel ← config, canStart, isRunning, isStarting
|
||||
├─ TaskProgressBar ← task, stageIndex, progressWidth
|
||||
├─ StageStatsPanel ×5 ← task.stats.{scan,preprocess,match,dedupe,organize}
|
||||
├─ TaskInfoPanel ← task 基本信息
|
||||
├─ TaskFileList ← items
|
||||
└─ TaskLogStream ← logs
|
||||
```
|
||||
|
||||
## 阶段统计配置(消除重复)
|
||||
|
||||
```javascript
|
||||
// utils/workbench.js
|
||||
export const STAGE_STATS_CONFIG = {
|
||||
scan: [
|
||||
{ key: 'total_found', label: '候选音频', color: 'white' },
|
||||
{ key: 'queued', label: '成功入队', color: 'emerald' },
|
||||
{ key: 'skipped_locked', label: '最近写入跳过', color: 'amber' },
|
||||
{ key: 'skipped_invalid', label: '无效文件', color: 'rose', error: true },
|
||||
// { key: 'ignored_non_audio', label: '静默忽略非音频', fullWidth: true }
|
||||
],
|
||||
preprocess: [
|
||||
{ key: 'input_items', label: '输入项目', color: 'white' },
|
||||
{ key: 'output_items', label: '有效输出', color: 'emerald' },
|
||||
// ... 其余字段
|
||||
],
|
||||
match: [ /* ... */ ],
|
||||
dedupe: [ /* ... */ ],
|
||||
organize: [ /* ... */ ]
|
||||
};
|
||||
```
|
||||
|
||||
StageStatsPanel 根据 stageName 查找配置,自动生成 `<StatCard>` 列表。
|
||||
|
||||
## 兼容性
|
||||
|
||||
- 保留所有现有功能不变
|
||||
- props 接口与现有 constants/STAGES 定义兼容
|
||||
- WebSocket 事件处理逻辑不变,仅位置改变
|
||||
- MissingTagsInlinePanel 保持不变
|
||||
|
||||
## 非目标(不在本次范围)
|
||||
|
||||
- 后端 API 修改
|
||||
- 新增任务类型
|
||||
- 配置表单重构(SettingsPage 独立优化)
|
||||
- MissingTagsInlinePanel 整合(后续单独优化)
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. **Phase 1**: 提取共享常量到 `utils/workbench.js`
|
||||
2. **Phase 2**: 创建 `useTaskStream` hook(最复杂,WebSocket 事件处理)
|
||||
3. **Phase 3**: 创建 `useTaskRunner` hook(任务启动逻辑)
|
||||
4. **Phase 4**: 创建 StageStatsPanel 组件(消除最大重复)
|
||||
5. **Phase 5**: 创建其余 5 个展示组件
|
||||
6. **Phase 6**: 重写 WorkbenchPage 为轻量容器
|
||||
7. **Phase 7**: 构建验证
|
||||
@@ -0,0 +1,139 @@
|
||||
# SettingsPage 重构 — 设计规格
|
||||
|
||||
> 创建日期: 2026-05-08
|
||||
> 状态: 设计中
|
||||
|
||||
## 概述
|
||||
|
||||
将 SettingsPage.jsx 从 ~700 行单体组件重构为 8 个聚焦组件 + 1 个自定义 hook 的模块化架构,继承深色专业主题风格。
|
||||
|
||||
### 核心痛点
|
||||
|
||||
- 所有配置节(路径/调度/通知/元数据服务)内联渲染
|
||||
- 导出/导入对话框逻辑(~150 行)耦合在页面组件中
|
||||
- 调度 cron 解析逻辑(~140 行工具函数)占据文件头部
|
||||
- Toast 通知、元数据连通性检测、网络状态管理混杂在一处
|
||||
|
||||
## 设计决策
|
||||
|
||||
| 维度 | 决策 |
|
||||
|------|------|
|
||||
| 视觉风格 | 继承深色专业主题(indigo/slate) |
|
||||
| 组件拆分 | 5 个配置节组件 + 2 个对话框组件 + 1 个服务状态组件 |
|
||||
| 状态管理 | `useSettingsForm` hook 封装 localConfig、调度更新逻辑 |
|
||||
| 后端改动 | 无需改动 |
|
||||
|
||||
## 组件架构
|
||||
|
||||
```
|
||||
src/
|
||||
├── pages/
|
||||
│ └── SettingsPage.jsx # ~100行容器
|
||||
├── components/settings/
|
||||
│ ├── CorePathsSection.jsx # 核心目录配置(输入/输出/回收站)
|
||||
│ ├── ScheduleSection.jsx # 定时调度配置(每日/每周/Cron)
|
||||
│ ├── AdvancedStrategySection.jsx # 高级策略(元数据回退、素材下载等)
|
||||
│ ├── NotificationSection.jsx # 通知配置(钉钉/Telegram/邮件)
|
||||
│ ├── MetadataServicesSection.jsx # 元数据服务配置(8个provider)
|
||||
│ ├── ConfigExportDialog.jsx # 配置导出对话框
|
||||
│ ├── ConfigImportDialog.jsx # 配置导入对话框
|
||||
│ └── ServiceStatusBadge.jsx # 服务连通性状态徽章
|
||||
├── hooks/
|
||||
│ └── useSettingsForm.js # 配置表单状态 + 调度更新 + 导出/导入
|
||||
└── utils/
|
||||
└── schedule.js # 调度工具函数(从 SettingsPage 头部抽取)
|
||||
```
|
||||
|
||||
### 组件职责
|
||||
|
||||
**SettingsPage** — 页面容器(~100行)
|
||||
- 通过 useSettingsForm hook 管理配置状态
|
||||
- 渲染 5 个配置节组件 + 2 个对话框
|
||||
- 不包含任何配置渲染细节
|
||||
|
||||
**CorePathsSection** — 核心目录配置
|
||||
- Props: input, output, trash, onUpdate
|
||||
- 三个文本输入字段(输入目录/输出目录/回收站)
|
||||
|
||||
**ScheduleSection** — 定时调度配置
|
||||
- Props: schedule, onUpdate
|
||||
- 三种调度类型选择(每日/每周/Cron)+ 时间选择 + 星期选择
|
||||
|
||||
**AdvancedStrategySection** — 高级策略配置
|
||||
- Props: advancedStrategy, onUpdate
|
||||
- 元数据回退、素材下载等开关
|
||||
|
||||
**NotificationSection** — 通知配置
|
||||
- Props: notifications, onUpdate
|
||||
- 钉钉 Webhook/Secret、Telegram Bot Token/ChatID、Email SMTP 配置
|
||||
|
||||
**MetadataServicesSection** — 元数据服务配置
|
||||
- Props: metadata, netStatus, onUpdate
|
||||
- 8 个元数据 provider 的 URL/Key 配置 + 连通性状态徽章
|
||||
|
||||
**ConfigExportDialog** — 导出对话框
|
||||
- Props: isOpen, isExporting, password, passwordConfirm, onClose, onExport, onPasswordChange
|
||||
- 密码确认 + 导出按钮
|
||||
|
||||
**ConfigImportDialog** — 导入对话框(多阶段:解密密码 → 确认 → 保存)
|
||||
- Props: importDialog state, onClose, onDecrypt, onConfirm
|
||||
- 文件选择 → 密码输入 → 配置预览确认
|
||||
|
||||
**ServiceStatusBadge** — 服务状态徽章
|
||||
- Props: status, latencyMs, message
|
||||
- 探测中/在线/警告/离线/未检测 五种状态
|
||||
|
||||
### 自定义 Hook
|
||||
|
||||
**useSettingsForm**
|
||||
- 封装 localConfig 状态管理
|
||||
- 调度类型/时间/日期/Cron 更新函数
|
||||
- 保存/导出/导入/网络检测逻辑
|
||||
- Toast 通知状态
|
||||
- 返回 { localConfig, netStatus, toast, isSaving, updateField, updateSchedule, handleSave, handleExport, handleImport, ... }
|
||||
|
||||
### 数据流
|
||||
|
||||
```
|
||||
SettingsPage (顶层 ~100行)
|
||||
│
|
||||
├─ useSettingsForm() ──→ localConfig, updateField, updateSchedule, handleSave...
|
||||
│
|
||||
├─ CorePathsSection ← config.input/output/trash
|
||||
├─ ScheduleSection ← config.schedule
|
||||
├─ AdvancedStrategySection ← config.advancedStrategy
|
||||
├─ NotificationSection ← config.notifications
|
||||
├─ MetadataServicesSection ← config.metadata + netStatus
|
||||
├─ ConfigExportDialog ← exportState, onClose, onExport
|
||||
└─ ConfigImportDialog ← importState, onDecrypt, onConfirm
|
||||
```
|
||||
|
||||
### 工具函数抽取
|
||||
|
||||
`scheduler.js` 从 SettingsPage 头部(1-142 行)抽取:
|
||||
- `normalizeSchedule`, `getScheduleSummary`
|
||||
- `buildDailyCron`, `buildWeeklyCron`
|
||||
- `formatTimeFromCron`, `padCronSegment`
|
||||
- `formatBackupTimestamp`
|
||||
|
||||
## 兼容性
|
||||
|
||||
- 保留所有现有功能不变
|
||||
- `saveConfig` API 调用格式不变
|
||||
- `fetchMetadataStatus` API 调用不变
|
||||
- `handleSave` 同时更新父组件 config 和 taskState
|
||||
|
||||
## 非目标(不在本次范围)
|
||||
|
||||
- 后端 API 修改
|
||||
- 新增配置项
|
||||
- LibraryPage / HistoryPage / MissingTagsInlinePanel 优化(后续单独处理)
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. **Phase 1**: 抽取调度工具函数到 `utils/schedule.js`
|
||||
2. **Phase 2**: 创建 `useSettingsForm` hook
|
||||
3. **Phase 3**: 创建 5 个配置节组件
|
||||
4. **Phase 4**: 创建 2 个对话框组件 + ServiceStatusBadge
|
||||
5. **Phase 5**: 重写 SettingsPage 为轻量容器
|
||||
6. **Phase 6**: 构建验证
|
||||
Reference in New Issue
Block a user