diff --git a/static/test_interface5.html b/static/test_interface5.html
index 7d8fd0f..40e340a 100644
--- a/static/test_interface5.html
+++ b/static/test_interface5.html
@@ -21,7 +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; }
- .form-group input[type=text] { padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 14px; width: 150px; }
+ .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; }
@@ -50,14 +55,6 @@
.result-card .info { padding: 10px 12px; font-size: 12px; display: flex; justify-content: space-between; align-items: center; }
.result-card .info .badge { background: #2563eb; color: #fff; padding: 1px 8px; border-radius: 10px; font-size: 11px; }
- /* 预览叠加 */
- .preview-stack { position: relative; display: inline-block; line-height: 0; background: #222; border-radius: 8px; overflow: hidden; }
- .preview-stack img { display: block; max-width: 100%; max-height: 450px; }
- .preview-stack .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
-
- .preview-controls { display: flex; gap: 14px; align-items: center; font-size: 12px; color: #9ca3af; }
- .preview-controls label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
-
/* 三档 + 生发图 横向排列 */
.level-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.level-cell { background: #222; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; }
@@ -89,16 +86,22 @@
-
+
-
- JPG/PNG 正面照 | 发型序号 Female: 1椭圆/2花瓣/3心形/4直线/5波浪 | Male: 1椭圆/2倒弧/3M形/4直线 | 每个发型返回 middle/high/low 三档 + 生发图
+ JPG/PNG 正面照 | Female: 椭圆/花瓣/心形/直线/波浪 | Male: 椭圆/倒弧/M形/直线 | 每个发型返回 middle/high/low 三档 + 生发图
@@ -138,17 +141,52 @@ let _images = [], _origUrl = '', _center = null;
function $(id) { return document.getElementById(id); }
function setStatus(t, type) { const b=$('statusBar'); b.textContent=t; b.className='status '+type; }
+// 发型列表(同接口2)
+const HAIR_STYLES = {
+ female: [
+ { value:'1', label:'1. ellipse 椭圆' },
+ { value:'2', label:'2. flower 花瓣' },
+ { value:'3', label:'3. heart 心形' },
+ { value:'4', label:'4. straight 直线' },
+ { value:'5', label:'5. wave 波浪' },
+ ],
+ male: [
+ { value:'1', label:'1. ellipse 椭圆' },
+ { value:'2', label:'2. inverse_arc 倒弧' },
+ { value:'3', label:'3. m M形' },
+ { value:'4', label:'4. 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; });
+}
+
async function submitTest() {
const f = $('imageFile').files[0];
if (!f) { setStatus('请选择图片', 'error'); return; }
- const _hs = $('hairStyle').value.trim();
- if (!_hs) { setStatus('请填写发型序号(必填,如 1,2,3)', 'error'); return; }
+ const checked = [...document.querySelectorAll('#hairStyleGroup input:checked')].map(cb => cb.value);
+ if (!checked.length) { setStatus('请至少选择一个发型', 'error'); return; }
_origUrl = URL.createObjectURL(f);
$('submitBtn').disabled = true; $('submitBtn').textContent = '⏳ ...';
setStatus('请求中...', 'info'); $('resultsArea').classList.add('hidden');
- const fd = new FormData(); fd.append('image_file', f); fd.append('gender', $('gender').value); fd.append('hair_style', _hs);
+ const fd = new FormData(); fd.append('image_file', f); fd.append('gender', $('gender').value); fd.append('hair_style', checked.join(','));
const _reqStart = performance.now();
try {
const r = await fetch(API_BASE + '/api/v1/hairline/generate', { method:'POST', body:fd });
@@ -214,6 +252,7 @@ function copyJson() {
}
document.addEventListener('DOMContentLoaded', () => {
+ onGenderChange(); // 初始填充发型列表
const dz = $('imageFile');
dz.addEventListener('dragover', e => { e.preventDefault(); dz.style.borderColor='#2563eb'; });
dz.addEventListener('dragleave', () => dz.style.borderColor='#ddd');