# Stash 交接文档 > 更新于 2026-11-04 19:30(Asia/Shanghai)。本文件是当前状态,取代旧版历史快照。 > 新会话先读这份,再按需看 `README.md`、`docs/ADMIN-PLAN.md`、`stash-ui/README.md`。 ## 1. 一句话现状 Stash 是「本地项目托管 + 可配置导航首页」:Rust 单 crate 内嵌 React 前端,单管理员登录,内容库为 SQLite,分组 / 条目 / 首页卡片 / 站点设置都在 `/admin` 管理。 当前开发分支 `develop`,本地服务: - 前台 + 后台: - 管理后台: - 接口一览: - Vite 开发服务器 `5173` 当前**未运行**;需要时 `cd stash-web && npm run dev` ## 2. 仓库与分支 | 仓库 | 路径 | 分支 | 状态 | | --- | --- | --- | --- | | 主项目 | `D:\CNWei\CNW\Rust\stash` | `develop` | 工作区干净;功能最新 `1d1ece6`,本文件随后单独提交 | | 组件库 | `D:\CNWei\CNW\Rust\stash-ui` | `master` | 工作区只有忽略的 `.idea/`;`994436a` 最新 | - 主项目 remote 名为 `master`(不是 `origin`),地址 `https://gitea.ngmao.com/CNWei/stash.git`。 - `develop` 比 `master/develop` **领先 20 个提交,尚未推送**;此前 HTTPS 凭据不可用,需要时先准备 Gitea 凭据。 - `stash-ui` 也有 3 个未推送提交:`b97c77e`(SearchField suffix)、`46829cd`(Input leading)、`994436a`(EngineIcon)。 - `@stash/ui` 以 `file:../../stash-ui` 引入,`stash-web` 使用其 `dist/`;改组件库后必须重新 `npm run build`。 ## 3. 启动 / 构建 / 测试 前端产物会被 `build.rs` 内嵌,顺序不能反: ```powershell cd D:\CNWei\CNW\Rust\stash\stash-web npm run build # tsc -b + vite,产物 dist/ cd D:\CNWei\CNW\Rust\stash Get-Process stash -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*stash\target*' } | Stop-Process -Force # 否则 exe 被占用 cargo build Start-Process .\target\debug\stash.exe ` -RedirectStandardOutput "$env:TEMP\stash.log" ` -RedirectStandardError "$env:TEMP\stash-err.log" -WindowStyle Hidden ``` 测试(Windows 下覆盖 TEMP 权限): ```powershell $env:TEMP = "D:\CNWei\CNW\Rust\stash\target\tmp"; $env:TMP = $env:TEMP cargo test # 交接时 52 passed ``` 组件库: ```powershell cd D:\CNWei\CNW\Rust\stash-ui npm run build # dist/stash-ui.js + .css + types ``` ## 4. 代码地图 ``` src/ main.rs / lib.rs 启动、参数、日志 config.rs 端口 / 数据目录 / 托管目录 server.rs 全部 API + 内嵌前端 + SPA 回落 listing.rs 托管目录扫描 watcher.rs 文件监听 + SSE 防抖 db/ mod.rs Db 门面 + 迁移/种子测试 schema.rs 建表、种子、v15→…→v23 迁移 auth.rs admin / session / argon2id settings.rs settings JSON + 校验 entries.rs 条目 CRUD、浏览、点赞、审计 groups.rs 分组树 CRUD / 移动 / 排序 cards.rs 卡片与勾选分组 catalog.rs 分组树 + 条目查询组装 stash-web/src/ AppNext.tsx 前台壳:路由、卡片、侧栏、搜索框、主题 main.tsx /admin 与普通前台分流 settings.ts SiteSettings 类型 / 默认值 / API 客户端 manage.ts 分组、卡片、catalog2 客户端 items.ts 条目编辑客户端 api.ts 项目扫描 / SSE 客户端 components/ admin/AdminNext.tsx 后台全部面板 header/SiteHeader.tsx 品牌 / 滚动信息 / 操作图标 content/ 卡片、网格、详情、编辑器 sidebar/ 资料卡、本地服务、导航 stash-ui/src/components/ SearchField / Input / EngineIcon 等 ``` ## 5. 数据库(v23) 路径:`target/debug/data/stash.db`(`--data` 可覆盖)。 - `PRAGMA user_version = 23`;支持 0 建全量、15→16→…→23 迁移,高于程序版本拒绝启动。 - 当前表:`admin`、`audit`、`card`、`card_group`、`entry`、`entry_tag`、`node`、`session`、`setting`。 - 当前数据(交接时):15 个 node、44 条 entry、5 张 card;`PRAGMA foreign_key_check` 无异常。 - `section_block` 与 `node.view_mode / empty_text / show_in_sidebar / allow_groups` 已在 v23 删除。 - `entry.format` 是每条内容自己的 `apps / posters / articles`,同一分组可混合。 - `node.kind = 'section'` 是根分组,`group` 是子分组;`enabled` 控制整棵子树显示。 - 条目只存 `node_key`;格式、分组、卡片都通过业务 key 关联。 - 备份:`target/debug/data/stash.db.bak-pre-cleanup-v22` 是 v23 改造前快照;`/api/backup` 可下载当前快照。 - **不要直接 `cargo clean`/删除整个 `target`**:运行库和备份在 `target/debug/data/`。 ## 6. settings JSON `setting` 表 `key='site'`,API `GET/PATCH /api/settings`,`version` 乐观锁。当前字段: ```jsonc { "header": { "enabled": true, "speed": 24, "gap": 26, "items": [...] }, "sidebar": { "show_profile": true, "show_service": false, "show_nav": true }, "background": { "light": "", "dark": "" }, // 空 = 内置背景 "font": { "source": "builtin", "current": "", "items": [] }, // builtin = 文楷;custom = 用 items 里 current 那条 "search": { "default": "internal", "engines": [ { "id": "google", "name": "Google", "url": "https://www.google.com/search?q={query}", "icon": "", "enabled": true }, { "id": "bing", "name": "Bing", "url": "https://www.bing.com/search?q={query}", "enabled": true }, { "id": "baidu", "name": "百度", "url": "https://www.baidu.com/s?wd={query}", "enabled": true }, { "id": "sogou", "name": "搜狗", "url": "https://www.sogou.com/web?query={query}", "enabled": true }, { "id": "360", "name": "360", "url": "https://www.so.com/s?q={query}", "enabled": true } ] }, "profile": { "name": "...", "role": "...", "description": "...", "location": "...", "avatar": "" }, "site": { "title": "...", "favicon": "", "theme": "light", "brand": {...}, "actions": {...} } } ``` - `search.default` 可以是 `internal` 或某个引擎 id;默认默认值是 `internal`。 - 上面是字段结构示例;实际值以 `GET /api/settings` 为准(交接时 `search.default=internal`、`site.theme=light`,background 两项使用自定义 picsum 图)。 - 外部引擎 URL 必须以 `http(s)://` 开头并包含 `{query}`,否则后端 400。 - 引擎 id 只能用小写字母 / 数字 / `-` / `_`(1–30 位,`internal` 保留);内置五个用品牌图标, 后台新加的引擎 id 自动生成为 `custom-xxx`、图标用通用地球(组件库 EngineIcon 自动回落)。 - 每个引擎可带 `icon`(png / svg 地址,`/` 开头的托管路径或 http(s) 链接):给了就用 `` 渲染自己 的图标,留空回落到品牌图标 / 地球;SVG 走 img 是静态的,不执行脚本。 - `background.light/dark` 为空时用内置 `stash-web/src/assets/site-bg.jpg` / `site-bg-dark.jpg`;否则填托管目录 `public/` 路径或完整 URL。 - 旧 settings JSON 缺失字段会自动回落默认值;多余旧字段在下次保存时被丢弃。 ## 7. 当前功能 / 后台 IA 后台左侧导航: - **分组管理**:根分组 / 子分组树、编辑、移动、排序、启停、删除; - **数据管理**:按主分组列出条目(含子分组),每条可选格式; - **首页管理** - 页头:开关、速度、滚动条目、品牌 / 图标 / 配色; - 背景管理:亮色 / 暗色背景 URL + 预览 + 恢复内置; - 搜索框:默认搜索项、外部引擎的名称 / URL / 启停、添加 / 删除自定义引擎、恢复默认; - 侧边栏:资料卡 / 本地服务 / 分组导航显隐; - 内容卡片:卡片 + 勾选分组 + 预览条数 + 排序; - **资料管理**:头像、名称、角色、简介、位置; - **系统管理**:改密码、下载备份、正文字体(先选内置 / 字体链接;链接模式下可存多套字体,启用其中一条)。 搜索框行为: - 顶部悬浮标签显示当前引擎图标 + 名称,点击展开下拉; - 第一项固定「站内搜索」,分隔线后是启用的外部引擎; - 站内模式:输入过滤本地内容;回车打开第一个匹配条目/分组; - 外部模式:输入**不再过滤**本地内容;回车用该引擎 URL 新标签页搜索; - 当前选择存在本机 localStorage(`stash-search-engine`),刷新后仍用它;引擎被停用 / 删除时回落到后台默认项。 主题: - 深色背景来自 Alright 演示站,资源 `site-bg-dark.jpg`; - 明暗切换优先用 View Transition 整页快照交叉淡入(160ms),不支持时回退到 CSS 颜色过渡; - 首帧由 `index.html` 内联脚本按 localStorage / 系统偏好先上色; - 背景地址也缓存在 localStorage(`stash-background`),刷新首帧直接用它,设置回来再校准,不会先闪内置背景; - 页头图标显示**当前**实际明暗(深色月亮 / 浅色太阳),点它是切到另一侧; - 背景图两层(light/dark)交叉淡入。 ## 8. HTTP API(当前保留) ```text GET /api/health GET /api/projects GET /api/projects/events (SSE) GET /api/catalog2 分组树 + 卡片 GET /api/catalog/events SSE:catalog 变化 GET /api/settings PATCH /api/settings 需登录,{version,settings} GET /api/fonts font/ 目录里的字体清单(公开读) POST /api/nodes 需登录 PATCH /api/nodes/{key} 需登录 DELETE /api/nodes/{key} 需登录 POST /api/cards 需登录 PATCH /api/cards/{id} 需登录 DELETE /api/cards/{id} 需登录 PUT /api/cards/{id}/groups 需登录 GET /api/items/{key} POST /api/items 需登录 PATCH /api/items/{key} 需登录 DELETE /api/items/{key} 需登录 POST /api/items/{key}/view POST /api/items/{key}/like GET /api/backup 需登录 GET /api/auth/session POST /api/auth/setup / login / logout PATCH /api/auth/password ``` 已删除:`/api/catalog`、`/api/categories/*`、旧 `/api/groups/{id}`。 ## 9. 组件库改动(stash-ui) - `SearchField` 新增可选 `suffix` 与 `leading` 插槽; - `Input` 新增 `leading` ReactNode,优先于 `icon`; - 新增 `EngineIcon`(`internal/google/bing/baidu/sogou/360`),图标路径来自参考稿;`18px` 默认、`14px` 用于顶部小标签; - 构建产物已更新,`stash-web` 通过 file 依赖读取;改库后必须重建 dist,否则主项目构建仍用旧类型/资源。 ## 10. 已知限制 / 坑 | 项 | 说明 | | --- | --- | | 推送 | 本地 `develop` 领先远端 20 个提交,尚未推送;Gitea HTTPS 凭据需准备 | | 搜索引擎 | 内置五个(有品牌图标)+ 后台添加的自定义引擎(最多 10 个,通用地球图标) | | 搜索选择记忆 | 存本机 localStorage(`stash-search-engine`);换设备 / 清站点数据后回到后台默认 | | 图片上传 | 背景 / 头像 / Logo 只支持 URL,不支持上传 | | 卡片/分组拖拽 | 排序用数值 / 现有 SortableList;分组拖拽排序未做 | | 备份恢复 | 只有 `/api/backup` 下载;恢复需停机替换库文件 | | 旧接口 | 已删;不要再按旧文档调用 `/api/catalog` 或 categories | | 双份示例 | `public/git_helper/` 是 Rust 托管示例;`stash-web/public/git_helper/` 是 Vite dev 示例,**两份都保留** | | exe 占用 | 重启/构建前先杀 stash.exe,否则 `cargo build` 拒绝访问 | | 编码 | 源码 UTF-8;PowerShell 控制台可能显示乱码,以 read 工具为准,别用 Set-Content 改中文源码 | ## 11. 最近提交(主项目,倒序) ```text 1d1ece6 fix(group): 分组面包屑保留详情页外框 9d1e5dc fix(group): 分组页面包屑与详情页统一 4862f8f fix(search): 外部引擎模式不再过滤本地内容 aa6f341 feat(search): 按参考稿重做搜索框并支持后台配置 5ae2088 style(search): 引擎图标恢复 18px 200908c style(search): 引擎图标统一使用组件库图标 56f362f feat(search): 点击放大镜切换搜索引擎 8c1c658 feat(search): 效果五快捷栏加入本地搜索 038b7ec feat(search): 搜索框支持切换搜索引擎 a5d7859 fix(theme): 用整页快照过渡消除明暗割裂 5439ebf feat(admin): 增加背景管理 b9005dd style(theme): 暗色使用 Alright 同款深色背景 ``` 组件库最近: ```text 994436a feat(icons): 增加搜索引擎图标 46829cd feat(input): 增加左侧 leading 插槽 b97c77e feat(search): SearchField 增加 suffix 插槽 ``` ## 12. 新会话建议顺序 1. 打开 与 `/admin` 冒烟;确认 8080 在跑(当前 PID 会变,不必依赖 PID)。 2. 改前端:`cd stash-web && npm run build` → 杀 stash → `cargo build` → 启动。 3. 改组件库:先 `cd stash-ui && npm run build`,再构建 `stash-web`,最后 Rust。 4. 改设置结构:同时改 `src/db/settings.rs`、`stash-web/src/settings.ts`、后台面板和默认值;旧 JSON 由 serde 默认值兜底。 5. 改数据库结构:升 `SCHEMA_VERSION` 并补迁移与迁移测试;先备份 `target/debug/data/stash.db`。 6. 视觉改动用 Playwright 截图到 `stash-ui/shots/` 验证;脚本在 `stash-ui/.ref/`(不提交)。 7. 收尾跑 `cargo test`(52 条)和 `npm run build`,确认工作区干净。