您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
超级书签管理器是一个高效的书签管理工具,提供了添加、编辑、删除、排序、导出和导入书签的功能。界面简洁美观,支持拖拽排序和一次打开多个书签,提升用户的书签管理体验。
// ==UserScript== // @name 超级书签管理器软件 // @namespace http://tampermonkey.net/ // @version 1.24 // @description 超级书签管理器是一个高效的书签管理工具,提供了添加、编辑、删除、排序、导出和导入书签的功能。界面简洁美观,支持拖拽排序和一次打开多个书签,提升用户的书签管理体验。 // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net // @author wll // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @grant GM_log // @license AGPL-3.0-or-later // ==/UserScript== /* 脚本特点及好处: * 1. **集中管理**:提供一个居中显示的书签管理界面,可以一次性管理所有书签。 * 2. **快速添加**:通过菜单选项快速添加当前页面为书签,支持自定义书签名称。 * 3. **拖放排序**:支持拖放功能,可以方便地对书签进行排序调整。 * 4. **多列展示**:书签以最多四列的方式展示,布局合理,方便查看。 * 5. **书签编辑和删除**:提供直观的编辑和删除按钮,方便快速修改或移除书签。 * 6. **数据存储**:利用油猴自带的数据存储功能,确保书签数据持久保存。 * 7. **导入导出**:支持书签的导入和导出功能,方便在不同设备之间迁移书签。 * 8. **多选打开**:可以一次选择多个书签,并一键打开所有选中的书签。 * 9. **通知提示**:操作成功后会弹出通知提示,无需点击确认,操作体验流畅。 * 10. **精致界面**:界面美观简洁,字体和元素大小适中,小巧精致,提供良好的用户体验。 体验其便捷和高效的书签管理功能。 */ (function() { 'use strict'; const defaultBookmarks = [ { title: '百度', url: 'https://www.baidu.com' }, { title: '搜狗', url: 'https://www.sogou.com' }, { title: 'Bing', url: 'https://www.bing.com' }, { title: '谷歌', url: 'https://www.google.com' } ]; let isManagerOpen = false; // GM_log("脚本初始化中..."); GM_registerMenuCommand("管理书签", async () => { // GM_log("管理书签菜单被点击"); if (!isManagerOpen) { await openBookmarkManager(); } }); GM_registerMenuCommand("添加当前页到书签", async () => { // GM_log("添加当前页到书签菜单被点击"); await addCurrentPageBookmark(); }); async function initializeBookmarks() { // GM_log("初始化书签数据..."); let bookmarks = await GM_getValue('bookmarks', null); if (!bookmarks) { bookmarks = defaultBookmarks; await GM_setValue('bookmarks', bookmarks); // GM_log("书签已初始化为默认数据"); } return bookmarks; } async function getBookmarks() { const bookmarks = await GM_getValue('bookmarks', defaultBookmarks); // GM_log("书签数据已获取", bookmarks); return bookmarks; } async function setBookmarks(bookmarks) { // GM_log("设置书签数据", bookmarks); await GM_setValue('bookmarks', bookmarks); } async function getSelectedBookmarks() { const selectedBookmarks = await GM_getValue('selectedBookmarks', []); // GM_log("获取选择的书签", selectedBookmarks); return selectedBookmarks; } async function setSelectedBookmarks(selectedBookmarks) { // GM_log("设置选择的书签", selectedBookmarks); await GM_setValue('selectedBookmarks', selectedBookmarks); } function showNotification(message) { // GM_log("显示通知:", message); const notification = document.createElement('div'); notification.textContent = message; notification.style.position = 'fixed'; notification.style.top = '10px'; notification.style.right = '10px'; notification.style.padding = '10px'; notification.style.backgroundColor = '#007bfa'; notification.style.color = 'white'; notification.style.borderRadius = '5px'; notification.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)'; notification.style.zIndex = '9999'; document.body.appendChild(notification); setTimeout(() => { document.body.removeChild(notification); }, 1500); // 提示时间为 1.5 秒 } async function addCurrentPageBookmark() { // GM_log("添加当前页面到书签"); const bookmarks = await getBookmarks(); const currentUrl = window.location.href; const currentTitle = document.title; if (!bookmarks.some(bookmark => bookmark.url === currentUrl)) { const newTitle = prompt('输入书签名称', currentTitle); if (newTitle !== null && newTitle.trim() !== '') { const newBookmark = { title: newTitle.trim(), url: currentUrl }; bookmarks.push(newBookmark); await setBookmarks(bookmarks); showNotification('书签已添加'); await renderBookmarks(); } } else { showNotification('该页面已经在书签中'); } } async function exportBookmarks() { // GM_log("导出书签"); const bookmarks = await getBookmarks(); const date = new Date(); const dateStr = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}_${date.getHours().toString().padStart(2, '0')}-${date.getMinutes().toString().padStart(2, '0')}`; const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(bookmarks, null, 2)); const downloadAnchorNode = document.createElement('a'); downloadAnchorNode.setAttribute("href", dataStr); downloadAnchorNode.setAttribute("download", `超级书签管理器_${dateStr}.json`); document.body.appendChild(downloadAnchorNode); downloadAnchorNode.click(); downloadAnchorNode.remove(); showNotification('书签已导出'); } async function importBookmarks() { // GM_log("导入书签"); const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = 'application/json'; fileInput.onchange = async (event) => { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = async (e) => { try { const importedBookmarks = JSON.parse(e.target.result); const existingBookmarks = await getBookmarks(); const newBookmarks = importedBookmarks.filter(bookmark => !existingBookmarks.some(existing => existing.url === bookmark.url) ); if (newBookmarks.length > 0) { const allBookmarks = existingBookmarks.concat(newBookmarks); await setBookmarks(allBookmarks); await renderBookmarks(); showNotification(`书签已导入,共导入${newBookmarks.length}条新书签`); } else { showNotification('没有新书签被导入'); } } catch (error) { showNotification('导入失败: 无效的 JSON 文件'); } }; reader.readAsText(file); } }; fileInput.click(); } // 渲染书签列表 async function renderBookmarks() { // GM_log("渲染书签列表"); const bookmarkList = document.querySelector('.bookmark-list'); if (!bookmarkList) { // GM_log("未找到书签列表元素"); return; } const bookmarks = await getBookmarks(); const selectedBookmarks = await getSelectedBookmarks(); // GM_log("即将渲染的书签数据:", bookmarks); bookmarkList.innerHTML = ''; // Clear the list before re-rendering bookmarks.forEach((bookmark, index) => { const card = document.createElement('div'); card.style.position = 'relative'; card.style.border = '1px solid #ccc'; card.style.padding = '10px'; card.style.borderRadius = '5px'; card.style.backgroundColor = '#fff'; card.draggable = true; card.ondragstart = (e) => { e.dataTransfer.setData('text/plain', index); }; card.ondragover = (e) => { e.preventDefault(); }; card.ondrop = async (e) => { e.preventDefault(); const draggedIndex = e.dataTransfer.getData('text/plain'); const draggedBookmark = bookmarks.splice(draggedIndex, 1)[0]; bookmarks.splice(index, 0, draggedBookmark); await setBookmarks(bookmarks); await renderBookmarks(); showNotification('书签已排序'); }; const editButton = document.createElement('span'); editButton.innerHTML = '✎'; editButton.title = '编辑'; editButton.style.position = 'absolute'; editButton.style.top = '5px'; editButton.style.left = '5px'; editButton.style.fontSize = '14px'; editButton.style.cursor = 'pointer'; editButton.onclick = async (e) => { e.stopPropagation(); const newTitle = prompt('输入新的书签名称', bookmark.title); if (newTitle !== null && newTitle.trim() !== '') { bookmark.title = newTitle.trim(); await setBookmarks(bookmarks); await renderBookmarks(); showNotification('书签已修改'); } }; card.appendChild(editButton); const removeButton = document.createElement('span'); removeButton.innerHTML = '🗑'; removeButton.title = '删除'; removeButton.style.position = 'absolute'; removeButton.style.bottom = '5px'; removeButton.style.left = '5px'; removeButton.style.fontSize = '14px'; removeButton.style.cursor = 'pointer'; removeButton.onclick = async (e) => { e.stopPropagation(); bookmarks.splice(index, 1); await setBookmarks(bookmarks); await renderBookmarks(); showNotification('书签已删除'); }; card.appendChild(removeButton); const title = document.createElement('div'); title.textContent = bookmark.title; title.style.marginBottom = '30px'; title.style.cursor = 'pointer'; title.style.color = '#007bfa'; title.style.paddingRight = '20px'; title.onmouseover = () => { title.style.textDecoration = 'underline'; }; title.onmouseout = () => { title.style.textDecoration = 'none'; }; title.onclick = (e) => { if (e.target !== editButton && e.target !== removeButton) { window.open(bookmark.url, '_blank'); } }; card.appendChild(title); const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.className = 'bookmark-checkbox'; checkbox.style.position = 'absolute'; checkbox.style.top = '5px'; checkbox.style.right = '5px'; checkbox.setAttribute('data-url', bookmark.url); checkbox.checked = selectedBookmarks.includes(bookmark.url); checkbox.onclick = async (e) => { e.stopPropagation(); if (checkbox.checked) { selectedBookmarks.push(bookmark.url); } else { const index = selectedBookmarks.indexOf(bookmark.url); if (index !== -1) { selectedBookmarks.splice(index, 1); } } await setSelectedBookmarks(selectedBookmarks); }; card.appendChild(checkbox); card.onclick = (e) => { if (e.target !== checkbox && e.target !== editButton && e.target !== removeButton && e.target !== title) { window.open(bookmark.url, '_blank'); } }; bookmarkList.appendChild(card); }); // GM_log("书签列表渲染完成"); } async function openBookmarkManager() { // GM_log("打开书签管理器"); isManagerOpen = true; await initializeBookmarks(); const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; overlay.style.zIndex = '9999'; overlay.onclick = () => { document.body.removeChild(overlay); document.body.removeChild(bookmarkUI); isManagerOpen = false; // GM_log("关闭书签管理器"); }; const bookmarkUI = document.createElement('div'); bookmarkUI.className = 'bookmark-manager'; bookmarkUI.style.position = 'fixed'; bookmarkUI.style.top = '50%'; bookmarkUI.style.left = '50%'; bookmarkUI.style.transform = 'translate(-50%, -50%)'; bookmarkUI.style.width = '600px'; bookmarkUI.style.backgroundColor = '#f9f9f9'; bookmarkUI.style.border = '1px solid #ccc'; bookmarkUI.style.padding = '20px'; bookmarkUI.style.zIndex = '10000'; bookmarkUI.style.maxHeight = '80%'; bookmarkUI.style.overflowY = 'auto'; bookmarkUI.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)'; bookmarkUI.style.borderRadius = '10px'; bookmarkUI.style.fontFamily = 'Arial, sans-serif'; bookmarkUI.onclick = (e) => { e.stopPropagation(); }; const title = document.createElement('h2'); title.textContent = '书签管理'; title.style.textAlign = 'center'; title.style.marginTop = '0'; bookmarkUI.appendChild(title); const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'space-between'; buttonContainer.style.marginBottom = '10px'; bookmarkUI.appendChild(buttonContainer); const addButton = document.createElement('button'); addButton.textContent = '添加当前页到书签'; addButton.style.backgroundColor = '#007bfa'; addButton.style.color = 'white'; addButton.style.border = 'none'; addButton.style.padding = '10px'; addButton.style.borderRadius = '5px'; addButton.style.cursor = 'pointer'; addButton.onmouseover = () => { addButton.style.backgroundColor = '#005bb5'; }; addButton.onmouseout = () => { addButton.style.backgroundColor = '#007bfa'; }; addButton.onclick = async () => { await addCurrentPageBookmark(); await renderBookmarks(); }; buttonContainer.appendChild(addButton); const exportButton = document.createElement('button'); exportButton.textContent = '导出书签'; exportButton.style.backgroundColor = '#007bfa'; exportButton.style.color = 'white'; exportButton.style.border = 'none'; exportButton.style.padding = '10px'; exportButton.style.borderRadius = '5px'; exportButton.style.cursor = 'pointer'; exportButton.onmouseover = () => { exportButton.style.backgroundColor = '#005bb5'; }; exportButton.onmouseout = () => { exportButton.style.backgroundColor = '#007bfa'; }; exportButton.onclick = async () => { await exportBookmarks(); }; buttonContainer.appendChild(exportButton); const importButton = document.createElement('button'); importButton.textContent = '导入书签'; importButton.style.backgroundColor = '#007bfa'; importButton.style.color = 'white'; importButton.style.border = 'none'; importButton.style.padding = '10px'; importButton.style.borderRadius = '5px'; importButton.style.cursor = 'pointer'; importButton.onmouseover = () => { importButton.style.backgroundColor = '#005bb5'; }; importButton.onmouseout = () => { importButton.style.backgroundColor = '#007bfa'; }; importButton.onclick = async () => { await importBookmarks(); await renderBookmarks(); }; buttonContainer.appendChild(importButton); const openMultipleButton = document.createElement('button'); openMultipleButton.textContent = '打开选择的书签'; openMultipleButton.style.backgroundColor = '#007bfa'; openMultipleButton.style.color = 'white'; openMultipleButton.style.border = 'none'; openMultipleButton.style.padding = '10px'; openMultipleButton.style.borderRadius = '5px'; openMultipleButton.style.cursor = 'pointer'; openMultipleButton.onmouseover = () => { openMultipleButton.style.backgroundColor = '#005bb5'; }; openMultipleButton.onmouseout = () => { openMultipleButton.style.backgroundColor = '#007bfa'; }; openMultipleButton.onclick = () => { const selectedCheckboxes = document.querySelectorAll('.bookmark-checkbox:checked'); if (selectedCheckboxes.length === 0) { showNotification('请选择至少一个书签'); return; } selectedCheckboxes.forEach(checkbox => { const url = checkbox.getAttribute('data-url'); window.open(url, '_blank'); }); }; buttonContainer.appendChild(openMultipleButton); const bookmarkList = document.createElement('div'); bookmarkList.className = 'bookmark-list'; bookmarkList.style.display = 'grid'; bookmarkList.style.gridTemplateColumns = 'repeat(auto-fit, minmax(120px, 1fr))'; bookmarkList.style.gap = '10px'; bookmarkList.style.minHeight = '200px'; bookmarkUI.appendChild(bookmarkList); document.body.appendChild(overlay); document.body.appendChild(bookmarkUI); await renderBookmarks(); // 确保渲染书签列表在元素创建后执行 } initializeBookmarks(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址