请先登录后再访问文件管理页面。
- 返回首页 +请先登录后再访问文件管理页面。
+ 返回首页diff --git a/MEMORY.md b/MEMORY.md index 86ca19f..cc79c8e 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -41,3 +41,16 @@ - 部署 compose 中 DB 镜像应通过 `POSTGRES_IMAGE` 可配置,默认使用镜像站的 pgvector 镜像(`docker.m.daocloud.io/pgvector/pgvector:pg16`)。 - 宿主机 DB 暴露端口统一走 `POSTGRES_PORT`(默认 `5433`),用于规避与宿主机已有 PostgreSQL(常见 `5432`)冲突;容器内连接仍保持 `db:5432`。 - GitHub Actions 使用 `appleboy/ssh-action` 部署时,慢网环境需显式设置 `command_timeout`(建议 `45m`)并为 `docker compose pull` 增加重试,避免出现 `Run Command Timeout` 直接中断发布。 + +## 前端视觉口径(2026-04-12) + +- 后台视觉基线采用 `Slate + Cyan`(浅色)风格,优先使用 `web/src/app/globals.css` 中统一样式类: + - `surface-card` / `surface-card-muted` + - `notice` + `notice-error` / `notice-success` + - `btn-primary` / `btn-secondary` / `btn-danger` + - `control` + - `table-modern` / `table-head` / `table-body` +- 字体基线: + - 标题:`Space Grotesk` + - 正文:`Manrope` + - 等宽:`JetBrains Mono` diff --git a/memory/2026-04-12.md b/memory/2026-04-12.md index 5254030..46b819c 100644 --- a/memory/2026-04-12.md +++ b/memory/2026-04-12.md @@ -124,6 +124,28 @@ - 推送触发 `main` 发布,观察部署日志不再在固定时长点报 `Run Command Timeout`。 - 远端 `docker compose ps` 应显示 `db/api/web` 均为 `Up`(或 `healthy`)。 +## 追加改造(后台视觉风格方案 A) + +- 目标: + - 将后台从默认黑白风格升级为更现代的 `Slate + Cyan` 视觉基线,保持业务逻辑不变。 +- 处理: + - `web/src/app/layout.tsx`: + - 字体切换为 `Space Grotesk`(标题)+ `Manrope`(正文)+ `JetBrains Mono`(等宽)。 + - `web/src/app/globals.css`: + - 新增统一设计 token(背景/边框/强调色/文本层级)。 + - 新增通用样式类:`surface-card`、`surface-card-muted`、`notice`、`btn-*`、`control`、`table-*`。 + - 增加浅色渐变背景与柔和光斑,提升整体层次。 + - `web/src/app/admin/layout.tsx`: + - 后台侧栏、顶部标题区改为半透明磨砂卡片风格,激活态采用青色高亮。 + - `web/src/app/admin/**` 与 `web/src/app/page.tsx`: + - 统一替换卡片/按钮/表单/表格样式到新通用类,保持页面结构与交互逻辑不变。 +- 验证: + - `npm run lint:web` 通过。 + - `npm run build:web` 失败(环境问题,非本次样式改动引入): + - Turbopack 报 `Can't resolve '@tanstack/react-query'` / `Can't resolve 'react'`,但 `npm --workspace web ls react @tanstack/react-query --depth=0` 可见依赖存在。 +- 风险: + - 本次改动覆盖前端多个后台页面,主要风险是视觉回归与局部间距细节,需要联调页面人工验收。 + ## 追加修复(DB 端口冲突 + pgvector 基线) - 触发问题: diff --git a/web/src/app/admin/files/page.tsx b/web/src/app/admin/files/page.tsx index 86e03f0..df38620 100644 --- a/web/src/app/admin/files/page.tsx +++ b/web/src/app/admin/files/page.tsx @@ -379,14 +379,14 @@ export default function AdminFilesPage() { uploadMutation.isPending; if (initializing || filesQuery.isLoading) { - return
Loading files...
; + returnLoading files...
; } if (!user) { return (请先登录后再访问文件管理页面。
- 返回首页 +请先登录后再访问文件管理页面。
+ 返回首页你没有访问该页面的权限(需要 `file.read`)。
- 返回首页 +你没有访问该页面的权限(需要 `file.read`)。
+ 返回首页+{listError || errorMessage})} {feedbackMessage && ( -+{feedbackMessage})}-+ - 挂载点
-一期按挂载点浏览目录树,支持 VFS/S3。
+一期按挂载点浏览目录树,支持 VFS/S3。
{mounts.map((mount) => { const selected = mount.code === (listData?.current_mount.code ?? mountCode); @@ -427,35 +427,35 @@ export default function AdminFilesPage() { onClick={() => handleSelectMount(mount)} className={`w-full rounded-lg border px-3 py-2 text-left text-sm transition ${ selected - ? "border-black bg-black text-white dark:border-white dark:bg-white dark:text-black" - : "border-black/15 hover:bg-black/5 dark:border-white/20 dark:hover:bg-white/10" + ? "border-cyan-400 bg-gradient-to-r from-cyan-500 to-cyan-600 text-white shadow-[0_10px_22px_rgba(8,145,178,0.28)]" + : "border-[var(--border)] bg-white/70 text-slate-700 hover:border-cyan-200 hover:bg-cyan-50/70" }`} >{mount.name}
-+
{mount.backend.driver_type} · {mount.code}
); })} {mounts.length === 0 && ( -暂无可用挂载点。
+暂无可用挂载点。
)}+ -文件列表
-+
存储后端:{listData?.current_mount.backend.name ?? "-"}({listData?.current_mount.backend.driver_type ?? "-"})
+{(listData?.breadcrumbs ?? [{ name: "根目录", path: "/" }]).map((crumb, index, all) => (@@ -506,11 +506,11 @@ export default function AdminFilesPage() { value={newDirectoryName} onChange={(event) => setNewDirectoryName(event.target.value)} placeholder="新建目录名" - className="w-full max-w-xs rounded-md border border-black/15 bg-transparent px-3 py-2 text-sm outline-none focus:border-black/40 dark:border-white/20 dark:focus:border-white/40" + className="w-full max-w-xs control" />))}{crumb.name} - {index < all.length - 1 && /} + {index < all.length - 1 && /}{ if (!newDirectoryName.trim()) { setErrorMessage("目录名称不能为空"); @@ -526,8 +526,8 @@ export default function AdminFilesPage() { )} -- +
+
- + {items.map((item) => { const isActive = activeItemPath === item.path; return ( @@ -551,17 +551,17 @@ export default function AdminFilesPage() { {item.is_dir ? `[DIR] ${item.name}` : item.name} {isActive && canManage && ( - 名称 类型 @@ -537,7 +537,7 @@ export default function AdminFilesPage() {操作 +setRenameName(event.target.value)} placeholder="新名称" - className="w-48 rounded-md border border-black/15 bg-transparent px-2 py-1 text-xs outline-none focus:border-black/40 dark:border-white/20 dark:focus:border-white/40" + className="control w-48 px-2 py-1 text-xs" />submitRename(item)} disabled={renameMutation.isPending} > @@ -573,17 +573,17 @@ export default function AdminFilesPage() { value={moveTargetParentPath} onChange={(event) => setMoveTargetParentPath(event.target.value)} placeholder="目标目录(如 /a/b)" - className="w-48 rounded-md border border-black/15 bg-transparent px-2 py-1 text-xs outline-none focus:border-black/40 dark:border-white/20 dark:focus:border-white/40" + className="control w-48 px-2 py-1 text-xs" /> setMoveNewName(event.target.value)} placeholder="新名称(可选)" - className="w-40 rounded-md border border-black/15 bg-transparent px-2 py-1 text-xs outline-none focus:border-black/40 dark:border-white/20 dark:focus:border-white/40" + className="control w-40 px-2 py-1 text-xs" /> submitMove(item)} disabled={moveMutation.isPending} > @@ -591,7 +591,7 @@ export default function AdminFilesPage() { 取消 @@ -602,14 +602,14 @@ export default function AdminFilesPage() { {item.is_dir ? "目录" : item.mime_type ?? "文件"} {item.is_dir ? "-" : formatFileSize(item.size)} -{formatDate(item.modified_at)} -{formatDate(item.synced_at)} +{formatDate(item.modified_at)} +{formatDate(item.synced_at)} {item.is_dir && (handleOpenDirectory(item)} > 进入 @@ -618,7 +618,7 @@ export default function AdminFilesPage() { {!item.is_dir && ( void handleDownload(item)} > 下载 @@ -628,7 +628,7 @@ export default function AdminFilesPage() { <> startRename(item)} disabled={operationBusy} > @@ -636,7 +636,7 @@ export default function AdminFilesPage() { startMove(item)} disabled={operationBusy} > @@ -644,7 +644,7 @@ export default function AdminFilesPage() { handleDelete(item)} disabled={deleteMutation.isPending} > @@ -659,7 +659,7 @@ export default function AdminFilesPage() { })} {items.length === 0 && ( - diff --git a/web/src/app/admin/layout.tsx b/web/src/app/admin/layout.tsx index 4d806de..682dd93 100644 --- a/web/src/app/admin/layout.tsx +++ b/web/src/app/admin/layout.tsx @@ -70,7 +70,7 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) if (initializing || loadingMenus) { return (+ 当前目录为空 - ); } @@ -78,19 +78,24 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) if (!user) { return (Loading admin workspace...
+Loading admin workspace...
- ); } return ( -请先登录后再访问后台。
- 返回首页 +请先登录后再访问后台。
+ 返回首页--