feat: 新增进度条、收藏夹、历史记录、 通知提醒功能
## 新功能 1. 进度条 - 可视化抓取进度 2. 收藏夹 - 持久收藏磁力链接(♡按钮) 3. 历史记录 - 关键词搜索历史(点击输入框显示) 4. 通知提醒 - 完成时提示音 + 浏览器通知 ## 技术实现 - 使用 localStorage 存储收藏和历史 - 使用 Web Audio API 播放提示音 - 使用 Notification API 显示浏览器通知 - CSS 进度条动画效果
This commit is contained in:
546
content.js
546
content.js
@@ -472,12 +472,100 @@
|
||||
'}',
|
||||
'.magnet-empty-state-text{',
|
||||
' font-size:14px;line-height:1.6;',
|
||||
'}',
|
||||
|
||||
/* === 进度条 === */',
|
||||
'.magnet-progress-container{',
|
||||
' width:100%;height:6px;background:var(--m-bg-secondary);border-radius:3px;overflow:hidden;margin-top:8px;',
|
||||
'}',
|
||||
'.magnet-progress-bar{',
|
||||
' height:100%;background:linear-gradient(90deg, var(--m-accent), #00f5c4);border-radius:3px;transition:width 0.3s ease;',
|
||||
'}',
|
||||
'.magnet-progress-text{',
|
||||
' display:flex;justify-content:space-between;font-size:11px;color:var(--m-text-muted);margin-top:4px;',
|
||||
'}',
|
||||
|
||||
/* === 收藏按钮 === */',
|
||||
'.magnet-favorite-btn{',
|
||||
' padding:6px 10px;background:transparent;border:1px solid var(--m-border);border-radius:8px;cursor:pointer;font-size:11px;color:var(--m-text-muted);transition:all 0.2s ease;',
|
||||
'}',
|
||||
'.magnet-favorite-btn:hover{',
|
||||
' border-color:var(--m-accent-secondary);color:var(--m-accent-secondary);',
|
||||
'}',
|
||||
'.magnet-favorite-btn.is-favorite{',
|
||||
' background:rgba(167,139,250,0.15);border-color:var(--m-accent-secondary);color:var(--m-accent-secondary);',
|
||||
'}',
|
||||
|
||||
/* === 收藏视图 === */',
|
||||
'#magnet-favorites-view .magnet-favorite-item{',
|
||||
' display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--m-bg-card);border:1px solid var(--m-border);border-radius:var(--m-radius-md);margin-bottom:8px;',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-item:hover{',
|
||||
' border-color:var(--m-border-accent);',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-title{',
|
||||
' flex:1;font-size:12px;color:var(--m-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-actions{',
|
||||
' display:flex;gap:6px;',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-copy,',
|
||||
'#magnet-favorites-view .magnet-favorite-remove{',
|
||||
' padding:5px 8px;border:none;border-radius:6px;cursor:pointer;font-size:10px;font-weight:600;transition:all 0.2s ease;',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-copy{',
|
||||
' background:linear-gradient(135deg, var(--m-accent), #00f5c4);color:var(--m-bg-deep);',
|
||||
'}',
|
||||
'#magnet-favorites-view .magnet-favorite-remove{',
|
||||
' background:rgba(239,68,68,0.15);color:var(--m-error);',
|
||||
'}',
|
||||
|
||||
/* === 历史记录下拉 === */',
|
||||
'.magnet-history-dropdown{',
|
||||
' position:absolute;top:100%;left:0;right:0;background:var(--m-bg-card);border:1px solid var(--m-border);border-radius:var(--m-radius-md);box-shadow:var(--m-shadow-lg);z-index:100;max-height:200px;overflow-y:auto;',
|
||||
'}',
|
||||
'.magnet-history-item{',
|
||||
' padding:10px 14px;cursor:pointer;font-size:12px;color:var(--m-text-primary);transition:background 0.2s ease;',
|
||||
'}',
|
||||
'.magnet-history-item:hover{',
|
||||
' background:var(--m-bg-secondary);',
|
||||
'}',
|
||||
'.magnet-history-item:first-child{',
|
||||
' border-radius:var(--m-radius-md) var(--m-radius-md) 0 0;',
|
||||
'}',
|
||||
'.magnet-history-item:last-child{',
|
||||
' border-radius:0 0 var(--m-radius-md) var(--m-radius-md);',
|
||||
'}',
|
||||
'.magnet-history-clear{',
|
||||
' padding:10px 14px;border-top:1px solid var(--m-border);font-size:11px;color:var(--m-error);cursor:pointer;text-align:center;',
|
||||
'}'
|
||||
].join('');
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function setPanelView(viewName) {
|
||||
var resultsView = document.getElementById('magnet-results-view');
|
||||
var cacheView = document.getElementById('magnet-cache-view');
|
||||
var favoritesView = document.getElementById('magnet-favorites-view');
|
||||
var resultsBtn = document.getElementById('magnet-view-results');
|
||||
var cacheBtn = document.getElementById('magnet-view-cache');
|
||||
var favoritesBtn = document.getElementById('magnet-view-favorites');
|
||||
|
||||
if (!resultsView || !cacheView || !favoritesView || !resultsBtn || !cacheBtn || !favoritesBtn) {
|
||||
return;
|
||||
}
|
||||
|
||||
resultsView.classList.toggle('is-active', viewName === 'results');
|
||||
cacheView.classList.toggle('is-active', viewName === 'cache');
|
||||
favoritesView.classList.toggle('is-active', viewName === 'favorites');
|
||||
resultsBtn.classList.toggle('is-active', viewName === 'results');
|
||||
cacheBtn.classList.toggle('is-active', viewName === 'cache');
|
||||
favoritesBtn.classList.toggle('is-active', viewName === 'favorites');
|
||||
|
||||
if (viewName === 'favorites') {
|
||||
renderFavoritesList();
|
||||
}
|
||||
}
|
||||
var resultsView = document.getElementById('magnet-results-view');
|
||||
var cacheView = document.getElementById('magnet-cache-view');
|
||||
var resultsBtn = document.getElementById('magnet-view-results');
|
||||
@@ -527,7 +615,7 @@
|
||||
|
||||
var panel = document.createElement('div');
|
||||
panel.id = 'magnet-floating-panel';
|
||||
panel.innerHTML = '<div class="magnet-panel-header"><div class="magnet-panel-brand"><div class="magnet-panel-title">MAGNET LINKS</div><div class="magnet-panel-subtitle">智能抓取 · 缓存加速 · 一键复制</div></div><div class="magnet-panel-head-actions"><button id="magnet-view-results" class="magnet-panel-switch is-active">结果</button><button id="magnet-view-cache" class="magnet-panel-switch">缓存</button><button class="magnet-panel-close" title="关闭">×</button></div></div><div class="magnet-settings" id="magnet-settings"></div><div class="magnet-panel-content"><div id="magnet-results-view" class="magnet-view is-active"><div class="magnet-view-toolbar"><div><div class="magnet-view-title">搜索结果</div><div class="magnet-view-meta">关键词命中的磁力链接</div></div><div class="magnet-view-meta">共 <span id="magnet-count-num">0</span> 条</div></div><div class="magnet-list" id="magnet-list"></div></div><div id="magnet-cache-view" class="magnet-view"><div class="magnet-view-toolbar"><div><div class="magnet-view-title">缓存总览</div><div class="magnet-view-meta">数据统计与快照管理</div></div><div class="magnet-view-toolbar-actions"><button id="magnet-refresh-cache" class="magnet-panel-switch is-active">刷新</button><button id="magnet-clear-cache-inline" class="magnet-panel-switch">清空</button></div></div><div id="magnet-cache-panel"></div></div></div><div class="magnet-panel-footer"><div id="magnet-status">设置参数后开始抓取</div><button id="magnet-copy-all">一键复制全部</button></div>';
|
||||
panel.innerHTML = '<div class="magnet-panel-header"><div class="magnet-panel-brand"><div class="magnet-panel-title">MAGNET LINKS</div><div class="magnet-panel-subtitle">智能抓取 · 缓存加速 · 一键复制</div></div><div class="magnet-panel-head-actions"><button id="magnet-view-results" class="magnet-panel-switch is-active">结果</button><button id="magnet-view-favorites" class="magnet-panel-switch">收藏</button><button id="magnet-view-cache" class="magnet-panel-switch">缓存</button><button class="magnet-panel-close" title="关闭">×</button></div></div><div class="magnet-settings" id="magnet-settings"></div><div class="magnet-panel-content"><div id="magnet-results-view" class="magnet-view is-active"><div class="magnet-view-toolbar"><div><div class="magnet-view-title">搜索结果</div><div class="magnet-view-meta">关键词命中的磁力链接</div></div><div class="magnet-view-meta">共 <span id="magnet-count-num">0</span> 条</div></div><div class="magnet-list" id="magnet-list"></div></div><div id="magnet-favorites-view" class="magnet-view"><div class="magnet-view-toolbar"><div><div class="magnet-view-title">我的收藏</div><div class="magnet-view-meta">持久保存的磁力链接</div></div><div class="magnet-view-toolbar-actions"><button id="magnet-clear-favorites" class="magnet-panel-switch">清空收藏</button></div></div><div id="magnet-favorites-list"></div></div><div id="magnet-cache-view" class="magnet-view"><div class="magnet-view-toolbar"><div><div class="magnet-view-title">缓存总览</div><div class="magnet-view-meta">数据统计与快照管理</div></div><div class="magnet-view-toolbar-actions"><button id="magnet-refresh-cache" class="magnet-panel-switch is-active">刷新</button><button id="magnet-clear-cache-inline" class="magnet-panel-switch">清空</button></div></div><div id="magnet-cache-panel"></div></div></div><div class="magnet-panel-footer"><div id="magnet-status">设置参数后开始抓取</div><div class="magnet-progress-container"><div class="magnet-progress-bar" id="magnet-progress-bar" style="width:0%"></div></div><div class="magnet-progress-text"><span id="magnet-progress-label">等待开始</span><span id="magnet-progress-percent">0%</span></div><button id="magnet-copy-all">一键复制全部</button></div>';
|
||||
document.body.appendChild(panel);
|
||||
|
||||
setPanelView('results');
|
||||
@@ -569,7 +657,48 @@
|
||||
panel.style.display = 'none';
|
||||
ball.style.display = 'flex';
|
||||
};
|
||||
var favoritesSwitch = panel.querySelector('#magnet-view-favorites');
|
||||
if (favoritesSwitch) {
|
||||
favoritesSwitch.onclick = function() {
|
||||
setPanelView('favorites');
|
||||
};
|
||||
}
|
||||
|
||||
var clearFavoritesBtn = panel.querySelector('#magnet-clear-favorites');
|
||||
if (clearFavoritesBtn) {
|
||||
clearFavoritesBtn.onclick = function() {
|
||||
if (confirm('确定要清空所有收藏吗')) {
|
||||
saveFavorites([]);
|
||||
renderFavoritesList();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var copyAllBtn = panel.querySelector('#magnet-copy-all');
|
||||
if (copyAllBtn) {
|
||||
copyAllBtn.onclick = function() {
|
||||
var links = allMagnetLinks.length > 0
|
||||
? allMagnetLinks.slice()
|
||||
: Array.from(document.querySelectorAll('.magnet-item .magnet-copy-btn'))
|
||||
.map(function(btn) { return btn.getAttribute('data-magnet'); })
|
||||
.filter(function(link) { return !!link; });
|
||||
if (links.length === 0) {
|
||||
alert('暂无可复制的磁力链接');
|
||||
return;
|
||||
}
|
||||
var allLinks = links.join('\n');
|
||||
navigator.clipboard.writeText(allLinks)
|
||||
.then(function() {
|
||||
alert('已复制 ' + links.length + ' 个磁力链接!');
|
||||
})
|
||||
.catch(function(err) {
|
||||
var errorMsg = err && err.message ? err.message : '复制失败';
|
||||
alert('复制失败: ' + errorMsg);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return panel;
|
||||
var copyAllBtn = panel.querySelector('#magnet-copy-all');
|
||||
if (copyAllBtn) {
|
||||
copyAllBtn.onclick = function() {
|
||||
@@ -754,6 +883,280 @@
|
||||
if (countEl) countEl.textContent = count;
|
||||
}
|
||||
|
||||
// === 进度条功能 ===
|
||||
function updateProgress(current, total, label) {
|
||||
var progressBar = document.getElementById('magnet-progress-bar');
|
||||
var progressLabel = document.getElementById('magnet-progress-label');
|
||||
var progressPercent = document.getElementById('magnet-progress-percent');
|
||||
|
||||
if (progressBar) {
|
||||
var percent = total > 0 ? Math.round((current / total) * 100) : 0;
|
||||
progressBar.style.width = percent + '%';
|
||||
}
|
||||
if (progressLabel) {
|
||||
progressLabel.textContent = label || ('进度: ' + current + '/' + total);
|
||||
}
|
||||
if (progressPercent) {
|
||||
var percent = total > 0 ? Math.round((current / total) * 100) : 0;
|
||||
progressPercent.textContent = percent + '%';
|
||||
}
|
||||
}
|
||||
|
||||
function resetProgress() {
|
||||
updateProgress(0, 0, '等待开始');
|
||||
}
|
||||
|
||||
// === 收藏夹功能 ===
|
||||
var FAVORITES_KEY = 'magnet-favorites';
|
||||
var favoritesCache = null;
|
||||
|
||||
function loadFavorites() {
|
||||
if (favoritesCache !== null) {
|
||||
return favoritesCache;
|
||||
}
|
||||
try {
|
||||
var stored = localStorage.getItem(FAVORITES_KEY);
|
||||
favoritesCache = stored ? JSON.parse(stored) : [];
|
||||
} catch (e) {
|
||||
favoritesCache = [];
|
||||
}
|
||||
return favoritesCache;
|
||||
}
|
||||
|
||||
function saveFavorites(favorites) {
|
||||
try {
|
||||
localStorage.setItem(FAVORITES_KEY, JSON.stringify(favorites));
|
||||
favoritesCache = favorites;
|
||||
} catch (e) {
|
||||
log('保存收藏失败: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
function isFavorited(link) {
|
||||
var favorites = loadFavorites();
|
||||
return favorites.some(function(f) { return f.link === link; });
|
||||
}
|
||||
|
||||
function toggleFavorite(title, link, btn) {
|
||||
var favorites = loadFavorites();
|
||||
var existingIndex = favorites.findIndex(function(f) { return f.link === link; });
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
favorites.splice(existingIndex, 1);
|
||||
btn.classList.remove('is-favorite');
|
||||
btn.innerHTML = '♡';
|
||||
btn.title = '收藏';
|
||||
} else {
|
||||
favorites.push({
|
||||
title: title,
|
||||
link: link,
|
||||
addedAt: Date.now()
|
||||
});
|
||||
btn.classList.add('is-favorite');
|
||||
btn.innerHTML = '♥';
|
||||
btn.title = '取消收藏';
|
||||
}
|
||||
|
||||
saveFavorites(favorites);
|
||||
}
|
||||
|
||||
function renderFavoritesList() {
|
||||
var list = document.getElementById('magnet-favorites-list');
|
||||
if (!list) return;
|
||||
|
||||
var favorites = loadFavorites();
|
||||
list.innerHTML = '';
|
||||
|
||||
if (favorites.length === 0) {
|
||||
list.innerHTML = '<div class="magnet-empty-state"><div class="magnet-empty-state-icon">📭</div><div class="magnet-empty-state-text">暂无收藏\br>点击结果列表中的 ♡ 按钮添加收藏</div></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
favorites.forEach(function(fav) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'magnet-favorite-item';
|
||||
|
||||
var titleEl = document.createElement('div');
|
||||
titleEl.className = 'magnet-favorite-title';
|
||||
titleEl.textContent = fav.title;
|
||||
titleEl.title = fav.title;
|
||||
|
||||
var actionsEl = document.createElement('div');
|
||||
actionsEl.className = 'magnet-favorite-actions';
|
||||
|
||||
var copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'magnet-favorite-copy';
|
||||
copyBtn.textContent = '复制';
|
||||
copyBtn.onclick = function() {
|
||||
navigator.clipboard.writeText(fav.link)
|
||||
.then(function() {
|
||||
copyBtn.textContent = '已复制';
|
||||
setTimeout(function() { copyBtn.textContent = '复制'; }, 1000);
|
||||
});
|
||||
};
|
||||
|
||||
var removeBtn = document.createElement('button');
|
||||
removeBtn.className = 'magnet-favorite-remove';
|
||||
removeBtn.textContent = '删除';
|
||||
removeBtn.onclick = function() {
|
||||
var favorites = loadFavorites();
|
||||
var idx = favorites.findIndex(function(f) { return f.link === fav.link; });
|
||||
if (idx >= 0) {
|
||||
favorites.splice(idx, 1);
|
||||
saveFavorites(favorites);
|
||||
renderFavoritesList();
|
||||
}
|
||||
};
|
||||
|
||||
actionsEl.appendChild(copyBtn);
|
||||
actionsEl.appendChild(removeBtn);
|
||||
item.appendChild(titleEl);
|
||||
item.appendChild(actionsEl);
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
// === 历史记录功能 ===
|
||||
var HISTORY_KEY = 'magnet-search-history';
|
||||
var MAX_HISTORY = 20;
|
||||
|
||||
function loadSearchHistory() {
|
||||
try {
|
||||
var stored = localStorage.getItem(HISTORY_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function saveSearchHistory(keyword) {
|
||||
if (!keyword || typeof keyword !== 'string' || !keyword.trim()) {
|
||||
return;
|
||||
}
|
||||
keyword = keyword.trim();
|
||||
var history = loadSearchHistory();
|
||||
// 移除已存在的相同关键词
|
||||
var idx = history.indexOf(keyword);
|
||||
if (idx >= 0) {
|
||||
history.splice(idx, 1);
|
||||
}
|
||||
// 添加到开头
|
||||
history.unshift(keyword);
|
||||
// 限制数量
|
||||
if (history.length > MAX_HISTORY) {
|
||||
history = history.slice(0, MAX_HISTORY);
|
||||
}
|
||||
try {
|
||||
localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
|
||||
} catch (e) {
|
||||
log('保存历史记录失败: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
function showHistoryDropdown(input) {
|
||||
var history = loadSearchHistory();
|
||||
if (history.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 移除已存在的下拉框
|
||||
var existing = document.querySelector('.magnet-history-dropdown');
|
||||
if (existing) existing.remove();
|
||||
|
||||
var dropdown = document.createElement('div');
|
||||
dropdown.className = 'magnet-history-dropdown';
|
||||
|
||||
history.forEach(function(kw) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'magnet-history-item';
|
||||
item.textContent = kw;
|
||||
item.onclick = function() {
|
||||
input.value = kw;
|
||||
dropdown.remove();
|
||||
input.focus();
|
||||
};
|
||||
dropdown.appendChild(item);
|
||||
});
|
||||
|
||||
var clearItem = document.createElement('div');
|
||||
clearItem.className = 'magnet-history-clear';
|
||||
clearItem.textContent = '清空历史';
|
||||
clearItem.onclick = function() {
|
||||
localStorage.removeItem(HISTORY_KEY);
|
||||
dropdown.remove();
|
||||
};
|
||||
dropdown.appendChild(clearItem);
|
||||
|
||||
input.parentNode.style.position = 'relative';
|
||||
input.parentNode.appendChild(dropdown);
|
||||
|
||||
// 点击外部关闭
|
||||
setTimeout(function() {
|
||||
document.addEventListener('click', function closeDropdown(e) {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
dropdown.remove();
|
||||
document.removeEventListener('click', closeDropdown);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// === 通知功能 ===
|
||||
function playNotificationSound() {
|
||||
try {
|
||||
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
var oscillator = audioContext.createOscillator();
|
||||
var gainNode = audioContext.createGain();
|
||||
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(audioContext.destination);
|
||||
|
||||
oscillator.frequency.value = 800;
|
||||
oscillator.type = 'sine';
|
||||
|
||||
gainNode.gain.setValue(0.3);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);
|
||||
|
||||
oscillator.start(audioContext.currentTime);
|
||||
oscillator.stop(audioContext.currentTime + 0.3);
|
||||
} catch (e) {
|
||||
log('播放提示音失败: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
function showBrowserNotification(title, body) {
|
||||
if (!('Notification' in window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Notification.permission === 'granted') {
|
||||
new Notification(title, { body: body, icon: chrome.runtime ? chrome.runtime.getURL('icon.png') : undefined });
|
||||
} else if (Notification.permission !== 'denied') {
|
||||
Notification.requestPermission().then(function(permission) {
|
||||
if (permission === 'granted') {
|
||||
new Notification(title, { body: body, icon: chrome.runtime ? chrome.runtime.getURL('icon.png') : undefined });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function notifyComplete(count, duration) {
|
||||
playNotificationSound();
|
||||
var durationText = '';
|
||||
if (duration && duration > 0) {
|
||||
var seconds = Math.floor(duration / 1000);
|
||||
if (seconds >= 60) {
|
||||
durationText = ',耗时 ' + Math.floor(seconds / 60) + ' 分 ' + (seconds % 60) + ' 秒';
|
||||
} else {
|
||||
durationText = ',耗时 ' + seconds + ' 秒';
|
||||
}
|
||||
}
|
||||
showBrowserNotification('磁力链接抓取完成', '共获取 ' + count + ' 个磁力链接' + durationText);
|
||||
}
|
||||
var countEl = document.getElementById('magnet-count-num');
|
||||
if (countEl) countEl.textContent = count;
|
||||
}
|
||||
|
||||
function clearMagnetList(skipPersist) {
|
||||
var list = document.getElementById('magnet-list');
|
||||
if (list) list.innerHTML = '';
|
||||
@@ -794,6 +1197,100 @@
|
||||
titleEl.title = safeTitle;
|
||||
titleEl.textContent = safeTitle;
|
||||
|
||||
var btnContainer = document.createElement('div');
|
||||
btnContainer.style.cssText = 'display:flex;gap:6px;flex-shrink:0;';
|
||||
|
||||
var copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'magnet-copy-btn';
|
||||
copyBtn.setAttribute('data-magnet', safeLink);
|
||||
copyBtn.textContent = '复制';
|
||||
|
||||
// 收藏按钮
|
||||
var favoriteBtn = document.createElement('button');
|
||||
favoriteBtn.className = 'magnet-favorite-btn';
|
||||
favoriteBtn.innerHTML = '♡';
|
||||
favoriteBtn.title = '收藏';
|
||||
favoriteBtn.onclick = function() {
|
||||
toggleFavorite(safeTitle, safeLink, favoriteBtn);
|
||||
};
|
||||
|
||||
// 检查是否已收藏
|
||||
isFavorite(safeLink).then(function(isFav) {
|
||||
if (isFav) {
|
||||
favoriteBtn.classList.add('is-favorite');
|
||||
favoriteBtn.title = '取消收藏';
|
||||
}
|
||||
});
|
||||
|
||||
titleEl.onclick = function() {
|
||||
navigator.clipboard.writeText(safeLink)
|
||||
.then(function() {
|
||||
titleEl.textContent = '已复制: ' + safeTitle.substring(0, 20) + '...';
|
||||
setTimeout(function() {
|
||||
titleEl.textContent = safeTitle;
|
||||
}, 1500);
|
||||
})
|
||||
.catch(function(err) {
|
||||
var errorMsg = err && err.message ? err.message : '复制失败';
|
||||
log('标题复制失败: ' + errorMsg);
|
||||
updateStatus('复制失败,请检查剪贴板权限', 'error');
|
||||
});
|
||||
};
|
||||
|
||||
copyBtn.onclick = function() {
|
||||
navigator.clipboard.writeText(safeLink)
|
||||
.then(function() {
|
||||
copyBtn.textContent = '已复制';
|
||||
setTimeout(function() {
|
||||
copyBtn.textContent = '复制';
|
||||
}, 1000);
|
||||
})
|
||||
.catch(function(err) {
|
||||
var errorMsg = err && err.message ? err.message : '复制失败';
|
||||
log('按钮复制失败: ' + errorMsg);
|
||||
updateStatus('复制失败,请检查剪贴板权限', 'error');
|
||||
});
|
||||
};
|
||||
|
||||
item.appendChild(titleEl);
|
||||
btnContainer.appendChild(favoriteBtn);
|
||||
btnContainer.appendChild(copyBtn);
|
||||
item.appendChild(btnContainer);
|
||||
|
||||
list.appendChild(item);
|
||||
setPanelView('results');
|
||||
updateCount(list.children.length);
|
||||
|
||||
if (!options || !options.skipPersist) {
|
||||
scheduleStatePersist();
|
||||
}
|
||||
}
|
||||
var list = document.getElementById('magnet-list');
|
||||
if (!list) return;
|
||||
|
||||
var safeTitle = typeof title === 'string' ? title : String(title || '');
|
||||
var safeLink = typeof link === 'string' ? link : String(link || '');
|
||||
if (!safeLink) return;
|
||||
|
||||
if (magnetRecordMap[safeLink]) {
|
||||
return;
|
||||
}
|
||||
|
||||
magnetRecordMap[safeLink] = safeTitle || '恢复记录';
|
||||
allMagnetRecords.push({
|
||||
title: magnetRecordMap[safeLink],
|
||||
link: safeLink
|
||||
});
|
||||
allMagnetLinks.push(safeLink);
|
||||
|
||||
var item = document.createElement('div');
|
||||
item.className = 'magnet-item';
|
||||
|
||||
var titleEl = document.createElement('span');
|
||||
titleEl.className = 'magnet-title';
|
||||
titleEl.title = safeTitle;
|
||||
titleEl.textContent = safeTitle;
|
||||
|
||||
var copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'magnet-copy-btn';
|
||||
copyBtn.setAttribute('data-magnet', safeLink);
|
||||
@@ -1796,6 +2293,11 @@
|
||||
}
|
||||
|
||||
updateStatus('第' + page + '/' + context.normalizedEnd + '页...', 'loading');
|
||||
|
||||
// 更新进度条
|
||||
var totalPages = context.normalizedEnd - (context.startPage || startPage) + 1;
|
||||
var currentPage = page - (context.startPage || startPage) + 1;
|
||||
updateProgress(currentPage, totalPages, '第' + page + '/' + context.normalizedEnd + '页');
|
||||
|
||||
var pageUrl = context.baseUrl + page + '.html';
|
||||
try {
|
||||
@@ -1876,6 +2378,18 @@
|
||||
progressRuntime.startPage = earlyStart;
|
||||
progressRuntime.endPage = earlyEnd;
|
||||
progressRuntime.resumeFromPage = earlyStart;
|
||||
|
||||
// 重置进度条
|
||||
resetProgress();
|
||||
|
||||
// 记录开始时间
|
||||
var startTime = Date.now();
|
||||
stopFetching = false;
|
||||
progressRuntime.isRunning = true;
|
||||
progressRuntime.stoppedByUser = false;
|
||||
progressRuntime.startPage = earlyStart;
|
||||
progressRuntime.endPage = earlyEnd;
|
||||
progressRuntime.resumeFromPage = earlyStart;
|
||||
|
||||
var panel = createFloatingPanel();
|
||||
var ball = document.getElementById('magnet-float-ball');
|
||||
@@ -2010,6 +2524,28 @@
|
||||
|
||||
var keywordMsg = keyword ? ' (关键词:' + keyword + ' 匹配:' + searchContext.matchedThreads + '帖)' : '';
|
||||
var failedMsg = searchContext.failedPages > 0 ? ',失败页:' + searchContext.failedPages : '';
|
||||
|
||||
// 更新进度条为100%
|
||||
updateProgress(normalizedEnd - normalizedStart + 1, normalizedEnd - normalizedStart + 1, '已完成');
|
||||
|
||||
if (stopFetching) {
|
||||
progressRuntime.stoppedByUser = true;
|
||||
updateStatus('已停止 - 找到' + searchContext.allMagnets.size + '个磁力' + keywordMsg + ',已处理帖子:' + searchContext.totalFetched + failedMsg, 'error');
|
||||
} else {
|
||||
progressRuntime.stoppedByUser = false;
|
||||
progressRuntime.resumeFromPage = normalizedEnd + 1;
|
||||
updateStatus('完成! 共' + searchContext.allMagnets.size + '个磁力' + keywordMsg + ',已处理帖子:' + searchContext.totalFetched + failedMsg, 'done');
|
||||
|
||||
// 发送完成通知
|
||||
var duration = Date.now() - startTime;
|
||||
notifyComplete(searchContext.allMagnets.size, duration);
|
||||
|
||||
// 保存搜索历史
|
||||
if (keyword) {
|
||||
saveSearchHistory(keyword);
|
||||
}
|
||||
}
|
||||
var failedMsg = searchContext.failedPages > 0 ? ',失败页:' + searchContext.failedPages : '';
|
||||
if (stopFetching) {
|
||||
progressRuntime.stoppedByUser = true;
|
||||
updateStatus('已停止 - 找到' + searchContext.allMagnets.size + '个磁力' + keywordMsg + ',已处理帖子:' + searchContext.totalFetched + failedMsg, 'error');
|
||||
@@ -2058,6 +2594,14 @@
|
||||
var keywordDiv = document.createElement('div');
|
||||
keywordDiv.className = 'magnet-control-row';
|
||||
keywordDiv.innerHTML = '<input type="text" id="keyword-input" placeholder="关键词(逗号分隔多关键词)" style="width:100%;padding:11px 14px;border:1px solid rgba(0,212,170,0.3);border-radius:12px;font-size:13px;box-sizing:border-box;background:#0f1419;color:#f0f4f8;box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)">';
|
||||
|
||||
// 添加历史记录下拉功能
|
||||
var keywordInput = keywordDiv.querySelector('#keyword-input');
|
||||
if (keywordInput) {
|
||||
keywordInput.addEventListener('focus', function() {
|
||||
showHistoryDropdown(keywordInput);
|
||||
});
|
||||
}
|
||||
|
||||
var pageRange = document.createElement('div');
|
||||
pageRange.className = 'magnet-control-row';
|
||||
|
||||
Reference in New Issue
Block a user