(apiPath, container, checkbox, selectGroup)
| 195 | |
| 196 | // 通用:构建自定义多选下拉组件并处理联动 |
| 197 | async function loadServiceSelect(apiPath, container, checkbox, selectGroup) { |
| 198 | if (!checkbox || !container) return; |
| 199 | let services = []; |
| 200 | try { |
| 201 | services = await api.get(apiPath); |
| 202 | } catch (e) {} |
| 203 | |
| 204 | if (!services || services.length === 0) { |
| 205 | checkbox.disabled = true; |
| 206 | checkbox.title = '请先在设置中添加对应服务'; |
| 207 | const label = checkbox.closest('label'); |
| 208 | if (label) label.style.opacity = '0.5'; |
| 209 | container.innerHTML = '<div class="msd-empty">暂无可用服务</div>'; |
| 210 | } else { |
| 211 | const items = services.map(s => |
| 212 | `<label class="msd-item"> |
| 213 | <input type="checkbox" value="${s.id}" checked> |
| 214 | <span>${escapeHtml(s.name)}</span> |
| 215 | </label>` |
| 216 | ).join(''); |
| 217 | container.innerHTML = ` |
| 218 | <div class="msd-dropdown" id="${container.id}-dd"> |
| 219 | <div class="msd-trigger" onclick="toggleMsd('${container.id}-dd')"> |
| 220 | <span class="msd-label">全部 (${services.length})</span> |
| 221 | <span class="msd-arrow">▼</span> |
| 222 | </div> |
| 223 | <div class="msd-list">${items}</div> |
| 224 | </div>`; |
| 225 | // 监听 checkbox 变化,更新触发器文字 |
| 226 | container.querySelectorAll('.msd-item input').forEach(cb => { |
| 227 | cb.addEventListener('change', () => updateMsdLabel(container.id + '-dd')); |
| 228 | }); |
| 229 | // 点击外部关闭 |
| 230 | document.addEventListener('click', (e) => { |
| 231 | const dd = document.getElementById(container.id + '-dd'); |
| 232 | if (dd && !dd.contains(e.target)) dd.classList.remove('open'); |
| 233 | }, true); |
| 234 | } |
| 235 | |
| 236 | // 联动显示/隐藏服务选择区 |
| 237 | checkbox.addEventListener('change', () => { |
| 238 | if (selectGroup) selectGroup.style.display = checkbox.checked ? 'block' : 'none'; |
| 239 | }); |
| 240 | } |
| 241 | |
| 242 | function toggleMsd(ddId) { |
| 243 | const dd = document.getElementById(ddId); |
no test coverage detected