From 5de1382262290dfe886effafd888be886e52f7ee Mon Sep 17 00:00:00 2001 From: stash Date: Thu, 29 Oct 2026 20:31:52 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=E4=BA=A4=E6=8E=A5?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=88=E6=9E=B6=E6=9E=84=E3=80=81=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E3=80=81=E7=8A=B6=E6=80=81=E3=80=81=E9=99=90=E5=88=B6?= =?UTF-8?q?=E3=80=81=E4=B8=8B=E4=B8=80=E6=AD=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HANDOFF.md | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 HANDOFF.md diff --git a/HANDOFF.md b/HANDOFF.md new file mode 100644 index 0000000..51a0fc2 --- /dev/null +++ b/HANDOFF.md @@ -0,0 +1,207 @@ +# Stash 交接文档 + +> 写于 2026-10-29。新会话第一件事:读这份 + `docs/ADMIN-PLAN.md` + `stash-ui/README.md`。 + +## 0. 一句话现状 + +Stash 已从「只读本地导航站」升级为**可登录、可配置、可编辑内容的本地发布台**: + +- 登录(单用户,argon2id + Cookie 会话); +- `/admin` 设置页(页头滚动信息 / 首页卡片 / 侧栏 / 资料 / 系统); +- 条目就地编辑(Drawer + 乐观锁); +- 分区新增/删除、浏览/点赞/分享/跳转; +- 数据库自动迁移到 **v17**; +- 前端 100% 使用组件库 `@stash/ui`(v0.2.0,41 个组件)。 + +当前数据库里**没有管理员密码**,打开 8080 点「登录」是**首次设置密码**流程。 + +## 1. 仓库与运行环境 + +| 项目 | 路径 | 分支 | 端口 | 说明 | +| --- | --- | --- | --- | --- | +| 新版(组件重构) | `D:\CNWei\CNW\Rust\stash` | `feat/use-stash-ui` | **8080** | 所有新功能都在这里 | +| 旧版(1:1 基线) | `D:\CNWei\CNW\Rust\stash-old`(worktree) | `develop` | **8081** | 只用于视觉对照,不要改 | +| 组件库 | `D:\CNWei\CNW\Rust\stash-ui` | `master` | — | tag `v0.1.0` / `v0.2.0` | + +后端:Rust 2024 + Axum 0.8 + rusqlite(bundled)。前端:React 19 + Vite + TS + CSS Modules,`@stash/ui` 通过 `file:` 依赖引入。 + +### 启动 / 构建(顺序重要) + +```powershell +# 1) 前端(产物会被 build.rs 内嵌,必须先构建) +cd D:\CNWei\CNW\Rust\stash\stash-web +npm run build + +# 2) 先杀掉正在运行的 stash.exe,否则 cargo 会报「拒绝访问」 +Get-Process stash -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*stash\target*' } | Stop-Process -Force + +# 3) 后端 +cd .. +cargo build +Start-Process .\target\debug\stash.exe -RedirectStandardOutput "$env:TEMP\stash.log" -RedirectStandardError "$env:TEMP\stash-err.log" -WindowStyle Hidden +``` + +旧版(8081,仅在需要对照时): + +```powershell +D:\CNWei\CNW\Rust\stash-old\target\debug\stash.exe --port 8081 +``` + +### 测试 + +Windows 下 `TEMP` 权限有问题,跑测试要覆盖临时目录: + +```powershell +$env:TEMP = "D:\CNWei\CNW\Rust\stash\target\tmp"; $env:TMP = $env:TEMP +cargo test # 当前 48 passed +``` + +## 2. 目录 / 文件地图 + +``` +src/ + main.rs / lib.rs 启动、日志 + config.rs 端口 / 数据目录(默认 target/debug/data) + server.rs 全部路由(API + 内嵌前端 + SPA 回落) + error.rs StashError(含 Conflict → 409) + db/ + mod.rs Db 门面(所有方法)+ 迁移测试 + schema.rs 建表、种子、版本迁移(0/15→16→17) + auth.rs 管理员、密码哈希、会话(token 只存 sha256) + settings.rs settings JSON(header/sidebar/sections/profile) + entries.rs 条目读取/编辑、浏览数、点赞、审计 + categories.rs 分区新增/删除 + catalog.rs 查询组装(前端三种视图) +stash-web/src/ + App.tsx 主页壳、登录弹窗、编辑器、设置应用 + main.tsx 入口分流(/admin 与 /login) + auth.ts / settings.ts / items.ts 前端 API 客户端 + components/ + header/SiteHeader.tsx 品牌 + 滚动信息 + 操作图标 + admin/AdminPage.tsx /admin 全部 Tab + auth/LoginDialog.tsx Modal 登录 + auth/PasswordInput.tsx 带显隐切换的密码框 + content/ 首页、分区、条目、文章、编辑器 + sidebar/ 资料卡、服务面板、导航 +docs/ADMIN-PLAN.md 后台方案 + P0–P4 实施记录 + 未做项 +README.md 运行、路由、库结构、登录说明 +``` + +## 3. 功能清单(已完成) + +### 登录 +- 单用户 `admin`,密码 argon2id; +- 会话:随机 32 字节 token,HttpOnly + SameSite=Strict + Path=/,7 天,库里存 sha256; +- 登录失败 5 次锁 60 秒;写接口校验 Origin;写接口需要会话。 + +### `/admin` +| Tab | 能力 | +| --- | --- | +| 页头滚动信息 | 启用开关、速度 8–120、条目增删/排序、标签与色调、占位符 `{count}` `{project}` `{status}` | +| 首页卡片 | 显示/隐藏、标题覆盖、预览条数、顺序、**新增分类**、**删除分类**(不可删的显示灰色按钮) | +| 侧栏导航 | 显示/隐藏、顺序、删除分类、新增分类 | +| 资料 | 头像 URL、名称、角色、简介、位置(应用到侧栏资料卡) | +| 系统 | 修改密码(清空所有会话)、下载备份(VACUUM INTO 快照) | + +保存:`PATCH /api/settings`(`version` 乐观锁,冲突 409);成功用 Toast(2.4s 自动消失)。 + +### 内容编辑 +- 详情页 `[编辑]` 只在登录后显示; +- 打开右侧 Drawer:标题、简介、标签、一句话评价、正文 Markdown、封面、跳转地址; +- `PATCH /api/items/{key}`,`updatedAt` 乐观锁; +- 保存后 `catalog.reload()` 局部刷新,不整页刷新。 + +### 详情操作条 +- 浏览:进入页面 `POST /api/items/{key}/view`,数字 +1; +- 点赞:可切换,`POST /like`,localStorage 记住状态; +- 分享:复制当前链接,Toast 反馈; +- 跳转:`href` 为 `#` 时置灰。 + +## 4. HTTP API + +``` +GET /api/health +GET /api/projects GET /api/projects/events (SSE) +GET /api/catalog GET /api/catalog/events (SSE) + +GET /api/auth/session -> {authenticated, has_admin, username} +POST /api/auth/setup {password} 仅当无管理员 +POST /api/auth/login {password} +POST /api/auth/logout +PATCH /api/auth/password {current, next} + +GET /api/settings -> {version, settings} +PATCH /api/settings {version, settings} 需登录 + +GET /api/items/{key} -> 原始字段(编辑表单) +PATCH /api/items/{key} {updatedAt, item} 需登录 +POST /api/items/{key}/view +POST /api/items/{key}/like {liked} + +POST /api/categories {id,title,kind} 需登录 +DELETE /api/categories/{id} 需登录,级联,local 不可删 + +GET /api/backup SQLite 快照附件 需登录 +``` + +## 5. 数据库与迁移 + +- 文件:开发态在 `target/debug/data/stash.db`;可用 `--root` / 数据目录覆盖(见 `config.rs`)。 +- 当前 `PRAGMA user_version = 17`;`schema::migrate` 逐级升级:0 建全量、15→16→17、更高版本拒绝启动。 +- 主要表:`node`、`entry`、`entry_tag`、`section_block`、`admin`、`session`、`setting`、`audit`。 +- `entry.updated_at` 用于编辑乐观锁;`setting` 表 `key='site'` 存站点 JSON。 +- **设置/内容都是 SQLite**:备份用 `/api/backup`,恢复需停机替换文件。 + +## 6. 认证运维 + +- 忘记密码:删除 `admin` 行(或整库)后重启 → 回到首次设置。 + ```powershell + node -e "const {DatabaseSync}=require('node:sqlite');const d=new DatabaseSync('target/debug/data/stash.db');d.exec('DELETE FROM admin; DELETE FROM session;')" + ``` +- 改密码:`/admin → 系统`,成功后该账号所有会话失效,需要重新登录。 +- 首个管理员由 `/api/auth/setup` 创建,密码至少 8 位。 + +## 7. 组件库 `@stash/ui` + +- 41 个组件,文档站:`cd stash-ui && npm run dev`(也可 `npm run build:site` 后看 `dist-site`)。 +- 关键命令:`npm run typecheck && npm run lint && npm run build && npm run build:site`。 +- 组件契约:`docs/COMPONENTS.md`;设计规范:`DESIGN.md`;外部风格接入流程:`docs/STYLE-INTAKE.md`(闸门:截图 → 映射 → 决策 → 评审 → 再写代码)。 +- 主题:`themes/example.css` 只改变量;页面禁止写组件内部选择器。 +- **判断归属**:全局配置放 `/admin`;页面版式(间距、布局容器)写在页面 CSS;只有「第二个页面也复用」的才抽组件。 + +## 8. 验证与截图 + +- 后端逻辑:`cargo test`(48 passed,覆盖迁移/登录/设置/条目编辑/分区)。 +- 前端构建:`stash-web npm run build`(tsc -b + vite)。 +- 视觉/交互:Playwright 脚本在 `stash-ui/.ref/*.mjs`(不提交 git),截图在 `stash-ui/shots/`。 + - `measure-final.mjs` **已过时**(旧 1:1 对照用),选择器 `.app header` 仍可用; + - `c3-check.mjs`、`d-check.mjs`、`p2-check.mjs` 是后期功能检查脚本。 +- 常用冒烟:首页卡片、`/admin` 各 Tab、详情编辑、登录弹窗。 + +## 9. 已知限制 / 未做 + +| 项 | 状态 | +| --- | --- | +| 备份恢复/导入 | 只提供下载快照;恢复需停机替换 `stash.db` | +| 回收站/软删除 | 未做,删除分类会级联删条目(有二次确认) | +| 图片上传 | 只支持 URL;上传需存储目录、大小/类型校验 | +| 拖拽排序 | 用上移/下移按钮替代 | +| 多用户/角色 | 未做,当前单管理员 | +| 分区编辑 UI | 可新建/删除,但改标题/图标仍要改库(可后续补 `PATCH /api/categories/:id`) | +| 登录限流 | 进程内计数,重启清空 | + +## 10. 约定与坑 + +- 回复用中文,表格化优先;视觉工作要截图验证。 +- **任何共享组件改动**都要在 `docs/COMPONENTS.md` 补契约 + changelog,并说明兼容性。 +- PowerShell 写文件注意 UTF-8;优先用编辑工具,别用 `Set-Content` 写带中文的源码。 +- 改前端后必须 `npm run build` 再 `cargo build`,否则内嵌资源是旧的。 +- 重启前先杀 `stash.exe`,否则 cargo 报「拒绝访问」。 +- `/login` 是旧地址,`main.tsx` 会重定向到 `/`;登录已改为弹窗。 +- 前端路由:`/`、`/c/<分区>`、`/c/<分区>/<分组>`、`/c/<分区>/i/<条目>`,`/admin` 独立壳。 + +## 11. 新会话建议的下一步 + +1. 先跑 `cargo test` + 打开 8080 冒烟,确认基线; +2. 若要继续产品化:分区编辑(标题/图标/色条)、回收站、图片上传、拖拽排序; +3. 若要发布:确认 `stash-ui` 以 `file:` 引入的方式在发布构建里如何锁定版本(建议改为 git tag 依赖或构建前 `npm pack`)。