完成视频复刻和优化
This commit is contained in:
@@ -20,8 +20,8 @@ import {
|
||||
ArrowUpRight,
|
||||
} from "lucide-react";
|
||||
import { api, ApiError, type QuickCreateJob } from "../api";
|
||||
import { ConfirmModal } from "../components/overlays";
|
||||
import { forgetQuickCreateJob, readQuickCreateJobId, rememberQuickCreateJob } from "../quick-create-lock";
|
||||
import { ConfirmModal, OverlayPortal, useBodyScrollLock } from "../components/overlays";
|
||||
import { forgetQuickCreateJob, readQuickCreateJobId, rememberQuickCreateJob, stripQuickCreateSuffix } from "../quick-create-lock";
|
||||
import type { ModelConfig } from "../types";
|
||||
import {
|
||||
DEFAULT_BILLING_RATES,
|
||||
@@ -75,7 +75,7 @@ function formatClock(seconds: number) {
|
||||
}
|
||||
|
||||
function historyTitle(item: QuickCreateJob) {
|
||||
return (item.title || item.product_name || "极速成片").replace(/ · 极速成片$/, "");
|
||||
return stripQuickCreateSuffix(item.title || item.product_name || "一键成片");
|
||||
}
|
||||
|
||||
function jobIsComplete(item: QuickCreateJob) {
|
||||
@@ -140,6 +140,7 @@ export function QuickCreatePage({
|
||||
const [pollEpoch, setPollEpoch] = useState(0);
|
||||
const [history, setHistory] = useState<QuickCreateJob[]>([]);
|
||||
const [playing, setPlaying] = useState<{ url: string; title: string } | null>(null);
|
||||
useBodyScrollLock(Boolean(playing));
|
||||
const videoConfigs = useMemo(
|
||||
() => modelConfigs.filter((config) => config.capability === "video" && config.status === "active"),
|
||||
[modelConfigs],
|
||||
@@ -261,7 +262,7 @@ export function QuickCreatePage({
|
||||
if (next.status === "succeeded") {
|
||||
if (watchedGeneratingRef.current && completedNoticeRef.current !== next.id) {
|
||||
completedNoticeRef.current = next.id;
|
||||
notifyRef.current?.("success", "极速成片已生成");
|
||||
notifyRef.current?.("success", "一键成片已生成");
|
||||
projectCreatedRef.current?.();
|
||||
}
|
||||
if (next.project_id) quickCreateStatusRef.current?.(next.project_id, next.status);
|
||||
@@ -274,8 +275,8 @@ export function QuickCreatePage({
|
||||
if (terminalNoticeRef.current !== next.id) {
|
||||
terminalNoticeRef.current = next.id;
|
||||
const message = next.status === "cancelled"
|
||||
? "极速成片已取消"
|
||||
: next.error_message || "极速成片未完成,已完成的步骤会保留,可重试继续";
|
||||
? "一键成片已取消"
|
||||
: next.error_message || "一键成片未完成,已完成的步骤会保留,可重试继续";
|
||||
notifyRef.current?.(next.status === "cancelled" ? "info" : "error", message);
|
||||
}
|
||||
if (next.project_id) quickCreateStatusRef.current?.(next.project_id, next.status);
|
||||
@@ -293,10 +294,10 @@ export function QuickCreatePage({
|
||||
setJobId("");
|
||||
clearDraft();
|
||||
forgetQuickCreateJob();
|
||||
notifyRef.current?.("info", "已清除其他账号的极速成片记录");
|
||||
notifyRef.current?.("info", "已清除其他账号的一键成片记录");
|
||||
return;
|
||||
}
|
||||
notifyRef.current?.("error", error instanceof Error ? error.message : "读取极速成片进度失败");
|
||||
notifyRef.current?.("error", error instanceof Error ? error.message : "读取一键成片进度失败");
|
||||
timer = window.setTimeout(poll, 8000);
|
||||
}
|
||||
};
|
||||
@@ -369,7 +370,7 @@ export function QuickCreatePage({
|
||||
if (next.status === "queued" || next.status === "running") {
|
||||
onNotify?.("success", "已从上次进度继续生成");
|
||||
} else if (next.status === "succeeded") {
|
||||
onNotify?.("success", "极速成片已生成");
|
||||
onNotify?.("success", "一键成片已生成");
|
||||
} else {
|
||||
onNotify?.("error", next.error_message || "继续生成失败,已完成的步骤会保留");
|
||||
}
|
||||
@@ -429,15 +430,15 @@ export function QuickCreatePage({
|
||||
setSavedImages(created.product_images || []);
|
||||
setSourceProductId(created.product_id || "");
|
||||
rememberQuickCreateJob(created.id);
|
||||
onNotify?.("success", "极速成片任务已启动");
|
||||
onNotify?.("success", "一键成片任务已启动");
|
||||
onProjectCreated?.();
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError && error.status === 503) {
|
||||
setServiceUnavailable(true);
|
||||
setUnavailableMessage(error.message || "极速成片服务暂不可用,请稍后再试");
|
||||
onNotify?.("info", error.message || "极速成片服务暂不可用,请稍后再试");
|
||||
setUnavailableMessage(error.message || "一键成片服务暂不可用,请稍后再试");
|
||||
onNotify?.("info", error.message || "一键成片服务暂不可用,请稍后再试");
|
||||
} else {
|
||||
onNotify?.("error", error instanceof Error ? error.message : "极速成片启动失败");
|
||||
onNotify?.("error", error instanceof Error ? error.message : "一键成片启动失败");
|
||||
}
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
@@ -556,7 +557,7 @@ export function QuickCreatePage({
|
||||
<header className="project-builder-header quick-create-header">
|
||||
<div className="project-builder-title">
|
||||
<button type="button" className="image-back-button" onClick={onBack} aria-label={backLabel}><ArrowLeft /></button>
|
||||
<div><h1>极速成片</h1></div>
|
||||
<div><h1>一键成片</h1></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -760,7 +761,7 @@ export function QuickCreatePage({
|
||||
<span className="quick-failed-icon"><AlertCircle /></span>
|
||||
<h2>
|
||||
{serviceUnavailable
|
||||
? "极速成片暂不可用"
|
||||
? "一键成片暂不可用"
|
||||
: isCancelled
|
||||
? "已取消本次生成"
|
||||
: reviewBlocked
|
||||
@@ -798,9 +799,9 @@ export function QuickCreatePage({
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section className="quick-history" aria-label="过往极速成片项目">
|
||||
<section className="quick-history" aria-label="过往一键成片项目">
|
||||
<div className="quick-history-head">
|
||||
<h2>过往极速成片项目</h2>
|
||||
<h2>过往一键成片项目</h2>
|
||||
<span>{history.length}个项目</span>
|
||||
</div>
|
||||
{history.length ? (
|
||||
@@ -828,7 +829,7 @@ export function QuickCreatePage({
|
||||
<div className="quick-history-copy">
|
||||
<span className={`quick-history-badge${badge === "已完成" ? "" : " is-wait"}`}>{badge}</span>
|
||||
<h3>{historyTitle(item)}</h3>
|
||||
<p>极速成片 · {scenes}场 · {item.result?.aspect_ratio || item.settings?.aspect_ratio || "9:16"} · {(item.result?.resolution || item.settings?.resolution || "720p").toUpperCase()} · {item.result?.video_model || item.settings?.video_model_label || "智能模型"}</p>
|
||||
<p>一键成片 · {scenes}场 · {item.result?.aspect_ratio || item.settings?.aspect_ratio || "9:16"} · {(item.result?.resolution || item.settings?.resolution || "720p").toUpperCase()} · {item.result?.video_model || item.settings?.video_model_label || "智能模型"}</p>
|
||||
</div>
|
||||
<button type="button" className="quick-history-open" onClick={() => openProfessional(item.project_id, item.status)}>
|
||||
<ArrowUpRight />查看项目
|
||||
@@ -838,7 +839,7 @@ export function QuickCreatePage({
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<p className="quick-history-empty">还没有完成的极速成片,生成成功后会出现在这里。</p>
|
||||
<p className="quick-history-empty">还没有完成的一键成片,生成成功后会出现在这里。</p>
|
||||
)}
|
||||
</section>
|
||||
|
||||
@@ -846,7 +847,7 @@ export function QuickCreatePage({
|
||||
open={confirmCancel}
|
||||
title="确认取消生成?"
|
||||
subtitle="当前任务将停止"
|
||||
detail="取消后,本次极速成片不会继续生成;已完成的商品和素材会保留在专业创作项目中。"
|
||||
detail="取消后,本次一键成片不会继续生成;已完成的商品和素材会保留在专业创作项目中。"
|
||||
confirmText="确认取消"
|
||||
icon={<AlertCircle size={16} />}
|
||||
dismissable={!cancelling}
|
||||
@@ -855,6 +856,7 @@ export function QuickCreatePage({
|
||||
/>
|
||||
|
||||
{playing ? (
|
||||
<OverlayPortal>
|
||||
<div className="quick-player-bg" onClick={() => setPlaying(null)} role="presentation">
|
||||
<div className="quick-player" onClick={(event) => event.stopPropagation()} role="dialog" aria-modal="true" aria-label={playing.title}>
|
||||
<div className="quick-player-bar">
|
||||
@@ -864,6 +866,7 @@ export function QuickCreatePage({
|
||||
<video src={playing.url} controls autoPlay playsInline controlsList="nodownload" />
|
||||
</div>
|
||||
</div>
|
||||
</OverlayPortal>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user