193 lines
7.0 KiB
JavaScript
193 lines
7.0 KiB
JavaScript
// 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();
|
||
});
|
||
}
|