feat(front): 前台切换到分组树 + 卡片组合

- 新 AppNext:首页按 /api/catalog2 的卡片勾选渲染(支持混合格式、每组条数),侧栏按分组树 + tree_hidden 渲染
- 分组页 /g/<key>、条目页 /g/<key>/i/<id>;条目在子树内递归查找,面包屑显示祖先链
- SPA 回落增加 /g/ 前缀;旧 /c/... 地址兼容
- 文档同步(路由、API、v19、限制)
- 测试 59 passed;Playwright 验证首页/混合卡片/分组页/条目页/侧栏隐藏
This commit is contained in:
2026-10-30 20:45:39 +08:00
parent 2ccfb9b623
commit 165d3f112e
7 changed files with 641 additions and 27 deletions
+27 -18
View File
@@ -94,18 +94,18 @@ README.md 运行、路由、库结构、登录说明
- 会话:随机 32 字节 token,HttpOnly + SameSite=Strict + Path=/,7 天,库里存 sha256;
- 登录失败 5 次锁 60 秒;写接口校验 Origin;写接口需要会话。
### `/admin`
### `/admin`(新原子模型)
| Tab | 能力 |
| --- | --- |
| 页头滚动信息 | 启用开关、速度 8–120、条目增删/排序、标签与色调、占位符 `{count}` `{project}` `{status}` |
| 首页卡片 | 显示/隐藏、标题覆盖、预览条数、顺序、**新增分类**、**删除分类**(不可删的显示灰色按钮) |
| 内容 | 弹窗新增应用/海报/图文条目(选分区;开启子分组的分区可选分组或「直属分区」);列表逐条编辑(含换分区/分组)与删除 |
| 分区 | 分区类型(应用/海报/图文)、标题、图标、色条、预览条数、**「子分组」开关(拨动即保存)**;开关打开时管理分组与首页卡片预览 |
| 侧栏导航 | 分类显示/隐藏、顺序、删除/新增;开启子分组的分区可显隐/排序/新建分组;空分组不出现在侧栏 |
| 资料 | 头像 URL、名称、角色、简介、位置(应用到侧栏资料卡) |
| 系统 | 修改密码(清空所有会话)、下载备份(VACUUM INTO 快照) |
| 分组管理 | 多层分组树:新建根/子分组、改名、根分组格式(应用/海报/图文)、删除(级联子分组与条目) |
| 内容 | 选分组新增/编辑/删除条目;条目只属于一个分组 |
| 侧边栏 | 分组树逐项勾选(`settings.sidebar.tree_hidden`),子分组可单独勾选 |
| 首页卡片 | 新建/改名/删除卡片;勾选若干分组(可混合格式),每组单独设条数 |
| 页头 | 启用开关、速度、条目、标签与色调 |
| 资料 | 头像 URL、名称、角色、简介、位置 |
| 系统 | 修改密码、下载备份 |
保存:页头 / 首页卡片 / 资料走 `PATCH /api/settings`(`version` 乐观锁,冲突 409);「内容」「分区」逐项保存(条目、分区、分组各自接口);成功用 Toast(2.4s 自动消失)。
保存:分组/内容/卡片逐项保存;侧边栏、页头、资料走 `PATCH /api/settings`(`version` 乐观锁)。
### 内容编辑
- 详情页 `[编辑]` 只在登录后显示;
@@ -124,7 +124,16 @@ README.md 运行、路由、库结构、登录说明
```
GET /api/health
GET /api/projects GET /api/projects/events (SSE)
GET /api/catalog GET /api/catalog/events (SSE)
GET /api/catalog GET /api/catalog/events (SSE) 旧结构(兼容)
GET /api/catalog2 分组树 + 卡片(新前台/后台)
GET /api/cards 卡片列表
POST /api/nodes {key,title,parentKey?,format?} 需登录
PATCH /api/nodes/{key} {title,parentKey?,sort?,format?} 需登录
DELETE /api/nodes/{key} 需登录,级联
POST /api/cards {title} 需登录
PATCH /api/cards/{id} {title?,sort?} 需登录
DELETE /api/cards/{id} 需登录
PUT /api/cards/{id}/groups [{groupKey,previewLimit}] 需登录
GET /api/auth/session -> {authenticated, has_admin, username}
POST /api/auth/setup {password} 仅当无管理员
@@ -155,8 +164,8 @@ GET /api/backup SQLite 快照附件 需登录
## 5. 数据库与迁移
- 文件:开发态在 `target/debug/data/stash.db`;可用 `--root` / 数据目录覆盖(见 `config.rs`)。
- 当前 `PRAGMA user_version = 18`;`schema::migrate` 逐级升级:0 建全量、15→16→17→18、更高版本拒绝启动。
- `node.allow_groups` 是「允许子分组」开关(与类型无关);老库升级时应用类默认开启,其余默认关闭,已有分组的非应用分区自动开启。
- 当前 `PRAGMA user_version = 19`;`schema::migrate` 逐级升级:0 建全量、15→16→17→18→19、更高版本拒绝启动。
- `node` 是统一分组树(根节点 `kind='section'` 带 `view_mode` 格式,子节点 `kind='group'` 可多层);`card` / `card_group` 是首页卡片的展示组合(卡片不拥有内容)。
- 主要表:`node`、`entry`、`entry_tag`、`section_block`、`admin`、`session`、`setting`、`audit`。
- `entry.updated_at` 用于编辑乐观锁;`setting` 表 `key='site'` 存站点 JSON。
- **设置/内容都是 SQLite**:备份用 `/api/backup`,恢复需停机替换文件。
@@ -192,13 +201,13 @@ GET /api/backup SQLite 快照附件 需登录
| 项 | 状态 |
| --- | --- |
| 备份恢复/导入 | 只提供下载快照;恢复需停机替换 `stash.db` |
| 回收站/软删除 | 未做,删除分类会级联删条目(有二次确认) |
| 回收站/软删除 | 未做,删除分组会级联删子分组与条目(有二次确认) |
| 图片上传 | 只支持 URL;上传需存储目录、大小/类型校验 |
| 拖拽排序 | 用上移/下移按钮替代 |
| 拖拽排序 | 分组/卡片顺序暂用创建顺序;上移下移/拖拽未做 |
| 多用户/角色 | 未做,当前单管理员 |
| 分区编辑 UI | 已支持标题/图标/色条/类型/预览条数(`PATCH /api/categories/{id}`);改类型会自动迁移条目 |
| 条目移动 | 编辑弹窗里可直接换分区 / 分组(`PATCH /api/items/{key}` 的 `nodeKey`) |
| 分组管理 | 由分区的「子分组」开关控制(与类型无关);关闭时条目平铺、分组内容不丢;分组拖拽排序未做 |
| 分组移动 UI | 后端 `PATCH /api/nodes/{key}` 支持 `parentKey` 移动与防环;后台暂未暴露移动入口 |
| 条目移动 | 内容弹窗里可直接换分组(`PATCH /api/items/{key}` 的 `nodeKey`) |
| 旧接口 | `/api/catalog`、`/api/categories/*`、`/api/groups/*` 仍保留给旧组件/兼容,后续可删 |
| 登录限流 | 进程内计数,重启清空 |
## 10. 约定与坑
@@ -209,7 +218,7 @@ GET /api/backup SQLite 快照附件 需登录
- 改前端后必须 `npm run build` 再 `cargo build`,否则内嵌资源是旧的。
- 重启前先杀 `stash.exe`,否则 cargo 报「拒绝访问」。
- `/login` 是旧地址,`main.tsx` 会重定向到 `/`;登录已改为弹窗。
- 前端路由:`/`、`/c/<分区>`、`/c/<分区>/<分组>`、`/c/<分区>/i/<条目>`,`/admin` 独立壳。
- 前端路由:`/`、`/g/<分组 key>`、`/g/<分组 key>/i/<条目>`;旧 `/c/...` 地址按第一个路径段当分组 key 兼容,`/admin` 独立壳。
## 11. 新会话建议的下一步