()
| 1774 | // 弹出 CPA 服务选择框,返回 Promise<{cpa_service_id: number|null}|null> |
| 1775 | // null 表示用户取消,{cpa_service_id: null} 表示使用全局配置 |
| 1776 | function selectCpaService() { |
| 1777 | return new Promise(async (resolve) => { |
| 1778 | const modal = document.getElementById('cpa-service-modal'); |
| 1779 | const listEl = document.getElementById('cpa-service-list'); |
| 1780 | const closeBtn = document.getElementById('close-cpa-modal'); |
| 1781 | const cancelBtn = document.getElementById('cancel-cpa-modal-btn'); |
| 1782 | const globalBtn = document.getElementById('cpa-use-global-btn'); |
| 1783 | |
| 1784 | // 加载服务列表 |
| 1785 | listEl.innerHTML = '<div style="text-align:center;color:var(--text-muted)">加载中...</div>'; |
| 1786 | modal.classList.add('active'); |
| 1787 | |
| 1788 | let services = []; |
| 1789 | try { |
| 1790 | services = await api.get('/cpa-services?enabled=true'); |
| 1791 | } catch (e) { |
| 1792 | services = []; |
| 1793 | } |
| 1794 | |
| 1795 | if (services.length === 0) { |
| 1796 | listEl.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:12px;">暂无已启用的 CPA 服务,将使用全局配置</div>'; |
| 1797 | } else { |
| 1798 | listEl.innerHTML = services.map(s => ` |
| 1799 | <div class="cpa-service-item" data-id="${s.id}" style=" |
| 1800 | padding: 10px 14px; |
| 1801 | border: 1px solid var(--border); |
| 1802 | border-radius: 8px; |
| 1803 | cursor: pointer; |
| 1804 | transition: background 0.15s; |
| 1805 | display: flex; |
| 1806 | justify-content: space-between; |
| 1807 | align-items: center; |
| 1808 | "> |
| 1809 | <div> |
| 1810 | <div style="font-weight:500;">${escapeHtml(s.name)}</div> |
| 1811 | <div style="font-size:0.8rem;color:var(--text-muted);">${escapeHtml(s.api_url)}</div> |
| 1812 | </div> |
| 1813 | <span class="badge" style="background:var(--success-color);color:#fff;font-size:0.7rem;padding:2px 8px;border-radius:10px;">选择</span> |
| 1814 | </div> |
| 1815 | `).join(''); |
| 1816 | |
| 1817 | listEl.querySelectorAll('.cpa-service-item').forEach(item => { |
| 1818 | item.addEventListener('mouseenter', () => item.style.background = 'var(--surface-hover)'); |
| 1819 | item.addEventListener('mouseleave', () => item.style.background = ''); |
| 1820 | item.addEventListener('click', () => { |
| 1821 | cleanup(); |
| 1822 | resolve({ cpa_service_id: parseInt(item.dataset.id) }); |
| 1823 | }); |
| 1824 | }); |
| 1825 | } |
| 1826 | |
| 1827 | function cleanup() { |
| 1828 | modal.classList.remove('active'); |
| 1829 | closeBtn.removeEventListener('click', onCancel); |
| 1830 | cancelBtn.removeEventListener('click', onCancel); |
| 1831 | globalBtn.removeEventListener('click', onGlobal); |
| 1832 | } |
| 1833 | function onCancel() { cleanup(); resolve(null); } |
no test coverage detected