优化脚本

This commit is contained in:
Azmat@qq.com
2026-08-25 16:40:22 +08:00
parent e2ec2d14af
commit df6784b90c
22 changed files with 893 additions and 156 deletions
+26 -14
View File
@@ -635,6 +635,14 @@ export function App() {
}
}
async function deleteProjectAction(projectId: string) {
const ok = await action(() => api.deleteProject(projectId), "项目已删除");
if (ok !== null && projectId === activeProjectIdRef.current) {
setActiveProjectId("");
setProjectDetail(null);
}
}
async function runProductBatch<T>(ids: string[], work: (id: string) => Promise<T>, successText: string): Promise<ProductBatchResult> {
const uniqueIds = Array.from(new Set(ids));
if (!uniqueIds.length) return { succeededIds: [], failedIds: [] };
@@ -804,7 +812,7 @@ export function App() {
return null;
}
await refreshBilling();
setNotice({ type: "success", text: okText });
if (okText) setNotice({ type: "success", text: okText });
return assets[0].id;
}
@@ -889,7 +897,7 @@ export function App() {
function renderPage() {
switch (page) {
case "dashboard":
return <Dashboard products={products} projects={projects} productTotal={productTotal} projectTotal={projectTotal} billing={billing} userName={currentUser.username} loading={!dataLoaded} navigate={navigate} />;
return <Dashboard products={products} projects={projects} productTotal={productTotal} projectTotal={projectTotal} billing={billing} userName={currentUser.username} loading={!dataLoaded} navigate={navigate} onDelete={deleteProjectAction} />;
case "products":
return (
<ProductsPage
@@ -946,14 +954,7 @@ export function App() {
initialTab={route.tab}
onCreate={(payload) => action(() => api.createProject(payload), "项目已创建")}
openPipeline={(projectId) => navigate("pipeline", { projectId })}
onDelete={async (projectId) => {
const ok = await action(() => api.deleteProject(projectId), "项目已删除");
// 删的是当前激活项目就清掉残留 id/详情,否则后续新建/进管线会拿着已删 id 去拉 → 404 / 卡 loading
if (ok !== null && projectId === activeProjectIdRef.current) {
setActiveProjectId("");
setProjectDetail(null);
}
}}
onDelete={deleteProjectAction}
/>
);
case "projectWizard":
@@ -1082,7 +1083,7 @@ export function App() {
case "settingsNotify":
return <SettingsPage user={currentUser} team={currentTeam} initialSection="notify" preferences={preferences} sessions={sessions} onSavePreferences={savePreferences} onRevokeSession={revokeSession} onRevokeOthers={revokeOtherSessions} onSaveProfile={saveProfile} onChangePassword={changeOwnPassword} onUploadAvatar={uploadOwnAvatar} onResetAvatar={resetOwnAvatar} onNotify={(text) => setNotice({ type: "success", text })} onLogout={logout} />;
default:
return <Dashboard products={products} projects={projects} productTotal={productTotal} projectTotal={projectTotal} billing={billing} userName={currentUser.username} loading={!dataLoaded} navigate={navigate} />;
return <Dashboard products={products} projects={projects} productTotal={productTotal} projectTotal={projectTotal} billing={billing} userName={currentUser.username} loading={!dataLoaded} navigate={navigate} onDelete={deleteProjectAction} />;
}
}
@@ -1123,6 +1124,7 @@ export function App() {
project={pipelineProject}
scriptModelName={publicModelDisplayName(pipelineTextModel, "AI")}
textModels={modelConfigs.filter((m) => m.capability === "text" && m.status === "active")}
videoModels={modelConfigs.filter((m) => m.capability === "video" && m.status === "active")}
loading={loading}
navigate={navigate}
onBack={() => goBack("projects")}
@@ -1149,10 +1151,20 @@ export function App() {
onAdoptVideoVersion={(segmentId, versionId) => action(() => api.adoptVideoVersion(pipelineProject.id, { video_segment_id: segmentId, version_id: versionId }), "已采用该版本")}
onGenerateVoiceover={(payload) => action(() => api.generateVoiceover(pipelineProject.id, payload), "配音已生成")}
onGenerateBaseAsset={async (kind, prompt, label, referenceAssetId) => {
// 异步:提交→轮询出图→刷新;返回新资产 id 供「立绘→三视图」链式生成
// 异步:提交→轮询出图→刷新。角色立绘成功后立刻据该立绘出三视图,用户不必再进详情点一次。
// referenceAssetId:角色重跑时传当前立绘 → 后端走 image_edit 参考它,保持人物一致
const assetId = await submitAndPollAsset(() => api.generateBaseAsset(pipelineProject.id, { kind, prompt, label, reference_asset_id: referenceAssetId }), "基础资产已生成");
return assetId ? { adopted_asset: assetId } : null;
const assetId = await submitAndPollAsset(
() => api.generateBaseAsset(pipelineProject.id, { kind, prompt, label, reference_asset_id: referenceAssetId }),
kind === "person" ? "" : "基础资产已生成",
);
if (!assetId) return null;
if (kind === "person") {
await submitAndPollAsset(
() => api.generateTriview(pipelineProject.id, { portrait_asset_id: assetId }),
"角色立绘与三视图已生成",
);
}
return { adopted_asset: assetId };
}}
onGenerateStoryboard={(prompt) =>
// 只「提交」(秒回);出图由后台 pollStoryboardQuiet 驱动 —— 不占全局 loading,不锁其它场按钮(对标视频「开始生成」)