feat(接口2/7): hair_style改为多选复选框,新增接口7测试页,网关注册v2路由

- 接口2/7测试页:发型从单选下拉框改为多选复选框+全选/全不选,提交时逗号分隔
- 新建static/test_interface7.html(基于接口2测试页,紫色主题,调用/api/v1/hair/grow-v2)
- gateway/app.py:注册/api/v1/hair/grow-v2代理路由 + 首页索引
- integration.html:新增接口7完整文档卡片(入参/出参/测试页链接)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ubuntu
2026-06-22 23:43:39 +08:00
co-authored by Claude
parent 9678b54267
commit 76bae98073
4 changed files with 362 additions and 4 deletions
+57 -3
View File
@@ -21,6 +21,12 @@
.form-group { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.form-group label { font-size: 13px; font-weight: 600; color: #374151; }
.form-group select { padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 14px; }
.hair-checkboxes { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center; }
.hair-checkboxes label { font-size: 13px; font-weight: 500; color: #374151; cursor: pointer; display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.hair-checkboxes label input[type=checkbox] { cursor: pointer; }
.checkbox-actions { display: flex; gap: 6px; margin-left: 4px; }
.checkbox-actions button { font-size: 11px; padding: 2px 8px; border-radius: 4px; border: 1px solid #d1d5db; background: #f9fafb; cursor: pointer; }
.checkbox-actions button:hover { background: #e5e7eb; }
.btn { padding: 10px 28px; border: none; border-radius: 8px; font-size: 15px; cursor: pointer; font-weight: 600; transition: .2s; }
.btn-primary { background: #2563eb; color: #fff; }
.btn-primary:hover { background: #1d4ed8; }
@@ -63,7 +69,7 @@
<body>
<div class="container">
<h1>💇 接口2 — C端生发 测试</h1>
<p class="subtitle">POST /api/v1/hair/grow &nbsp;|&nbsp; 正面照 + 性别 → 每个方案展示:原图 / 发际线叠加 / 生发效果</p>
<p class="subtitle">POST /api/v1/hair/grow &nbsp;|&nbsp; 正面照 + 性别 + 发型多选 → 所选发型的预览图与生发图</p>
<div class="card">
<div class="card-body">
@@ -71,7 +77,17 @@
<div class="file-input"><input type="file" id="imageFile" accept="image/jpeg,image/png,.jpg,.jpeg,.png"></div>
<div class="form-group">
<label>性别</label>
<select id="gender"><option value="female" selected>👩 Female</option><option value="male">👨 Male</option></select>
<select id="gender" onchange="onGenderChange()"><option value="female" selected>👩 Female</option><option value="male">👨 Male</option></select>
</div>
<div class="form-group" style="align-items:flex-start">
<label style="padding-top:3px">发型</label>
<div>
<div class="hair-checkboxes" id="hairStyleGroup"></div>
<div class="checkbox-actions" style="margin-top:4px">
<button type="button" onclick="selectAllHair(true)">全选</button>
<button type="button" onclick="selectAllHair(false)">全不选</button>
</div>
</div>
</div>
<div class="form-group">
<label>inpaint 遮罩</label>
@@ -95,7 +111,7 @@
<div class="results-layout hidden" id="resultsArea">
<div class="col-main">
<div class="card">
<div class="card-header"><span>🗂️ 全部方案 — 一覧</span></div>
<div class="card-header"><span>🗂️ 生发结果</span></div>
<div class="card-body" id="schemesContainer"></div>
</div>
</div>
@@ -128,7 +144,10 @@ async function submitTest() {
$('submitBtn').disabled = true; $('submitBtn').textContent = '⏳ 请求中...';
setStatus('⏳ 请求中(生发图生成较慢,请耐心)...', 'info'); $('resultsArea').classList.add('hidden');
const checked = [...document.querySelectorAll('#hairStyleGroup input:checked')].map(cb => cb.value);
if (checked.length === 0) { setStatus('请至少勾选一个发型', 'error'); $('submitBtn').disabled = false; $('submitBtn').textContent = '🚀 提交'; return; }
const fd = new FormData(); fd.append('image_file', f); fd.append('gender', $('gender').value);
fd.append('hair_style', checked.join(','));
fd.append('use_mask', $('useMask').value);
fd.append('prompt', $('promptInput').value);
try {
@@ -196,7 +215,42 @@ function copyJson() {
});
}
const HAIR_STYLES = {
female: [
{ value:'1', label:'ellipse 椭圆形' },
{ value:'2', label:'flower 花瓣形' },
{ value:'3', label:'heart 心形' },
{ value:'4', label:'straight 直线形' },
{ value:'5', label:'wave 波浪形' },
],
male: [
{ value:'1', label:'ellipse 椭圆形' },
{ value:'2', label:'inverse_arc 倒弧形' },
{ value:'3', label:'m M形' },
{ value:'4', label:'straight 直线形' },
]
};
function onGenderChange() {
const g = $('gender').value;
const div = $('hairStyleGroup');
div.innerHTML = '';
HAIR_STYLES[g].forEach(s => {
const cb = document.createElement('input');
cb.type = 'checkbox'; cb.value = s.value; cb.id = 'hs_' + s.value;
const lb = document.createElement('label');
lb.htmlFor = cb.id; lb.appendChild(cb);
lb.appendChild(document.createTextNode(' ' + s.label));
div.appendChild(lb);
});
}
function selectAllHair(select) {
document.querySelectorAll('#hairStyleGroup input[type=checkbox]').forEach(cb => { cb.checked = select; });
}
document.addEventListener('DOMContentLoaded', () => {
onGenderChange(); // 初始填充发型列表
const dz = $('imageFile');
dz.addEventListener('dragover', e => { e.preventDefault(); dz.style.borderColor='#2563eb'; });
dz.addEventListener('dragleave', () => dz.style.borderColor='#ddd');