docs(plan): v0.2 adds Pi subagents and scheduled-jobs board
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
b839ed4056
commit
16ab2a6c84
97 files changed
+592
-648
No files matched your search
@@ -94,13 +94,13 @@ function PathsPanel({ detail }: { detail: LibraryDetail }) {
|
||||
const rootOf = (id: string | null) => roots.data?.items.find((r) => r.id === id);
|
||||
const bindings = detail.pathBindings.filter((b) => b.status !== "superseded");
|
||||
return (
|
||||
<Panel title="实际路径与库根" description="路径绑定一旦建立不随译名变化;执行进程可访问的绝对路径按库根拼接">
|
||||
<Panel title="实际路径与库根" description="路径绑定建立后不随译名变化">
|
||||
{bindings.length === 0 && detail.assets.length === 0 ? (
|
||||
<EmptyState
|
||||
plain
|
||||
icon={FolderTree}
|
||||
title="还没有入库文件"
|
||||
description="收录目标满足后,文件位置会显示在这里。"
|
||||
description="版本目标满足后,文件位置显示在这里。"
|
||||
className="py-8"
|
||||
/>
|
||||
) : (
|
||||
@@ -171,17 +171,23 @@ function IdentityPanel({ detail }: { detail: LibraryDetail }) {
|
||||
const candidates = detail.identities.filter((i) => i.status === "proposed" || i.status === "conflicted");
|
||||
return (
|
||||
<Panel
|
||||
title="外部身份映射"
|
||||
description="本地 UUID 是主身份,TMDB 等外部 ID 是可修订的辅助映射"
|
||||
title="外部身份"
|
||||
description="以本地 ID 为准,外部身份可修改"
|
||||
actions={
|
||||
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
|
||||
<PencilLine />
|
||||
改映射
|
||||
修改
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{list.length === 0 ? (
|
||||
<EmptyState plain icon={SearchX} title="还没有外部映射" description="可以手动指定 TMDB id。" className="py-8" />
|
||||
<EmptyState
|
||||
plain
|
||||
icon={SearchX}
|
||||
title="还没有外部身份"
|
||||
description="点「修改」手动指定 TMDB ID。"
|
||||
className="py-8"
|
||||
/>
|
||||
) : (
|
||||
<ul className="space-y-2">
|
||||
{list.map((i) => (
|
||||
@@ -244,7 +250,7 @@ function MetadataPanel({ detail, entity }: { detail: LibraryDetail; entity: Medi
|
||||
return (
|
||||
<Panel
|
||||
title="元数据"
|
||||
description={`字段级来源;锁定的字段刷新时不会被改写 · 最近刷新 ${formatDateTime(detail.entity.lastMetadataRefreshAt)}`}
|
||||
description={`锁定的字段刷新时不变 · 最近刷新 ${formatDateTime(detail.entity.lastMetadataRefreshAt)}`}
|
||||
actions={
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -252,7 +258,7 @@ function MetadataPanel({ detail, entity }: { detail: LibraryDetail; entity: Medi
|
||||
disabled={refresh.isPending}
|
||||
onClick={() =>
|
||||
refresh.mutate(undefined, {
|
||||
onSuccess: () => toast.success("已提交元数据刷新(锁定字段保持不变)"),
|
||||
onSuccess: () => toast.success("已提交刷新"),
|
||||
onError: (err) => toast.error(errorMessage(err, "刷新失败")),
|
||||
})
|
||||
}
|
||||
@@ -299,7 +305,7 @@ function MetadataPanel({ detail, entity }: { detail: LibraryDetail; entity: Medi
|
||||
</Button>
|
||||
}
|
||||
title={`解锁「${ENTITY_FIELD_LABEL[field]}」?`}
|
||||
description="取消人工覆盖与锁定,下次刷新会按来源优先级重新取值。"
|
||||
description="取消人工修改,下次刷新按来源优先级取值。"
|
||||
confirmLabel="解锁"
|
||||
onConfirm={() =>
|
||||
unlock.mutateAsync(field).then(
|
||||
@@ -348,15 +354,15 @@ function MetadataPanel({ detail, entity }: { detail: LibraryDetail; entity: Medi
|
||||
function SlotsPanel({ detail, units }: { detail: LibraryDetail; units: ContentUnit[] }) {
|
||||
if (detail.slots.length === 0) {
|
||||
return (
|
||||
<Panel title="收录目标(Slot)">
|
||||
<Panel title="版本目标">
|
||||
<EmptyState
|
||||
plain
|
||||
icon={CalendarClock}
|
||||
title="这部作品还没有收录目标"
|
||||
description="在订阅与收录规则里新建订阅或 Slot,系统会按目标持续补齐与升级。"
|
||||
title="还没有版本目标"
|
||||
description="新建订阅或版本目标后,按目标补齐和升级。"
|
||||
action={
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link to={consolePath("subscriptions")}>去订阅与收录规则</Link>
|
||||
<Link to={consolePath("subscriptions")}>去订阅</Link>
|
||||
</Button>
|
||||
}
|
||||
className="py-8"
|
||||
@@ -366,7 +372,7 @@ function SlotsPanel({ detail, units }: { detail: LibraryDetail; units: ContentUn
|
||||
}
|
||||
const assetOf = (id: string | null) => detail.assets.find((a) => a.asset.id === id);
|
||||
return (
|
||||
<Panel title="收录目标(Slot)" description="每个目标独立判断硬条件、软偏好与升级;状态均配文字">
|
||||
<Panel title="版本目标" description="每个目标单独判断硬条件、软偏好和升级">
|
||||
<div className="grid gap-3 xl:grid-cols-2">
|
||||
{detail.slots.map((s) => {
|
||||
const cur = assetOf(s.currentAssetId);
|
||||
@@ -449,11 +455,7 @@ function UnitsPanel({ entity, detail }: { entity: ReturnType<typeof useEntityDet
|
||||
a.segment.localeCompare(b.segment),
|
||||
);
|
||||
return (
|
||||
<Panel
|
||||
title="内容单元"
|
||||
description="季 / 集 / 期与分段;临时单元是按解析结果先建的,确认或改编号后锁定"
|
||||
bodyClassName="p-0 sm:p-0"
|
||||
>
|
||||
<Panel title="内容单元" description="临时单元按解析结果创建,确认或改编号后锁定" bodyClassName="p-0 sm:p-0">
|
||||
<DataTable
|
||||
plain
|
||||
columns={columns}
|
||||
@@ -463,9 +465,8 @@ function UnitsPanel({ entity, detail }: { entity: ReturnType<typeof useEntityDet
|
||||
error={entity.error}
|
||||
onRetry={() => entity.refetch()}
|
||||
empty={{
|
||||
title: detail.entity.kind === "movie" ? "电影没有分集单元" : "还没有内容单元",
|
||||
description:
|
||||
detail.entity.kind === "movie" ? "电影按内容版本核对完整性。" : "识别到新集或期后会自动建临时单元。",
|
||||
title: detail.entity.kind === "movie" ? "电影没有季和集" : "还没有内容单元",
|
||||
description: detail.entity.kind === "movie" ? "电影按内容版本核对完整性。" : "识别到新集后会建临时单元。",
|
||||
}}
|
||||
/>
|
||||
</Panel>
|
||||
@@ -548,11 +549,7 @@ function DownloadsPanel({ detail }: { detail: LibraryDetail }) {
|
||||
},
|
||||
];
|
||||
return (
|
||||
<Panel
|
||||
title="下载历史与校验结果"
|
||||
description="下载与入库串成一个业务过程;整理记录含逐文件核验"
|
||||
bodyClassName="p-0 sm:p-0"
|
||||
>
|
||||
<Panel title="下载历史与校验结果" bodyClassName="p-0 sm:p-0">
|
||||
<DataTable
|
||||
plain
|
||||
columns={columns}
|
||||
@@ -595,7 +592,7 @@ export default function LibraryDetailPage() {
|
||||
{back}
|
||||
<ErrorState
|
||||
title={notFound ? "作品不存在" : "作品加载失败"}
|
||||
error={notFound ? "这个 ID 没有对应的作品,可能已被删除。" : detail.error}
|
||||
error={notFound ? "找不到这个 ID 的作品。" : detail.error}
|
||||
onRetry={notFound ? undefined : () => detail.refetch()}
|
||||
/>
|
||||
</>
|
||||
@@ -638,13 +635,13 @@ export default function LibraryDetailPage() {
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link to={`${consolePath("subscriptions")}?mediaEntityId=${e.id}`}>
|
||||
<CalendarClock />
|
||||
订阅与目标
|
||||
查看订阅
|
||||
</Link>
|
||||
</Button>
|
||||
{e.status !== "merged" ? (
|
||||
<Button variant="outline" size="sm" onClick={() => setMerging(true)}>
|
||||
<GitMerge />
|
||||
合并到另一作品
|
||||
合并作品
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user