Files
xiaoxia-saas/apps/web/src/pages/generate/components/BatchGenerationGrid.tsx
T
xiaoxia ab90a5ec9f
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 11s
CI/CD Pipeline / Check push changed paths (push) Successful in 11s
CI/CD Pipeline / Integration Tests (push) Successful in 4m12s
CI/CD Pipeline / Validate - Style (push) Successful in 5m8s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m2s
CI/CD Pipeline / Frontend Unit Tests (push) Failing after 3m46s
CI/CD Pipeline / Build Staging API Image (push) Successful in 34s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 29s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m3s
CI/CD Pipeline / Unit Tests (push) Successful in 11m1s
CI/CD Pipeline / Validate - Security (push) Successful in 13m26s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Failing after 14h57m53s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 15h18m20s
CI/CD Pipeline / PR Build Web Image (push) Failing after 15h18m21s
CI/CD Pipeline / PR Build API Image (push) Failing after 15h18m21s
CI/CD Pipeline / Build Production API Image (push) Failing after 14h57m6s
CI/CD Pipeline / Retag skipped Staging API Image (push) Failing after 14h57m10s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 14h57m6s
CI/CD Pipeline / Build Production Web Image (push) Failing after 14h57m6s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Failing after 14h57m10s
CI/CD Pipeline / CI Gate (push) Failing after 14h57m6s
CI/CD Pipeline / Frontend Lint (push) Failing after 15h16m42s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 15h33m52s
fix: #1800 批量生成进度卡片布局 + #1893 文案库 AI 入口 UX 细节 (#1937)
fix: #1800 批量生成进度卡片布局 + #1893 文案库 AI 入口 UX 细节

- #1800: 卡片标题加 ellipsis 防溢出,grid 列宽 minmax(320px,1fr) max380px,card-head flex 布局
- #1893: AI 生成标题/改写按钮 disabled 时用 Tooltip 包裹 span,改写弹窗 loading 时禁关禁点
2026-09-15 23:31:26 +08:00

139 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 第5步「确认生成」— 批量渲染进度网格(Issue #1677 / #1800 布局修复)
*
* N 个正式生成任务各自独立卡片:进度条 / 成功成片播放 / 失败原因 + 单独重试。
* 数据来自 useGenerateVideo 的 batchTasks(useGenerationPolling 实时回传)。
*
* #1800 修复点:
* - 不再用 inline style 硬编码 grid 列宽 / 卡片 maxWidth,改由 CSS 统一控制
* (便于响应式 + 避免 inline 覆盖类规则)。
* - 标题图标 + 文本拆分为独立 span,文本 span 加 flex:1/min-width:0/ellipsis,
* 防止长标题在窄列里溢出导致与相邻卡片进度条视觉重叠。
*/
import React from "react"
import { LoadingOutlined, CheckCircleFilled, CloseCircleOutlined } from "@ant-design/icons"
import type { BatchTaskState } from "../hooks/generate-video/useGenerationPolling"
import type { GeneratedVideo } from "@/api/template-editor"
interface BatchGenerationGridProps {
tasks: BatchTaskState[]
/** 变体标题(按变体序号取) */
titles: string[]
/** 失败任务重试 */
onRetryTask: (taskId: string) => void
}
const BatchGenerationGrid: React.FC<BatchGenerationGridProps> = ({
tasks,
titles,
onRetryTask,
}) => {
const sorted = [...tasks].sort(
(a, b) => Number(a.variantIndex || 0) - Number(b.variantIndex || 0),
)
return (
<div className="xx-form-section">
<div className="xx-preview-header">
<h3>🎬 正在生成 {tasks.length} 个视频</h3>
<span style={{ fontSize: 13, color: "var(--text-secondary, #666)" }}>
完成 {tasks.filter((t) => t.status === "completed").length} / {tasks.length}
</span>
</div>
{/* #1800: grid 列宽 / gap / justify 全部交由 .xx-batch-gen-grid CSS 控制 */}
<div className="xx-batch-gen-grid">
{sorted.map((task) => {
const title = titles[task.variantIndex] || `视频 ${task.variantIndex + 1}`
const video = (task.videos?.[0] || null) as GeneratedVideo | null
return (
<div key={task.taskId} className={`xx-batch-gen-card status-${task.status}`}>
<div className="xx-batch-gen-card-head">
<span className="xx-batch-gen-card-title" title={title}>
{task.status === "completed" ? (
<CheckCircleFilled
className="xx-batch-gen-card-icon"
style={{ color: "#52c41a" }}
/>
) : task.status === "failed" ? (
<CloseCircleOutlined
className="xx-batch-gen-card-icon"
style={{ color: "#ef4444" }}
/>
) : (
<LoadingOutlined
className="xx-batch-gen-card-icon"
style={{ color: "#1677ff" }}
/>
)}
<span className="xx-batch-gen-card-title-text">
视频 {task.variantIndex + 1}:{title}
</span>
</span>
</div>
<div className="xx-batch-gen-card-body">
{task.status === "running" && (
<>
<div className="xx-gen-progress-bar">
<div
className="xx-gen-progress-bar-fill"
style={{ width: `${Math.min(task.progress, 100)}%` }}
/>
</div>
<div className="xx-batch-gen-card-pct">{Math.round(task.progress)}%</div>
</>
)}
{task.status === "completed" && video && (
// 竖屏自适应容器(#1750):成片固定 1080×1920(9:16),
// 视频按真实宽高比 contain 显示,黑底居中,杜绝横屏播放器左右大黑边
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
background: "transparent",
borderRadius: 8,
padding: 0,
}}
>
<video
src={video.download_url || video.file_url}
controls
style={{
width: "100%",
maxHeight: "70vh",
aspectRatio: "9 / 16",
objectFit: "cover",
borderRadius: 4,
background: "transparent",
}}
poster={video.thumbnail_url}
/>
</div>
)}
{task.status === "completed" && !video && (
<div className="xx-batch-gen-card-done">✅ 已完成(成片可在下一步选择封面)</div>
)}
{task.status === "failed" && (
<div className="xx-batch-gen-card-failed">
<div className="xx-batch-gen-card-err">{task.error || "生成失败"}</div>
<button
type="button"
className="xx-btn xx-btn-primary xx-btn-sm"
onClick={() => onRetryTask(task.taskId)}
>
🔄 重试此视频
</button>
</div>
)}
</div>
</div>
)
})}
</div>
</div>
)
}
export default BatchGenerationGrid