Files
stash/HANDOFF.md
T
CNWei fdfd17657c feat(search): 自定义引擎支持图标地址(png / svg)
- settings.search.engines[] 新增 icon:空=品牌图标/通用地球,'/' 开头走托管目录,或 http(s) 链接
- 后端校验图标地址(空 / 托管路径 / http(s),≤500 字符)
- 后台每张引擎卡加「图标地址」输入;前后台都用组件库 EngineIcon 的 src(<img> 渲染,SVG 静态不执行脚本)
- @stash/ui 0.3.4
2026-11-06 12:30:15 +08:00

14 KiB
Raw Blame History

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,本地服务:

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 内嵌,顺序不能反:

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 权限):

$env:TEMP = "D:\CNWei\CNW\Rust\stash\target\tmp"; $env:TMP = $env:TEMP
cargo test                    # 交接时 52 passed

组件库:

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 乐观锁。当前字段:

{
  "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) 链接):给了就用 <img> 渲染自己 的图标,留空回落到品牌图标 / 地球;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(当前保留)

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. 最近提交(主项目,倒序)

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 同款深色背景

组件库最近:

994436a feat(icons): 增加搜索引擎图标
46829cd feat(input): 增加左侧 leading 插槽
b97c77e feat(search): SearchField 增加 suffix 插槽

12. 新会话建议顺序

  1. 打开 http://127.0.0.1:8080 与 /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,确认工作区干净。