基于 Electron + Vite + Vue 3 的 Windows 平台本地 AI 绘画模型管理软件,单文件便携 EXE,开箱即用。
- 扫描与自动分类:递归扫描
.safetensors/.ckpt/.pt/.pth/.bin,按名称关键词自动分类为 Checkpoint / TextEncoders / VAE / LoRA,其余归入「其他模型」;支持二级分类标签、LoRA 标签(角色/风格/概念等)与 Checkpoint 基底模型标注;进度展示、随时取消、可排除目录 - 多模型库:保存多个模型根目录,侧栏一键切换;每个库的元数据与封面相互独立;切换时优先读取库内本地索引秒开列表,再后台校验磁盘结果;索引随局部扫描/删除增量维护,不再等待下一次全量扫描才更新
- 跨库移动/复制:把模型(含标注、封面、同名 sidecar)在多个已保存库之间整体迁移——保持库内相对路径镜像,元数据键与封面引用零重写直接生效;移动模式成功后清理源(同盘瞬时 rename,跨盘自动回退复制),目标已有同名文件跳过不覆盖,目标库存在未同步日志时拒绝迁移防止标注回退
- 目录监控:可选开启变更自动重扫——轮询快照比对(条目增删/重命名)+ 低频内容校验(同名覆盖写入),防抖合并后变更子树走局部增量扫描就地合并,不误触发关联写入
- 文件管理:重命名模型文件(扩展名保持不变,同名 sidecar 与标注同步迁移)、删除移入系统回收站并清理关联数据、打开所在文件夹、复制路径/推荐参数、原生右键菜单
- 模型导入:从本机任意位置多选模型文件,或直接从资源管理器拖拽模型文件到窗口(默认复制入台,按住
Shift松开为移动入台),复制或移动入台;同名.txt/.civitai.info/ 预览图一并搬运,重名自动追加编号,不覆盖库内文件;导入前磁盘空间预检,导入中显示全局进度并支持取消(已完成条目保留,未完成目标自动清理),导入后局部扫描即时入列 - 重复检测:后台按体积预筛预热 SHA256(默认只计算大小相同的候选模型,避免全库读盘;可在设置中切换「全库预热/关闭」),渐进就绪无需重扫;内容完全相同的重复模型以角标提示,一键筛选重复项(按哈希分组聚拢),智能保留评分/收藏/最新最优副本、冗余副本批量移入回收站
- 双视图浏览:网格/列表切换,虚拟滚动支撑数千模型流畅浏览;缩略图后台缓存、多预览图悬停轮播;「智能视图」可保存当前搜索/筛选/排序组合,侧栏一键切换
- 搜索与筛选:按名称/备注/触发词搜索,支持中文拼音全拼/首字母(如
yueguang、ygbh)与英文模糊子序列匹配;按分类与收藏筛选,多种排序;搜索框支持结构化语法(与筛选叠加):base:pony(基底家族)、tag:"我的标签"、type:lora、size:>1gb、score:>=4、fav:yes、nsfw:no、broken:yes(疑似损坏),多个条件 AND 组合 - 封面管理:上传 / Ctrl+V 粘贴 / 拖拽导入多张预览图,可设默认封面,自动识别同名 sidecar 图,孤儿文件自动清理;一键移除全部示例图时同步清理对应失效缩略图
- 收藏 / 评分 / NSFW:星标收藏、五星评分即时保存;NSFW 模型封面默认模糊展示(可关闭),设置页可一键隐藏全部 NSFW 模型(含手动标注;搜索、分类计数、标签池与重复筛选同步收敛,不再命中隐藏模型)
- 文件元数据自动解析:safetensors 头部本地毫秒级解析(仅读头部,零网络)——训练元信息(标题/作者/基底模型/网络结构/精度/训练分辨率)、张量统计(参数量、主精度、文本编码器·UNet·VAE 字节构成)与按键名推导的架构家族(SD1.5/SDXL/Flux/SD3.5);触发词候选与推荐分辨率一键填入,绝不覆盖用户标注
- 标签管理:设置页对全库自由标签重命名/合并/移除,整库生效并即时落盘(目标名已存在时自动合并);标签较多时支持搜索检索,筛选下拉同样可在全量标签池中检索稀有标签
- 推荐参数:为每个模型保存采样步数、CFG、采样器、调度器、精度、推荐分辨率区间与备注
- 批量操作:
Ctrl+点击快速多选、Shift+点击范围选择(与资源管理器同语义);批量收藏/评分/NSFW/标签/触发词填充/Civitai 识别/禁用/删除;长耗时批量可随时Esc请求取消并保留已完成部分 - Civitai 在线识别:走 civitai.red 站点(NSFW 模型无需跳转即可识别),按文件 SHA256 反查模型版本,一键补全空缺的触发词与备注(绝不覆盖已有标注),可勾选示例图批量导入为封面;哈希结果持久缓存并由后台队列预热,首次识别也可秒级返回
- 应用内检查更新:设置页一键查询 GitHub Releases 最新版本;启动后延迟静默自动检查(可关闭),发现新版本时提示并可直接在设置页下载
- 关联存储:界面设置(主题/视图/智能视图/扫描规则等)与封面、参数、备注等用户数据全部保存在模型根目录的
.modelvault/内,按相对路径关联,随文件夹移动/复制保持关联——换电脑打开即恢复完整配置;库内移动/重命名后重扫时自动重关联元数据(宁可不绑也绝不绑错);库目录离线(被移动/盘符未挂载)时写入自动挂起并保留在内存,恢复后补写,绝不在失效路径重建目录 - 数据备份:一键将当前库的设置与标注、封面打包为 zip,支持完整 / 仅标注 / 当前筛选结果三种范围,可恢复到任意模型文件夹(恢复前自动快照防覆盖);提供模型库体检——幽灵标注 / 失效封面引用 / 孤儿封面 / 模型文件完整性(0 字节、头部不可解析、数据区截断)的只读检查;标注与封面问题支持一键安全修复,疑似损坏模型仅提示并引导重新下载/替换
- 模型清单导出:设置页「数据管理」中将当前搜索/筛选/排序结果导出为 CSV(Excel 可直接打开)/ Markdown 表格 / JSON(保留结构化字段),便于外部整理与分享
- 体验细节:亮/暗/跟随系统主题(同步原生标题栏)、强调色预设与自定义、卡片尺寸与展示内容配置、详情页全屏画廊、窗口尺寸位置记忆
模型浏览:卡片式首页,左侧分类筛选与计数、顶部搜索与排序,扫描全程异步不阻塞 UI。
模型详情:上传/粘贴封面图片、编辑推荐参数与备注。
Civitai模型站识别:一键识别Civitai模型站对应链接并获取示例图。
软件设置:支持丰富的自定义设置内容。
环境要求:Windows 10 及以上,Node.js ≥ 22.22.2(package.json engines 强制要求;CI 与发布构建统一以 Node 24 执行)。
# 1. 安装依赖(prepare 脚本自动激活 husky pre-commit 钩子)
npm install
# 2. 启动开发模式(热重载)
npm startpre-commit 门禁(lint-staged):提交前对暂存文件依次执行
eslint --fix与prettier --write(js/mjs/cjs/vue),json/css/html/md/yml 走prettier --write;修复结果自动重新暂存,ESLint 报错即阻断提交。CI 全量门禁口径不变,钩子仅把反馈前移到本地。
| 组件 | 版本 | 说明 |
|---|---|---|
| Electron | ^45 | 跨平台桌面运行时 |
| electron-vite | ^6 | 构建/开发工具链,内置 HMR 热重载 |
| Vue 3 | ^3.5 | 渲染进程前端框架 |
| electron-builder | ^26 | Windows 打包(portable 单文件便携版) |
| Vite | ^8 | 底层构建引擎(Rolldown 内核) |
| vitest | ^5 | 单元测试(主进程 + 渲染层 store/组件) |
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 聚焦搜索框 | Ctrl+F |
全局可用(面板打开或未选文件夹时无效) |
| 进入多选并全选 | Ctrl+A |
作用于当前筛选结果;输入框内保持原生全选 |
| 退出多选 | Esc |
批量进行中先请求取消(保留已完成部分);无多选时清空搜索 |
| 批量收藏 | Ctrl+D |
多选模式批量收藏;详情打开时收藏当前模型 |
| 批量删除 | Delete |
多选模式移入系统回收站(弹确认层) |
| 快速勾选 | Ctrl+点击 |
非多选模式直接进入多选并选中该卡片/行 |
| 范围选择 | Shift+点击 |
从上次点击项范围选中(与资源管理器同语义) |
| 网格/列表导航 | 方向键 / Home / End |
移动焦点卡片/行 |
| 激活焦点项 | Enter / Space |
打开详情;多选模式下切换选中 |
| 收藏 / 删除焦点项 | F / Delete |
焦点卡片快速收藏;弹出删除确认 |
输入控件(搜索框/文本域/下拉)内除
Ctrl+F外均不拦截按键,保持原生文本编辑行为。
| 命令 | 说明 |
|---|---|
npm start / npm run dev |
启动开发模式(主进程/渲染进程热重载) |
npm run build |
编译主进程、preload、渲染进程到 out/ |
npm run lint |
ESLint 代码检查(flat config,错误级规则) |
npm run typecheck |
TypeScript checkJs 纯类型检查(shared/preload/main/renderer JS,严格度棘轮) |
npm test |
运行单元测试(vitest,test:watch 为监视模式) |
npm run test:coverage |
运行单元测试并生成覆盖率报告(含防退化阈值门禁) |
npm run smoke |
启动 out/ 编译产物冒烟检查(主窗口/页面加载/preload+IPC 往返/图片协议) |
npm run preview |
以生产构建产物启动应用预览 |
npm run dist |
编译并打包单文件便携版 EXE 到 dist/{version}/ |
npm run dist:dir |
编译并生成免安装目录(快速验证打包结果) |
- 打包配置见
electron-builder.yml(portable 单文件便携版,x64),产物为dist/{version}/ModelVault-{version}.exe - 单文件 EXE 运行时不在其所在目录生成任何文件:引导信息(库列表/激活库)与日志保存在
%APPDATA%\modelvault\,库设置与模型元数据随库保存在用户选择的模型文件夹 - 首次启动需解压到系统临时目录,启动速度略慢于常规安装版;Windows 10+ 可直接运行,无额外运行时依赖
- 如需更换应用图标,替换
build/icon.ico(需包含 256×256 及以上尺寸);也可临时放置 512×512 以上的正方形icon.png到build/,运行node scripts/generate-icon.mjs生成多尺寸 ico(源图不入库)
ModelVault/
├── build/ # 打包资源:应用图标 icon.ico
├── image/ # 软件界面截图(README 展示用)
├── .github/workflows/ # CI 质量门禁(ci.yml)+ 标签发布构建(release.yml)
├── scripts/ # 工具脚本(启动冒烟 smoke / 应用图标生成 / CSP 检查)
├── src/
│ ├── shared/ # 主/渲染进程共享契约与常量(分类标签/扩展名/默认设置/
│ │ # 枚举/错误码;IPC 契约注册表按域拆分在 ipc-schema/,
│ │ # 异常字段安全读取助手 error-text.js)
│ ├── main/ # 主进程
│ │ ├── index.js # 应用入口:生命周期、单实例锁、全局错误处理
│ │ ├── windows/mainWindow.js # 主窗口创建/管理(窗口状态记忆、WCO 标题栏)
│ │ ├── menu.js # 窗口级快捷键(无原生菜单栏模式)
│ │ ├── ipc.js # IPC 处理器注册入口(应用信息/主题/异常上报)
│ │ ├── ipc/models/ # 模型管理 IPC 适配层(按域拆分:scan/decorate/covers/
│ │ │ # meta/misc/files/civitai/backup/store/)
│ │ ├── protocol.js # mvimg:// / civimg:// 图片协议门面(protocol/:
│ │ │ # local-image 白名单校验 / remote-image CDN 代理)
│ │ ├── fatal-error.js / quit.js / theme.js / logger.js / smoke.js(冒烟检查项)
│ │ ├── utils.js # 共享原语门面(utils/:路径/并发/网络/进程/文件系统)
│ │ └── services/ # 主进程服务层:扫描分类、关联存储(.modelvault/)、
│ │ # 原子写入、元数据重关联、目录监控、封面/缩略图、
│ │ # 装饰管线领域事实(decorate/)、备份恢复、
│ │ # 检查更新、Civitai 客户端、哈希预热、
│ │ # safetensors 头部解析等
│ ├── preload/ # 预加载脚本:index.js contextBridge + IPC 通道白名单、
│ │ # thumb-preload.js 缩略图渲染子窗口
│ └── renderer/ # 渲染进程(Vue 3)
│ └── src/
│ ├── App.vue / main.js / error-report.js # 根组件 / 入口 / 错误上报链路
│ ├── constants/ # 推荐参数常量、强调色预设
│ ├── store/ # 全局响应式状态(按域拆分:筛选/库切换/批量/
│ │ # 增量扫描/封面/Civitai/智能视图/派生数据等)
│ └── components/ # TopBar / Sidebar / VirtualModelGrid / VirtualModelList /
│ # ModelCard / ModelDetail(含 detail/ 封面面板、
│ # AutoInfoPanel、CivitaiPanel、CoverGallery)/
│ # BatchBar / ConfirmOverlay / StatsSection /
│ # SettingsPage / ToastHost
├── tests/ # vitest 单元测试(主进程 + 渲染层 store 与组件)
├── electron.vite.config.mjs # electron-vite 配置
├── electron-builder.yml # 打包配置(portable 单文件)
└── package.json
渲染进程没有裸 invoke 入口,所有 invoke 通道必须在 src/shared/ipc-schema/ 注册表登记(O-3 按域拆分:schema-*.js 域文件声明、index.js 聚合门面为唯一导入入口;单一来源:preload 白名单由注册表键集派生,payload schema 一并声明,未登记通道被 fail-closed 拒绝):
- 在
src/shared/ipc-schema/对应域文件(schema-app.js/schema-meta.js等schema-*.js)中登记通道:带参通道用vObj/vStr等构造器声明 payload 结构门禁,无参通道登记vVoid():
'my:channel': vObj({ fields: { id: vStr({ required: true, max: 2000 }) } })- 在
src/main/ipc.js或src/main/ipc/models/对应域模块中注册处理器(统一经wrapHandler,自动执行 schema 前置校验与异常兜底;事件推送类通道在IPC_EVENT_CHANNELS登记,preload 的订阅白名单由此派生):
wrapHandler('my:channel', async (event, payload) => {
return 'result'
})-
在
src/preload/index.js的api对象中添加语义化方法(内部统一走invokeValidated/subscribe),渲染进程通过window.api.myDomain.doThing(payload)调用。 -
业务失败返回
{ error: '展示文案' };preload 会在 IPC 边界统一附加稳定code(枚举见src/shared/error-codes.js,error文案保持不变)。新增失败路径优先用ipcError(IPC_ERROR.X, '文案')显式给码;渲染层按code做离线/繁忙/冲突等分支,不要匹配中文文案。
invoke 通道与两侧调用/注册点、事件通道与 preload 订阅点的一致性均由
tests/ipcSchema.test.js双向对账锁定,任一侧漏改即测试失败。
项目为纯 JavaScript,以 TypeScript 编译器 checkJs 模式做纯类型检查(npm run typecheck,无构建产物):tsconfig.json 当前覆盖 src/shared/(IPC 通道单一来源注册表、默认设置等跨进程契约)、src/preload/、src/main/ 全层(services、ipc handlers、协议/窗口/入口)以及 src/renderer/src/ 全部 .js(store/composables/components 纯逻辑/常量;.vue 模板不在 checkJs 范围,由组件测试覆盖)。src/renderer/src/store/global.d.ts 声明 window.api 与 *.vue/*.css 模块。覆盖范围与严格度按棘轮渐进扩展:严格度开关仅开启「实测零错误(或一次性修复后归零)」的项(当前已开启八项:strictFunctionTypes / strictBindCallApply / noImplicitThis / noFallthroughCasesInSwitch / noImplicitOverride / noUncheckedIndexedAccess / noImplicitReturns / useUnknownInCatchVariables;剩余 strictNullChecks(629)→ noImplicitAny(879)→ exactOptionalPropertyTypes 按错误量递增记账待消化,棘轮台账见 tsconfig.json 注释)。useUnknownInCatchVariables 消化模式已固化:catch 变量按 unknown 处理,.message/.code/.name/.stack 一律经 src/shared/error-text.js 纯助手(errorMessage/errorCode/errorName/errorStack)安全读取,非 Error 抛出值降级为可读文案、行为不漂移;为跨模块共享的数据结构补写 JSDoc 类型标注(如 SchemaRule/WatcherState/BackupManifest typedef)即可让检查器捕获字段改名/漏改类回归,也是消化剩余严格度开关的主要途径。
应用不显示原生菜单栏,快捷键在 src/main/menu.js 中通过 before-input-event 窗口级注册:F11 全屏切换;DevTools 与刷新快捷键仅在开发环境生效。窗口统一在 src/main/windows/ 管理,可参照 mainWindow.js 创建多窗口。
- 位置:
%APPDATA%\modelvault\logs\modelvault-YYYY-MM-DD.log(按天分文件,保留 14 天) - 用法:
import logger from './logger'后调用logger.info / warn / error - 性能基线(PERF-2):冷启动/切库等关键路径耗时以
[perf]前缀写入日志(startPerf打点,见src/main/services/perf.js;缩略图渲染仅记录超过 2s 的慢任务),优化前后可按前缀检索对比 - 主进程全局异常自动记录;渲染进程异常经
app:reportError通道上报写入同一日志,同类错误节流降噪
单元测试位于 tests/(91 个文件 / 1623 用例;渲染层 store 测试自 appStore.test.js 按域拆分为 appStore*.test.js,共享装配在 tests/helpers/storeTest.js):主进程纯逻辑与 IPC handler(node 环境)、渲染层 store 按域拆分测试、组件交互测试(@vue/test-utils + jsdom,文件头 // @vitest-environment jsdom 声明)。Electron API 在 tests/setup.js 中统一 mock,公共挂载/IPC 脚手架在 tests/helpers/ 中复用。新增纯函数模块或组件交互时请同步补充用例,运行 npm test 验证;npm run test:coverage 受防退化阈值门禁约束(Statements 75% / Branches 68% / Functions 72% / Lines 77%),门禁按「实测基线下浮 ~10pt」口径随基线上移棘轮渐进上调(棘轮记录见 vitest.config.mjs 注释)。
ci.yml:push 到 main / PR 时运行质量门禁(Node 24 单腿:ESLint → Prettier → 类型检查 → 单元测试(含覆盖率门禁)→ 三端编译 → 产物完整性校验 → 启动冒烟 → 覆盖率归档;release.yml打包同为 Node 24,验证与出货构建口径统一)release.yml:推送v*标签触发 Windows 打包,自动创建 GitHub Release 并附加 EXE 与 SHA256 校验和- 发版流程与版本号约定(A2):版本标签统一采用
v{major}.{minor}.{patch}语义化格式(如v0.6.0),且必须与package.json的version一致(workflow 内置校验,不一致即失败)。发版步骤:更新package.json版本号并提交 →git tag v0.6.0→ 推送标签即自动构建并创建 Release(新 Release 默认标记为 Latest);打包流程可在 Actions 页用workflow_dispatch输入版本号做不建 Release 的演练。历史Beta-0.x标签为遗留格式:应用内更新只识别 v 前缀纯数字三段版本(V-06 安全设计),Latest 为遗留标签时会自动回查 Release 列表取最新合规版本,列表内也无合规版本则视为暂无更新 - 代码签名(E1):配置仓库 Secrets
CSC_LINK(base64 PFX)与CSC_KEY_PASSWORD后,electron-builder 自动为 EXE 做 SHA256 Authenticode 签名;MODELVAULT_SIGNER_THUMBPRINT(证书 SHA1 指纹)会在构建期注入主进程,应用内更新下载复用与安装前均强制「签名有效 + 指纹一致」。未配置证书时构建继续,应用内更新退化为仅 SHA256 校验
contextIsolation: true+nodeIntegration: false+sandbox: true,渲染进程无 Node 能力;preload 仅暴露白名单通道mvimg://图片协议仅允许访问当前模型根目录内文件(越界返回 403);civimg://远程图片代理仅放行 Civitai 官方 CDN 域名白名单(https 强制,防 SSRF)- 渲染进程导航一律拦截,外部链接经系统浏览器打开;HTML 含 CSP 策略
- 模型删除移入系统回收站(非永久删除);扫描根目录白名单校验;删除/移动/重命名/禁用/跨库传输等破坏性操作统一按 realpath 校验归属,库内 junction 指向库外时拒绝;封面导入有图片魔数校验与大小预检
- 应用内更新强制 SHA256 校验;配置发布者证书指纹后,下载复用与安装前还会校验 Authenticode(状态 Valid + 指纹一致),失败即拒绝执行
- 开发类快捷键(DevTools/刷新)在生产环境禁用



