文案(控制台路由):去掉复述界面的说明,登录页不再提已取消的待处理
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
cfc9793dcd
commit
7abc4001d6
13 files changed
+26
-27
No files matched your search
@@ -28,7 +28,7 @@ export default function DiscoverPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader title="发现" description="TMDB、豆瓣、Bangumi 的热门与榜单;点开作品可订阅或搜索资源" />
|
<PageHeader title="发现" description="TMDB、豆瓣、Bangumi 的热门与榜单" />
|
||||||
<Tabs
|
<Tabs
|
||||||
value={view}
|
value={view}
|
||||||
onValueChange={(v) =>
|
onValueChange={(v) =>
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ export default function FilesTrashPage() {
|
|||||||
if (!snap?.title) return <span className="text-muted-foreground">—</span>;
|
if (!snap?.title) return <span className="text-muted-foreground">—</span>;
|
||||||
const label = `${snap.title}${snap.contentUnit ? ` ${snap.contentUnit}` : ""}`;
|
const label = `${snap.title}${snap.contentUnit ? ` ${snap.contentUnit}` : ""}`;
|
||||||
return (
|
return (
|
||||||
<span className="block max-w-48 text-meta" title="删除时已从媒体库移除;还原不会自动恢复">
|
<span className="block max-w-48 text-meta" title="还原后不会回到媒体库,需要时重新整理">
|
||||||
{snap.mediaEntityId ? (
|
{snap.mediaEntityId ? (
|
||||||
<Link className="underline underline-offset-2" to={`/console/library/${snap.mediaEntityId}`}>
|
<Link className="underline underline-offset-2" to={`/console/library/${snap.mediaEntityId}`}>
|
||||||
{label}
|
{label}
|
||||||
@@ -227,7 +227,7 @@ export default function FilesTrashPage() {
|
|||||||
) : (
|
) : (
|
||||||
label
|
label
|
||||||
)}
|
)}
|
||||||
<span className="block text-muted-foreground">已退役</span>
|
<span className="block text-muted-foreground">已移出媒体库</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -721,7 +721,7 @@ export default function FilesPage() {
|
|||||||
key: "scrape",
|
key: "scrape",
|
||||||
label: "刷新元数据",
|
label: "刷新元数据",
|
||||||
icon: RefreshCw,
|
icon: RefreshCw,
|
||||||
disabled: selected.every((e) => e.asset) ? null : "只对已整理的文件",
|
disabled: selected.every((e) => e.asset) ? null : "只能刷新已整理的文件",
|
||||||
onSelect: () => act("scrape", selected),
|
onSelect: () => act("scrape", selected),
|
||||||
});
|
});
|
||||||
items.push({
|
items.push({
|
||||||
@@ -854,7 +854,7 @@ export default function FilesPage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
aria-label={order === "asc" ? "升序,点此改为降序" : "降序,点此改为升序"}
|
aria-label={order === "asc" ? "升序,切换为降序" : "降序,切换为升序"}
|
||||||
title={order === "asc" ? "升序" : "降序"}
|
title={order === "asc" ? "升序" : "降序"}
|
||||||
onClick={() => patch({ order: order === "asc" ? "desc" : null })}
|
onClick={() => patch({ order: order === "asc" ? "desc" : null })}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ export default function ConsoleLayout() {
|
|||||||
if (session.isError) {
|
if (session.isError) {
|
||||||
return (
|
return (
|
||||||
<div className="grid min-h-screen place-items-center bg-background px-4">
|
<div className="grid min-h-screen place-items-center bg-background px-4">
|
||||||
<ErrorState title="无法获取登录状态" error={session.error} onRetry={() => session.refetch()} />
|
<ErrorState title="读取登录状态失败" error={session.error} onRetry={() => session.refetch()} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const meta = () => [{ title: "媒体库 · UHD 媒体自动化控制台"
|
|||||||
|
|
||||||
const FILTERS: { value: NonNullable<LibraryListQuery["filter"]>; label: string }[] = [
|
const FILTERS: { value: NonNullable<LibraryListQuery["filter"]>; label: string }[] = [
|
||||||
{ value: "gap", label: "有缺口" },
|
{ value: "gap", label: "有缺口" },
|
||||||
{ value: "attention", label: "需处理" },
|
{ value: "attention", label: "需要处理" },
|
||||||
{ value: "downloading", label: "下载中" },
|
{ value: "downloading", label: "下载中" },
|
||||||
{ value: "satisfied", label: "已满足" },
|
{ value: "satisfied", label: "已满足" },
|
||||||
];
|
];
|
||||||
@@ -27,7 +27,7 @@ const FILTERS: { value: NonNullable<LibraryListQuery["filter"]>; label: string }
|
|||||||
/** 各 Slot 状态计数:只列非零项,文字 + 语气 */
|
/** 各 Slot 状态计数:只列非零项,文字 + 语气 */
|
||||||
function SlotSummary({ counts }: { counts: LibraryItem["slotCounts"] }) {
|
function SlotSummary({ counts }: { counts: LibraryItem["slotCounts"] }) {
|
||||||
const parts = SLOT_STATUS_ORDER.filter((s) => counts[s] > 0);
|
const parts = SLOT_STATUS_ORDER.filter((s) => counts[s] > 0);
|
||||||
if (parts.length === 0) return <span className="text-meta text-muted-foreground">未设目标</span>;
|
if (parts.length === 0) return <span className="text-meta text-muted-foreground">没有收录版本</span>;
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{parts.map((s: SlotStatus) => (
|
{parts.map((s: SlotStatus) => (
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import { reasonCode, reasonLine } from "~/lib/reasons.ts";
|
|||||||
import { cn, formatBytes, formatDateTime } from "~/lib/utils.ts";
|
import { cn, formatBytes, formatDateTime } from "~/lib/utils.ts";
|
||||||
|
|
||||||
const FILE_STATUS: Record<PublicOrganizationFile["status"], { label: string; tone: StatusTone }> = {
|
const FILE_STATUS: Record<PublicOrganizationFile["status"], { label: string; tone: StatusTone }> = {
|
||||||
queued: { label: "排队", tone: "neutral" },
|
queued: { label: "排队中", tone: "neutral" },
|
||||||
running: { label: "执行中", tone: "neutral" },
|
running: { label: "整理中", tone: "neutral" },
|
||||||
succeeded: { label: "成功", tone: "success" },
|
succeeded: { label: "成功", tone: "success" },
|
||||||
failed: { label: "失败", tone: "destructive" },
|
failed: { label: "失败", tone: "destructive" },
|
||||||
skipped: { label: "跳过", tone: "neutral" },
|
skipped: { label: "已跳过", tone: "neutral" },
|
||||||
cancelled: { label: "已取消", tone: "neutral" },
|
cancelled: { label: "已取消", tone: "neutral" },
|
||||||
};
|
};
|
||||||
const ROLE_LABEL = {
|
const ROLE_LABEL = {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export default function SettingsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader title="设置" description="按接入对象和业务环节分组。密钥保存后不再显示。" />
|
<PageHeader title="设置" description="密钥保存后不再显示。" />
|
||||||
<div className="grid gap-6 lg:grid-cols-[14rem_minmax(0,1fr)] lg:gap-8">
|
<div className="grid gap-6 lg:grid-cols-[14rem_minmax(0,1fr)] lg:gap-8">
|
||||||
{/* 窄屏:搜索 + 分区下拉 + 节横排 */}
|
{/* 窄屏:搜索 + 分区下拉 + 节横排 */}
|
||||||
<div className="grid gap-3 lg:hidden">
|
<div className="grid gap-3 lg:hidden">
|
||||||
@@ -114,7 +114,7 @@ export default function SettingsPage() {
|
|||||||
</Select>
|
</Select>
|
||||||
<p className="text-caption text-muted-foreground">{section.description}</p>
|
<p className="text-caption text-muted-foreground">{section.description}</p>
|
||||||
{section.anchors.length > 1 ? (
|
{section.anchors.length > 1 ? (
|
||||||
<nav aria-label="本分区的节" className="scroll-bleed -mx-1 overflow-x-auto px-1 pb-1">
|
<nav aria-label="本分区目录" className="scroll-bleed -mx-1 overflow-x-auto px-1 pb-1">
|
||||||
<ul className="flex w-max gap-1.5">
|
<ul className="flex w-max gap-1.5">
|
||||||
{section.anchors.map((a) => (
|
{section.anchors.map((a) => (
|
||||||
<li key={a.id}>
|
<li key={a.id}>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import { errorMessage } from "~/lib/api.ts";
|
|||||||
const RESOLUTION: { value: ResolutionStatus; label: string }[] = [
|
const RESOLUTION: { value: ResolutionStatus; label: string }[] = [
|
||||||
{ value: "resolved", label: "已识别" },
|
{ value: "resolved", label: "已识别" },
|
||||||
{ value: "unresolved", label: "未识别" },
|
{ value: "unresolved", label: "未识别" },
|
||||||
{ value: "ambiguous", label: "有歧义" },
|
{ value: "ambiguous", label: "匹配到多部作品" },
|
||||||
{ value: "unidentifiable", label: "无法识别" },
|
{ value: "unidentifiable", label: "无法识别" },
|
||||||
];
|
];
|
||||||
const AGE = [
|
const AGE = [
|
||||||
@@ -207,7 +207,6 @@ export default function SiteWorkbenchPage() {
|
|||||||
<EmptyState
|
<EmptyState
|
||||||
icon={Globe}
|
icon={Globe}
|
||||||
title="站点不存在或已删除"
|
title="站点不存在或已删除"
|
||||||
description="回到站点页查看现有站点"
|
|
||||||
action={
|
action={
|
||||||
<Button asChild size="sm" variant="outline">
|
<Button asChild size="sm" variant="outline">
|
||||||
<Link to={consolePath("sites")}>
|
<Link to={consolePath("sites")}>
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ type Filter = "all" | "enabled" | "attention";
|
|||||||
const GROUPS: { kind: SiteKind; title: string; variant: "pt" | "public" | "subtitle" }[] = [
|
const GROUPS: { kind: SiteKind; title: string; variant: "pt" | "public" | "subtitle" }[] = [
|
||||||
{ kind: "pt", title: "PT 站", variant: "pt" },
|
{ kind: "pt", title: "PT 站", variant: "pt" },
|
||||||
{ kind: "public_bt", title: "公开 BT 站", variant: "public" },
|
{ kind: "public_bt", title: "公开 BT 站", variant: "public" },
|
||||||
{ kind: "rss_feed", title: "RSS 源", variant: "public" },
|
{ kind: "rss_feed", title: "自定义 RSS 源", variant: "public" },
|
||||||
{ kind: "torznab", title: "索引器", variant: "public" },
|
{ kind: "torznab", title: "Torznab 索引器", variant: "public" },
|
||||||
{ kind: "subtitle", title: "字幕站", variant: "subtitle" },
|
{ kind: "subtitle", title: "字幕站", variant: "subtitle" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const FILTERS: { value: Filter; label: string }[] = [
|
const FILTERS: { value: Filter; label: string }[] = [
|
||||||
{ value: "all", label: "全部" },
|
{ value: "all", label: "全部" },
|
||||||
{ value: "enabled", label: "已启用" },
|
{ value: "enabled", label: "已启用" },
|
||||||
{ value: "attention", label: "需处理" },
|
{ value: "attention", label: "需要处理" },
|
||||||
];
|
];
|
||||||
const SORTS: { value: SortKey; label: string }[] = [
|
const SORTS: { value: SortKey; label: string }[] = [
|
||||||
{ value: "name", label: "名称" },
|
{ value: "name", label: "名称" },
|
||||||
@@ -193,7 +193,7 @@ export default function SitesPage() {
|
|||||||
) : !shown.length ? (
|
) : !shown.length ? (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
icon={Globe}
|
icon={Globe}
|
||||||
title={filter === "attention" ? "没有需处理的站点" : "没有已启用的站点"}
|
title={filter === "attention" ? "没有需要处理的站点" : "没有已启用的站点"}
|
||||||
description="切换到「全部」查看其余站点"
|
description="切换到「全部」查看其余站点"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ function problems(d: SystemHealth): string[] {
|
|||||||
const disks = d.disks.filter((x) => x.level === "warn" || x.level === "critical");
|
const disks = d.disks.filter((x) => x.level === "warn" || x.level === "critical");
|
||||||
if (disks.length) out.push(`${disks.length} 个磁盘用量超过阈值`);
|
if (disks.length) out.push(`${disks.length} 个磁盘用量超过阈值`);
|
||||||
const mounts = d.mounts.filter((m) => m.status !== "online");
|
const mounts = d.mounts.filter((m) => m.status !== "online");
|
||||||
if (mounts.length) out.push(`${mounts.length} 个挂载根不可用`);
|
if (mounts.length) out.push(`${mounts.length} 个挂载点不可用`);
|
||||||
if (d.engine.level === "warn" || d.engine.level === "critical") out.push("任务积压或失败率偏高");
|
if (d.engine.level === "warn" || d.engine.level === "critical") out.push("任务积压或失败率偏高");
|
||||||
if (d.schedules.failing.length) out.push(`${d.schedules.failing.length} 个定时任务上次运行失败`);
|
if (d.schedules.failing.length) out.push(`${d.schedules.failing.length} 个定时任务上次运行失败`);
|
||||||
if (d.storage.level === "warn" || d.storage.level === "critical") out.push("存储用量超过告警线或预算,见「存储」");
|
if (d.storage.level === "warn" || d.storage.level === "critical") out.push("存储用量超过告警线或预算,见「存储」");
|
||||||
@@ -471,7 +471,7 @@ function worst(levels: HealthLevel[]): HealthLevel {
|
|||||||
function Mounts({ d }: { d: SystemHealth }) {
|
function Mounts({ d }: { d: SystemHealth }) {
|
||||||
const bad = d.mounts.filter((m) => m.status !== "online").length;
|
const bad = d.mounts.filter((m) => m.status !== "online").length;
|
||||||
return (
|
return (
|
||||||
<Card title="挂载根" icon={HardDrive} level={d.mounts.length ? (bad ? "critical" : "ok") : undefined}>
|
<Card title="挂载点" icon={HardDrive} level={d.mounts.length ? (bad ? "critical" : "ok") : undefined}>
|
||||||
{d.mounts.length === 0 ? (
|
{d.mounts.length === 0 ? (
|
||||||
<p className="text-caption text-muted-foreground">没有启用的媒体库目录、下载目录映射或 Alist 存储。</p>
|
<p className="text-caption text-muted-foreground">没有启用的媒体库目录、下载目录映射或 Alist 存储。</p>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ export const meta = () => [{ title: "订阅详情 · UHD 媒体自动化控制
|
|||||||
|
|
||||||
const TOTAL_SOURCE: Record<string, string> = {
|
const TOTAL_SOURCE: Record<string, string> = {
|
||||||
tmdb: "TMDB",
|
tmdb: "TMDB",
|
||||||
injected: "注入",
|
injected: "订阅里填写",
|
||||||
manual: "手动",
|
manual: "手动",
|
||||||
covered_floor: "按已整理",
|
covered_floor: "按已整理",
|
||||||
previous: "沿用",
|
previous: "沿用上次",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SubscriptionDetailPage() {
|
export default function SubscriptionDetailPage() {
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ const OP_TONE: Record<AssetOperation["status"], StatusTone> = {
|
|||||||
compensated: "warning",
|
compensated: "warning",
|
||||||
};
|
};
|
||||||
const OP_STATUS: Record<AssetOperation["status"], string> = {
|
const OP_STATUS: Record<AssetOperation["status"], string> = {
|
||||||
planned: "计划",
|
planned: "待执行",
|
||||||
started: "进行中",
|
started: "进行中",
|
||||||
succeeded: "成功",
|
succeeded: "成功",
|
||||||
failed: "失败",
|
failed: "失败",
|
||||||
skipped: "跳过",
|
skipped: "已跳过",
|
||||||
compensated: "已回滚",
|
compensated: "已回滚",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export default function LoginPage() {
|
|||||||
订阅、下载、整理
|
订阅、下载、整理
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-4 max-w-lg text-lead text-muted-foreground">
|
<p className="mt-4 max-w-lg text-lead text-muted-foreground">
|
||||||
每一步都有记录。拿不准的事项进待处理,等你决定。
|
每一步都有记录。拿不准的会停下来等你决定。
|
||||||
</p>
|
</p>
|
||||||
<ul className="mt-8 space-y-3 text-body text-muted-foreground">
|
<ul className="mt-8 space-y-3 text-body text-muted-foreground">
|
||||||
<li className="flex items-center gap-2.5">
|
<li className="flex items-center gap-2.5">
|
||||||
@@ -456,7 +456,7 @@ export default function LoginPage() {
|
|||||||
) : null}
|
) : null}
|
||||||
{session.isError ? (
|
{session.isError ? (
|
||||||
<p className="text-center text-meta text-muted-foreground">
|
<p className="text-center text-meta text-muted-foreground">
|
||||||
无法获取登录状态,
|
读取登录状态失败,
|
||||||
<button type="button" className="cursor-pointer underline" onClick={() => session.refetch()}>
|
<button type="button" className="cursor-pointer underline" onClick={() => session.refetch()}>
|
||||||
重试
|
重试
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in new issue
Block a user