Match LibTV share publish flow
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-18 15:09:48 +08:00
parent e6c8c140d8
commit d7f50984b4

View File

@ -246,6 +246,8 @@ const AUDIO_SOURCE_URL =
"https://liblibai-online.liblib.cloud/web/28aa80df5944499487381983a8f9bbdd/3ca0886d-d35f-4048-95bf-cc655e9c57fd.mp3";
const AUDIO_REFERENCE_IMAGE_URL =
"https://liblibai-online.liblib.cloud/web/ea95cb51f3d94addbb92dc003cd33b49/1342d344-2d95-41a1-a2aa-4d20869a318c.png";
const PUBLISH_MODAL_BG_URL =
"https://libtv-res.liblib.art/upload-images/4e7115e6ee6947b78d73e0203a85fc56/771d92a21c6dce69a97513d21ee3253fe0eedec9.png";
const STORY_SCRIPT_PROMPT = "根据我上传的剧本生成一个完整的故事脚本";
const AUDIO_TO_VIDEO_PROMPT =
"根据上传的音频生成对应场景画面,镜头语言、节奏、音乐匹配情绪变化,电影级质感。";
@ -545,7 +547,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
const [toolSearch, setToolSearch] = useState("");
const [isProjectLoading, setIsProjectLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [shareEnabled, setShareEnabled] = useState(false);
const [, setShareEnabled] = useState(false);
const [publishPublic, setPublishPublic] = useState(false);
const [canvasCommand, setCanvasCommand] = useState<CanvasCommandState>(null);
const [nodeContextMenu, setNodeContextMenu] = useState<NodeContextState>(null);
@ -1167,30 +1169,14 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
) : null}
{activePanel === "share" ? (
<LibModal onClose={() => setActivePanel(null)} title="分享">
<div className="space-y-4">
<div className="rounded-[8px] border border-white/8 bg-white/5 p-4">
<div className="font-medium">分享链接</div>
<div className="mt-1 text-[12px] text-white/42">复制当前画布链接,权限控制待接入。</div>
<button
className="mt-4 h-10 w-full rounded-[8px] bg-white font-semibold text-black hover:bg-white/90"
onClick={() => void copyShareLink()}
type="button"
>
<Copy className="mr-2 inline h-4 w-4" />
复制链接
</button>
</div>
<ToggleRow checked={shareEnabled} label="启用分享" onChange={() => setShareEnabled((value) => !value)} />
<button
className="h-10 w-full rounded-[8px] bg-[#2f7df6] font-semibold text-white hover:bg-[#3f8bff]"
onClick={() => setActivePanel("publish")}
type="button"
>
发布作品
</button>
</div>
</LibModal>
<SharePopover
onClose={() => setActivePanel(null)}
onCopyLink={() => {
void copyShareLink();
setActivePanel(null);
}}
onPublish={() => setActivePanel("publish")}
/>
) : null}
{activePanel === "publish" ? (
@ -3025,6 +3011,59 @@ function SkillsAccessModal({ onClose }: { onClose: () => void }) {
);
}
function SharePopover({
onClose,
onCopyLink,
onPublish,
}: {
onClose: () => void;
onCopyLink: () => void;
onPublish: () => void;
}) {
return (
<div
className="fixed right-[312px] top-[66px] z-[75] w-[360px] rounded-[16px] border border-white/10 bg-[#202020]/98 p-2 text-white shadow-[0_24px_80px_rgba(0,0,0,0.52)] backdrop-blur-[16px]"
data-canvas-overlay="true"
>
<button
aria-label="关闭分享菜单"
className="absolute inset-0 -z-10 cursor-default"
onClick={onClose}
type="button"
/>
<div className="flex flex-col gap-2">
<span className="pl-2 text-sm font-medium text-white/60">发布与分享</span>
<button
className="flex cursor-pointer items-center gap-3 rounded-xl p-2 text-left transition-colors hover:bg-white/8"
onClick={onPublish}
type="button"
>
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-white/10 text-white/80">
<StoreGlyph />
</span>
<span className="flex min-w-0 flex-col gap-1">
<span className="text-sm font-medium text-white">在LibTV上发布</span>
<span className="text-xs leading-snug text-white/70">发布你的作品和创作过程,让更多创作者看到。</span>
</span>
</button>
<button
className="flex cursor-pointer items-center gap-3 rounded-xl p-2 text-left transition-colors hover:bg-white/8"
onClick={onCopyLink}
type="button"
>
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-white/10 text-white/80">
<Copy className="h-5 w-5" />
</span>
<span className="flex min-w-0 flex-col gap-1">
<span className="text-sm font-medium text-white">分享链接</span>
<span className="text-xs leading-snug text-white/70">拥有此链接的人可以查看并复制你的画布。</span>
</span>
</button>
</div>
</div>
);
}
function MemberCenterPanel() {
return (
<div className="space-y-4">
@ -3179,48 +3218,138 @@ function PublishModal({
projectTitle: string;
publishPublic: boolean;
}) {
const cover = capturedWorkflows[0]?.cover || "";
return (
<LibModal onClose={onClose} title="发布作品到 LibTV" width={480}>
<div className="space-y-4">
{cover ? (
<div className="h-20 rounded-t-[8px] bg-cover bg-center" style={{ backgroundImage: `linear-gradient(90deg, rgba(0,0,0,.72), rgba(0,0,0,.12)), url(${cover})` }} />
) : null}
<div className="grid grid-cols-2 gap-3">
<UploadBox label="选择视频" />
<UploadBox label="选择封面" hint="建议上传横版图片" />
</div>
<label className="block">
<span className="mb-2 block text-[13px] text-white/72">作品名称 *</span>
<input className="h-10 w-full rounded-[8px] border border-white/10 bg-black/18 px-3 text-[13px] text-white outline-none" defaultValue={projectTitle || "未命名"} />
</label>
<label className="block">
<span className="mb-2 block text-[13px] text-white/72">作品描述</span>
<textarea className="min-h-[80px] w-full rounded-[8px] border border-white/10 bg-black/18 px-3 py-2 text-[13px] text-white outline-none" placeholder="请输入作品描述" />
</label>
<ToggleRow checked={publishPublic} label="公开画布" onChange={onTogglePublic} />
<div className="fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-[4px]" data-canvas-overlay="true">
<div className="relative max-h-[min(90dvh,880px)] w-[480px] max-w-[calc(100vw-32px)] overflow-y-auto overflow-x-hidden rounded-[16px] border border-white/12 bg-[#242424] p-4 text-white shadow-[0_30px_100px_rgba(0,0,0,0.58)]">
<div
className="absolute -top-[60px] left-0 z-0 h-[214px] w-[503px] bg-cover bg-center bg-no-repeat"
style={{
backgroundImage: `linear-gradient(to bottom, rgba(0,0,0,0.25) 70%, #242424 100%), url(${PUBLISH_MODAL_BG_URL})`,
}}
/>
<button
className="h-10 w-full rounded-[8px] bg-[#2f7df6] font-semibold text-white hover:bg-[#3f8bff]"
onClick={() => toast.info("发布接口待接入。")}
className="absolute right-4 top-4 z-[2] flex h-8 w-8 cursor-pointer items-center justify-center rounded-full text-white/80 transition-colors hover:bg-black/35 hover:text-white"
onClick={onClose}
type="button"
>
发布并投稿
<X className="h-4 w-4" />
</button>
<div className="relative z-[1] flex flex-col gap-4">
<div className="mt-3 flex max-w-[420px] flex-col gap-2">
<p className="text-[16px] font-medium text-white drop-shadow-[0_1px_3px_rgba(0,0,0,0.85)]">
发布作品到LibTV
</p>
<p className="text-[14px] font-normal leading-normal text-white/85 drop-shadow-[0_1px_2px_rgba(0,0,0,0.75)]">
您的作品将展示到LibTV Show,方便大家交流使用
</p>
</div>
<div className="mt-6 flex gap-3">
<UploadBox label="选择视频" />
<UploadBox label="选择封面" hint="建议上传横版图片" />
</div>
<label className="block">
<span className="mb-1.5 block text-sm font-medium text-white/88">
作品名称 <span className="text-red-500">*</span>
</span>
<input
className="h-10 w-full rounded-[8px] border border-white/10 bg-transparent px-3 text-[13px] text-white outline-none placeholder:text-white/35 focus:border-white/20"
defaultValue={projectTitle || "未命名"}
maxLength={120}
placeholder="请输入作品名称"
/>
</label>
<label className="block">
<span className="mb-1.5 block text-sm font-medium text-white/88">作品描述</span>
<textarea
className="min-h-[78px] w-full resize-none rounded-[8px] border border-white/10 bg-transparent px-3 py-2 text-[13px] text-white outline-none placeholder:text-white/35 focus:border-white/20"
maxLength={500}
placeholder="请输入作品描述"
/>
</label>
<div className="flex gap-3">
<label className="flex flex-1 flex-col gap-2">
<span className="text-sm font-medium text-white/88">活动标签</span>
<select className="h-10 rounded-[8px] border border-white/10 bg-transparent px-3 text-[13px] text-white/78 outline-none">
<option className="bg-[#242424]" value="0">不参与</option>
<option className="bg-[#242424]" value="1">LibTV Show</option>
</select>
</label>
<label className="flex flex-1 flex-col gap-2">
<span className="text-sm font-medium text-white/88">参赛赛道</span>
<select className="h-10 rounded-[8px] border border-white/10 bg-transparent px-3 text-[13px] text-white/45 outline-none">
<option className="bg-[#242424]" value="">请选择参赛单元</option>
<option className="bg-[#242424]" value="story">叙事短片</option>
<option className="bg-[#242424]" value="music">音乐影像</option>
</select>
</label>
</div>
<label className="block">
<span className="mb-1.5 flex items-center gap-1 text-sm font-medium text-white/88">
社媒链接
<HelpCircle className="h-3 w-3 text-white/48" />
</span>
<input
className="h-10 w-full rounded-[8px] border border-white/10 bg-transparent px-3 text-[13px] text-white outline-none placeholder:text-white/35 focus:border-white/20"
placeholder="请添加您在社媒发布该作品的链接"
/>
</label>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="text-[13px] text-white/86">公开画布</span>
<button
className={cn("relative h-5 w-9 rounded-full transition", publishPublic ? "bg-white" : "bg-white/18")}
onClick={onTogglePublic}
type="button"
>
<span className={cn("absolute top-[3px] h-3.5 w-3.5 rounded-full transition", publishPublic ? "left-[19px] bg-black" : "left-[3px] bg-white")} />
</button>
</div>
<button
className="cursor-pointer rounded-lg bg-[#478EFF] px-3 py-2 text-[13px] text-white transition-colors hover:bg-[#2563EB]"
onClick={() => toast.info("发布接口待接入。")}
type="button"
>
发布并投稿
</button>
</div>
<label className="mt-[-4px] flex cursor-pointer items-center gap-1">
<input className="h-3 w-3 accent-[#478EFF]" defaultChecked type="checkbox" />
<span className="text-[10px] text-white/60">
点击发布即代表同意
<a
className="text-[#478EFF] hover:underline"
href="https://www.liblib.art/activities/4b7ea7f1dbbf41669d9e05cd25a3fa77"
rel="noreferrer"
target="_blank"
>
《LibTV创作许可服务协议》
</a>
</span>
</label>
</div>
</div>
</LibModal>
</div>
);
}
function UploadBox({ hint, label }: { hint?: string; label: string }) {
return (
<button
className="flex h-28 flex-col items-center justify-center rounded-[8px] border border-white/10 bg-white/8 text-white/56 hover:bg-white/12 hover:text-white"
className="flex h-[120px] flex-1 flex-col items-center justify-center rounded-[8px] border border-white/8 bg-white/12 text-white/72 transition-colors hover:bg-white/16 hover:text-white"
onClick={() => toast.info(`${label}接口待接入。`)}
type="button"
>
<Plus className="h-5 w-5" />
<span className="mt-2 text-[13px]">{label}</span>
{hint ? <span className="mt-1 text-[11px] text-white/34">{hint}</span> : null}
{hint ? <span className="mt-2 text-[12px] text-white/42">{hint}</span> : null}
</button>
);
}