Files
sehuatang/popup.js
2026-03-18 00:28:14 +08:00

278 lines
12 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function sendMessageToBackground(message) {
return new Promise(function(resolve, reject) {
chrome.runtime.sendMessage(message, function(response) {
if (chrome.runtime.lastError) {
reject(new Error(chrome.runtime.lastError.message));
return;
}
resolve(response || null);
});
});
}
function setMessage(text, isError) {
var message = document.getElementById('message');
if (!message) return;
message.textContent = text || '';
message.style.color = isError ? '#ff8585' : '#8892a4';
}
var lastGoodCloudStats = null;
var lastGoodSyncStatus = null;
var syncProgressTimer = null;
var lastServerHealthy = null;
function wait(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms);
});
}
function setSyncProgress(text) {
var el = document.getElementById('syncProgressText');
if (!el) return;
el.textContent = text || '';
}
function startSyncProgress(prefix) {
var startedAt = Date.now();
var dots = 0;
if (syncProgressTimer) {
clearInterval(syncProgressTimer);
}
setSyncProgress((prefix || '正在同步') + ' 0s');
syncProgressTimer = setInterval(function() {
dots = (dots + 1) % 4;
var suffix = new Array(dots + 1).join('.');
var elapsed = Math.max(0, Math.floor((Date.now() - startedAt) / 1000));
setSyncProgress((prefix || '正在同步') + suffix + ' ' + elapsed + 's');
}, 500);
}
function stopSyncProgress(text) {
if (syncProgressTimer) {
clearInterval(syncProgressTimer);
syncProgressTimer = null;
}
setSyncProgress(text || '');
}
function updateStatus(status) {
if (status && status.authenticated !== undefined) {
lastGoodSyncStatus = status;
}
var accountDot = document.getElementById('accountDot');
var accountText = document.getElementById('accountText');
var email = document.getElementById('syncEmail');
var loggedOut = document.getElementById('authLoggedOut');
var loggedIn = document.getElementById('authLoggedIn');
var loggedInEmail = document.getElementById('loggedInEmail');
var healthy = !!(status && status.color === 'green');
var authenticated = !!(status && status.authenticated);
if (accountDot) accountDot.classList.toggle('ok', healthy);
if (accountText) accountText.textContent = status && (status.accountText || status.text) ? (status.accountText || status.text) : '账号状态未知';
if (email) email.textContent = status && status.email ? ('账号:' + status.email) : '';
if (loggedOut) loggedOut.classList.toggle('hidden', authenticated);
if (loggedIn) loggedIn.classList.toggle('hidden', !authenticated);
if (loggedInEmail) loggedInEmail.textContent = status && status.email ? ('当前账号:' + status.email) : '当前账号:未知';
}
function updateServerStatus(ok, text) {
var serverDot = document.getElementById('serverDot');
var serverText = document.getElementById('serverText');
lastServerHealthy = !!ok;
if (serverDot) serverDot.classList.toggle('ok', !!ok);
if (serverText) serverText.textContent = text || (ok ? '服务器状态正常' : '服务器状态异常');
}
function formatDateTime(value) {
if (!value) return '暂无';
try {
var date = new Date(value);
if (Number.isNaN(date.getTime())) return String(value);
return date.toLocaleString('zh-CN');
} catch (error) {
return String(value);
}
}
function renderCloudStats(stats) {
var summary = document.getElementById('cloudStatsSummary');
var latest = document.getElementById('cloudStatsLatest');
var tables = document.getElementById('cloudStatsTables');
if (!summary || !latest || !tables) return;
if (!stats || !stats.ok) {
if (lastGoodCloudStats && lastGoodCloudStats.ok) {
updateServerStatus(true, '服务器状态正常(展示最近一次成功数据)');
summary.textContent = '云端状态暂时刷新失败,显示最近一次成功数据';
latest.textContent = '最近成功更新:线程 ' + formatDateTime(lastGoodCloudStats.latest.threads) + ' 范围 ' + formatDateTime(lastGoodCloudStats.latest.coverages) + ' 页缓存 ' + formatDateTime(lastGoodCloudStats.latest.pages);
tables.textContent = '上次空间占用:' + (Array.isArray(lastGoodCloudStats.tables) ? lastGoodCloudStats.tables.map(function(table) {
return table.tableName + ' ' + table.sizeMb + 'MB';
}).join(' ') : '暂无');
return;
}
updateServerStatus(false, '服务器状态暂时不可读');
summary.textContent = '暂时无法读取云端状态';
latest.textContent = '';
tables.textContent = '';
return;
}
updateServerStatus(true, '服务器状态正常');
lastGoodCloudStats = stats;
summary.textContent = '帖子索引 ' + stats.counts.threads + ' 条(含磁力 ' + (stats.counts.magnetThreads || 0) + ' 条)/ 页缓存 ' + stats.counts.pages + ' 条 / 范围缓存 ' + stats.counts.coverages + ' 条 / 用户 ' + stats.counts.users + ' 个 / 保险柜 ' + stats.counts.vaultItems + ' 条';
latest.textContent = '最近更新:线程 ' + formatDateTime(stats.latest.threads) + ' 范围 ' + formatDateTime(stats.latest.coverages) + ' 页缓存 ' + formatDateTime(stats.latest.pages);
tables.textContent = '空间占用:' + (Array.isArray(stats.tables) ? stats.tables.map(function(table) {
return table.tableName + ' ' + table.sizeMb + 'MB';
}).join(' ') : '暂无');
}
function formatBytes(bytes) {
var value = Number(bytes || 0);
if (!Number.isFinite(value) || value <= 0) return '0 B';
if (value < 1024) return value + ' B';
if (value < 1024 * 1024) return (value / 1024).toFixed(1) + ' KB';
if (value < 1024 * 1024 * 1024) return (value / 1024 / 1024).toFixed(2) + ' MB';
return (value / 1024 / 1024 / 1024).toFixed(2) + ' GB';
}
function renderLocalStats(stats) {
var summary = document.getElementById('localStatsSummary');
var storage = document.getElementById('localStatsStorage');
var meta = document.getElementById('localStatsMeta');
if (!summary || !storage || !meta) return;
if (!stats || !stats.ok) {
summary.textContent = '暂时无法读取本地状态';
storage.textContent = '';
meta.textContent = '';
return;
}
summary.textContent = '帖子索引 ' + stats.counts.threads + ' 条(含磁力 ' + (stats.counts.magnetThreads || 0) + ' 条)/ 页缓存 ' + stats.counts.pages + ' 条 / 范围缓存 ' + stats.counts.coverages + ' 条 / 收藏 ' + stats.counts.favorites + ' 条 / 历史 ' + stats.counts.history + ' 条';
storage.textContent = '本地存储占用:' + formatBytes(stats.storage.usage) + ' / ' + formatBytes(stats.storage.quota);
meta.textContent = '上传抑制元数据:线程 ' + stats.counts.uploadMetaThreads + ' 条 范围 ' + stats.counts.uploadMetaCoverages + ' 条 页 ' + stats.counts.uploadMetaPages + ' 条';
}
async function refreshStatus() {
try {
var response = await sendMessageToBackground({ action: 'cloudGetSyncStatus' });
if (response && response.ok !== false) {
updateStatus(response || { color: 'red', text: '状态未知', authenticated: false });
return;
}
if (lastGoodSyncStatus) {
updateStatus(lastGoodSyncStatus);
setMessage('云同步状态暂时刷新失败,显示最近一次成功状态', true);
return;
}
updateStatus({ color: 'red', text: '云同步异常', authenticated: false, email: '' });
} catch (error) {
if (lastGoodSyncStatus) {
updateStatus(lastGoodSyncStatus);
setMessage('云同步状态暂时刷新失败,显示最近一次成功状态', true);
return;
}
updateStatus({ color: 'red', text: '云同步异常', authenticated: false, email: '' });
setMessage('状态获取失败:' + error.message, true);
}
}
async function refreshCloudStats() {
var attempts = 0;
var response = null;
var error = null;
for (attempts = 0; attempts < 3; attempts++) {
try {
response = await sendMessageToBackground({ action: 'cloudGetCacheStats' });
if (response && response.ok) {
renderCloudStats(response);
return;
}
} catch (err) {
error = err;
}
await wait(500 * (attempts + 1));
}
renderCloudStats(null);
if (error) {
setMessage('云端状态暂时刷新失败,稍后会自动重试', true);
}
}
async function refreshLocalStats() {
try {
var response = await sendMessageToBackground({ action: 'localGetCacheStats' });
renderLocalStats(response);
} catch (error) {
renderLocalStats(null);
}
}
async function submitAuth(action) {
var emailInput = document.getElementById('emailInput');
var passwordInput = document.getElementById('passwordInput');
var email = emailInput ? emailInput.value.trim() : '';
var password = passwordInput ? passwordInput.value : '';
if (!email || !password) {
setMessage('请输入邮箱和密码', true);
return;
}
setMessage(action === 'cloudRegister' ? '正在注册...' : '正在登录...', false);
try {
var response = await sendMessageToBackground({ action: action, email: email, password: password });
if (!response || !response.ok) {
setMessage((action === 'cloudRegister' ? '注册失败:' : '登录失败:') + (response && response.error ? response.error : '未知错误'), true);
return;
}
if (passwordInput) passwordInput.value = '';
updateStatus(response.status || { color: 'green', text: '云同步正常', authenticated: true, email: email });
setMessage(action === 'cloudRegister' ? '注册成功,云同步已开启' : '登录成功,云同步已开启', false);
} catch (error) {
setMessage((action === 'cloudRegister' ? '注册失败:' : '登录失败:') + error.message, true);
}
}
async function syncNow() {
setMessage('', false);
startSyncProgress('正在同步本地缓存到云端');
try {
await sendMessageToBackground({ action: 'cloudBackfillLocalCache', force: true });
stopSyncProgress('已提交同步任务,正在刷新状态...');
await wait(1200);
startSyncProgress('正在刷新云端状态');
await refreshStatus();
await refreshCloudStats();
await refreshLocalStats();
stopSyncProgress('同步完成');
setMessage('已触发云端回填', false);
} catch (error) {
stopSyncProgress('同步失败');
setMessage('同步失败:' + error.message, true);
}
}
async function logout() {
try {
await sendMessageToBackground({ action: 'cloudLogout' });
await refreshStatus();
setMessage('已退出登录', false);
} catch (error) {
setMessage('退出失败:' + error.message, true);
}
}
function openExternalUrl(url) {
chrome.tabs.create({ url: url });
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('loginBtn').addEventListener('click', function() { submitAuth('cloudLogin'); });
document.getElementById('registerBtn').addEventListener('click', function() { submitAuth('cloudRegister'); });
document.getElementById('syncNowBtn').addEventListener('click', syncNow);
document.getElementById('logoutBtn').addEventListener('click', logout);
document.getElementById('downloadNode2Btn').addEventListener('click', function() { openExternalUrl('http://7.haory.cn/x/x72/qBittorrent_5.1.4_x64_setup.exe'); });
document.getElementById('downloadOfficialBtn').addEventListener('click', function() { openExternalUrl('https://sourceforge.net/projects/qbittorrent/files/qbittorrent-win32/qbittorrent-5.1.4/qbittorrent_5.1.4_x64_setup.exe/download'); });
document.getElementById('downloadMotrixBtn').addEventListener('click', function() { openExternalUrl('http://7.haory.cn/x/x72/Motrix-Setup-1.8.19.exe'); });
refreshStatus();
refreshCloudStats();
refreshLocalStats();
});