(paramKey, currentVal)
| 499 | |
| 500 | // 渲染 protocol_option 内嵌表单(分组布局,与协议预设界面一致) |
| 501 | function _renderProtoOptionForm(paramKey, currentVal) { |
| 502 | const cur = (currentVal && typeof currentVal === 'object') ? currentVal : {}; |
| 503 | const sel = (k, v) => cur[k] !== undefined && String(cur[k]) === v ? 'selected' : ''; |
| 504 | const selEmpty = k => cur[k] === undefined || cur[k] === '' ? 'selected' : ''; |
| 505 | const inCls = 'w-full bg-white/5 border border-white/10 rounded px-2 py-1.5 text-white text-xs focus:outline-none focus:border-primary/50'; |
| 506 | const pk = escHtml(paramKey); |
| 507 | |
| 508 | const makeSelect = (f) => ` |
| 509 | <select id="${f.id}" class="${inCls}" style="color:white;" onchange="_syncProtoForm('${pk}')"> |
| 510 | <option value="" ${selEmpty(f.key)}>默认</option> |
| 511 | ${f.opts.map(([v, l]) => `<option value="${v}" ${sel(f.key, v)}>${l}</option>`).join('')} |
| 512 | </select>`; |
| 513 | const makeInput = (f) => ` |
| 514 | <input type="${f.type}" id="${f.id}" value="${escHtml(String(cur[f.key] ?? ''))}" placeholder="默认" |
| 515 | class="${inCls}" oninput="_syncProtoForm('${pk}')">`; |
| 516 | |
| 517 | const groupsHtml = _PROTO_GROUPS.map(g => { |
| 518 | const colCls = `grid grid-cols-${g.cols} gap-2`; |
| 519 | const fieldsHtml = g.fields.map(f => ` |
| 520 | <div> |
| 521 | <label class="block text-white/60 text-[11px] mb-0.5">${f.label}</label> |
| 522 | ${f.type === 'select' ? makeSelect(f) : makeInput(f)} |
| 523 | </div>`).join(''); |
| 524 | return ` |
| 525 | <div class="bg-white/5 rounded-lg p-3"> |
| 526 | <div class="text-white/70 text-xs font-semibold mb-2 border-b border-white/10 pb-1">${g.title}</div> |
| 527 | <div class="${colCls}">${fieldsHtml}</div> |
| 528 | </div>`; |
| 529 | }).join(''); |
| 530 | |
| 531 | return ` |
| 532 | <div class="mt-2 border border-white/10 rounded-lg overflow-hidden"> |
| 533 | <!-- 工具栏 --> |
| 534 | <div class="flex gap-2 px-3 py-2 bg-white/5 border-b border-white/10"> |
| 535 | <button type="button" onclick="_poLoadDefault('${pk}')" |
| 536 | class="text-xs px-2 py-1 rounded bg-white/10 hover:bg-white/20 text-white/80 transition-colors"> |
| 537 | <i class="fa fa-magic mr-1"></i>加载默认 |
| 538 | </button> |
| 539 | <button type="button" onclick="_poLoadPreset('${pk}')" |
| 540 | class="text-xs px-2 py-1 rounded bg-primary/30 hover:bg-primary/50 text-white transition-colors"> |
| 541 | <i class="fa fa-list mr-1"></i>从预设加载 |
| 542 | </button> |
| 543 | <button type="button" onclick="_poClear('${pk}')" |
| 544 | class="text-xs px-2 py-1 rounded bg-red-500/20 hover:bg-red-500/30 text-red-400 transition-colors"> |
| 545 | <i class="fa fa-eraser mr-1"></i>清空 |
| 546 | </button> |
| 547 | </div> |
| 548 | <!-- 分组内容 --> |
| 549 | <div class="space-y-2 p-3">${groupsHtml}</div> |
| 550 | </div>`; |
| 551 | } |
| 552 | |
| 553 | // 表单任意字段变化后同步回 _editParams |
| 554 | function _syncProtoForm(paramKey) { |
no test coverage detected