style(copy): fix remaining punctuation violations and make check:copy strict

Auto-fix of 602 string literals across 74 files (half-width punctuation next to
Chinese, parenthesised Chinese, quotes); biome reflow; e2/e6 assertions follow
the new full-width summaries. check:copy now runs with --strict in ci.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 21:34:51 +08:00
1 parent 0fccfe257d
commit fb84a71f80
76 files changed
+582 -570

No files matched your search

@@ -52,7 +52,7 @@ export function useSubscriptionOps() {
remove: (ids: string[]) =>
batch.mutateAsync({ ids, action: "delete" }).then((r) => {
const bad = r.results.filter((x) => !x.ok);
if (bad.length) toast.error(`${bad.length} 个没有删除:${bad[0]?.error ?? ""}`);
if (bad.length) toast.error(`${bad.length} 个没有删除:${bad[0]?.error ?? ""}`);
else toast.success(ids.length > 1 ? `已删除 ${ids.length} 个订阅` : "订阅已删除");
}),
batch: (ids: string[], a: "search" | "pause" | "resume") =>
@@ -215,8 +215,8 @@ export function DeleteSubscriptionsDialog({
<ConfirmDialog
open={open}
onOpenChange={onOpenChange}
title={ids.length > 1 ? `删除 ${ids.length} 个订阅?` : "删除这个订阅?"}
description="不再搜索和追更。已入库文件、版本目标和下载记录保留,可在订阅历史里重新订阅。"
title={ids.length > 1 ? `删除 ${ids.length} 个订阅?` : "删除这个订阅?"}
description="不再搜索和追更。已入库文件、版本目标和下载记录保留,可在订阅历史里重新订阅。"
confirmLabel="删除"
destructive
onConfirm={() =>
@@ -238,7 +238,7 @@ export function CellSheet({
}
}}
title={sel ? `${sel.season} · ${columnLabel(sel.col)}` : ""}
description={sel ? `${sel.row.name}${sel.row.slotId === null ? "(作品全部资产)" : ""}` : null}
description={sel ? `${sel.row.name}${sel.row.slotId === null ? "(作品全部资产)" : ""}` : null}
footer={
sel && c ? (
<>
@@ -254,7 +254,7 @@ export function CellSheet({
<Button
onClick={doFill}
disabled={!canFill || fill.isPending || done === c.unitKey}
title={canFill ? undefined : "订阅不在追踪中,先恢复"}
title={canFill ? undefined : "订阅不在追踪中,先恢复"}
>
<Wand2 />
{done === c.unitKey ? "已提交" : c.upgradable ? "补全更好版本" : "手动补全"}
@@ -282,7 +282,7 @@ export function CellSheet({
c.quality?.label ?? ([c.quality?.resolution, c.quality?.source].filter(Boolean).join(" ") || null),
},
{ label: "pri", value: c.pri !== null ? String(c.pri) : null },
{ label: "可升级", value: c.state === "have" ? (c.upgradable ? "是,低于目标档位" : "否") : null },
{ label: "可升级", value: c.state === "have" ? (c.upgradable ? "是,低于目标档位" : "否") : null },
{
label: "资产",
value: c.assetId ? (
@@ -306,17 +306,17 @@ export function CellSheet({
: null,
},
{ label: "原因", value: c.reason ? (SKIP_REASON[c.reason] ?? c.reason) : null },
{ label: "延后", value: c.deferred ? "有资源在等待重评(预算或自动补全关闭)" : null },
{ label: "延后", value: c.deferred ? "有资源在等待重评(预算或自动补全关闭)" : null },
]}
/>
</DetailSection>
{fillable ? (
<p className="text-meta text-muted-foreground">
手动补全不受自动补全开关和补全预算限制,仍受全局每日预算与缓存卷阈值约束。
手动补全不受自动补全开关和补全预算限制,仍受全局每日预算与缓存卷阈值约束。
</p>
) : null}
{sel.row.slotId === null && c.state === "missing" ? (
<p className="text-meta text-muted-foreground">这一行汇总全部版本。要补全,点具体版本目标那一行的格。</p>
<p className="text-meta text-muted-foreground">这一行汇总全部版本。要补全,点具体版本目标那一行的格。</p>
) : null}
</>
) : null}
@@ -137,7 +137,7 @@ export const SKIP_REASON: Record<string, string> = {
out_of_range: "集范围外",
not_aired: "未播出",
not_required: "该版本目标不要求这个内容版本",
suspected: "总集数未知,按已见最高集推断",
suspected: "总集数未知,按已见最高集推断",
deferred: "有延后的资源",
};
@@ -55,7 +55,7 @@ export function ProgressBlock({ x, className }: { x: Pick<Item, "progress" | "mo
"bg-[repeating-linear-gradient(90deg,var(--color-foreground)_0_4px,transparent_4px_8px)] opacity-20",
)}
role="img"
aria-label={`已入库 ${x.progress.have},在途 ${x.progress.inflight},总 ${x.progress.total ?? "未知"}`}
aria-label={`已入库 ${x.progress.have},在途 ${x.progress.inflight},总 ${x.progress.total ?? "未知"}`}
>
{unknown ? null : (
<>
@@ -53,7 +53,7 @@ export function SlotPanel({
setOrder.mutate(
{ id: sub.id, slotIds: rows.map((r) => r.id) },
{
onSuccess: () => toast.success(`主版本:${rows[0]?.name ?? ""}`),
onSuccess: () => toast.success(`主版本:${rows[0]?.name ?? ""}`),
onError: (e) => {
toast.error(errorMessage(e));
setRows(serverRows);
@@ -84,7 +84,7 @@ export function SlotPanel({
return (
<Panel
title="版本目标"
description="拖动调整顺序,第一个是主版本。主版本缺的照常追更;其他版本按下面的自动补全设置补齐。"
description="拖动调整顺序,第一个是主版本。主版本缺的照常追更;其他版本按下面的自动补全设置补齐。"
actions={
dirty ? (
<>
@@ -119,7 +119,7 @@ export function SlotPanel({
size="xs"
onClick={() => fillSlot(r)}
disabled={!canFill || fill.isPending || r.summary.missing === 0}
title={canFill ? undefined : "订阅不在追踪中,先恢复"}
title={canFill ? undefined : "订阅不在追踪中,先恢复"}
>
<Wand2 />
补全此版本
@@ -154,7 +154,7 @@ function WorkPicker({ onPick, error }: { onPick: (t: Target) => void; error?: st
kind: "title",
titleQuery: c.year ? `${c.title} ${c.year}` : c.title,
mediaKind: c.entityType === "movie" ? "movie" : "series",
note: `TMDB ${c.externalId},建档后自动关联`,
note: `TMDB ${c.externalId},建档后自动关联`,
});
const row = (key: string, main: ReactNode, sub: string, onClick: () => void) => (
<li key={key}>
@@ -178,7 +178,7 @@ function WorkPicker({ onPick, error }: { onPick: (t: Target) => void; error?: st
className="pl-9"
value={q}
aria-invalid={!!error}
placeholder="搜索标题 / 原名,库里没有的从 TMDB 选"
placeholder="搜索标题 / 原名,库里没有的从 TMDB 选"
onChange={(e) => setQ(e.target.value)}
/>
</div>
@@ -240,7 +240,7 @@ function WorkPicker({ onPick, error }: { onPick: (t: Target) => void; error?: st
</p>
) : null}
{s.data?.media && !s.data.media.tmdb.configured ? (
<p className="px-3 pb-2 text-meta text-muted-foreground">TMDB 未配置,只搜了媒体库。</p>
<p className="px-3 pb-2 text-meta text-muted-foreground">TMDB 未配置,只搜了媒体库。</p>
) : null}
</>
)}
@@ -405,7 +405,7 @@ export function SubscriptionFormDialog({
<DialogHeader>
<DialogTitle>{editing ? "编辑订阅" : "新建订阅"}</DialogTitle>
<DialogDescription>
{editing ? titleText : "从媒体库或 TMDB 选作品;库里没有的按标题追踪,建档后自动关联。"}
{editing ? titleText : "从媒体库或 TMDB 选作品;库里没有的按标题追踪,建档后自动关联。"}
</DialogDescription>
</DialogHeader>
{dup ? (
@@ -413,7 +413,7 @@ export function SubscriptionFormDialog({
role="alert"
className="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-sm text-foreground"
>
<span>这部作品的同一季已有订阅,不能重复创建。</span>
<span>这部作品的同一季已有订阅,不能重复创建。</span>
<Link
to={consolePath("subscriptions", dup)}
onClick={onClose}
@@ -445,7 +445,7 @@ export function SubscriptionFormDialog({
<p className="truncate text-sm font-medium text-foreground">{titleText}</p>
)}
<p className="mt-0.5 text-meta text-muted-foreground">
{target.kind === "entity" ? "媒体库作品" : (target.note ?? "按标题追踪,尚未建档")}
{target.kind === "entity" ? "媒体库作品" : (target.note ?? "按标题追踪,尚未建档")}
</p>
</div>
<Button variant="ghost" size="sm" onClick={() => setTarget(null)}>
@@ -486,7 +486,7 @@ export function SubscriptionFormDialog({
<FormField
label="季"
htmlFor={f("season")}
hint={editing ? "季建好后不能改;要换季就新建订阅" : entityId ? undefined : "作品建档后可选季"}
hint={editing ? "季建好后不能改;要换季就新建订阅" : entityId ? undefined : "作品建档后可选季"}
>
<Pick
id={f("season")}
@@ -534,7 +534,7 @@ export function SubscriptionFormDialog({
label="总集数"
htmlFor={f("total")}
error={err("total")}
hint={d.totalLocked ? "锁定后元数据刷新不再改写" : "空 = 按 TMDB;不锁定时只升不降"}
hint={d.totalLocked ? "锁定后元数据刷新不再改写" : "空 = 按 TMDB;不锁定时只升不降"}
>
<Input
id={f("total")}
@@ -620,7 +620,7 @@ export function SubscriptionFormDialog({
) : subSlots.length === 0 ? (
<p className="text-caption text-muted-foreground">还没有版本目标。在对比视图里新建。</p>
) : (
<FormField label="顺序" htmlFor={f("order")} hint="第一个是主版本;其他版本按自动补全设置补齐">
<FormField label="顺序" htmlFor={f("order")} hint="第一个是主版本;其他版本按自动补全设置补齐">
<SlotOrderList
items={order ?? subSlots.map((s) => ({ id: s.id, name: s.name }))}
onChange={setOrderState}
@@ -634,7 +634,7 @@ export function SubscriptionFormDialog({
htmlFor={f("tpl")}
hint={
target?.kind === "entity"
? "作品还没有版本目标时按模板顺序创建,第一个是主版本"
? "作品还没有版本目标时按模板顺序创建,第一个是主版本"
: "作品建档后按模板创建版本目标"
}
>
@@ -653,7 +653,7 @@ export function SubscriptionFormDialog({
<FormField
label="升级策略"
htmlFor={f("upgrade")}
hint="作用于这个订阅的全部版本目标;已入库低于目标档位时继续找更好的"
hint="作用于这个订阅的全部版本目标;已入库低于目标档位时继续找更好的"
>
<Pick
id={f("upgrade")}
@@ -675,7 +675,7 @@ export function SubscriptionFormDialog({
<FormField
label="规则组"
htmlFor={f("groups")}
hint="按选择顺序串联;不选 = 订阅默认规则组。版本目标自己的规则组另算"
hint="按选择顺序串联;不选 = 订阅默认规则组。版本目标自己的规则组另算"
>
{groups.isPending ? (
<p className="text-caption text-muted-foreground">读取规则组…</p>
@@ -697,7 +697,7 @@ export function SubscriptionFormDialog({
)}
</FormField>
<div className="grid gap-3 sm:grid-cols-2">
<FormField label="包含" htmlFor={f("inc")} hint="每行一个正则,匹配标题、副标题和标签">
<FormField label="包含" htmlFor={f("inc")} hint="每行一个正则,匹配标题、副标题和标签">
<Textarea
id={f("inc")}
rows={3}
@@ -761,7 +761,7 @@ export function SubscriptionFormDialog({
label="搜索关键词"
htmlFor={f("kw")}
error={err("keywords")}
hint="每行一个,追加在标题和别名之后;最多 10 个"
hint="每行一个,追加在标题和别名之后;最多 10 个"
>
<Textarea
id={f("kw")}
@@ -775,7 +775,7 @@ export function SubscriptionFormDialog({
<Section title="搜索与优先级">
<div className="grid gap-3 sm:grid-cols-3">
<FormField
label="主动搜索间隔(小时)"
label="主动搜索间隔(小时)"
htmlFor={f("interval")}
error={err("searchIntervalHours")}
hint="空 = 24;0 = 关"
@@ -843,7 +843,7 @@ export function AutoFillFields({
<div className="space-y-3">
{compact ? null : (
<p className="text-meta text-muted-foreground">
主版本缺的照常追更。开启后,主版本已有的单元也会为其他版本搜索下载;关闭时只记为缺失,可手动补全。
主版本缺的照常追更。开启后,主版本已有的单元也会为其他版本搜索下载;关闭时只记为缺失,可手动补全。
</p>
)}
<div className="grid gap-3 sm:grid-cols-3">
@@ -867,7 +867,7 @@ export function AutoFillFields({
))}
</fieldset>
</FormField>
<FormField label="每天最多(个单元)" htmlFor={`${idPrefix}-units`} error={errors.unitsPerDay}>
<FormField label="每天最多(个单元)" htmlFor={`${idPrefix}-units`} error={errors.unitsPerDay}>
<Input
id={`${idPrefix}-units`}
inputMode="numeric"
@@ -888,7 +888,9 @@ export function AutoFillFields({
/>
</FormField>
</div>
<p className="text-meta text-muted-foreground">预算只算自动补全的计划,超出的延到次日;同时受全局每日预算限制。</p>
<p className="text-meta text-muted-foreground">
预算只算自动补全的计划,超出的延到次日;同时受全局每日预算限制。
</p>
</div>
);
}