diff --git a/core/backend/README.md b/core/backend/README.md index 1f3abc7..c20211e 100644 --- a/core/backend/README.md +++ b/core/backend/README.md @@ -19,7 +19,7 @@ Start workers in separate terminals: ```bash cd /Users/maidong/Desktop/zyc/qiyuan_gitea/AirShelf/core/backend source .venv/bin/activate -celery -A airshelf worker -l info +celery -A airshelf worker -l info -P threads -c 4 # 线程池 4 并发(出图/视频可并行;勿用 -P solo 串行) ``` `ffmpeg` must be available on `PATH` for Stage5 export jobs. diff --git a/core/frontend/src/design-restraint.css b/core/frontend/src/design-restraint.css index a477822..875fc5d 100644 --- a/core/frontend/src/design-restraint.css +++ b/core/frontend/src/design-restraint.css @@ -869,6 +869,7 @@ main { position: relative; background: var(--background-base); min-width: 0; } } .chip-wrap.open .chip-menu { display: block; } .chip-menu.align-right { left: auto; right: 0; } +.chip-menu.align-up { top: auto; bottom: calc(100% + 4px); } .chip-menu .mi { height: 32px; padding: 0 10px; font-size: 13px; color: var(--accent-black); diff --git a/core/frontend/src/routes/pipeline.tsx b/core/frontend/src/routes/pipeline.tsx index 9cd9883..5b34f3c 100644 --- a/core/frontend/src/routes/pipeline.tsx +++ b/core/frontend/src/routes/pipeline.tsx @@ -842,6 +842,16 @@ export function PipelinePage(props: { // 脚本模型下拉:用户可选 豆包/GPT-5.5/Gemini(空 = 用后端默认文本模型) const [scriptModelId, setScriptModelId] = useState(""); const activeScriptModelId = scriptModelId || textModels?.[0]?.id || ""; + // 模型选择小按钮(输入框下方)· 自建 restraint 下拉(幽灵触发 + popover 菜单),不再用原生 select + inline + const [modelMenuOpen, setModelMenuOpen] = useState(false); + const activeModel = textModels?.find((m) => m.id === activeScriptModelId); + const activeModelName = activeModel?.display_name || activeModel?.name || "默认模型"; + useEffect(() => { + if (!modelMenuOpen) return; + const close = (e: MouseEvent) => { if (!(e.target as HTMLElement).closest(".chat-model-pick")) setModelMenuOpen(false); }; + document.addEventListener("click", close); + return () => document.removeEventListener("click", close); + }, [modelMenuOpen]); // 删除分镜的两步确认(行内变红,3 秒不二次点击自动复位;不用原生 confirm) const [armedDelete, setArmedDelete] = useState(null); // 行35 · 单条分镜重跑 / 删除的即时反馈:正在处理的 shot id(按钮转「处理中」并禁用) @@ -2267,17 +2277,24 @@ export function PipelinePage(props: { - {/* 模型选择小按钮(放输入框下方,对齐 ChatGPT/Lovart) */} + {/* 模型选择小按钮(输入框下方,对齐 ChatGPT/Lovart)· 复用 restraint chip 下拉,向上展开 */} {textModels && textModels.length > 0 ? ( - +
+ +
+ {textModels.map((m) => ( +
{ setScriptModelId(m.id); setModelMenuOpen(false); }} + onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setScriptModelId(m.id); setModelMenuOpen(false); } }}> + {m.display_name || m.name} + +
+ ))} +
+
) : null}