PromptManager
PromptManager
项目概览
PromptManager 是一款面向 AI Prompt 工程师的本地化 Prompt 管理工具,采用纯前端无后端架构,通过浏览器原生 File System Access API 直接读写用户本地文件系统,实现 Prompt 的创建、编辑、检索、分类与导入导出。项目以 .md(Markdown + YAML Frontmatter)作为统一存储格式,兼顾可读性与结构化元数据管理。
核心定位:解决 AI 使用过程中 Prompt 模板散落在各处、缺乏统一管理和快速检索的问题。
技术栈
| 层级 | 技术选型 | 版本 |
|---|---|---|
| 框架 | React 19 + React Router 7 | 19.2.4 / 7.14.0 |
| 构建工具 | Vite 8 | 8.0.4 |
| 样式方案 | Tailwind CSS 4 + 自定义 CSS 变量主题系统 | 4.2.2 |
| 代码编辑器 | Monaco Editor(@monaco-editor/react) | 4.7.0 |
| Markdown 渲染 | react-markdown + remark-gfm | 10.1.0 |
| 元数据解析 | gray-matter(YAML Frontmatter 标准) | 4.0.3 |
| 持久化 | IndexedDB(idb-keyval) + File System Access API | 6.2.2 |
| 数据导出 | JSZip | 3.10.1 |
| 包管理 | pnpm | — |
架构设计
整体分层
src/
├── main.jsx # 应用入口
├── App.jsx # 路由定义 + 全局 Provider 挂载
├── contexts/
│ └── SettingsContext.jsx # 全局状态管理(主题/语言/工作区句柄)
├── components/ # 布局 & 复用 UI 组件
│ ├── Layout.jsx # Sidebar + Outlet 的根布局壳
│ ├── Sidebar.jsx # 导航侧边栏(含 WorkspaceTree 嵌套)
│ ├── TopToolbar.jsx # 通用顶部工具栏
│ ├── WorkspaceTree.jsx # 递归文件树(惰性展开)
│ └── SavePromptDialog.jsx # 保存对话框(含目录浏览器)
├── pages/ # 页面级组件
│ ├── Editor.jsx # 核心:Prompt 编辑器(Monaco + 实时预览)
│ ├── Library.jsx # Prompt 库(搜索/标签/排序)
│ └── Settings.jsx # 设置页(主题/语言/工作区/导入导出)
└── utils/
├── fileSystem.js # File System Access API 全套封装
└── i18n.js # 轻量级中英双语字典
数据流架构
┌─────────────────────────────────────────────────────────────────┐
│ SettingsContext │
│ (theme, language, workspaceHandle) ← 全局单一数据源 │
└──────────┬──────────────────────────────┬───────────────────────┘
│ │
┌─────▼─────┐ ┌──────▼──────┐
│ Editor │ │ Library │
│ 页面 │ │ 页面 │
└─────┬─────┘ └──────┬──────┘
│ │
▼ ▼
┌───────────────────────────────────────────────┐
│ fileSystem.js 封装层 │
│ │
│ readFile / writeFile ← 读写 .md 文件 │
│ readMetadata / writeMetadata ← 读写索引 │
│ parseMarkdown / stringifyMarkdown ← 格式转换 │
│ syncMetadataIndex ← 增量同步 │
└───────────────────┬───────────────────────────┘
│
▼
┌───────────────────────────────────────────────┐
│ File System Access API (浏览器原生) │
│ │
│ FileSystemDirectoryHandle ← 用户选定的目录 │
│ IndexedDB (idb-keyval) ← 句柄持久化 │
└───────────────────────────────────────────────┘
核心功能模块
1. Monaco Editor 编辑器
文件:src/pages/Editor.jsx
- 集成 Monaco Editor,支持 Markdown 语法高亮、代码折叠、自动换行
- 左右分屏布局:左侧为编辑区,右侧为 react-markdown 实时预览
- 顶部内联编辑器:支持文件名直接修改、Tag 标签的增删操作
- PreviewBar 组件通过
React.memo隔离,避免编辑区每次击键触发预览组件重渲染 - 自定义 Monaco 主题
logicCanvasDark,与应用深色模式无缝融合
性能优化:PreviewBar 使用 memo + useCallback 稳定引用,确保击键不会导致 Monaco 实例重新协调。
2. 文件存储引擎
文件:src/utils/fileSystem.js
核心设计决策:无后端,通过浏览器 File System Access API 直接操作本地文件系统。
关键实现:
- 工作区持久化:
pickWorkspace()将FileSystemDirectoryHandle写入 IndexedDB,restoreWorkspace()在应用启动时静默恢复,用户无需重复授权 - 目录递归扫描:
scanDirectory()递归遍历目录树,统计文件数量与磁盘占用 - 元数据索引(
.metadata.json):维护所有.md文件的结构化索引(tags、preview、lastModified),避免每次加载都全量解析文件 - 增量同步机制(
syncMetadataIndex()):通过file.lastModified时间戳比对,仅重新解析被外部修改过的文件,并自动清理已删除文件的索引条目 - 兼容性设计:元数据 schema 从 v1(纯 tag 数组)到 v2(带 preview 和 lastModified 的对象),
normaliseMetaEntry()保证新旧格式无缝兼容
3. Markdown 序列化引擎
文件:src/utils/fileSystem.js 中的 parseMarkdown() / stringifyMarkdown()
采用 YAML Frontmatter 作为标准格式:
---
tags:
- backend
- java
- spring-boot
preview: 这是一个用于后端开发架构的标准化 Prompt 模板
---
# Prompt 正文内容...
解析策略(三层容错):
- 首选 gray-matter 库解析 — 标准 YAML Frontmatter
- 手动正则回退 — 当 gray-matter 解析失败时,用正则提取
---块中的 tags 和 preview - 旧版 HTML 注释兼容 — 支持
<!-- tags: ... -->格式的遗留文件,实现无感迁移
自愈机制:parseMarkdown() 包含循环剥离逻辑,自动清理因多次保存产生的"千层饼"(多个 YAML 头部叠加)问题。stringifyMarkdown() 则通过 YAML 敏感字符检测,对 preview 值自动加引号,防止特殊字符破坏 YAML 结构。
跨平台处理:所有输入先经过 \r\n → \n 归一化,确保 Windows 换行符不会导致正则失效。
4. Prompt 库与检索系统
文件:src/pages/Library.jsx
- 级联计算架构:三个
useMemo链式派生 — 热门标签 → 搜索词解析 → 过滤排序结果,任一上游变化自动级联更新 - 搜索算法:标签精确匹配(
===) + 摘要模糊匹配(includes),多关键词取并集并按命中数打分排序 - 两种排序模式:相关度排序(
score降序)和最近修改排序(lastModified降序),一键切换 - 快速加载 + 静默同步:先从
.metadata.json缓存快速渲染,后台异步执行syncMetadataIndex()增量更新
5. 保存流程与冲突处理
文件:src/components/SavePromptDialog.jsx
保存对话框实现了完整的目录浏览器,支持:
- 路径面包屑导航:可逐级深入子目录
- 原地新建文件夹:保存时可在任意位置创建新目录
- 三种保存模式:
- 新建文件:检测同名冲突,直接阻止覆盖(非静默覆盖)
- 编辑已有文件(路径+文件名未变):静默覆盖
- 移动/重命名文件:删除旧路径的物理文件 + 清理旧元数据索引,写入新位置
- 写入原子性:写入失败时调用
writable.abort()确保文件句柄不泄漏
6. 递归文件树
文件:src/components/WorkspaceTree.jsx
- 惰性加载:目录节点仅在用户点击展开时才异步加载子条目,避免启动时全量扫描
- React.memo 优化:
WorkspaceNode组件使用memo包裹,展开/折叠操作不会导致兄弟节点重渲染 - 路径状态管理:通过
Set维护expandedPaths,activeFilePath高亮当前编辑的文件
7. 工作区导入导出
文件:src/pages/Settings.jsx
- 导出:使用 JSZip 递归打包整个工作区目录为
.zip压缩包,通过 Blob URL 触发浏览器下载 - 导入:通过
<input type="file" accept=".md">导入单个 Markdown 文件,自动携带内容跳转至编辑器页面
8. Vite 自定义插件:Git 状态监控
文件:vite.config.js 中的 gitStatusPlugin()
- 仅在开发模式下生效,提供
/api/git-status中间件 - 通过
spawnSync调用git log和git status,返回最近提交时间和工作区干净状态 - 安全加固:硬编码 git 命令参数数组(无字符串拼接),CORS 仅允许
127.0.0.1:5173,锁死 dev server 到 loopback 地址
9. 国际化(i18n)
文件:src/utils/i18n.js
- 轻量级字典方案,覆盖侧边栏、编辑器、设置页等全部 UI 文案
- 支持
en(英文)和zh(简体中文),跟随系统偏好自动初始化 t()函数支持 dot-notation 键名,缺失键自动降级到英文并打印console.warn
10. 全局状态管理
文件:src/contexts/SettingsContext.jsx
基于 React Context + useState 的轻量方案,管理三项全局状态:
| 状态 | 持久化方式 | 初始化逻辑 |
|---|---|---|
theme | localStorage (pm:theme) | 优先读取存储值,否则跟随 prefers-color-scheme |
language | localStorage (pm:language) | 默认 'en' |
workspaceHandle | IndexedDB (idb-keyval) | 启动时 restoreWorkspace() 静默恢复 |
关键技术亮点
1. 无后端本地优先架构
完全依赖浏览器原生能力(File System Access API + IndexedDB),零服务器成本,数据完全在用户本地,隐私性极高。
2. YAML Frontmatter 三层容错解析
从标准库解析到手动正则到旧格式兼容,确保任何历史版本的文件都能正确读取,并在下次保存时自动迁移到标准格式。
3. 元数据索引与增量同步
.metadata.json 作为 Sidecar 索引文件,避免每次都全量解析所有 .md 文件。通过文件修改时间戳实现增量同步,外部编辑器修改的文件也能被自动感知。
4. Monaco Editor 性能隔离
将 PreviewBar 用 React.memo 隔离,配合 useCallback 稳定回调引用,避免编辑区每秒数十次的击键事件触发 Monaco 实例的完整重渲染。
5. 保存流程的状态机设计
通过 originalFile(null vs object)精确区分新建/编辑两种模式,配合路径比对实现"同路径静默覆盖 + 不同路径冲突阻止 + 跨路径物理文件清理"的三段式保存逻辑。
项目统计
| 指标 | 数据 |
|---|---|
| 源文件数 | 12 个(.jsx / .js) |
| 代码符号数 | 125 个 |
| 依赖关系边 | 245 条 |
| 核心 npm 依赖 | 10 个(均为主流库) |
| 当前版本 | v0.1.1-alpha |