- Trim descriptions, empty states, confirm buttons and toasts to facts - Unify terms per glossary: 待处理/待识别/整理记录/运行记录/凭证/子会话/Agent 上游 - Subscription-login termsNote states facts only (borrowed client identity, ToS/ban risk) - Shorter, concrete goal templates for built-in Agent checks - Human-readable nouns instead of table names in instance CRUD errors - Audit labels for pi_upstream / schedule / automation_grant actions - Glossary: add 上游、订阅登录、凭证、定时任务、巡检、运行记录、子会话、停止、持续授权 Co-Authored-By: Claude Opus 5.5 <[email protected]>
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import { toast } from "sonner";
|
|
import { useUpdateSettings } from "~/api/settings.ts";
|
|
import { StatusBadge } from "~/components/console/status-badge.tsx";
|
|
import { Button } from "~/components/ui/button.tsx";
|
|
import { errorMessage } from "~/lib/api.ts";
|
|
import { str } from "./resource-section.tsx";
|
|
import { type CardSpec, SettingsCard, SettingsGate } from "./settings-card.tsx";
|
|
|
|
// 元数据:TMDB API Key(只写,存 secret)与 Base URL
|
|
|
|
const TMDB_CARD: CardSpec = {
|
|
anchor: "tmdb",
|
|
title: "TMDB",
|
|
description: "留空时用环境变量 TMDB_API_KEY / TMDB_ACCESS_TOKEN / TMDB_BASE_URL。",
|
|
fields: [
|
|
{
|
|
name: "metadata.tmdbApiKey",
|
|
label: "API Key",
|
|
kind: "password",
|
|
hint: "v3 API Key 或 v4 Read Access Token;留空不修改",
|
|
wide: true,
|
|
},
|
|
{
|
|
name: "metadata.tmdbBaseUrl",
|
|
label: "Base URL",
|
|
kind: "url",
|
|
placeholder: "https://api.themoviedb.org",
|
|
hint: "自建反代时填写;留空用官方地址",
|
|
wide: true,
|
|
},
|
|
],
|
|
fromSettings: (s) => ({ "metadata.tmdbApiKey": "", "metadata.tmdbBaseUrl": s.metadata.tmdbBaseUrl ?? "" }),
|
|
toPatch: (v) => ({
|
|
metadata: {
|
|
tmdbBaseUrl: str(v["metadata.tmdbBaseUrl"]) || null,
|
|
...(str(v["metadata.tmdbApiKey"]) ? { tmdbApiKey: str(v["metadata.tmdbApiKey"]) } : {}),
|
|
},
|
|
}),
|
|
extra: (s) => <TmdbKeyStatus saved={!!s.metadata.tmdbApiKeySecretRef} />,
|
|
};
|
|
|
|
function TmdbKeyStatus({ saved }: { saved: boolean }) {
|
|
const update = useUpdateSettings();
|
|
return (
|
|
<div className="mb-2 flex flex-wrap items-center gap-2">
|
|
<StatusBadge tone={saved ? "success" : "neutral"}>{saved ? "API Key 已保存" : "未保存 API Key"}</StatusBadge>
|
|
{saved ? (
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="xs"
|
|
className="hover:text-destructive"
|
|
disabled={update.isPending}
|
|
onClick={async () => {
|
|
try {
|
|
await update.mutateAsync({ metadata: { tmdbApiKey: null } });
|
|
toast.success("TMDB API Key 已清除");
|
|
} catch (err) {
|
|
toast.error(errorMessage(err, "清除失败"));
|
|
}
|
|
}}
|
|
>
|
|
清除
|
|
</Button>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function MetadataSection() {
|
|
return <SettingsGate>{(s) => <SettingsCard section="metadata" spec={TMDB_CARD} settings={s} />}</SettingsGate>;
|
|
}
|