模特上身图提示词重构 + 图片创作页 UI 调整
后端(模特上身图提示词): - build_model_tryon_prompt_refs 重写:穿戴/非穿戴分流(穿戴=真实穿身替换原衣, 非穿戴=手持/佩戴/使用不动原衣)、每张按 index 变化动作/场景/镜头、负面词尾接、 多图参考序号自适应(参考图1~N=商品,参考图N+1=模特) - 新增 _product_reference_urls:商品参考图真实上传图优先、排除 AI 生成图、可多张(≤3), 无真实图回落 cover - worker run_standalone_image_task 模特分支改用多图取图 + 传 index/n_product 前端(图片创作/工作室): - 生成数量改 1/2/4;图片比例新增「手动输入」(宽:高 两输入框) - 临时隐藏「商品库」按钮 - 模特卡:去掉 // 真人模特,标题改图片底部白字遮罩层 + 单行省略 - 工作室壳负边距对齐 .content padding,修复上下被遮挡/裁切 其他:并入此前未提交的商品页改动、脚本 Agent/格式实测文档与 demo
This commit is contained in:
@@ -432,7 +432,7 @@ const MODE_META: Record<
|
||||
const RATIO_OPTIONS = ["1:1", "3:4", "4:5", "9:16", "16:9"];
|
||||
const COUNT_OPTIONS = ["1", "2", "4"];
|
||||
const MODEL_RATIO_OPTIONS = ["1:1", "3:4", "9:16"];
|
||||
const MODEL_COUNT_OPTIONS = ["4", "8", "12"];
|
||||
const MODEL_COUNT_OPTIONS = ["1", "2", "4"];
|
||||
const COVER_COUNT_OPTIONS = ["4", "8", "12"];
|
||||
|
||||
/* 图片创作 · 空态提示词建议 chip(基线 image-optimize EXAMPLES) */
|
||||
@@ -528,6 +528,10 @@ export function ImageWorkbenchPage({
|
||||
const product = products.find((item) => item.id === productId) || products[0];
|
||||
const [prompt, setPrompt] = useState(meta.promptTemplate(products[0]?.title || "商品"));
|
||||
const [ratio, setRatio] = useState(meta.ratio);
|
||||
// 手动输入比例:开启后用 W:H 两个输入框自定义,关闭则用预设 pill
|
||||
const [ratioManual, setRatioManual] = useState(false);
|
||||
const [ratioW, setRatioW] = useState("");
|
||||
const [ratioH, setRatioH] = useState("");
|
||||
const [style, setStyle] = useState("auto");
|
||||
const [count, setCount] = useState(mode === "image" ? "4" : "4");
|
||||
// 模特单选(长度恒 0/1);平台改回多选(P0③:可选多个平台,各出一组结果)
|
||||
@@ -613,6 +617,9 @@ export function ImageWorkbenchPage({
|
||||
if (product) setPrompt(meta.promptTemplate(product.title));
|
||||
// mode 或商品切换都重置 prompt 与默认比例
|
||||
setRatio(meta.ratio);
|
||||
setRatioManual(false);
|
||||
setRatioW("");
|
||||
setRatioH("");
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [productId, mode]);
|
||||
|
||||
@@ -1323,11 +1330,11 @@ export function ImageWorkbenchPage({
|
||||
{product?.title || "未选择 · 请在左侧商品空间选一个"}
|
||||
</span>
|
||||
</div>
|
||||
{/* P0④:商品库全屏选择器入口(多选商品,各起一批) */}
|
||||
<button className="iw-pl-btn" type="button" onClick={() => { setPlDraft(productId ? [productId] : []); setPlQuery(""); setPlCat(""); setPlOpen(true); }} title="从商品库选择">
|
||||
{/* P0④:商品库全屏选择器入口(多选商品,各起一批) — 临时屏蔽 */}
|
||||
{/* <button className="iw-pl-btn" type="button" onClick={() => { setPlDraft(productId ? [productId] : []); setPlQuery(""); setPlCat(""); setPlOpen(true); }} title="从商品库选择">
|
||||
<LayoutGrid size={13} />
|
||||
商品库
|
||||
</button>
|
||||
</button> */}
|
||||
<span className="spacer" />
|
||||
<div className="tb-search-wrap">
|
||||
{searchOpen && (
|
||||
@@ -1402,9 +1409,8 @@ export function ImageWorkbenchPage({
|
||||
<span className="ph-frame">{item.name.slice(0, 4)}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="m-name">{item.name}</div>
|
||||
</div>
|
||||
<div className="m-name">{item.name}</div>
|
||||
<div className="m-tag">// 真人模特</div>
|
||||
</button>
|
||||
);
|
||||
})
|
||||
@@ -1423,9 +1429,8 @@ export function ImageWorkbenchPage({
|
||||
</span>
|
||||
<div className="placeholder m-thumb">
|
||||
<span className="ph-frame">{item.name}</span>
|
||||
<div className="m-name">{item.name}</div>
|
||||
</div>
|
||||
<div className="m-name">{item.name}</div>
|
||||
<div className="m-tag">{item.tag}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -1481,13 +1486,52 @@ export function ImageWorkbenchPage({
|
||||
<button
|
||||
type="button"
|
||||
key={value}
|
||||
className={`opt ${ratio === value ? "active" : ""}`}
|
||||
onClick={() => setRatio(value)}
|
||||
className={`opt ${!ratioManual && ratio === value ? "active" : ""}`}
|
||||
onClick={() => { setRatioManual(false); setRatio(value); }}
|
||||
>
|
||||
{value}
|
||||
</button>
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
className={`opt ${ratioManual ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setRatioManual(true);
|
||||
if (ratioW && ratioH) setRatio(`${ratioW}:${ratioH}`);
|
||||
}}
|
||||
>
|
||||
手动输入
|
||||
</button>
|
||||
</div>
|
||||
{ratioManual && (
|
||||
<div className="iw-ratio-manual">
|
||||
<input
|
||||
className="input"
|
||||
type="number"
|
||||
min={1}
|
||||
placeholder="宽"
|
||||
value={ratioW}
|
||||
onChange={(event) => {
|
||||
const w = event.target.value;
|
||||
setRatioW(w);
|
||||
if (w && ratioH) setRatio(`${w}:${ratioH}`);
|
||||
}}
|
||||
/>
|
||||
<span className="sep">:</span>
|
||||
<input
|
||||
className="input"
|
||||
type="number"
|
||||
min={1}
|
||||
placeholder="高"
|
||||
value={ratioH}
|
||||
onChange={(event) => {
|
||||
const h = event.target.value;
|
||||
setRatioH(h);
|
||||
if (ratioW && h) setRatio(`${ratioW}:${h}`);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="iw-sub">
|
||||
|
||||
Reference in New Issue
Block a user