Files
Oxicloud/status.md
T
cjw 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
docs(status): record filter-merge task completion (29d0c335)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-27 20:00:03 +08:00

14 KiB
Raw Blame History

status.md — 计划与进度记录

本文件由 agent 自动维护,规则见 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 <上游仓库地址>。)