- glossary: 10 punctuation rules (full-width in Chinese, CJK/Latin spacing, full-width parens around Chinese, single ellipsis, 「」 quotes, period rules) - scripts/check-copy-punctuation.mjs: checks string literals, templates and JSX text (not comments, types, keys, match/compare strings); --fix, --strict, --by-file; wired into deno task ci as check:copy in warn mode - --fix applied to web, server and contracts; files other lanes were editing (subscriptions, sites, browser, agent, auth/account, inventory) left for them - tests updated for the changed messages 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>;
|
|
}
|