优化住流程和添加复刻视频页面
This commit is contained in:
@@ -1450,10 +1450,9 @@ export function PipelinePage(props: {
|
||||
const recommended = useMemo(
|
||||
() => recommendSetup({
|
||||
category: setupProduct?.category,
|
||||
targetAudience: setupProduct?.target_audience,
|
||||
title: setupProduct?.title,
|
||||
}),
|
||||
[setupProduct?.category, setupProduct?.target_audience, setupProduct?.title]
|
||||
[setupProduct?.category, setupProduct?.title]
|
||||
);
|
||||
const wizard = project.metadata?.wizard;
|
||||
const [setupOpen, setSetupOpen] = useState(false);
|
||||
@@ -1464,7 +1463,9 @@ export function PipelinePage(props: {
|
||||
const [setupStructure, setSetupStructure] = useState<VideoStructure>(
|
||||
coerceVideoStructure(wizard?.video_structure, recommended.structure)
|
||||
);
|
||||
const [setupPersona, setSetupPersona] = useState<string>(coercePersona(wizard?.persona, SETUP_PERSONA_KEYS[0] || "urban"));
|
||||
const [setupPersona, setSetupPersona] = useState<string>(
|
||||
coercePersona(wizard?.persona, recommended.persona || SETUP_PERSONA_KEYS[0] || "urban")
|
||||
);
|
||||
const [setupDuration, setSetupDuration] = useState<number>(() => {
|
||||
if (typeof wizard?.total_duration === "number") return clampDuration(wizard.total_duration);
|
||||
// 兼容一期向导存的字符串档位("0-30" → 30)
|
||||
@@ -1476,12 +1477,16 @@ export function PipelinePage(props: {
|
||||
const setupTouched = useRef(false);
|
||||
const wizardHasCombo = Boolean(wizard?.presentation_format && wizard?.video_structure);
|
||||
const wizardHasDuration = typeof wizard?.total_duration === "number" || Boolean(wizard?.duration);
|
||||
const wizardHasPersona = Boolean(wizard?.persona);
|
||||
useEffect(() => {
|
||||
if (setupTouched.current || wizardHasCombo) return;
|
||||
setSetupFormat(recommended.format);
|
||||
setSetupStructure(recommended.structure);
|
||||
if (!wizardHasDuration) setSetupDuration(recommended.duration);
|
||||
}, [recommended.format, recommended.structure, recommended.duration, wizardHasCombo, wizardHasDuration]);
|
||||
if (setupTouched.current) return;
|
||||
if (!wizardHasCombo) {
|
||||
setSetupFormat(recommended.format);
|
||||
setSetupStructure(recommended.structure);
|
||||
if (!wizardHasDuration) setSetupDuration(recommended.duration);
|
||||
}
|
||||
if (!wizardHasPersona) setSetupPersona(recommended.persona);
|
||||
}, [recommended.format, recommended.structure, recommended.persona, recommended.duration, wizardHasCombo, wizardHasDuration, wizardHasPersona]);
|
||||
|
||||
// ── 5.2 换商品重跑 ── 新建向导选的套路模板由后端回填进 metadata.wizard,这里只读不写
|
||||
const templateName = typeof wizard?.template_name === "string" ? wizard.template_name : "";
|
||||
@@ -1875,7 +1880,7 @@ export function PipelinePage(props: {
|
||||
`${base}\n以上是我拆解一条参考视频得到的分镜稿。请照搬它的镜头顺序、每镜时长比例、景别、机位、运镜、人物动作和声音层次,`
|
||||
+ `把人物、商品、品牌、台词全部换成我自己的商品;参考视频里出现的商品、品牌、人物一律不要保留。`
|
||||
+ `写 visual 时把每镜的景别、机位、运镜、动作、表情、音效、背景音乐、字幕、备注折进导演说明书,不要压成一句画面摘要。`
|
||||
+ `原稿里标注「无 / 不可见 / 听不清 / 存疑」的地方不要编造,由你按我的商品补全。目标人群:${personaLabel}`,
|
||||
+ `原稿里标注「无 / 不可见 / 听不清 / 存疑」的地方不要编造,由你按我的商品补全。人物设定:${personaLabel}`,
|
||||
`上传视频提炼 · ${combo}`,
|
||||
"video",
|
||||
);
|
||||
@@ -1891,7 +1896,7 @@ export function PipelinePage(props: {
|
||||
// 上传脚本:先识别原稿结构,再补齐钩子 / 卖点证明 / 转化,而不是照抄一遍
|
||||
await runScriptGeneration(
|
||||
`${base}\n以上是我已有的脚本。请先识别它的结构与叙述顺序,尽量保留原意与原有表达,再据此整理成镜头脚本;`
|
||||
+ `其中开头钩子、卖点的证明方式、结尾转化引导如有缺失或偏弱,请补齐补强。目标人群:${personaLabel}`,
|
||||
+ `其中开头钩子、卖点的证明方式、结尾转化引导如有缺失或偏弱,请补齐补强。人物设定:${personaLabel}`,
|
||||
`上传脚本 · ${combo}`,
|
||||
"manual",
|
||||
);
|
||||
@@ -3326,11 +3331,11 @@ export function PipelinePage(props: {
|
||||
<div className="setup-rec">{STRUCTURE_HINT[setupStructure]}</div>
|
||||
<label className="setup-field">
|
||||
<span className="sf-k">人物</span>
|
||||
<select className="setup-select" value={setupPersona} onChange={(e) => setSetupPersona(e.target.value)}>
|
||||
<select className="setup-select" value={setupPersona} onChange={(e) => { setupTouched.current = true; setSetupPersona(e.target.value); }}>
|
||||
{SETUP_PERSONA_KEYS.map((k) => <option key={k} value={k}>{WIZ_PERSONA_LABEL[k]}</option>)}
|
||||
</select>
|
||||
</label>
|
||||
<div className="setup-rec">根据商品目标人群推荐</div>
|
||||
<div className="setup-rec">{recommended.reason} · {WIZ_PERSONA_LABEL[recommended.persona] || recommended.persona}</div>
|
||||
{/* 时长:15/30/45/60;每镜固定 15 秒 */}
|
||||
<label className="setup-field">
|
||||
<span className="sf-k">时长</span>
|
||||
@@ -3343,10 +3348,11 @@ export function PipelinePage(props: {
|
||||
{/* ← 返回:收起设定卡,回到「脚本辅助生成 / 上传脚本」入口页 */}
|
||||
<button type="button" className="btn btn-ghost btn-sm" onClick={() => setSetupOpen(false)}>← 返回</button>
|
||||
<button type="button" className="btn btn-ghost btn-sm" title={recommended.reason} onClick={() => {
|
||||
// 重新推荐:回到按商品信息算出的那一组(不是随机换,随机换等于没推荐)
|
||||
// 重新推荐:回到按商品品类算出的那一组(不是随机换,随机换等于没推荐)
|
||||
setupTouched.current = false;
|
||||
setSetupFormat(recommended.format);
|
||||
setSetupStructure(recommended.structure);
|
||||
setSetupPersona(recommended.persona);
|
||||
setSetupDuration(recommended.duration);
|
||||
}}>重新推荐</button>
|
||||
<button type="button" className="btn btn-primary btn-sm" disabled={loading || scriptFileBusy || videoDigestBusy || ((setupSource === "manual" || setupSource === "video") && !chatText.trim())} onClick={() => void runScriptWithSetup()}>确定</button>
|
||||
|
||||
Reference in New Issue
Block a user