feat(web): simplify subscription and manual download flows and sync UHD styles
This commit is contained in:
1 parent
27c0f27434
commit
c3c4456913
33 files changed
+1083
-633
No files matched your search
@@ -3,6 +3,7 @@ import { Pencil, Plus, Target } from "lucide-react";
|
||||
import { useId, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { useRuleGroups } from "~/api/rules.ts";
|
||||
import { useCreateSlot, useSlots, useUpdateSlot } from "~/api/slots.ts";
|
||||
import { DetailSheet } from "~/components/console/detail-sheet.tsx";
|
||||
import { EmptyState, ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
|
||||
@@ -12,6 +13,7 @@ import { Input } from "~/components/ui/input.tsx";
|
||||
import { Switch } from "~/components/ui/switch.tsx";
|
||||
import { ApiRequestError, errorMessage } from "~/lib/api.ts";
|
||||
import { formatBytes } from "~/lib/utils.ts";
|
||||
import { ChipToggleGroup } from "./parts.tsx";
|
||||
import { SlotCard } from "./slot-card.tsx";
|
||||
import { draftFromJson, draftToJson, emptyDraft, type SlotRulesDraft, SlotRulesEditor } from "./slot-rules.tsx";
|
||||
|
||||
@@ -46,7 +48,9 @@ export function SlotsPanel({
|
||||
}) {
|
||||
const q = useSlots({ mediaEntityId });
|
||||
const [editing, setEditing] = useState<AcquisitionSlot | "new" | null>(null);
|
||||
const slots = q.data?.items ?? [];
|
||||
const slots = (q.data?.items ?? []).filter(
|
||||
(s) => !subscriptionId || s.subscriptionId === subscriptionId || s.subscriptionId === null,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
@@ -89,9 +93,14 @@ export function SlotsPanel({
|
||||
) : undefined
|
||||
}
|
||||
actions={
|
||||
<Button variant="ghost" size="icon-sm" aria-label={`编辑 ${s.name}`} onClick={() => setEditing(s)}>
|
||||
<Pencil />
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
{subscriptionId && s.subscriptionId === null ? (
|
||||
<span className="text-meta text-muted-foreground">作品共用</span>
|
||||
) : null}
|
||||
<Button variant="ghost" size="icon-sm" aria-label={`编辑 ${s.name}`} onClick={() => setEditing(s)}>
|
||||
<Pencil />
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
@@ -127,6 +136,8 @@ function SlotEditorSheet({
|
||||
const id = useId();
|
||||
const create = useCreateSlot();
|
||||
const update = useUpdateSlot();
|
||||
const groups = useRuleGroups({ enabled: "true" });
|
||||
const [ruleGroupIds, setRuleGroupIds] = useState<string[]>(slot?.ruleGroupIds ?? []);
|
||||
const [name, setName] = useState(slot?.name ?? "");
|
||||
const [distinctGroup, setDistinctGroup] = useState(slot?.distinctGroup ?? "");
|
||||
const [requireDistinct, setRequireDistinct] = useState(slot?.requireDistinctAsset ?? false);
|
||||
@@ -145,6 +156,7 @@ function SlotEditorSheet({
|
||||
if (Object.keys(errs).length || !meta.success || !rules.ok) return;
|
||||
const common = {
|
||||
...rules.value,
|
||||
ruleGroupIds,
|
||||
distinctGroup: meta.data.distinctGroup || null,
|
||||
requireDistinctAsset: requireDistinct,
|
||||
};
|
||||
@@ -232,6 +244,20 @@ function SlotEditorSheet({
|
||||
</div>
|
||||
<Switch checked={requireDistinct} onCheckedChange={setRequireDistinct} aria-label="要求独立文件" />
|
||||
</div>
|
||||
<FormField label="收录组合规则" hint="不选时沿用订阅兼容设置或默认规则;最后一个带档位的组决定优先级">
|
||||
<ChipToggleGroup
|
||||
label="收录组合规则"
|
||||
ordered
|
||||
options={[
|
||||
...(groups.data?.items ?? []).map((g) => ({ value: g.id, label: g.name })),
|
||||
...ruleGroupIds
|
||||
.filter((gid) => !(groups.data?.items ?? []).some((g) => g.id === gid))
|
||||
.map((gid) => ({ value: gid, label: `${gid}(规则不可用)` })),
|
||||
]}
|
||||
value={ruleGroupIds}
|
||||
onChange={setRuleGroupIds}
|
||||
/>
|
||||
</FormField>
|
||||
<SlotRulesEditor value={draft} onChange={setDraft} errors={errors} />
|
||||
</DetailSheet>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user