// EveryPublish 客户端渲染进程逻辑 const $ = (id) => document.getElementById(id); // ---- 页签切换 ---- document.querySelectorAll('.tab').forEach((tab) => { tab.addEventListener('click', () => { document.querySelectorAll('.tab').forEach((t) => t.classList.remove('active')); document.querySelectorAll('.page').forEach((p) => p.classList.remove('active')); tab.classList.add('active'); $('page-' + tab.dataset.tab).classList.add('active'); }); }); // ---- 状态页 ---- let currentServer = ''; let currentWeb = 'http://127.0.0.1:3003'; async function refreshStatus() { try { const s = await window.api.status(); if (s && s.server) currentServer = s.server; $('st-server').textContent = (s && s.server) || '-'; $('st-device').textContent = s && s.deviceId > 0 ? '#' + s.deviceId + '(' + (s.name || '') + ')' : '未配对'; $('st-session').textContent = (s && s.session) || '-'; const dot = $('st-dot'); if (!s) { $('st-online').textContent = '核心未就绪'; dot.className = 'dot gray'; } else if (s.online) { $('st-online').textContent = '在线'; dot.className = 'dot green'; } else { $('st-online').textContent = s.deviceId > 0 ? '离线(自动重连中)' : '未配对'; dot.className = 'dot orange'; } } catch (e) { $('st-online').textContent = '核心未就绪'; $('st-dot').className = 'dot gray'; } } setInterval(refreshStatus, 3000); refreshStatus(); $('btn-open-web').addEventListener('click', () => { const url = currentWeb || currentServer || 'http://127.0.0.1:3003'; window.api.openWeb(url); }); $('btn-open-data').addEventListener('click', () => window.api.openDataDir()); // ---- 配对页 ---- $('btn-pair').addEventListener('click', async () => { const code = $('pair-code').value.trim(); const name = $('pair-name').value.trim(); const res = $('pair-result'); if (!code) { res.textContent = '请输入配对码'; res.className = 'msg err'; return; } $('btn-pair').disabled = true; res.textContent = '配对中...'; res.className = 'msg'; try { const r = await window.api.pair(code, name); if (r && r.code === 0) { res.textContent = '配对成功,正在连接服务器(可到「状态」页查看)'; res.className = 'msg ok'; } else { res.textContent = (r && r.message) || '配对失败'; res.className = 'msg err'; } } catch (e) { res.textContent = '配对失败:' + e; res.className = 'msg err'; } $('btn-pair').disabled = false; }); // ---- 挑战页 ---- let selectedChallenge = null; let pollTimer = null; let knownChallengeIds = new Set(); const KIND_LABEL = { qr: '扫码', sms: '短信验证码', confirm: 'APP 确认', captcha: '图形验证码', pending: '等待设备' }; async function refreshChallenges() { try { const r = await window.api.challenges(); const list = (r && r.list) || []; const fresh = list.filter((ch) => ch.challengeId && !knownChallengeIds.has(ch.challengeId)); if (fresh.length && knownChallengeIds.size > 0 && window.api.notify) { window.api.notify('EveryPublish 需要处理挑战', fresh.map((ch) => ch.platform || '平台').join('、') + ' 有新的扫码或验证码任务'); } knownChallengeIds = new Set(list.map((ch) => ch.challengeId).filter(Boolean)); const badge = $('ch-badge'); if (list.length > 0) { badge.textContent = list.length; badge.classList.remove('hidden'); } else badge.classList.add('hidden'); const box = $('ch-list'); box.replaceChildren(); list.forEach((ch) => { const div = document.createElement('div'); div.className = 'item' + (selectedChallenge && selectedChallenge.challengeId === ch.challengeId ? ' selected' : ''); const label = document.createElement('span'); const platform = document.createElement('b'); platform.textContent = ch.platform || '?'; label.append(platform, document.createTextNode(' · ' + (KIND_LABEL[ch.kind] || ch.kind))); const prompt = document.createElement('span'); prompt.className = 'p'; prompt.textContent = ch.prompt || ''; div.append(label, prompt); div.addEventListener('click', () => selectChallenge(ch)); box.appendChild(div); }); if (!list.length) { const empty = document.createElement('p'); empty.className = 'hint'; empty.textContent = '暂无待处理挑战'; box.appendChild(empty); } } catch (e) { /* 忽略 */ } } function selectChallenge(ch) { selectedChallenge = ch; refreshChallenges(); const detail = $('ch-detail'); detail.classList.remove('hidden'); const qr = ch.qrUrl || ch.qrToken || ''; const img = $('ch-qr'); if (qr && (qr.startsWith('http') || qr.startsWith('file://'))) { img.src = qr; img.classList.remove('hidden'); } else { img.classList.add('hidden'); } $('ch-value').value = ''; $('ch-result').textContent = ''; } $('btn-solve').addEventListener('click', async () => { if (!selectedChallenge) return; const value = $('ch-value').value.trim() || 'confirmed'; const res = $('ch-result'); try { const r = await window.api.solve(selectedChallenge.challengeId, value); if (r && r.code === 0) { res.textContent = '已提交,等待服务器确认'; res.className = 'msg ok'; selectedChallenge = null; $('ch-detail').classList.add('hidden'); refreshChallenges(); } else { res.textContent = (r && r.message) || '提交失败'; res.className = 'msg err'; } } catch (e) { res.textContent = '提交失败:' + e; res.className = 'msg err'; } }); function startPolling() { if (pollTimer) return; pollTimer = setInterval(refreshChallenges, 2000); refreshChallenges(); } startPolling(); // ---- 设置页 ---- async function loadSettings() { try { const cfg = await window.api.getConfig(); $('set-server').value = (cfg && cfg.server) || 'http://127.0.0.1:8090'; $('set-web').value = (cfg && cfg.webUrl) || 'http://127.0.0.1:3003'; currentWeb = $('set-web').value; $('set-fake').checked = !!(cfg && cfg.fakeAll); $('set-autostart').checked = await window.api.getAutoStart(); } catch (e) { /* 忽略 */ } } loadSettings(); $('btn-save').addEventListener('click', async () => { const server = $('set-server').value.trim(); const webUrl = $('set-web').value.trim(); const res = $('set-result'); if (!server) { res.textContent = '请填写服务器地址(内网部署填 http://服务器IP:8090)'; res.className = 'msg err'; return; } if (!webUrl) { res.textContent = '请填写网站地址'; res.className = 'msg err'; return; } const cfg = { server: server, webUrl: webUrl, fakeAll: $('set-fake').checked }; await window.api.saveConfig(cfg); await window.api.setAutoStart($('set-autostart').checked); currentServer = server; currentWeb = webUrl; res.textContent = '已保存,核心进程已重启'; res.className = 'msg ok'; }); $('btn-quit').addEventListener('click', () => window.api.quit()); // 核心就绪提示 if (window.api.onCoreReady) { window.api.onCoreReady(() => { $('st-online').textContent = '核心已就绪'; refreshStatus(); }); }