fix(web): visual QA front-end items U4–U6, U13–U16 and copy list

- U4: form save failures toast the first problem and scroll/focus the first
  invalid field (policy draft, settings cards, resource drawers, subscription
  form) via lib/form-errors.
- U5: FormField keeps 8px between a hint and the next label.
- U6: file manager status bar keeps free space left-aligned, clear of the
  Agent button.
- U13: move/copy dialog stops "target is the source folder / inside the
  source" before requesting a preview (transferTargetProblem + tests).
- U14: account popover uses the solid float material.
- U15/U16: inbox tile hint shortened; TMDB assign dialog uses the shared
  Select and labelled fields (type, TMDB ID, note).
- Copy: "TMDB 已保存" spacing, API Key block no longer repeats the section
  title, whole-day intervals read "每 7 天", "最高级别:提示",
  "延后:已有计划在途", failed records show "未生成目标路径", upstream model
  column "默认模型".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 16:58:38 +08:00
1 parent 2ae780d2a1
commit 082c556a67
18 files changed
+130 -38

No files matched your search

@@ -104,8 +104,8 @@ export function ApiKeysSection() {
<SettingsBlock
section="api-keys"
anchor="keys"
title="API Key"
description="签发给外部程序(媒体服务器插件、脚本)的 Key,按权限范围授权。本机 Token 在「账户与安全」。"
title="已签发的 Key"
description="给媒体服务器插件、脚本等外部程序用,按权限范围授权。本机 Token 在「账户与安全」。"
plain
actions={
<Button size="sm" onClick={() => setOpen(true)}>
@@ -84,7 +84,7 @@ export function PiUpstreamsBlock() {
key: "model",
header: "模型",
hideBelow: "sm",
cell: (r) => <code className="text-meta break-all">{r.defaultModel ?? "provider 默认"}</code>,
cell: (r) => <code className="text-meta break-all">{r.defaultModel ?? "默认模型"}</code>,
},
{ key: "status", header: "状态", cell: (r) => <UpstreamStatusBadge u={r} /> },
]}
@@ -159,7 +159,7 @@ function UpstreamDrawer({
try {
await update.mutateAsync({ id: upstream.id, body: parsed.data });
setV((s) => ({ ...s, apiKey: "" }));
toast.success(`${v.name.trim()}已保存`);
toast.success(`${v.name.trim()} 已保存`);
} catch (err) {
toast.error(errorMessage(err, "保存失败"));
}
@@ -14,6 +14,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~
import { Switch } from "~/components/ui/switch.tsx";
import { Textarea } from "~/components/ui/textarea.tsx";
import { errorMessage } from "~/lib/api.ts";
import { revealFirstError } from "~/lib/form-errors.ts";
// 设置页里"实例类"资源的通用段落:列表 + 新建/编辑抽屉 + 删除 + 行内动作。
// 表单用 contracts 的 Create/Update schema 做 zod 校验;凭证字段只写,编辑时留空表示不变。
@@ -193,6 +194,7 @@ function ResourceFormDrawer<Row extends { id: string }>({
fe[config.fields[0]?.name ?? ""] ??= fe[""];
}
setErrors(fe);
revealFirstError();
return;
}
setErrors({});
@@ -12,6 +12,7 @@ import { ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
import { zodFieldErrors } from "~/components/console/form-field.tsx";
import { Button } from "~/components/ui/button.tsx";
import { errorMessage } from "~/lib/api.ts";
import { revealFirstError } from "~/lib/form-errors.ts";
import { FieldControl, type FieldSpec, type FormValues } from "./resource-section.tsx";
import { SettingsBlock } from "./settings-block.tsx";
@@ -56,13 +57,14 @@ export function SettingsCard({
fe[spec.fields.find((f) => k.startsWith(f.name.split(".")[0] ?? ""))?.name ?? k] ??= m;
}
setErrors(fe);
revealFirstError();
return;
}
setErrors({});
try {
const next = await update.mutateAsync(patch);
setValues(spec.fromSettings(next));
toast.success(`${spec.title}已保存`);
toast.success(`${spec.title} 已保存`);
} catch (err) {
toast.error(errorMessage(err, "保存失败"));
}