fix: 测试清单(8) 新一轮 — ZWQ/PMC/设置/团队 多项修复
视频/工作台/商品库(ZWQ): - row19 视频阶段移除已取消的【上传视频】按钮 (pipeline.tsx) - row20 工作台统计栏(总项目/进行中/成片)点击跳转视频项目对应 tab (dashboard/projects/route-config/App) - row21 最新项目跳转改用真实 projectId, 不再跳到最近打开项目 (dashboard.tsx) - row22+PMC28 网格/列表视图模式持久化(localStorage), 跨菜单记住用户选择 (projects/ai-tools + 新 hook use-view-mode.ts) - row24 已有三视图的演员/模特直接复用, 不再强制点AI生成三视图 (pipeline.tsx) 图片生成/设置(PMC): - row27 任务中心: 6个进行中状态补全归类, 不再把生成中误判为失败栏 (stage-config.ts) - row29 头像上传500: avatar_url 存公读直链替代超长预签名URL(URLField max_length=200溢出) (accounts/views.py, 需部署) - row30 显示名保存后回显: 改读 first_name 回退 username, 修刷新仍旧名 (settings.tsx) - row31/32 隐藏【创作默认】【显示】两个设置模块 (settings.tsx) 平台套图(YYX): - row3 图片预览铺满占位 (ai-tools-page.css) 团队: - PMC25 充值/邀请成员/设置月限额三弹窗禁止点遮罩误关 (team.tsx) 含平台套图线上提示词优化(services.py/views.py/api.ts, 前序会话遗留一并提交) 构建: tsc --noEmit=0, npm run build=0 (1755模块); 后端 py_compile OK 注: row29 头像/后端项需部署生效 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1615,8 +1615,6 @@ export function PipelinePage(props: {
|
||||
const [propsTab, setPropsTab] = useState<"subtitle" | "transition" | "bgm">("subtitle");
|
||||
const edHydratedRef = useRef(false);
|
||||
const bgmFileRef = useRef<HTMLInputElement | null>(null);
|
||||
const videoUploadRef = useRef<HTMLInputElement | null>(null);
|
||||
const [uploadTargetSeg, setUploadTargetSeg] = useState<string | null>(null);
|
||||
// 提交一个新编辑态(进 undo 栈)
|
||||
const commitEdit = useCallback((next: EditorState) => {
|
||||
setEdHistory((h) => [...h.slice(-49), edState]);
|
||||
@@ -2350,16 +2348,6 @@ export function PipelinePage(props: {
|
||||
// (旧的转场黑闪提示层已删:双缓冲槽位的 opacity 过渡就是真转场预览)
|
||||
|
||||
// Stage 4 / 5 文件上传
|
||||
function onPickVideoFile(event: ChangeEvent<HTMLInputElement>) {
|
||||
const file = event.target.files?.[0];
|
||||
event.target.value = "";
|
||||
if (file && uploadTargetSeg) onUploadVideoSegment(uploadTargetSeg, file);
|
||||
setUploadTargetSeg(null);
|
||||
}
|
||||
function triggerVideoUpload(segmentId: string) {
|
||||
setUploadTargetSeg(segmentId);
|
||||
videoUploadRef.current?.click();
|
||||
}
|
||||
// 导出全部:把本项目所有已采用视频片段打成一个 zip 下载
|
||||
const [exporting, setExporting] = useState(false);
|
||||
const [exportErr, setExportErr] = useState("");
|
||||
@@ -3355,18 +3343,12 @@ export function PipelinePage(props: {
|
||||
<div className="bar-wrap"><span style={{ width: `${pct}%` }}></span></div>
|
||||
<span className="muted mono" style={{ fontSize: "12px" }}>{pct}%</span>
|
||||
<button className="btn btn-sm btn-primary" type="button" disabled={loading || !segments.length || activeVideoCount > 0} onClick={() => guardVideoGen(shots, null, submitAllVideosOptimistic)}>{loading ? <><span className="spinner btn-spin" aria-hidden="true" />提交中…</> : anyStarted ? "↻ 全部重跑" : "▶ 开始生成视频"}</button>
|
||||
<button className="btn btn-sm" type="button" disabled={loading || !segments.length} onClick={() => triggerVideoUpload((segments.find((s) => s.status !== "succeeded") || segments[0]).id)}>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: "4px" }}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><path d="M17 8l-5-5-5 5" /><path d="M12 3v12" /></svg>
|
||||
上传视频
|
||||
</button>
|
||||
{/* 导出全部:把所有已完成片段打包成 zip 一次性下载 */}
|
||||
<button className="btn btn-sm" type="button" disabled={exporting || segDone === 0} title={exportErr || "把所有已完成视频片段打包下载"} onClick={() => void exportAllVideos()}>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: "4px" }}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><path d="M7 10l5 5 5-5" /><path d="M12 15V3" /></svg>
|
||||
{exporting ? "导出中…" : exportErr ? "导出失败" : "导出全部"}
|
||||
</button>
|
||||
</div>
|
||||
<input ref={videoUploadRef} type="file" accept="video/*" style={{ display: "none" }} onChange={onPickVideoFile} />
|
||||
|
||||
{segments.length ? (
|
||||
<div className="video-grid" id="video-grid">
|
||||
{segments.map((seg) => {
|
||||
@@ -3963,6 +3945,17 @@ export function PipelinePage(props: {
|
||||
const triVersions = triGroup?.candidate_assets ?? [];
|
||||
const viewTriAsset = (adTriId && triVersions.includes(adTriId)) ? adTriId : (triGroup?.adopted_asset || triVersions.at(-1) || "");
|
||||
const triUrl = candUrl(triGroup, viewTriAsset);
|
||||
// 已有三视图判定(ZWQ-row24):优先看 BaseGroup(流水线内生成的三视图组);其次看资产 metadata
|
||||
// 沿用 library.tsx 同款判定:tri_view/triview/has_triview/three_view/tri_views 任一为真即已有;
|
||||
// 模特库正面图(metadata.view==="frontal")本身与三视图同批生成,直接算已就绪。
|
||||
const assetAlreadyHasTri: boolean = (() => {
|
||||
if (triUrl) return true;
|
||||
const m: Record<string, unknown> = (viewPortraitAsset ? byId.get(viewPortraitAsset)?.metadata : null) || {};
|
||||
const has = m.tri_view ?? m.triview ?? m.has_triview ?? m.three_view ?? m.tri_views;
|
||||
if (has === true || (Array.isArray(has) && has.length > 0) || (typeof has === "string" && (has as string).trim())) return true;
|
||||
if (m.view === "frontal") return true; // 模特库正面图:generate_model 同批出了三视图
|
||||
return false;
|
||||
})();
|
||||
const pBK = `addet-portrait:${entity.key}`;
|
||||
// 没立绘时(尤其 seed 首次生成),立绘在 worker 跑 ~30s,本地 isBusy 早已落回 → 用 pendingHas 兜底转圈
|
||||
const busyPortrait = isBusy(pBK) || (!portraitUrl && pendingHas(adDetail.kind, entity.name));
|
||||
@@ -4037,7 +4030,7 @@ export function PipelinePage(props: {
|
||||
{triUrl && <button className="ad-zoom-btn" type="button" title="查看大图" onClick={() => setPreview({ src: triUrl, kind: "image", name: `${entity.name} · 三视图` })}>{zoomSvg}</button>}
|
||||
</div>
|
||||
</div>
|
||||
{!triUrl && !busyTri && (
|
||||
{!assetAlreadyHasTri && !busyTri && (
|
||||
<div className="asset-detail-tip">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9" /><path d="M12 8v4M12 16h.01" /></svg>
|
||||
<span>{viewPortraitAsset ? "三视图据这版立绘生成,保证正/侧/背多角度一致。点下方按钮生成。" : "请先生成左侧「立绘」,有了立绘才能据它生成三视图。"}</span>
|
||||
|
||||
Reference in New Issue
Block a user