Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3430c2fb6d | |||
| 4b04c6401c |
@@ -889,9 +889,22 @@
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.vv-btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.vv-btn-primary.vv-btn-disabled-gray,
|
||||
.vv-btn-primary:disabled.vv-btn-disabled-gray {
|
||||
background: #d1d5db !important;
|
||||
color: #6b7280 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none !important;
|
||||
transform: none !important;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.vv-btn-primary.vv-btn-disabled-gray:hover {
|
||||
box-shadow: none !important;
|
||||
transform: none !important;
|
||||
}
|
||||
.vv-btn-ghost {
|
||||
background: #fff;
|
||||
color: #6b7280;
|
||||
@@ -1129,6 +1142,49 @@
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.vv-asset-voice .vv-thumb-name-txt {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
.vv-asset-voice .vv-thumb-dur {
|
||||
flex: 0 0 auto;
|
||||
font-size: 11px;
|
||||
color: #9ca3af;
|
||||
background: #f3f4f6;
|
||||
padding: 1px 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.vv-asset-voice .vv-thumb-ph {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex: 0 0 36px;
|
||||
font-size: 20px;
|
||||
border-radius: 50%;
|
||||
background: #f3f0ff;
|
||||
color: #7c3aed;
|
||||
}
|
||||
.vv-asset-voice .vv-thumb-card img,
|
||||
.vv-asset-voice .vv-thumb-card video {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex: 0 0 36px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.vv-asset-voice .vv-thumb-check {
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.vv-modal-empty {
|
||||
flex: 1;
|
||||
@@ -1180,13 +1236,29 @@
|
||||
}
|
||||
|
||||
/* 列禁用态 */
|
||||
.vv-col-disabled .vv-section {
|
||||
.vv-col-disabled .vv-section-body,
|
||||
.vv-col-disabled .vv-step-subhead,
|
||||
.vv-col-disabled .vv-credits,
|
||||
.vv-col-disabled .vv-preview,
|
||||
.vv-col-disabled .vv-error,
|
||||
.vv-col-disabled .vv-hint-gray,
|
||||
.vv-col-disabled .vv-hint-yellow {
|
||||
opacity: 0.55;
|
||||
pointer-events: none;
|
||||
}
|
||||
.vv-col-disabled .vv-section .vv-btn-primary {
|
||||
background: #d1d5db !important;
|
||||
cursor: not-allowed;
|
||||
.vv-col-disabled .vv-btn-primary,
|
||||
.vv-col-disabled .vv-btn-primary:hover {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.vv-col-disabled .vv-section .vv-form-row,
|
||||
.vv-col-disabled .vv-section .vv-pill-row,
|
||||
.vv-col-disabled .vv-section input,
|
||||
.vv-col-disabled .vv-section textarea,
|
||||
.vv-col-disabled .vv-section .ant-select,
|
||||
.vv-col-disabled .vv-section .vv-pill,
|
||||
.vv-col-disabled .vv-section .vv-action-btn,
|
||||
.vv-col-disabled .vv-section .vv-audio-cell,
|
||||
.vv-col-disabled .vv-section .vv-step-lock {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Section 内小标题 */
|
||||
@@ -1289,16 +1361,6 @@
|
||||
}
|
||||
|
||||
/* 列禁用态 */
|
||||
.vv-col-disabled .vv-section {
|
||||
opacity: 0.55;
|
||||
}
|
||||
.vv-col-disabled .vv-section .vv-btn,
|
||||
.vv-col-disabled .vv-section button,
|
||||
.vv-col-disabled .vv-section input,
|
||||
.vv-col-disabled .vv-section textarea,
|
||||
.vv-col-disabled .vv-section .ant-select {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Section 内小标题 */
|
||||
.vv-section-subtitle {
|
||||
|
||||
@@ -1357,20 +1357,24 @@ const ViralVideoPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* STEP2 主按钮:✍️ 生成文案 */}
|
||||
{step2Enabled &&
|
||||
task.uiStep !== "step2_copy_ready" &&
|
||||
{/* STEP2 主按钮:✍️ 生成文案(文案未确认前显示) */}
|
||||
{task.uiStep !== "step2_copy_ready" &&
|
||||
task.uiStep !== "step3_ready" &&
|
||||
task.uiStep !== "step3_generating" &&
|
||||
task.uiStep !== "step3_done" && (
|
||||
<button
|
||||
className="vv-btn vv-btn-primary"
|
||||
className={`vv-btn vv-btn-primary ${!step2Enabled ? "vv-btn-disabled-gray" : ""}`}
|
||||
onClick={handleGenerateCopy}
|
||||
disabled={task.uiStep === "step2_generating" || !step2Enabled}
|
||||
title={!step2Enabled ? "请先完成图片分析" : ""}
|
||||
>
|
||||
{task.uiStep === "step2_generating" ? (
|
||||
<>
|
||||
<span className="vv-spinner" /> AI 创作中…
|
||||
<span className="vv-spinner" /> AI 生成文案中…
|
||||
</>
|
||||
) : !step2Enabled ? (
|
||||
<>
|
||||
<EditOutlined /> 生成文案(请先完成图片分析)
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@@ -1485,27 +1489,41 @@ const ViralVideoPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 步骤提示/主按钮 */}
|
||||
{!step2Enabled && (
|
||||
<div className="vv-hint-gray">请先在 STEP 1 上传素材并点击「分析图片」</div>
|
||||
)}
|
||||
{step2Enabled && !step3Enabled && (
|
||||
<div className="vv-hint-yellow">请在 STEP 2 配置参数并点击「生成文案」</div>
|
||||
)}
|
||||
{task.uiStep === "step3_ready" && (
|
||||
<button className="vv-btn vv-btn-primary" onClick={handleGenerateVideo}>
|
||||
<VideoCameraOutlined /> 开始生成视频
|
||||
</button>
|
||||
)}
|
||||
{task.uiStep === "step3_generating" && (
|
||||
<button className="vv-btn vv-btn-primary" disabled>
|
||||
<span className="vv-spinner" /> AI 正在生成视频中…
|
||||
</button>
|
||||
)}
|
||||
{task.uiStep === "step3_done" && outputUrl && (
|
||||
<button className="vv-btn vv-btn-ghost vv-btn-block" onClick={resetTask}>
|
||||
<ReloadOutlined /> 再生成一个
|
||||
{/* STEP3 主按钮:🎬 开始生成视频(始终展示,状态驱动 disabled/文案) */}
|
||||
{task.uiStep !== "step3_done" ? (
|
||||
<button
|
||||
className={`vv-btn vv-btn-primary ${!step3Enabled ? "vv-btn-disabled-gray" : ""}`}
|
||||
onClick={handleGenerateVideo}
|
||||
disabled={task.uiStep === "step3_generating" || !step3Enabled}
|
||||
title={
|
||||
!step3Enabled
|
||||
? !step2Enabled
|
||||
? "请先完成图片分析"
|
||||
: "请先在 STEP 2 生成并确认文案"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
{task.uiStep === "step3_generating" ? (
|
||||
<>
|
||||
<span className="vv-spinner" /> AI 正在生成视频中…
|
||||
</>
|
||||
) : !step3Enabled ? (
|
||||
<>
|
||||
<VideoCameraOutlined /> 开始生成视频
|
||||
{!step2Enabled ? "(请先完成图片分析)" : "(请先确认文案)"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<VideoCameraOutlined /> 开始生成视频
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
) : (
|
||||
outputUrl && (
|
||||
<button className="vv-btn vv-btn-ghost vv-btn-block" onClick={resetTask}>
|
||||
<ReloadOutlined /> 再生成一个
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -199,7 +199,16 @@ export default function AssetPickerModal({
|
||||
<div className="vv-empty-icon">
|
||||
{kind === "image" ? "🖼️" : kind === "video" ? "🎬" : "🎵"}
|
||||
</div>
|
||||
该素材库暂无{KIND_LABEL[kind]}素材
|
||||
{kind === "voice" ? (
|
||||
<>
|
||||
<div style={{ marginTop: 8, fontSize: 13 }}>暂无配音素材</div>
|
||||
<div style={{ marginTop: 4, fontSize: 12, color: "#9ca3af" }}>
|
||||
请先在「配音/我的音色」中上传音频文件,或在素材库管理中添加
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>该素材库暂无{KIND_LABEL[kind]}素材</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className={`vv-asset-thumbs vv-asset-${kind}`}>
|
||||
@@ -221,7 +230,12 @@ export default function AssetPickerModal({
|
||||
)}
|
||||
{active && <div className="vv-thumb-check">✓</div>}
|
||||
<div className="vv-thumb-name" title={asset.name}>
|
||||
{asset.name}
|
||||
<span className="vv-thumb-name-txt">{asset.name}</span>
|
||||
{kind === "voice" &&
|
||||
typeof asset.duration === "number" &&
|
||||
asset.duration > 0 && (
|
||||
<span className="vv-thumb-dur">{Math.round(asset.duration)}s</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user