save code
This commit is contained in:
+5
-1
@@ -37,6 +37,7 @@ NODE_MODEL = "11" # 模特
|
|||||||
NODE_SHIRT = "10" # 上衣
|
NODE_SHIRT = "10" # 上衣
|
||||||
# NODE_PANTS = "4" # 裤子
|
# NODE_PANTS = "4" # 裤子
|
||||||
NODE_OUTPUT = "33" # 输出
|
NODE_OUTPUT = "33" # 输出
|
||||||
|
NODE_PROMPT = "31" # 文本提示(PrimitiveStringMultiline)
|
||||||
|
|
||||||
app = FastAPI(title="ComfyUI 换装服务")
|
app = FastAPI(title="ComfyUI 换装服务")
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ def upload_to_oss(image_path, object_name=None):
|
|||||||
class TryOnRequest(BaseModel):
|
class TryOnRequest(BaseModel):
|
||||||
model_image: str # base64 模特图片
|
model_image: str # base64 模特图片
|
||||||
shirt_image: str # base64 上衣图片
|
shirt_image: str # base64 上衣图片
|
||||||
|
change_desc: str = "" # 换装/编辑描述,可空;非空时替换节点 31 的 inputs
|
||||||
|
|
||||||
|
|
||||||
class TryOnResponse(BaseModel):
|
class TryOnResponse(BaseModel):
|
||||||
@@ -155,7 +157,9 @@ async def try_on(req: TryOnRequest):
|
|||||||
# 加载工作流模板
|
# 加载工作流模板
|
||||||
workflow = json.loads(WORKFLOW_PATH.read_text(encoding="utf-8"))
|
workflow = json.loads(WORKFLOW_PATH.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
desc = (req.change_desc or "").strip()
|
||||||
|
if desc:
|
||||||
|
workflow[NODE_PROMPT]["inputs"] = {"value": desc}
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||||
# 解码两张图片
|
# 解码两张图片
|
||||||
|
|||||||
@@ -196,6 +196,49 @@
|
|||||||
background: #7c3aed22;
|
background: #7c3aed22;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prompt-panel {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 900px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
background: #1a1a24;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #2a2a3a;
|
||||||
|
}
|
||||||
|
.prompt-panel .prompt-title {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #a78bfa;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.radio-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.radio-row input { margin-top: 3px; accent-color: #7c3aed; flex-shrink: 0; }
|
||||||
|
.change-desc-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
background: #12121a;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 88px;
|
||||||
|
}
|
||||||
|
.change-desc-input:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.upload-grid { grid-template-columns: 1fr; }
|
.upload-grid { grid-template-columns: 1fr; }
|
||||||
h1 { font-size: 1.5rem; }
|
h1 { font-size: 1.5rem; }
|
||||||
@@ -226,6 +269,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="prompt-panel" id="prompt-panel">
|
||||||
|
<div class="prompt-title">提示词(change_desc)</div>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-default" value="default" checked />
|
||||||
|
<span>使用默认(传空,不覆盖工作流节点 31)</span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-custom" value="custom" />
|
||||||
|
<span>自定义提示词</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="change-desc" class="change-desc-input" placeholder="输入换装/编辑描述…" rows="4" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
||||||
<div class="status-bar" id="status-bar"></div>
|
<div class="status-bar" id="status-bar"></div>
|
||||||
|
|
||||||
@@ -261,6 +317,19 @@
|
|||||||
setupUpload('input-model', 'preview-model', 'card-model', 'model');
|
setupUpload('input-model', 'preview-model', 'card-model', 'model');
|
||||||
setupUpload('input-shirt', 'preview-shirt', 'card-shirt', 'shirt');
|
setupUpload('input-shirt', 'preview-shirt', 'card-shirt', 'shirt');
|
||||||
|
|
||||||
|
const promptDefault = document.getElementById('prompt-default');
|
||||||
|
const promptCustom = document.getElementById('prompt-custom');
|
||||||
|
const changeDescEl = document.getElementById('change-desc');
|
||||||
|
function syncPromptUi() {
|
||||||
|
changeDescEl.disabled = !promptCustom.checked;
|
||||||
|
}
|
||||||
|
promptDefault.addEventListener('change', syncPromptUi);
|
||||||
|
promptCustom.addEventListener('change', syncPromptUi);
|
||||||
|
|
||||||
|
function getChangeDesc() {
|
||||||
|
return promptCustom.checked ? changeDescEl.value.trim() : '';
|
||||||
|
}
|
||||||
|
|
||||||
function updateRunButton() {
|
function updateRunButton() {
|
||||||
const btn = document.getElementById('btn-run');
|
const btn = document.getElementById('btn-run');
|
||||||
btn.disabled = !(images.model && images.shirt);
|
btn.disabled = !(images.model && images.shirt);
|
||||||
@@ -298,6 +367,7 @@
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model_image: images.model,
|
model_image: images.model,
|
||||||
shirt_image: images.shirt,
|
shirt_image: images.shirt,
|
||||||
|
change_desc: getChangeDesc(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ NODE_MODEL = "11" # 模特
|
|||||||
NODE_SHIRT = "10" # 上衣
|
NODE_SHIRT = "10" # 上衣
|
||||||
NODE_PANTS = "4" # 裤子
|
NODE_PANTS = "4" # 裤子
|
||||||
NODE_OUTPUT = "33" # 输出
|
NODE_OUTPUT = "33" # 输出
|
||||||
|
NODE_PROMPT = "31" # 文本提示(PrimitiveStringMultiline)
|
||||||
|
|
||||||
app = FastAPI(title="ComfyUI 换装服务")
|
app = FastAPI(title="ComfyUI 换装服务")
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ class TryOnRequest(BaseModel):
|
|||||||
model_image: str # base64 模特图片
|
model_image: str # base64 模特图片
|
||||||
shirt_image: str # base64 上衣图片
|
shirt_image: str # base64 上衣图片
|
||||||
pants_image: str # base64 裤子图片
|
pants_image: str # base64 裤子图片
|
||||||
|
change_desc: str = "" # 换装/编辑描述,可空;非空时替换节点 31 的 inputs
|
||||||
|
|
||||||
|
|
||||||
class TryOnResponse(BaseModel):
|
class TryOnResponse(BaseModel):
|
||||||
@@ -146,6 +148,10 @@ async def try_on(req: TryOnRequest):
|
|||||||
# 加载工作流模板
|
# 加载工作流模板
|
||||||
workflow = json.loads(WORKFLOW_PATH.read_text(encoding="utf-8"))
|
workflow = json.loads(WORKFLOW_PATH.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
desc = (req.change_desc or "").strip()
|
||||||
|
if desc:
|
||||||
|
workflow[NODE_PROMPT]["inputs"] = {"value": desc}
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||||
# 解码三张图片
|
# 解码三张图片
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -196,6 +196,49 @@
|
|||||||
background: #7c3aed22;
|
background: #7c3aed22;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prompt-panel {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 900px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
background: #1a1a24;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #2a2a3a;
|
||||||
|
}
|
||||||
|
.prompt-panel .prompt-title {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #a78bfa;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.radio-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.radio-row input { margin-top: 3px; accent-color: #7c3aed; flex-shrink: 0; }
|
||||||
|
.change-desc-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
background: #12121a;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 88px;
|
||||||
|
}
|
||||||
|
.change-desc-input:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.upload-grid { grid-template-columns: 1fr; }
|
.upload-grid { grid-template-columns: 1fr; }
|
||||||
h1 { font-size: 1.5rem; }
|
h1 { font-size: 1.5rem; }
|
||||||
@@ -235,6 +278,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="prompt-panel" id="prompt-panel">
|
||||||
|
<div class="prompt-title">提示词(change_desc)</div>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-default" value="default" checked />
|
||||||
|
<span>使用默认(传空,不覆盖工作流节点 31)</span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-custom" value="custom" />
|
||||||
|
<span>自定义提示词</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="change-desc" class="change-desc-input" placeholder="输入换装/编辑描述…" rows="4" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
||||||
<div class="status-bar" id="status-bar"></div>
|
<div class="status-bar" id="status-bar"></div>
|
||||||
|
|
||||||
@@ -271,6 +327,19 @@
|
|||||||
setupUpload('input-shirt', 'preview-shirt', 'card-shirt', 'shirt');
|
setupUpload('input-shirt', 'preview-shirt', 'card-shirt', 'shirt');
|
||||||
setupUpload('input-pants', 'preview-pants', 'card-pants', 'pants');
|
setupUpload('input-pants', 'preview-pants', 'card-pants', 'pants');
|
||||||
|
|
||||||
|
const promptDefault = document.getElementById('prompt-default');
|
||||||
|
const promptCustom = document.getElementById('prompt-custom');
|
||||||
|
const changeDescEl = document.getElementById('change-desc');
|
||||||
|
function syncPromptUi() {
|
||||||
|
changeDescEl.disabled = !promptCustom.checked;
|
||||||
|
}
|
||||||
|
promptDefault.addEventListener('change', syncPromptUi);
|
||||||
|
promptCustom.addEventListener('change', syncPromptUi);
|
||||||
|
|
||||||
|
function getChangeDesc() {
|
||||||
|
return promptCustom.checked ? changeDescEl.value.trim() : '';
|
||||||
|
}
|
||||||
|
|
||||||
function updateRunButton() {
|
function updateRunButton() {
|
||||||
const btn = document.getElementById('btn-run');
|
const btn = document.getElementById('btn-run');
|
||||||
btn.disabled = !(images.model && images.shirt && images.pants);
|
btn.disabled = !(images.model && images.shirt && images.pants);
|
||||||
@@ -309,6 +378,7 @@
|
|||||||
model_image: images.model,
|
model_image: images.model,
|
||||||
shirt_image: images.shirt,
|
shirt_image: images.shirt,
|
||||||
pants_image: images.pants,
|
pants_image: images.pants,
|
||||||
|
change_desc: getChangeDesc(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -31,18 +31,26 @@ def change_cloth_base64():
|
|||||||
|
|
||||||
kuzi_img = data.get('kuzi_img')
|
kuzi_img = data.get('kuzi_img')
|
||||||
|
|
||||||
|
change_desc = data.get('change_desc')
|
||||||
|
if change_desc is None:
|
||||||
|
change_desc = ''
|
||||||
|
elif not isinstance(change_desc, str):
|
||||||
|
return jsonify({"ret": -1, "state": -1, "msg": "change_desc must be a string"}), 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if kuzi_img:
|
if kuzi_img:
|
||||||
payload = {
|
payload = {
|
||||||
'model_image': human_img,
|
'model_image': human_img,
|
||||||
'shirt_image': cloth_img,
|
'shirt_image': cloth_img,
|
||||||
'pants_image': kuzi_img,
|
'pants_image': kuzi_img,
|
||||||
|
'change_desc': change_desc,
|
||||||
}
|
}
|
||||||
response = requests.post('http://127.0.0.1:12223/try-on', json=payload, timeout=360)
|
response = requests.post('http://127.0.0.1:12223/try-on', json=payload, timeout=360)
|
||||||
else:
|
else:
|
||||||
payload = {
|
payload = {
|
||||||
'model_image': human_img,
|
'model_image': human_img,
|
||||||
'shirt_image': cloth_img,
|
'shirt_image': cloth_img,
|
||||||
|
'change_desc': change_desc,
|
||||||
}
|
}
|
||||||
response = requests.post('http://127.0.0.1:12222/try-on', json=payload, timeout=360)
|
response = requests.post('http://127.0.0.1:12222/try-on', json=payload, timeout=360)
|
||||||
|
|
||||||
|
|||||||
+12
-26
@@ -1,45 +1,31 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# 启动本机换装网关与 service2 / service3。
|
||||||
|
# ComfyUI 在其它机器运行;service2/service3 内已配置远端 COMFYUI_URL。
|
||||||
|
|
||||||
|
ROOT="/home/ubuntu/change_cloth_server"
|
||||||
LOG_DIR="/home/ubuntu/log"
|
LOG_DIR="/home/ubuntu/log"
|
||||||
mkdir -p "$LOG_DIR"
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始停止旧进程..."
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始停止旧进程..."
|
||||||
|
|
||||||
# 杀掉已有进程
|
# 按命令行中的脚本绝对路径结束旧实例(与下方 nohup 路径一致)
|
||||||
pkill -f "main.py" 2>/dev/null && echo " 已停止 ComfyUI" || echo " ComfyUI 未在运行"
|
pkill -f "${ROOT}/change2/service2.py" 2>/dev/null && echo " 已停止 service2" || echo " service2 未在运行"
|
||||||
pkill -f "change_cloth_server/change2/service2.py" 2>/dev/null && echo " 已停止 service2" || echo " service2 未在运行"
|
pkill -f "${ROOT}/change3/service3.py" 2>/dev/null && echo " 已停止 service3" || echo " service3 未在运行"
|
||||||
pkill -f "change_cloth_server/change3/service3.py" 2>/dev/null && echo " 已停止 service3" || echo " service3 未在运行"
|
pkill -f "${ROOT}/change_app.py" 2>/dev/null && echo " 已停止 change_app" || echo " change_app 未在运行"
|
||||||
pkill -f "change_cloth_server/change_app.py" 2>/dev/null && echo " 已停止 change_app" || echo " change_app 未在运行"
|
|
||||||
|
|
||||||
# 等待进程退出
|
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始启动服务..."
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始启动服务..."
|
||||||
|
|
||||||
# 启动 ComfyUI(使用项目 venv)
|
|
||||||
COMFYUI_PYTHON="/home/ubuntu/ComfyUI/.venv/bin/python"
|
|
||||||
if [ -x "$COMFYUI_PYTHON" ]; then
|
|
||||||
cd /home/ubuntu/ComfyUI
|
|
||||||
nohup "$COMFYUI_PYTHON" main.py >> "$LOG_DIR/comfyui.log" 2>&1 &
|
|
||||||
echo " ComfyUI 已启动 (PID: $!)"
|
|
||||||
else
|
|
||||||
cd /home/ubuntu/ComfyUI
|
|
||||||
nohup python3 main.py >> "$LOG_DIR/comfyui.log" 2>&1 &
|
|
||||||
echo " ComfyUI 已启动 (PID: $!)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 启动 service2 / service3 / change_app(使用 python3,依赖已 pip install --user)
|
|
||||||
export PATH="/home/ubuntu/.local/bin:$PATH"
|
export PATH="/home/ubuntu/.local/bin:$PATH"
|
||||||
cd /home/ubuntu/change_cloth_server/change2
|
|
||||||
nohup python3 service2.py >> "$LOG_DIR/service2.log" 2>&1 &
|
nohup python3 "${ROOT}/change2/service2.py" >> "$LOG_DIR/service2.log" 2>&1 &
|
||||||
echo " service2 已启动 (PID: $!)"
|
echo " service2 已启动 (PID: $!)"
|
||||||
|
|
||||||
cd /home/ubuntu/change_cloth_server/change3
|
nohup python3 "${ROOT}/change3/service3.py" >> "$LOG_DIR/service3.log" 2>&1 &
|
||||||
nohup python3 service3.py >> "$LOG_DIR/service3.log" 2>&1 &
|
|
||||||
echo " service3 已启动 (PID: $!)"
|
echo " service3 已启动 (PID: $!)"
|
||||||
|
|
||||||
cd /home/ubuntu/change_cloth_server
|
nohup python3 "${ROOT}/change_app.py" >> "$LOG_DIR/change_app.log" 2>&1 &
|
||||||
nohup python3 change_app.py >> "$LOG_DIR/change_app.log" 2>&1 &
|
|
||||||
echo " change_app 已启动 (PID: $!)"
|
echo " change_app 已启动 (PID: $!)"
|
||||||
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 所有服务启动完毕,日志目录: $LOG_DIR"
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动完毕(ComfyUI 请在外部机器保证可用)。日志目录: $LOG_DIR"
|
||||||
|
|||||||
@@ -198,6 +198,49 @@
|
|||||||
.raw-resp.visible { display: block; }
|
.raw-resp.visible { display: block; }
|
||||||
.raw-resp pre { white-space: pre-wrap; }
|
.raw-resp pre { white-space: pre-wrap; }
|
||||||
|
|
||||||
|
.prompt-panel {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 960px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
background: #1a1a24;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #2a2a3a;
|
||||||
|
}
|
||||||
|
.prompt-panel .prompt-title {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #a78bfa;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.radio-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.radio-row input { margin-top: 3px; accent-color: #7c3aed; flex-shrink: 0; }
|
||||||
|
.change-desc-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
background: #12121a;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 88px;
|
||||||
|
}
|
||||||
|
.change-desc-input:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.upload-grid { grid-template-columns: 1fr; }
|
.upload-grid { grid-template-columns: 1fr; }
|
||||||
h1 { font-size: 1.5rem; }
|
h1 { font-size: 1.5rem; }
|
||||||
@@ -241,6 +284,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="prompt-panel" id="prompt-panel">
|
||||||
|
<div class="prompt-title">提示词(change_desc)</div>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-default" value="default" checked />
|
||||||
|
<span>使用默认(请求中传空字符串,不覆盖工作流)</span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-row">
|
||||||
|
<input type="radio" name="prompt_mode" id="prompt-custom" value="custom" />
|
||||||
|
<span>自定义提示词</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="change-desc" class="change-desc-input" placeholder="输入换装/编辑描述…" rows="4" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
<button class="btn-run" id="btn-run" disabled>开始换装</button>
|
||||||
<div class="status-bar" id="status-bar"></div>
|
<div class="status-bar" id="status-bar"></div>
|
||||||
|
|
||||||
@@ -295,6 +351,19 @@
|
|||||||
setupUpload('input-cloth', 'preview-cloth', 'card-cloth', 'clear-cloth', 'cloth');
|
setupUpload('input-cloth', 'preview-cloth', 'card-cloth', 'clear-cloth', 'cloth');
|
||||||
setupUpload('input-kuzi', 'preview-kuzi', 'card-kuzi', 'clear-kuzi', 'kuzi');
|
setupUpload('input-kuzi', 'preview-kuzi', 'card-kuzi', 'clear-kuzi', 'kuzi');
|
||||||
|
|
||||||
|
const promptDefault = document.getElementById('prompt-default');
|
||||||
|
const promptCustom = document.getElementById('prompt-custom');
|
||||||
|
const changeDescEl = document.getElementById('change-desc');
|
||||||
|
function syncPromptUi() {
|
||||||
|
changeDescEl.disabled = !promptCustom.checked;
|
||||||
|
}
|
||||||
|
promptDefault.addEventListener('change', syncPromptUi);
|
||||||
|
promptCustom.addEventListener('change', syncPromptUi);
|
||||||
|
|
||||||
|
function getChangeDesc() {
|
||||||
|
return promptCustom.checked ? changeDescEl.value.trim() : '';
|
||||||
|
}
|
||||||
|
|
||||||
function updateRunButton() {
|
function updateRunButton() {
|
||||||
document.getElementById('btn-run').disabled = !(images.human && images.cloth);
|
document.getElementById('btn-run').disabled = !(images.human && images.cloth);
|
||||||
}
|
}
|
||||||
@@ -329,6 +398,7 @@
|
|||||||
const body = {
|
const body = {
|
||||||
human_img: images.human,
|
human_img: images.human,
|
||||||
cloth_img: images.cloth,
|
cloth_img: images.cloth,
|
||||||
|
change_desc: getChangeDesc(),
|
||||||
};
|
};
|
||||||
if (images.kuzi) body.kuzi_img = images.kuzi;
|
if (images.kuzi) body.kuzi_img = images.kuzi;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user