Files

104 lines
9.9 KiB
Markdown
Raw Permalink Normal View History

2026-09-20 00:28:52 +08:00
# status.md — 计划与进度记录
> 本文件由 agent 自动维护,规则见 [AGENTS.md](AGENTS.md) 末尾的"本地 fork 维护规则"一节。
> 新条目加在"进行中"区域顶部;完成后移入"已完成"。
## 进行中
(暂无)
## 已完成
### [2026-09-19] 缩略图路径 DB 点查缓存(find_attached_blob 进程内缓存)
- **状态**: 已完成(commit `d33d1932`;cargo fmt --check ✓;clippy --all-features --all-targets -D warnings 0 警告 ✓;`cargo test --lib` 927 通过 0 失败,含新增 5 个缓存契约测试 ✓)
- **计划**: 给缩略图热路径(ETag 计算 `thumbnail_content_id` + tier 2b)每次请求都要打的 `find_attached_blob` DB 点查加进程内缓存(moka::future + try_get_with,正+负缓存,Err 不入缓存;写路径成功后失效;删除经 `ThumbnailRefreshHook::on_file_deleted` 搭车失效 + 60s TTL 兜底)。缓解"每次进照片墙 = 每张可见图 1-2 次 DB 点查"的负载。
- **改动文件**:
- `src/infrastructure/services/dedup_service.rs` — 模块顶 `ATTACHED_BLOB_CACHE_*` 常量 + `AttachedBlobKey` + `AttachedLookupFault`;`attached_blob_cache` 字段/`build_attached_blob_cache`;`find_attached_blob` 缓存包装(SQL 下移 `find_attached_blob_uncached` 返回 `sqlx::Result`,Err 永不入缓存);`store_attached_blob`/`store_attached_blob_if_absent` 成功路径失效(`Inserted` 臂失效 + AlreadyPresent 读回注释);`invalidate_attached_blobs_for_file`;5 个纯内存单测
- `src/infrastructure/services/thumbnail_service.rs` — `ThumbnailRefreshHook::on_file_deleted` 搭车失效(补 `self.dedup.clone()`)
- `docs/architecture/caching.md` — Layer 1 表新增 Attached blob 行 + "The attached-blob cache" 小节(键/正负缓存/两条诚实规则)
- `docs/architecture/derived-and-attached-blobs.md` — Lifecycle 节新增"Reads are cached"段落(缓存失效协议)
- **仅本地文件**: 无新增(`status.md` 本身)
- **上游冲突风险**: 低 — 两个上游文件均为局部追加,无重排
- **备注**: 本机此前无 Rust 工具链,本次顺带装好 rustup stable 1.98.1(minimal+clippy+rustfmt)、VS Build Tools 2022(MSVC 14.44 + SDK 10.0.26100)、Node 前端构建(`static-dist/` 已生成)——后续 agent 可直接跑 `cargo` 检查;注意 shell 无管理员权限,提权操作需 UAC 确认
### [2026-09-19] 文档更新:公开分享端点与落地页行为
- **状态**: 已完成
- **计划**: 按 AGENTS.md 的文档约定,把本会话的分享相关修复/功能同步进架构文档与用户指南
- **改动文件**:
- `docs/architecture/share-integration.md` — 公开路由表补全(download/contents/file/zip 共 6 条);新增 "/file/{file_id} 文件作用域"(file 分享仅限分享项本身、folder 分享限子树、其余 404 反枚举)与"落地页 meta 富化"(mime_type/size 仅展示、查询失败不失败响应)两小节
- `docs/guide/sharing.md` — 新增 "What recipients see" 用户向小节(单文件内联预览/视频流式拖动、文件夹浏览 + ZIP)
- **上游冲突风险**: 低 — 两文档均属低频改动区
### [2026-09-19] 文件页刷新按钮
- **状态**: 已完成(vitest 467 通过;svelte-check 0 错误;我改的文件 prettier/eslint 全绿)
- **计划**: actions 工具栏加手动刷新,点击重拉当前文件夹列表
- **改动文件**:
- `frontend/src/routes/files/[...path]/+page.svelte` — "New folder" 右侧新增刷新按钮:`load(true)` 重置分页拉第 1 页,`loading` 时禁用,图标 `repeat`(沿用 AdminJobsPanel 先例),testid `files-refresh-btn`
- `frontend/static/locales/{en,zh,zh-TW}.json` — `common.refresh`(刷新 / 重新整理)
- `frontend/src/routes/files/page.test.ts` — 点击刷新 → `fetchFolderPage` 第二次调用
- **上游冲突风险**: 中 — files 页与 locales 是上游活跃区,但改动面小
### [2026-09-19] 文件页文件夹内容统计
- **状态**: 已完成(验证同上)
- **计划**: 进入文件夹时在面包屑旁显示内容统计
- **改动文件**:
- `frontend/src/routes/files/[...path]/+page.svelte` — `folderStat` derived(对 `rlItems` 即点文件过滤后的展示列表计数;分页未完时数字尾随 "+");统计 span 渲染在 breadcrumb snippet 内(`.rl-breadcrumb` 本身是 flex);空文件夹不显示
- `frontend/static/locales/{en,zh,zh-TW}.json` — `files.folder_stat`(其余 13 语言回退英文)
- `frontend/src/routes/files/page.test.ts` — 精确计数 / 分页 "+" 两条测试
- **上游冲突风险**: 中 — 同上
### [2026-09-19] 开发环境修复 + 测试 locale 固定
- **状态**: 已完成
- **计划**: 本机装 Node 跑前端检查;修复暴露出的换行符与 locale 问题
- **改动文件**:
- `frontend/src/lib/utils/time.test.ts` — `vi.spyOn(Intl, 'RelativeTimeFormat')` 固定 `en` locale(time.ts 用运行时默认 locale,中文系统上 `/second/` 等英文断言必挂);注意 mock 需普通函数(time.ts 经 `new` 调用)
- 环境级(无仓库 diff): winget 装 Node 26.7.0;`core.autocrlf=false`(仓库级)+ `git rm --cached -r . && git reset --hard` 全量重写工作区为 LF——修复 276 个文件的 Prettier 假报错
- **仅本地文件**: 无新增
- **上游冲突风险**: 低 — LF 归一化后与上游(CI 全 LF)一致;建议后续给 `.gitattributes` 加 `* text=auto eol=lf`(未做,待定)
### [2026-09-19] 文件页模糊筛选搜索 + 批量操作共享化
- **状态**: 已完成(`npm run check` 0 错误 0 警告;`vitest run` 467 个测试全部通过)
- **计划**:
1. 文件页(`/files/[...path]`)新增搜索过滤栏:关键词(防抖)+ 类型/大小/时间预设 + 递归开关,
筛选生效时列表切换为当前文件夹的递归搜索(`GET /api/search` 的 `folder_id`+`recursive`,
空 `query` 后端视为匹配全部),支持结果多选/全选 + 批量收藏/移动/复制/下载/删除
2. 批量操作提取为共享 composable,`/search` 结果页同步接入选择 + 批量操作(项目去重规范)
3. 两处页内裸 `apiFetch`(favorites/batch、batch/download)改为 endpoint 封装
- **改动文件**:
- 新增(仅本地):
- `frontend/src/lib/components/SearchFilterBar.svelte` — 搜索过滤栏组件(关键词 + 高级筛选 + 递归开关)
- `frontend/src/lib/composables/useResourceActions.svelte.ts` — 共享批量操作(收藏/下载/删除/移动/复制 + MoveDialog 状态)
- `frontend/src/lib/utils/searchFilters.ts` — 类型/大小/时间预设模型 → `SearchOptions` 映射
- `frontend/src/lib/utils/mapLimit.ts` — 有界并发工具(自文件页提取)
- 以上各文件的 Vitest 测试(`*.test.ts`)
- 修改(上游文件):
- `frontend/src/routes/files/[...path]/+page.svelte` — 搜索模式状态/`runSearch`/模式切换/Escape 优先级/深链兼容;批量 handler 换用 composable
- `frontend/src/routes/search/+page.svelte` — 接入选择 + 批量操作;筛选逻辑改用共享 searchFilters;MoveDialog 绑定 composable
- `frontend/src/lib/api/endpoints/batch.ts` — 新增 `downloadBatch()`
- `frontend/src/lib/api/endpoints/favorites.ts` — 新增 `addFavoritesBatch()`
- `frontend/src/routes/files/page.test.ts`、`frontend/src/routes/search/page.test.ts` — mock 补齐 + 新增搜索模式/批量删除测试
- `frontend/static/locales/*.json`(16 个语言文件)— 新增 `filter.*` 6 个 key(zh/zh-TW 为真实翻译)
- **仅本地文件**: `status.md`、上述新增的 4 个源文件及其测试
- **上游冲突风险**: 高 — locales 与两个页面文件是上游活跃区;页面文件改动较大(files 页 ~490 行、search 页 ~170 行 diff),合并时需逐块核对本地意图
- **设计要点**(合并上游时用于核对行为):
- 批量操作参数化接口:`getItems/getSelected/clearSelection/onChanged/afterDelete` 回调注入;
文件页 `getItems` 按模式切换(`searchActive ? searchItems : orderedItems`),`onChanged` 按模式重跑搜索或重载目录
- 删除保持 per-item `mapLimit(ids, 6)` 行为(后端 `POST /api/batch/trash` 批量软删存在,切换记为可选后续)
- 搜索分页 limit 50;"全选"只覆盖已加载页(与 ResourceList 既有语义一致)
- 文件页搜索 wire 层 `type` 排序映射为 `name`(`SortBy` 无 type),`modified_at` 映射为 `updated_at`;始终传 sortBy 不传 relevance
- Escape 优先级:清除选中 → 清除筛选;过滤输入框内 Escape 自行处理并 stopPropagation
### [2026-09-15] 单文件分享无法流式预览修复
- **状态**: 已完成(commit `68e21f4b`;本机无 Rust 环境,fmt/clippy/api-test 未能在本地运行——**push 前需在有 Rust 的环境跑 `just check` + `just api-test`**)
- **计划**: 修复单文件分享落地页预览窗口无内容/按钮失效——根因是 `resolve_folder_share` 对 `item_type != "folder"` 一律拒绝,`/api/s/{token}/file/{id}` 对 file 分享返回 400
- **改动文件**:
- `src/application/services/share_browse_service.rs` — `assert_file_in_share` 改为按 `item_type` 分支:file 分享仅接受 `file_id == share.item_id`;folder 分享维持 ltree 子树校验;其余一律 404(反枚举,保持与"文件不存在"同形)
- `src/interfaces/api/handlers/share_handler.rs` — OpenAPI `file_id` 参数描述同步("the shared item itself, or a file inside the shared folder's subtree")
- `tests/api/public_shares.hurl` — 8b 节扩展:file 分享 token 流式取自身 item(200 + disposition)+ 局外人 id 404 断言
- **仅本地文件**: 无
- **上游冲突风险**: 中 — `share_browse_service.rs` 属上游安全敏感活跃区;改动集中在单个函数,冲突时按"file 分享限自身、folder 限子树、其余 404"核对意图
## 上游合并记录
(暂无。首次合并前先 `git remote add upstream <上游仓库地址>`。)