白
|
26523d1b54
|
feat(filelib): 操作日志模块——防篡改哈希链、组合查询与 CSV 导出
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-08-06 22:54:45 +08:00 |
|
白
|
c96ea60482
|
docs(adr): member-group ADR 改号 0028→0038,避免与 agent-config-folder-tree 撞号
|
2026-08-06 00:58:51 +08:00 |
|
白
|
dc271ff9f3
|
Merge branch 'maoyuanyang-main'
# Conflicts:
# hub/filelib-web/src/lib/GrantsPanel.svelte
# hub/filelib-web/src/lib/OverviewPanel.svelte
# hub/filelib-web/src/lib/types.ts
# hub/src/database/filelib/grantService.ts
|
2026-08-03 15:35:44 +08:00 |
|
ymy
|
53ef364af2
|
chore(filelib-web): 老师端左栏宽度对齐管理员后台(240px)
|
2026-07-31 15:06:08 +08:00 |
|
ymy
|
06aa6f0dfb
|
chore(filelib-web): 左栏加宽168->200px,标题与菜单间加横线
|
2026-07-31 15:02:59 +08:00 |
|
ymy
|
672f05c66a
|
chore(filelib-web): 左栏加「教研数据库」标题,用户身份+退出移至栏底,顶栏去掉身份区
|
2026-07-31 14:57:01 +08:00 |
|
ymy
|
e9cecbf071
|
chore(filelib-web): 放大网格图标(文件夹54->72/项目50->66/文件46->60),列宽118->132
|
2026-07-31 14:51:55 +08:00 |
|
ymy
|
d9cde19bdf
|
fix(filelib): 恢复保留原名,撞名报清晰错误而非自动加后缀(ADR-0035,supersede ADR-0033)
恢复不再改名;同名兄弟占位时抛 409 name_conflict_on_restore + 人话提示,
操作者自行重命名现有节点或彻底删除旧节点后再恢复。
|
2026-07-31 14:28:34 +08:00 |
|
ymy
|
d39ebed62e
|
fix(filelib-web): 卡片右键补 stopPropagation,不再被背景菜单覆盖(导致看不到删除等节点操作)
|
2026-07-31 14:16:20 +08:00 |
|
ymy
|
09338f355a
|
chore(filelib-web): 详情弹窗加删除按钮(MANAGE 专属,进回收站可恢复),删除入口不再只在右键菜单
|
2026-07-31 14:11:26 +08:00 |
|
ymy
|
beaa92de2e
|
feat(filelib): 彻底删除改与条目可见性同权(ADR-0034,supersede ADR-0031 仅管理员条款)
能删进回收站(MANAGE)的人就能清空;无关者 404(D8)。二次确认与
node.purge 审计不变;BinView 彻底删除按钮对全部可见条目开放。
|
2026-07-31 14:01:46 +08:00 |
|
ymy
|
9e38d1e011
|
fix(filelib): 恢复撞名不再死锁,自动改名「(已恢复)」(ADR-0033)
- restore 前查活跃兄弟:撞名则恢复为「原名(已恢复[/ N])」(截断计入
128 长度预算),同事务落审计并记 renamedFrom;API 返回最终名
- BinView toast 提示改名;测试补撞名/二次恢复用例
|
2026-07-31 13:52:23 +08:00 |
|
ymy
|
83a6b012b7
|
feat(filelib): 移除最近打开模块(ADR-0032,supersede ADR-0031 对应半部)
- FileLibRecentVisit 删表(手写迁移;表当日新建无生产数据)
- recentService/recentRoutes/RecentView 删除;GridLibraryView 埋点与
navTarget 跳转一并移除;types 清 RecentEntry
- 左栏保留 文件库/回收站(ADR-0031 回收站半部不受影响)
- breadcrumb 的 role 字段保留(独立可用的增量字段)
|
2026-07-31 13:39:18 +08:00 |
|
ymy
|
d072e9ec1e
|
feat(filelib): 老师端左栏导航:回收站 + 最近打开(ADR-0031)
- 回收站:listBin(祖先全活跃的已删顶点;管理员/直连 MANAGE 可见)、
restore(与 D15 对称只清本节点,落审计)、purge(仅管理员,pathIds 枚举
子树按深度降序分批硬删,绕过 self-FK RESTRICT)
- 最近打开:FileLibRecentVisit 表(filePath='' 兜底 PG 唯一索引),客户端
成功打开后上报(VIEW 门禁,upsert 刷新),列表 20 条,D8/D15 可见性过滤
- 前端:/app 左栏(文件库/最近打开/回收站);RecentView/BinView;
GridLibraryView 埋点 + navTarget 跳转(breadcrumb 建栈,role 已捎带)
- 测试:filelib-nav 集成 4 例;全套 79 例绿
|
2026-07-31 13:27:04 +08:00 |
|
ymy
|
0fd21e51f7
|
feat(filelib-web): 老师端文件库改网盘式网格浏览(下钻导航+右键菜单)
- 新 GridLibraryView:双击下钻文件夹/项目,面包屑+返回跳级,项目内文件同网格,
双击进 FileEditor 预览;工具条按上下文出新建文件夹/项目/文件
- 右键菜单(ContextMenu):打开/新建子文件夹/重命名/授权管理/详情/删除,
按节点 role 动态显隐;文件菜单:打开预览/下载/删除;空白处右键出新建+刷新
- GridCard 大图标卡片(琥珀文件夹/立方体项目/文档文件);授权与详情复用
GrantsPanel/OverviewPanel(Modal 加 maxW prop);Icon 补 5 个图标
- 管理后台 /database 保留树状 LibraryView 不动;后端零改动
|
2026-07-31 12:02:23 +08:00 |
|
ymy
|
39a2be6347
|
feat(filelib): 项目级授权恒生效,移除独立权限开关(ADR-0030)
- permission.ts: effectiveRole 删除 D11 冻结分支,输入不再含开关字段
- treeService: 停止读 FileLibProjectSettings;建项目不再写默认行
- grantService/routes: 删 setIndependentPermission 与 PUT 路由;节点详情 DTO 去掉 independentPermission
- filelib-web: 概览 tab 移除开关;NodeDetail 类型同步
- 测试: 单测/集成改为断言恒生效语义;ADR-0030 废除契约 D11/P5
- FileLibProjectSettings 表保留(存量行忽略,不再读写),审计词表保留历史读取
|
2026-07-30 22:27:45 +08:00 |
|
白
|
87bbf0bd57
|
feat(filelib-web): 刷新页面时保持树展开、选中节点、tab 与文件夹位置
|
2026-07-27 21:27:09 +08:00 |
|
白
|
8eda04f1d9
|
fix(filelib-web): 文件内容无变化时不提交 commit
|
2026-07-27 21:21:15 +08:00 |
|
白
|
1dab83f9db
|
feat(filelib): 项目新增修改历史 tab 并隐藏 version hash id
|
2026-07-27 21:19:59 +08:00 |
|
白
|
8c26c42e0c
|
feat(filelib-web): 编辑器增加 Typst 语法高亮支持
|
2026-07-27 21:02:02 +08:00 |
|
白
|
fe38d0b8a9
|
feat(filelib-web): 文件编辑改为模态框并集成 CodeMirror 语法高亮
|
2026-07-27 20:53:16 +08:00 |
|
白
|
e194670d74
|
feat(filelib-web): 文件面板支持资源管理器式文件夹导航与图标视图切换
|
2026-07-27 20:48:23 +08:00 |
|
白
|
3b544d99f4
|
feat(filelib): 导出改为下载 cph 编译的真实 PDF
|
2026-07-27 20:25:29 +08:00 |
|
ymy
|
947f969967
|
chore(filelib-web): 详情容器加宽到 1400px,宽屏下授权表格全列无遮挡;仅文件预览挤压时出横向滚动条
|
2026-07-27 17:00:41 +08:00 |
|
ymy
|
2e08c0a734
|
chore(filelib-web): 授权表格外套横向滚动容器,修删除列贴边与文件预览打开时表格挤压
|
2026-07-27 16:54:07 +08:00 |
|
ymy
|
fc908eaf3b
|
chore(filelib-web): 拉宽授权表格:容器 880→1120px,单元格留白/禁换行,长 id 截断+悬停全文
|
2026-07-27 16:47:05 +08:00 |
|
ymy
|
cc4d9d907c
|
chore(filelib-web): 授权成员单元格只留头像+名称,userId 与飞书 ID 拆为独立两列
GrantDto 增加 principalOpenId(USER 主体的 feishuOpenId),GROUP 行两列显示 —;
搜索过滤同步覆盖 openId。
|
2026-07-27 16:40:25 +08:00 |
|
ymy
|
ad1a464f22
|
chore(filelib-web): 授权成员单元格改用首字母圆形头像(复用 Avatar 组件)
|
2026-07-27 16:22:01 +08:00 |
|
ymy
|
12a1246a7a
|
chore(filelib-web): 移除添加授权弹窗底部的 8.1 规则提示语
|
2026-07-27 16:16:16 +08:00 |
|
ymy
|
be17f74fc2
|
chore(filelib-web): 文件库权限名称汉化(VIEW/EDIT/MANAGE → 只读/可编辑/可管理)
统一走新增共享常量 labels.ts ROLE_LABEL(与 OverviewPanel 既有文案一致);
覆盖授权表格与弹窗下拉、详情头 tag、树节点角标;API 传参仍用英文枚举。
|
2026-07-27 15:57:41 +08:00 |
|
白
|
4849a765da
|
fix(filelib): 授权表与侧栏展示 displayName 而非裸 userId
GrantDto 加 principalName:USER → User.displayName,GROUP → MemberGroup.name,
取不到行(用户/组已删)时回落为 principalId,与 /database/api/me 同一回落语义。
解析走批量 helper(两条 IN 查询,非 N+1),listGrants/putGrants/forceAdjustGrants
三个出口共用,保证 GET 与 PUT 响应同形状。组不按 archivedAt 过滤 —— 已归档组的
历史授权仍需显示名字,否则管理员无法辨认后收回。
principalName 是纯展示字段;写路径仍只认 principalId,不得据此做授权判断。
前端:
- GrantsPanel 主体列由裸 id 改为展示名,id 移入 title 供排查;收回确认框同步。
- LibraryView 侧栏身份区改用 $me.displayName(/me 早已返回,此前未消费)。
- types.ts 去掉重复声明的 Grant 与无引用的 GroupSearchResult。
集成测试断言三种情形(displayName / 组名 / 已删主体回落)。
|
2026-07-27 15:56:07 +08:00 |
|
白
|
82241afb56
|
feat(filelib)!: VersionStore 改为真 git,一项目一仓库
内存 store 换成 gitVersionStore:init 建目录并 git init,VersionId 是
commit hash,某文件的版本取 `git log -1 -- <path>`(D16 文件级版本不因
别的文件提交而失效)。删除也是一个 commit,旧版本仍可读。决策见 ADR-0030。
git 用 execFile 调系统二进制,不引依赖。每次调用钉死 --git-dir/--work-tree
并禁 hooks、隔离全局 gitconfig:项目仓库是老师上传的数据,而 storage root
默认就在本 repo 内,不钉死会让命令落到外层仓库上。
同时:
- 单文件上限改为 HUB_FILELIB_MAX_FILE_BYTES(缺省 10MiB),前端从
/database/config 读,不再两处硬编码
- commit 身份 name=displayName、email=<userId>@filelib.paradigm-edu.net;
message 缺省为「【用户名】修改了【路径】」,调用方显式传则优先
- 上传改走弹窗,路径与 commit 信息可手填(原先 prompt 只能填路径)
BREAKING CHANGE: VersionId 由计数器(v1/v2)变为 commit hash;
CommitRequest.author 由字符串变为 { userId, displayName? }。
旧 .version-store.json 不迁移,此前建的项目报 repo_not_found。
|
2026-07-27 15:55:01 +08:00 |
|
ymy
|
0dd2ae347e
|
feat(filelib-web): 授权面板表格化:搜索、添加弹窗、权限下拉与成员跳转
- GrantsPanel 重写为表格:顶部左侧授权成员搜索框(名称/id/类型过滤),
右侧「添加授权」弹窗(类型 + 主体搜索选择 + 权限);行内权限下拉
直接改级(复用 PUT upsert),操作列删除;成员单元格跳转用户管理
(?q= 过滤)或 Group 管理(?select= 选中)。
- grantService: GrantDto 增加 principalName,list/put/force 三处统一
批量回填(用户 displayName / 组 name),前端不再只显示裸 id。
- 用户管理页加过滤框并从 ?q= 初始化;GroupAdmin 支持 ?select= 直达。
- 测试:resetDb 补 MemberGroup 三表清理(全局表不被 org/user 级联清到,
此前跨用例污染导致级联软删用例断言失败);cph_hub_test 补 migrate。
- 顺带合并 types.ts 里重复的 Grant 声明(interface 合并残留)。
|
2026-07-27 15:13:57 +08:00 |
|
白
|
a306c58db2
|
fix(filelib-web): 退出登录后管理后台真正跳回登录页
管理后台外壳把「未登录跳 /database/admin」写在 onMount 里,只判断一次。
但 logout() 只清前端 store(它与老师端 /app 共用,那边 me=null 是终态、
不跳转),退出后这层壳重新渲染进 me===null 分支,onMount 不会再跑,
于是永远停在「跳转到登录页…」。
把这道权限门移到 $effect,对任何一次「变成未登录」都生效。条件里的
$authChecked 是必要的 —— 否则首屏 session 请求未回时 me 仍是初始 null,
会把已登录用户直接弹去登录页。
顺带修好「无权访问管理后台」分支里同一个死胡同的退出按钮。
/auth/logout 的 204 本身没有问题。
|
2026-07-27 14:24:11 +08:00 |
|
ymy
|
91afd3c1b1
|
fix(filelib-web): 文件库树加载失败时显示错误而非永久加载中
|
2026-07-27 14:09:35 +08:00 |
|
白
|
cdeb29ccf2
|
fix(database): 补回文件库的「授权」tab 与 /me 的显示名
迁移时整个授权 tab 连同四个端点一起漏掉了 —— 后端一直可用,前端零调用:
GET/PUT/DELETE /nodes/:id/grants
PUT /projects/:id/independent-permission
权限编辑是这个后台的核心用途,而它此前在界面上完全不可达。
tab 组装也修正为与旧 libraryBrowser 一致:概览恒有、文件仅 PROJECT、
授权仅 MANAGE。注意文件夹也有授权 tab —— 它虽是透明组织节点,授权仍
挂在节点上(ADR-0021);此前文件夹一个 tab 都没有。
GrantsPanel 的语义按契约 8.1:创建者授权不给收回入口;MANAGE 仅创建者
可授,前端不拦,后端 fail closed 的报错原样呈现;GROUP 主体走
/groups/search 下拉选,不手敲 id。
/database/api/me 加 displayName 与 avatarUrl:侧栏此前显示原始 userId。
旧页面是服务端渲染,handler 里查 Prisma 就有名字;页面不再服务端渲染后
(ADR-0029),模板闭包过的数据也是被迁移的契约的一部分,不是旧实现的
无关细节。
概览面板同时补回丢失的「类型」「更新时间」两行、导出 target 下拉、
节点标题旁的角色 tag,以及整块缺失的独立权限开关。
|
2026-07-26 20:19:47 +08:00 |
|
白
|
eeb8f56742
|
fix(filelib-web): 补齐 Group 管理面板,与旧后端面板逐条对齐
迁移时误把分支上一个早先存在的简易 GroupAdmin(281 行)当成迁移产物,
它与旧 renderGroupsPanel(747 行)从来不是同一个东西,于是后端 8 个
group 端点前端只调了 5 个。
补上的功能(端点一直可用,只是没有入口):
PATCH /groups/:id 重命名 / 改描述
GET /groups?includeArchived=1 列出已归档组
POST /groups/:id/restore 恢复(连带恢复已归档祖先链,子树仍归档)
GET /users/search 成员选择器,不再手敲 userId
影响最实际的是恢复:软删的组此前在界面上无法恢复。
补上的交互:折叠树、组名过滤(命中项保留整条祖先链,过滤态强制展开)、
右键菜单(归档组只给「恢复」)、面包屑、统计条、树底部计数、成员表的
头像/openId/加入时间三列。
types.ts 之前也是截断的:MemberGroupNode 少 archivedAt,
MemberGroupMember 少 feishuOpenId/avatarUrl/joinedAt —— 类型里没有,
UI 自然渲染不出来。
一处实现偏离:折叠状态用数组而非 Set。Svelte 5 的 $state 深层代理不
跟踪 Set 变更,用 Set 会点了没反应。
groups tab 外框补 padding:20px/overflow:hidden,对齐旧 #tab-groups,
否则面板贴着侧边栏。
|
2026-07-26 20:19:30 +08:00 |
|
白
|
325b4fc137
|
fix(filelib-web): 补回迁移丢失的共享组件样式层与图标集
第一版迁移只把 uiTheme.ts 的 @theme 颜色令牌搬了过来,155 行里约 90
行的组件类(.btn/.panel/.input/.select/table.list/.tag/.switch/
.link-danger/.quiet 等)被丢掉,于是每个组件各自内联重述按钮、输入框、
面板的样式 —— 正是旧代码的重复问题被原样复刻,后台观感明显退化。
现在 app.css 是设计系统的唯一去处:@theme 管令牌,@layer components
管组件类。组件只带布局工具类,不重述组件样式。
图标集同样是丢的:旧面板有 13 个内联 SVG,新版一个不剩,只有纯文字的
「+」「删除」—— 这是"简陋"最直接的来源。提成 Icon.svelte 共享。
Group 节点沿用两人剪影而非文件夹图标:MemberGroup 与文件库的
FOLDER/PROJECT 是两套无关层级,图标不应混淆(ADR-0028/0021)。
顺手修 FilesPanel 的 uploadInput:bind:this 的目标要用 $state,
否则 Svelte 5 下不保证更新。
|
2026-07-26 20:19:10 +08:00 |
|
白
|
3d0f4e5c2d
|
feat(filelib-web): 把 /database 各页从后端 HTML 拼接迁到 SvelteKit 路由
登录页、后台外壳与六个 tab 全部成为客户端路由:
/database/admin 登录(迁自 renderLoginPage)
/database/dashboard 概览(迁自 renderDashboard)
.../library .../users .../groups .../search .../settings
六个 tab 是真 URL,不再是 location.hash + display:none —— 刷新不丢
位置,链接可分享。
BrowserShell 拆成 LibraryView,加 showUserFooter:老师端 /app 显示
身份/登出页脚,后台的文件库 tab 不显示(外层已有身份区)。
bootstrap 走 /database/config 而非 /database/api/login-info:后者由
teacherApp 在 silo org 查找成功后才注册,前者无条件注册,登录页在
org 未就绪时也必须能拿到配置。
后端拥有的链接(OAuth、DEV 一键登录)标 data-sveltekit-reload,
否则被客户端路由拦下。
|
2026-07-26 20:17:43 +08:00 |
|
白
|
de9f846fd0
|
build(filelib-web): 从 Svelte+Vite 改为 SvelteKit(adapter-static)
纯 SPA:adapter-static + fallback index.html,不做 SSR/预渲染。
index.html / main.ts / App.svelte 由 app.html + src/routes/ 取代。
两项配置是承重的(ADR-0029),不是风格选择:
appDir: '_filelib' 默认 _app 会与 admin-web 在根上注册的 /_app/*
撞成 Fastify 重复路由,启动即抛错。
paths.relative: false 同一份 index.html 会在 /app 和
/database/dashboard/users 等不同深度送出,
相对资源路径会解析到错的 base。
dev 代理表列出后端拥有的全部路径:JSON API、免鉴权 bootstrap
(/database/config)、OAuth、以及 DEV 一键登录端点 —— 后者不代理会被
SPA 回退吃掉。
|
2026-07-26 20:17:27 +08:00 |
|
白
|
11a7ec8004
|
feat(database): 后台成员组(MemberGroup)管理与嵌套解析
|
2026-07-26 18:06:18 +08:00 |
|
ymy
|
4021e58d5d
|
feat(database): init database folder frontend and permission
|
2026-07-23 23:41:11 +08:00 |
|