Draggable Note — 支持拖拽排序的极简桌面记事本。
本文件是使用与上手文档:这是什么、怎么跑起来、怎么用。方案与依赖取舍见 dnote起步方案.md;界面与交互硬约定见 design.md;日志见 日志使用说明.md;踩过的坑见 开发经验.md。
- 桌面框架:Tauri 2
- 前端:Vue 3 + TypeScript + Tailwind CSS 3 + Vite 6
- 存储:纯文本文件(
<数据目录>/dnote.txt与dnote-secondary.txt,一行一条,临时文件 + rename 原子写)
- 一行一条笔记:整份笔记就是一个无边框多行文本域,点哪儿都能直接改,没有卡片、表头、保存按钮。
- 编辑就是记事本:回车在光标处断行(行首回车即把当前行下推、新行插在当前位置)、退格 /
Delete合并相邻两行、↑↓在行间移动、Ctrl+A全选、Ctrl+Z撤销 —— 全是浏览器原生行为,应用不自己实现一套。 - 快捷键:
Ctrl+D删除当前行、Alt+↑/Alt+↓上下移动当前行(光标跟着走,列不变),两者都能Ctrl+Z撤回;选中多行时两者都作用于整个选区(删除选中的全部行 / 整块上下移动一行,选区跟着走、可连按);Alt+S展开 / 收起次级面板。 - 行内操作:当前行(光标所在行)会高亮;把指针停在这一行上,右侧浮出「复制当前行 / 删除当前行」两个按钮,不占行内空间,删除同样能
Ctrl+Z撤回。 - 右键菜单:编辑器里右键弹出「复制 / 删除」,选中多行时按整个选区来(
复制 3 行/删除 3 行);最下方「清除连续空行」永远作用于整篇 —— 连续的空行只留一个(纯空格行也算空行)。 - 拖拽调序:按住行首悬停出现的拖拽点上下拖动即可调整位置,拖动中行序实时跟着走,松手落盘。
- 顺序完全手动:不做任何自动排序(不按时间、不按字母),顺序只由拖拽决定,重启后保持。
- 允许空行:空行是合法内容,原样存储、原样显示,不做任何自动清理。
- 存储内容 = 界面内容:后台存的就是这些行本身,没有 id、没有序号、没有时间戳;
dnote.txt可以直接用记事本打开核对。 - 多行选择与复制:拖选或 Shift 键选区跨越多行时,
Ctrl+C复制出的就是选中那段文本(原生)。 - 多行粘贴:一次粘贴进来多行文本(如从别的编辑器复制一段)原样按行落下(原生)。
- 置顶:默认置顶,右上角图钉一键切换,选择会被记住。
- 托盘常驻:托盘左键切换显示 / 隐藏(正看着时收回,否则一次就唤到前台并聚焦),标题栏「-」同样是隐藏,托盘右键「显示 / 退出」。
- 任务栏与 Alt+Tab:窗口在任务栏里有按钮、
Alt+Tab能切到它;点任务栏按钮即最小化 / 还原(与托盘、标题栏「-」一样都是唤回入口)。 - 全局热键
F9:在任何程序前台时按它唤起 / 收回窗口(缺省开)。可在设置面板关掉 —— 关掉后 F9 交还系统(它注册期间是独占的,别的程序收不到)。 - 单实例(仅 release):正式构建同时只允许一个窗口,二次启动唤起已有窗口;开发构建不抢单实例锁,不会和常驻的 release 实例打架。
- 窗口记忆:尺寸与位置重启后恢复。
- 深色外观:标题条、托盘与安装包一律深色,没有主题切换;笔记区的前景与背景颜色可在设置面板里换(含浅色搭配)。
- 设置面板:标题条齿轮打开(在标题条下方内嵌,不开独立窗口)—— 笔记正文字号、行高比、前景颜色、背景颜色、背景透明度、二十档颜色搭配推荐(含深色与浅色系)、全局热键
F9开关、开机自启。偏好都记在本机,不进笔记文件。 - 全量笔记备份:设置面板里一键把两块面板的笔记打包成一个 zip(导出),或从 zip 覆盖回来(导入)。只含笔记(不含字号、颜色、热键这些偏好);导入只认 dnote 导出的 zip(包内含清单,缺了直接报错),导入前会二次确认,主面板那一次替换还能用
Ctrl+Z撤销。 - 帮助面板:标题条上的
?打开(同样在标题条下方内嵌,与设置面板互斥)—— 顶部显示版本号,两列快捷键表格 + 「与普通笔记应用的区别」。 - 次级面板:右侧一栏放「不常改的笔记」,默认收起(主面板右缘中间那颗圆形把手展开,窗口会相应加宽一栏;展开后同一颗把手变成
‹,点它收回);操作与主面板完全一样,但存另一个文件,两边互不牵动。宽度分两处拖:窗口右缘只改次级那一栏(主面板不动),两栏之间的分界线只改主面板(次级让位、窗口不动),都会记住。
前置要求:Rust、Node(pnpm)、Windows WebView2。
# 安装前端依赖
pnpm install
# 开发模式(启动 Vite + Tauri 窗口)
pnpm dev
# 构建(等效 tauri build,NSIS 安装包)
pnpm release- 笔记存于
<数据目录>/dnote.txt(主面板)与<数据目录>/dnote-secondary.txt(次级面板),一行一条,行序即顺序;文件内容与界面逐行一致,两块面板各写各的文件、互不牵动。 - 数据目录:dev 在
<项目根>/dnote-data/(DNOTE_DATA_DIR可重定向),release 在应用配置目录(%APPDATA%\com.dnote.perphyyoung),两种构建互不共享。 - 行格式:每行都以
\n结尾(含最后一行);读取时按\n切分并丢弃末尾由终止换行产生的空串,兼容手改出来的 CRLF。这样末尾空行也能原样往返(原因见开发经验.md§2.1)。 - 写入是整文件重写,走
dnote.txt.tmp+rename原子替换,异常退出最多丢最后一个防抖窗口(400ms)。 - 窗口尺寸 / 位置由官方
tauri-plugin-window-state存于应用配置目录(release 为.window-state.json,dev 为window-state.dev.json);DNOTE_WINDOW_STATE可指定别的文件(e2e 靠它把窗口几何与 dev 分开,免得互相覆盖)。
当前只在 Windows 上开发与验证(Tauri 2 + WebView2)。macOS / Linux 未测试——不是「不支持」,而是没有验证过。
工具链:
- Windows + WebView2(随 Edge 安装,通常已具备);
- Rust:最低版本见
src-tauri/Cargo.toml的rust-version; - pnpm 12:版本已固定在
package.json的packageManager,请勿用其它大版本安装依赖(会改写pnpm-lock.yaml); CARGO_TARGET_DIR:指向共享目录,与其它 Tauri 项目共用编译产物;共享 target 是全局一把锁,多项目不能并行 build。- dev 与 release 并存:单实例锁只在 release 注册,
pnpm dev随时可起,不必先关掉已安装的 dnote(可用 release 版常驻记需求、dev 版并行开发)。dev 之间则并存不了 —— vite 的strictPort会占住 1420,第二个pnpm dev直接报端口占用。
质量门唯一入口是 pnpm check(format → build:rs → gen:bindings → typecheck → build);改完代码先跑它,通过后再按需跑测试。
| 命令 | 内容 |
|---|---|
pnpm dev |
开发模式(Vite + Tauri,debug 构建自动导出 src/bindings.ts) |
pnpm check |
质量门:format → build:rs → gen:bindings → typecheck → build |
pnpm test |
全部单元测试(vitest 纯逻辑 + cargo test) |
pnpm test:ui / pnpm test:rs |
只跑前端 / 只跑 Rust 单测 |
pnpm e2e |
Playwright e2e(CDP 连真实调试二进制,先自动构建一次) |
pnpm build:rs / pnpm gen:bindings |
手动重编 Rust / 复写 src/bindings.ts |
pnpm release |
构建安装包(NSIS) |
src/bindings.ts 是 tauri-specta 运行期导出的生成物:不手改、不入格式化,Rust 命令签名变更后由 pnpm check / pnpm dev 自动复写。
换图标:node scripts/gen-icon.mjs && pnpm tauri icon app-icon.png,再把产物 icon.png 拷成 public/icon.png 作 favicon。
换 dev 图标:node scripts/gen-dev-icon.mjs(默认生成 src-tauri/icons/tray-dev.rgba + 两张预览图)。dev 构建的托盘与任务栏都用它,release 用应用图标;脚本与 Rust 样板都是通用的,可整段复制到别的 Tauri 项目。
| 文件 | 用途 |
|---|---|
dnote起步方案.md |
方案与决策记录:决定过什么、为什么 |
design.md |
界面与交互硬约定:必须怎样表现 |
开发经验.md |
踩过的坑与「为什么」;排查问题先翻它 |
日志使用说明.md |
日志位置、级别开关、前后端打点方式 |
通用语言.md |
术语中英对照与命名口径 |
AGENTS.md |
给 AI 协作者的规则与文档分工 |
GPL-3.0