feat(web): 作品页与订阅选季的剧集组轨道和季卡片
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
265340751c
commit
7d5ba35280
9 files changed
+827
-138
No files matched your search
@@ -13,6 +13,7 @@ import { ExternalLink, Search, X } from "lucide-react";
|
||||
import { type ReactNode, useEffect, useId, useMemo, useState } from "react";
|
||||
import { Link } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { useEpisodeGroups } from "~/api/episode-mapping.ts";
|
||||
import { useEntityFromCandidate } from "~/api/files.ts";
|
||||
import { downloaders, useSiteOptions } from "~/api/instances.ts";
|
||||
import { useEntityDetail, useLibraryRoots } from "~/api/library.ts";
|
||||
@@ -29,6 +30,8 @@ import {
|
||||
import { FormField } from "~/components/console/form-field.tsx";
|
||||
import { consolePath } from "~/components/console/nav.ts";
|
||||
import { AbsoluteNumberingHint } from "~/components/episode-mapping/subscription-summary.tsx";
|
||||
import { SubscriptionSeasonPicker } from "~/components/library/episode-structure.tsx";
|
||||
import { hasStructureChoice } from "~/components/library/episode-structure-model.ts";
|
||||
import { PRIORITY, SEASON_SCOPE, SUB_MODE } from "~/components/library/labels.ts";
|
||||
import { ChipToggleGroup } from "~/components/library/parts.tsx";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
@@ -333,6 +336,9 @@ export function SubscriptionFormDialog({
|
||||
const isMovie = kind === "movie";
|
||||
|
||||
const detail = useEntityDetail(entityId && !isMovie ? entityId : undefined);
|
||||
// 作品有剧集组可选时,新建订阅用「季集结构轨道 + 季卡片」选季(学 MP);编辑时季不能改,仍是下拉
|
||||
const epGroups = useEpisodeGroups(entityId && !isMovie && !editing ? entityId : undefined);
|
||||
const seasonCards = !editing && !!entityId && hasStructureChoice(epGroups.data);
|
||||
const seasons = (detail.data?.contentUnits ?? [])
|
||||
.filter((u) => u.kind === "season" && u.seasonNumber !== null)
|
||||
.sort((a, b) => (a.seasonNumber ?? 0) - (b.seasonNumber ?? 0));
|
||||
@@ -537,27 +543,38 @@ export function SubscriptionFormDialog({
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
{!isMovie && seasonCards && entityId ? (
|
||||
<FormField label="季" hint="按作品当前的季集结构订阅;换剧集组等于改作品设置,会先确认">
|
||||
<SubscriptionSeasonPicker
|
||||
entityId={entityId}
|
||||
value={d.seasonUnitId}
|
||||
onChange={(v) => patch({ seasonUnitId: v })}
|
||||
/>
|
||||
</FormField>
|
||||
) : null}
|
||||
{isMovie ? null : (
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<FormField
|
||||
label="季"
|
||||
htmlFor={f("season")}
|
||||
hint={
|
||||
editing ? "季建好后不能改;要换季就新建订阅" : entityId ? undefined : "作品加入媒体库后可选季"
|
||||
}
|
||||
>
|
||||
<Pick
|
||||
id={f("season")}
|
||||
value={d.seasonUnitId}
|
||||
onChange={(v) => patch({ seasonUnitId: v })}
|
||||
placeholder="全部季"
|
||||
options={seasons.map((s) => ({
|
||||
value: s.id,
|
||||
label: s.seasonNumber === 0 ? "特别篇" : `第 ${s.seasonNumber} 季`,
|
||||
}))}
|
||||
disabled={editing || !entityId}
|
||||
/>
|
||||
</FormField>
|
||||
{seasonCards ? null : (
|
||||
<FormField
|
||||
label="季"
|
||||
htmlFor={f("season")}
|
||||
hint={
|
||||
editing ? "季建好后不能改;要换季就新建订阅" : entityId ? undefined : "作品加入媒体库后可选季"
|
||||
}
|
||||
>
|
||||
<Pick
|
||||
id={f("season")}
|
||||
value={d.seasonUnitId}
|
||||
onChange={(v) => patch({ seasonUnitId: v })}
|
||||
placeholder="全部季"
|
||||
options={seasons.map((s) => ({
|
||||
value: s.id,
|
||||
label: s.seasonNumber === 0 ? "特别篇" : `第 ${s.seasonNumber} 季`,
|
||||
}))}
|
||||
disabled={editing || !entityId}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
<FormField label="季范围" htmlFor={f("scope")}>
|
||||
<Pick
|
||||
id={f("scope")}
|
||||
|
||||
Reference in new issue
Block a user