视频复刻优化替换商品和替换角色

This commit is contained in:
Azmat@qq.com
2026-08-31 16:40:16 +08:00
parent db71b29009
commit e24ca1b0de
9 changed files with 253 additions and 71 deletions
+4 -2
View File
@@ -37,6 +37,8 @@ const KIND_LABEL: Record<string, string> = { product: "商品", person: "角色"
const SOURCE_LABEL: Record<string, string> = { ai: "脚本辅助生成", theme: "脚本辅助生成", manual: "上传脚本", video: "上传视频提炼" };
// 上传自有脚本 / 上传视频提炼入口暂隐,改 true 即可恢复
const SHOW_SCRIPT_IMPORT = false;
// 脚本模型选择入口暂隐(目前仅一个模型),改 true 或多模型时可恢复
const SHOW_SCRIPT_MODEL_PICKER = false;
// 旁白配音音色预设(语音合成经典版试用包实测可用,与后端 VOICEOVER_VOICES 对齐)
const VO_VOICES = [
{ key: "BV700_streaming", label: "灿灿 · 活力女声" },
@@ -3350,8 +3352,8 @@ export function PipelinePage(props: {
</button>
</>
)}
{/* 模型选择小按钮(输入框下方,对齐 ChatGPT/Lovart)· 复用 restraint chip 下拉,向上展开 */}
{scriptPickerModels.length > 0 ? (
{/* 模型选择小按钮(输入框下方,对齐 ChatGPT/Lovart)· 目前单一模型先隐藏 */}
{SHOW_SCRIPT_MODEL_PICKER && scriptPickerModels.length > 1 ? (
<div ref={modelPickRef} className={`chip-wrap chat-model-pick${modelMenuOpen ? " open" : ""}`}>
<button type="button" className="chip" title="选择脚本生成模型" aria-expanded={modelMenuOpen} aria-haspopup="listbox" onClick={() => setModelMenuOpen((v) => !v)}>
{activeModelName}
+19 -5
View File
@@ -962,8 +962,11 @@ export function VideoReplacePage({
<div className="product-replace-options">
<button
type="button"
className={`replace-product-method${source === "library" ? " active" : ""}${librarySelected ? " has-product-preview" : ""}`}
className={`replace-product-method${source === "library" ? " active" : ""}${librarySelected ? " has-product-preview" : ""}${generating ? " is-disabled" : ""}`}
disabled={generating}
aria-disabled={generating}
onClick={() => {
if (generating) return;
if (replaceMode === "character") setPendingModelId(selectedModel?.id || "");
else setPendingProductId(selectedProduct?.id || "");
setLibraryOpen(true);
@@ -986,12 +989,17 @@ export function VideoReplacePage({
</button>
<div
className={`replace-product-method replace-temporary-method${source === "temporary" ? " active" : ""}${tempDisplay.length ? " has-images" : ""}${tempDrop.dragging ? " is-dragover" : ""}`}
className={`replace-product-method replace-temporary-method${source === "temporary" ? " active" : ""}${tempDisplay.length ? " has-images" : ""}${tempDrop.dragging ? " is-dragover" : ""}${generating ? " is-disabled" : ""}`}
role="button"
tabIndex={0}
{...tempDrop.dropProps}
onClick={() => tempInputRef.current?.click()}
tabIndex={generating ? -1 : 0}
aria-disabled={generating}
{...(!generating ? tempDrop.dropProps : {})}
onClick={() => {
if (generating) return;
tempInputRef.current?.click();
}}
onKeyDown={(event) => {
if (generating) return;
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
tempInputRef.current?.click();
@@ -1023,9 +1031,11 @@ export function VideoReplacePage({
type="button"
className="replace-temporary-remove"
aria-label={`删除第${index + 1}张临时${copy.temporaryNoun}`}
disabled={generating}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
if (generating) return;
if (tempFiles.length) {
setTempFiles((current) => current.filter((_, itemIndex) => itemIndex !== index));
} else {
@@ -1049,9 +1059,11 @@ export function VideoReplacePage({
<button
type="button"
className="replace-temporary-clear"
disabled={generating}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
if (generating) return;
if (!tempFiles.length && !tempAssetRefs.length) return;
setTempFiles([]);
setTempAssetRefs([]);
@@ -1072,8 +1084,10 @@ export function VideoReplacePage({
accept="image/jpeg,image/png,image/webp"
multiple
hidden
disabled={generating}
onClick={(event) => event.stopPropagation()}
onChange={(event) => {
if (generating) return;
addTempImages(event.target.files);
event.target.value = "";
}}
+17 -1
View File
@@ -503,11 +503,27 @@
border-radius: inherit;
}
.vrep-page .replace-product-method:hover {
.vrep-page .replace-product-method:hover:not(:disabled):not(.is-disabled) {
border-color: rgba(0, 47, 167, 0.28);
transform: translateY(-1px);
}
.vrep-page .replace-product-method:disabled,
.vrep-page .replace-product-method.is-disabled,
.vrep-page .replace-product-method[aria-disabled="true"] {
opacity: 0.55;
cursor: not-allowed;
transform: none !important;
pointer-events: none;
}
.vrep-page .replace-temporary-remove:disabled,
.vrep-page .replace-temporary-clear:disabled {
opacity: 0.45;
cursor: not-allowed;
pointer-events: none;
}
.vrep-page .replace-product-method.active {
border-color: var(--klein);
background: #f1f5ff;