feat: 任务列表右键菜单回调 + 主进程下载 + sharp 缩略图 + IPC 精简重构

- 任务右键菜单:实现打开输出目录(inputs/outputs/.cache 结构)、
    复制资源链接、重新编辑、再次生成、拉取结果、重新下载、收藏、删除记录
  - 主进程下载:通过 Electron net 模块绕过 CORS,支持 CDN 媒体文件下载
  - sharp 缩略图:替换 nativeImage,支持 4K/8K+ 大尺寸素材的流式处理
  - IPC 精简:40+ 冗余通道 → 15 个分组通道,移除未使用的 preload 桥接方法
  - 任务存储:新增收藏字段、schema 迁移、task-store 持久化
  - 清理废弃模块:canvas-ipc / updater / request / pricing

refactor: IPC/Preload/Services 模块化拆分 — 单一职责 + 向后兼容

  主要变更:
  - shared/constants/ipc-channels.ts → ipc/ 模块 (base/storage/canvas/updater)
  - electron/preload.ts → preload/ 模块 (base/safe-storage/file-storage/canvas)
  - electron/main/ipc/canvas-ipc.ts → canvas/ 模块 (types/walk/sidecar/mime/thumbnail)
  - electron/main/ipc/storage-ipc.ts → 提取 utils/ (path/download/thumbnail)
  - electron/main/updater.ts → updater/ 模块 (provider/platform-updaters)
  - src/services/request.ts → request/ 模块 (token/interceptors/methods)
  - src/shared/utils/pricing.ts → pricing/ 模块 (types/helpers/format/calculate/fields)
  - src/modules/home/center/views/ModelInputForm.tsx → 提取 utils + DependentFormItem

  架构优化:
  - 所有拆分均保持向后兼容(旧导入路径仍可用)
  - TypeScript 编译通过 ✓
  - 每个模块单一职责,平均 ~130 行
This commit is contained in:
2026-07-03 11:13:36 +08:00
parent 904edecd90
commit 136a17c0bf
69 changed files with 4139 additions and 2713 deletions

View File

@@ -1,95 +1,18 @@
// ============================================================
// IPC 通道名称常量 —— 避免魔法字符串
// IPC 通道名称常量 — 兼容层(已拆分为 ipc/ 子模块)
//
// @deprecated 请使用新的模块化导入:
// import { BIDIRECTIONAL } from '@/shared/constants/ipc';
// import { BIDIRECTIONAL_STORAGE } from '@/shared/constants/ipc/storage';
// ============================================================
/** 主进程 → 渲染进程 */
export const MAIN_TO_RENDERER = {
/** 主进程消息推送 */
MAIN_PROCESS_MESSAGE: 'main-process-message',
/** 主题变更通知 */
THEME_CHANGED: 'theme-changed',
/** 窗口聚焦通知 */
WINDOW_FOCUSED: 'window-focused',
/** 窗口失焦通知 */
WINDOW_BLURRED: 'window-blurred',
/** 画布窗口准备就绪 */
CANVAS_READY: 'canvas:ready',
/** 画布扫描进度 */
CANVAS_SCAN_PROGRESS: 'canvas:scan-progress',
} as const;
/** 渲染进程 → 主进程 */
export const RENDERER_TO_MAIN = {
/** 打开子窗口 */
OPEN_SUB_WINDOW: 'open-sub-window',
/** 关闭子窗口 */
CLOSE_SUB_WINDOW: 'close-sub-window',
/** 设置窗口标题 */
SET_WINDOW_TITLE: 'set-window-title',
/** 获取平台信息 */
GET_PLATFORM_INFO: 'get-platform-info',
/** 最小化窗口 */
MINIMIZE_WINDOW: 'minimize-window',
/** 最大化/还原窗口 */
TOGGLE_MAXIMIZE: 'toggle-maximize',
/** 关闭窗口 */
CLOSE_WINDOW: 'close-window',
/** 渲染进程日志上报 */
LOG_MESSAGE: 'log-message',
/** 画布:打开无限画布窗口 */
OPEN_CANVAS_WINDOW: 'canvas:open-window',
} as const;
/** 双向通信通道 */
export const BIDIRECTIONAL = {
/** 读取应用配置 */
READ_CONFIG: 'read-config',
/** 写入应用配置 */
WRITE_CONFIG: 'write-config',
/** 文件对话框 */
FILE_DIALOG: 'file-dialog',
/** safeStorage 加密(明文 → Base64 密文) */
SAFESTORAGE_ENCRYPT: 'safe-storage:encrypt',
/** safeStorage 解密Base64 密文 → 明文) */
SAFESTORAGE_DECRYPT: 'safe-storage:decrypt',
/** 文件写入Blob Buffer → 磁盘) */
FILE_WRITE: 'storage:file-write',
/** 文件读取(磁盘 → Base64 */
FILE_READ: 'storage:file-read',
/** 文件删除 */
FILE_DELETE: 'storage:file-delete',
/** 创建目录(递归) */
MAKE_DIR: 'storage:make-dir',
/** 在文件管理器中显示文件 */
SHOW_ITEM_IN_FOLDER: 'storage:show-item-in-folder',
/** 获取应用数据目录路径 */
GET_DATA_DIR: 'storage:get-data-dir',
/** 获取文件大小 */
FILE_SIZE: 'storage:file-size',
/** 文件/目录是否存在 */
FILE_EXISTS: 'storage:file-exists',
/** 画布:扫描目录 */
CANVAS_SCAN_DIRECTORY: 'canvas:scan-directory',
/** 画布:扫描项目(接收 projectPath主进程内部完成 buildScanRoots + walkDirectory */
CANVAS_SCAN_PROJECT: 'canvas:scan-project',
/** 画布:读取 sidecar 元数据 */
CANVAS_READ_SIDECAR: 'canvas:read-sidecar',
/** 画布:写入 sidecar 元数据 */
CANVAS_WRITE_SIDECAR: 'canvas:write-sidecar',
/** 画布:生成缩略图 */
CANVAS_GENERATE_THUMBNAIL: 'canvas:generate-thumbnail',
/** 画布:复制文件(导入) */
CANVAS_COPY_FILE: 'canvas:copy-file',
/** 画布:获取原生图片尺寸 */
CANVAS_GET_IMAGE_SIZE: 'canvas:get-image-size',
/** 画布:列出目录下的子文件夹(非递归,排除隐藏) */
CANVAS_LIST_SUBDIRS: 'canvas:list-subdirs',
/** 画布:扫描阶段文件(单个 episode/shot/stage 组合) */
CANVAS_SCAN_STAGE_FILES: 'canvas:scan-stage-files',
/** 画布:扫描资产文件(深度递归扫描 assets/ 目录) */
CANVAS_SCAN_ASSET_FILES: 'canvas:scan-asset-files',
/** 画布:创建目录 */
CANVAS_CREATE_DIRECTORY: 'canvas:create-directory',
/** 画布:启动原生文件拖拽(拖放媒体文件到外部应用) */
CANVAS_START_DRAG: 'canvas:start-drag',
} as const;
export {
MAIN_TO_RENDERER,
RENDERER_TO_MAIN,
BIDIRECTIONAL,
MAIN_TO_RENDERER_CANVAS,
RENDERER_TO_MAIN_CANVAS,
BIDIRECTIONAL_CANVAS,
MAIN_TO_RENDERER_UPDATER,
RENDERER_TO_MAIN_UPDATER,
} from './ipc';

View File

@@ -0,0 +1,45 @@
// ============================================================
// IPC 通道常量 — 基础通道(窗口、日志、主题等)
// ============================================================
/** 主进程 → 渲染进程 */
export const MAIN_TO_RENDERER = {
/** 主进程消息推送 */
MAIN_PROCESS_MESSAGE: 'main-process-message',
/** 主题变更通知 */
THEME_CHANGED: 'theme-changed',
/** 窗口聚焦通知 */
WINDOW_FOCUSED: 'window-focused',
/** 窗口失焦通知 */
WINDOW_BLURRED: 'window-blurred',
} as const;
/** 渲染进程 → 主进程 */
export const RENDERER_TO_MAIN = {
/** 打开子窗口 */
OPEN_SUB_WINDOW: 'open-sub-window',
/** 关闭子窗口 */
CLOSE_SUB_WINDOW: 'close-sub-window',
/** 设置窗口标题 */
SET_WINDOW_TITLE: 'set-window-title',
/** 获取平台信息 */
GET_PLATFORM_INFO: 'get-platform-info',
/** 最小化窗口 */
MINIMIZE_WINDOW: 'minimize-window',
/** 最大化/还原窗口 */
TOGGLE_MAXIMIZE: 'toggle-maximize',
/** 关闭窗口 */
CLOSE_WINDOW: 'close-window',
/** 渲染进程日志上报 */
LOG_MESSAGE: 'log-message',
} as const;
/** 双向通信通道 — 应用配置 */
export const BIDIRECTIONAL_CONFIG = {
/** 读取应用配置 */
READ_CONFIG: 'read-config',
/** 写入应用配置 */
WRITE_CONFIG: 'write-config',
/** 文件对话框 */
FILE_DIALOG: 'file-dialog',
} as const;

View File

@@ -0,0 +1,45 @@
// ============================================================
// IPC 通道常量 — 无限画布相关通道
// ============================================================
/** 主进程 → 渲染进程 — 画布 */
export const MAIN_TO_RENDERER_CANVAS = {
/** 画布窗口准备就绪 */
CANVAS_READY: 'canvas:ready',
/** 画布扫描进度 */
CANVAS_SCAN_PROGRESS: 'canvas:scan-progress',
} as const;
/** 渲染进程 → 主进程 — 画布 */
export const RENDERER_TO_MAIN_CANVAS = {
/** 画布:打开无限画布窗口 */
OPEN_CANVAS_WINDOW: 'canvas:open-window',
} as const;
/** 双向通信通道 — 画布 */
export const BIDIRECTIONAL_CANVAS = {
/** 画布:扫描目录 */
CANVAS_SCAN_DIRECTORY: 'canvas:scan-directory',
/** 画布:扫描项目(接收 projectPath主进程内部完成 buildScanRoots + walkDirectory */
CANVAS_SCAN_PROJECT: 'canvas:scan-project',
/** 画布:读取 sidecar 元数据 */
CANVAS_READ_SIDECAR: 'canvas:read-sidecar',
/** 画布:写入 sidecar 元数据 */
CANVAS_WRITE_SIDECAR: 'canvas:write-sidecar',
/** 画布:生成缩略图 */
CANVAS_GENERATE_THUMBNAIL: 'canvas:generate-thumbnail',
/** 画布:复制文件(导入) */
CANVAS_COPY_FILE: 'canvas:copy-file',
/** 画布:获取原生图片尺寸 */
CANVAS_GET_IMAGE_SIZE: 'canvas:get-image-size',
/** 画布:列出目录下的子文件夹(非递归,排除隐藏) */
CANVAS_LIST_SUBDIRS: 'canvas:list-subdirs',
/** 画布:扫描阶段文件(单个 episode/shot/stage 组合) */
CANVAS_SCAN_STAGE_FILES: 'canvas:scan-stage-files',
/** 画布:扫描资产文件(深度递归扫描 assets/ 目录) */
CANVAS_SCAN_ASSET_FILES: 'canvas:scan-asset-files',
/** 画布:创建目录 */
CANVAS_CREATE_DIRECTORY: 'canvas:create-directory',
/** 画布:启动原生文件拖拽(拖放媒体文件到外部应用) */
CANVAS_START_DRAG: 'canvas:start-drag',
} as const;

View File

@@ -0,0 +1,25 @@
// ============================================================
// IPC 通道常量 — 汇总导出
//
// 使用方式:
// import { MAIN_TO_RENDERER, BIDIRECTIONAL } from '@/shared/constants/ipc';
// import { BIDIRECTIONAL_STORAGE } from '@/shared/constants/ipc/storage';
// ============================================================
export { MAIN_TO_RENDERER, RENDERER_TO_MAIN, BIDIRECTIONAL_CONFIG } from './base';
export { BIDIRECTIONAL_STORAGE } from './storage';
export { MAIN_TO_RENDERER_CANVAS, RENDERER_TO_MAIN_CANVAS, BIDIRECTIONAL_CANVAS } from './canvas';
export { MAIN_TO_RENDERER_UPDATER, RENDERER_TO_MAIN_UPDATER } from './updater';
// ---------- 兼容性汇总(向后兼容) ----------
import { BIDIRECTIONAL_CONFIG } from './base';
import { BIDIRECTIONAL_STORAGE } from './storage';
import { BIDIRECTIONAL_CANVAS } from './canvas';
/** @deprecated 请使用按功能域拆分的导出 */
export const BIDIRECTIONAL = {
...BIDIRECTIONAL_CONFIG,
...BIDIRECTIONAL_STORAGE,
...BIDIRECTIONAL_CANVAS,
} as const;

View File

@@ -0,0 +1,37 @@
// ============================================================
// IPC 通道常量 — 存储相关通道
// ============================================================
/** 双向通信通道 — 文件存储 */
export const BIDIRECTIONAL_STORAGE = {
/** safeStorage 加密(明文 → Base64 密文) */
SAFESTORAGE_ENCRYPT: 'safe-storage:encrypt',
/** safeStorage 解密Base64 密文 → 明文) */
SAFESTORAGE_DECRYPT: 'safe-storage:decrypt',
/** 文件写入Blob Buffer → 磁盘) */
FILE_WRITE: 'storage:file-write',
/** 文件读取(磁盘 → Base64 */
FILE_READ: 'storage:file-read',
/** 文件删除 */
FILE_DELETE: 'storage:file-delete',
/** 创建目录(递归) */
MAKE_DIR: 'storage:make-dir',
/** 在文件管理器中显示文件 */
SHOW_ITEM_IN_FOLDER: 'storage:show-item-in-folder',
/** 获取应用数据目录路径 */
GET_DATA_DIR: 'storage:get-data-dir',
/** 获取文件大小 */
FILE_SIZE: 'storage:file-size',
/** 文件/目录是否存在 */
FILE_EXISTS: 'storage:file-exists',
/** 绝对路径文件写入(绕过 heixiu-data 沙箱,用于用户自定义输出目录) */
FILE_WRITE_ABSOLUTE: 'storage:file-write-absolute',
/** 绝对路径目录创建(绕过 heixiu-data 沙箱) */
MAKE_DIR_ABSOLUTE: 'storage:make-dir-absolute',
/** 主进程下载文件到绝对路径(绕过浏览器 CORS 限制) */
DOWNLOAD_TO_PATH: 'storage:download-to-path',
/** 获取系统下载目录路径 */
GET_DOWNLOADS_PATH: 'storage:get-downloads-path',
/** 生成图片缩略图(读取原图 → 缩放 → 写入目标路径) */
GENERATE_THUMBNAIL: 'storage:generate-thumbnail',
} as const;

View File

@@ -0,0 +1,27 @@
// ============================================================
// IPC 通道常量 — 自动更新相关通道
// ============================================================
/** 主进程 → 渲染进程 — 更新 */
export const MAIN_TO_RENDERER_UPDATER = {
/** 发现新版本 */
UPDATE_AVAILABLE: 'update-available',
/** 下载进度 */
UPDATE_PROGRESS: 'update-progress',
/** 更新已下载完成 */
UPDATE_DOWNLOADED: 'update-downloaded',
/** 更新出错 */
UPDATE_ERROR: 'update-error',
/** 当前已是最新版本 */
UPDATE_NOT_AVAILABLE: 'update-not-available',
} as const;
/** 渲染进程 → 主进程 — 更新 */
export const RENDERER_TO_MAIN_UPDATER = {
/** 安装更新 */
INSTALL_UPDATE: 'install-update',
/** 检查更新 */
CHECK_FOR_UPDATE: 'check-for-update',
/** 下载更新 */
DOWNLOAD_UPDATE: 'download-update',
} as const;