deb6dc831b
CI / Frontend end-to-end tests (via Playwright) (push) Blocked by required conditions
CI / changes (push) Waiting to run
CI / Frontend — svelte-check, ESLint, Stylelint, Prettier (push) Blocked by required conditions
CI / Message-bus spec — AsyncAPI + TypeScript DTO drift (push) Blocked by required conditions
CI / Migration ordering (new migrations postdate target branch) (push) Blocked by required conditions
CI / Rustfmt (push) Blocked by required conditions
CI / Clippy (push) Blocked by required conditions
CI / Wasm — fmt + clippy (push) Blocked by required conditions
CI / Wasm — release tests (push) Blocked by required conditions
CI / Plugins — fixtures + runtime tests (push) Blocked by required conditions
CI / Server Unit and Functionnal Tests (push) Blocked by required conditions
CI / Security Audit (push) Blocked by required conditions
CI / Build (push) Waiting to run
CI / API, WebDAV & OIDC tests (push) Blocked by required conditions
CI / Bundled-assets binary — embed + SPA-serve integration (push) Blocked by required conditions
CI / WebDAV RFC 4918 — litmus (59/59) (push) Blocked by required conditions
CI / CalDAV + CardDAV — python-caldav (push) Blocked by required conditions
Docker Build and Test / Build and Test Docker Image (push) Waiting to run
Docker Publish (release, main, dry-run) / Pre-publish Tests (push) Waiting to run
Docker Publish (release, main, dry-run) / Build & Push Multi-Arch (push) Blocked by required conditions
Co-Authored-By: Claude Code <noreply@anthropic.com>
128 lines
14 KiB
Markdown
128 lines
14 KiB
Markdown
# status.md — 计划与进度记录
|
||
|
||
> 本文件由 agent 自动维护,规则见 [AGENTS.md](AGENTS.md) 末尾的"本地 fork 维护规则"一节。
|
||
> 新条目加在"进行中"区域顶部;完成后移入"已完成"。
|
||
|
||
## 进行中
|
||
|
||
(暂无)
|
||
|
||
## 已完成
|
||
|
||
### [2026-09-21] 顶栏搜索框 × 筛选栏合并(并补齐筛选维度)
|
||
- **状态**: 已完成(commit `29d0c335`;`npm run check` 全绿:svelte-check 0 错 0 警 + eslint + stylelint + prettier;`vitest run` 492 通过 0 失败,连续两轮稳定)
|
||
- **计划**: 把上游顶栏搜索框与本地 `SearchFilterBar` 合并成一套筛选能力:顶栏搜索框内加筛选按钮 + 下拉面板(不动 70px 高度);文件页筛选栏保留,两处共享同一份筛选状态并同步到 URL(就地筛选行为不丢);`/search` 改为 URL 驱动、移除三个页内 select(改为可撤销 chips);同时补上后端已支持但前端未暴露的 `resource_types`(仅文件/仅文件夹)与创建时间维度。后端零改动。
|
||
- **改动文件**:
|
||
- 新增(仅本地):
|
||
- `frontend/src/lib/stores/filter.svelte.ts` — 共享筛选 store(模块级 `$state`,唯一真值)
|
||
- `frontend/src/lib/composables/useFilterUrlSync.svelte.ts` — store↔URL 双向同步(单 `$effect` + `lastSeenSearch` 回声抑制,一轮收敛不成环)
|
||
- `frontend/src/lib/components/FilterFields.svelte` — 5 个 select(类型/大小/修改/创建/条目种类)+ 递归开关,词表与 i18n 标签集中于此(inline/panel 两种布局)
|
||
- `frontend/src/lib/components/TopBarFilterPanel.svelte` — 顶栏下拉面板壳(清除/完成按钮,激活计数驱动 badge)
|
||
- `frontend/src/lib/components/FilterChips.svelte` — `/search` 可撤销 chips(按维度撤销 + 清除全部)
|
||
- 仅本地改造:
|
||
- `frontend/src/lib/utils/searchFilters.ts` — 新维度 `kind`/`created` + URL 序列化(`filtersFromParams`/`filterParamEntries`/`filterParamsToString`/`applyFilterParams`/`filterSearchOver`);测试 29 条
|
||
- `frontend/src/lib/components/SearchFilterBar.svelte` — 展开区改复用 `FilterFields`;`value` 为普通 prop(原地改共享代理,**故意不用 `$bindable`**,导入绑定不可再赋值)
|
||
- 上游文件:
|
||
- `frontend/src/lib/components/AppShell.svelte` — 搜索框内筛选按钮(右 44px,激活 badge)+ 面板接线;`searchActive`→`mobileSearchOpen`(CSS 类名不动);提交/建议吃筛选(`filterToSearchOptions`);Escape 链插入面板;全局点击关面板(`.search-container` 内不关)
|
||
- `frontend/src/lib/styles/ported/topbar.css` — 输入框右内边距 50→104px(预留 submit/筛选/清除三个控件)单行改动
|
||
- `frontend/src/routes/search/+page.svelte` — URL 驱动(`useFilterUrlSync(false)`)、删三个页内 select 与本地词表、接 `FilterChips`、`setScope` 只动 `in`/`scope`
|
||
- `frontend/src/routes/files/[...path]/+page.svelte` — 删本地 filter 状态改绑共享 store、`useFilterUrlSync(true)`、`folderTarget` 携带筛选参数(就地筛选/导航存活两不误)、驱动 effect 增加 `created`/`kind` 依赖
|
||
- `frontend/static/locales/*.json`(16 个)— `filter` 块新增 `modified_label`/`created_label`/`kind_label`/`kind.{all,file,folder}`(zh/zh-TW 真翻译,其余英文兜底;fr.json 按行拼接保持既有格式)
|
||
- 测试:`AppShell.test.ts`(+2:面板开关/预设随提交/清除)、`search/page.test.ts`(+2:URL 水合+chips、非法值回落)、`files/page.test.ts`(+2:深链水合+wire 参数、关键词写回恰好一次)、`searchFilters.test.ts`(扩到 31 条)
|
||
- **仅本地文件**: 上述 5 个新增源文件 + `status.md`
|
||
- **上游冲突风险**: 高 — `AppShell.svelte`、`topbar.css`、`routes/search/+page.svelte`、16 个 locale 均为上游活跃区。合并核对要点:① store 是唯一真值、URL 是投影(`lastSeenSearch` 回声抑制,勿改回双向各自 `goto`);② `?q=` 归属——files 页 `includeQuery=true`、`/search` 与顶栏 `false`(`applyFilterParams` 删 `q` 前先看该开关);③ `folderTarget` 三处 `goto` 带 `eslint-disable`(helper 内嵌 `resolve()`,规则看不穿);④ `filterSearchOver` 下沉在普通 `.ts` 是为避开 `.svelte.ts` 的 `prefer-svelte-reactivity`(勿移回 composable);⑤ 已知 dev-only 警告 `ownership_invalid_mutation`(共享代理按普通 prop 传入+原地改的既定设计,生产无影响)
|
||
|
||
|
||
### [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 <上游仓库地址>`。)
|