From 78c67cd097480e1d4b3da165e6be41cd69aecedc Mon Sep 17 00:00:00 2001 From: kaku Date: Tue, 20 May 2025 14:49:30 +0800 Subject: [PATCH] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E6=B5=B7=E8=B1=9A?= =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E5=AE=A4=E5=9F=9F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AutoHaiTun.js | 861 +++++++++++++++++++++++++------------------------- 1 file changed, 431 insertions(+), 430 deletions(-) diff --git a/AutoHaiTun.js b/AutoHaiTun.js index da2018d..4266571 100644 --- a/AutoHaiTun.js +++ b/AutoHaiTun.js @@ -1,431 +1,432 @@ -// ==UserScript== -// @name 海豚自动化工具 -// @namespace http://tampermonkey.net/ -// @version 1.3 -// @description 自动从代码块复制内容到编辑器,保存并重启笔记本 -// @author Kakune55 Carryc -// @match https://labs.wd.dolphin-labs.com/data-analysis/* -// @grant none -// @run-at document-idle -// ==/UserScript== - -(function() { - 'use strict'; - - // 通知管理器 - 管理多个通知的位置 - const NotificationManager = { - notifications: [], - baseTop: 45, // 初始顶部位置 - gap: 10, // 通知间距 - add: function(element) { - let topPosition = this.baseTop; - this.notifications.forEach(notification => { - if (notification.isConnected) { - const height = notification.offsetHeight; - topPosition += height + this.gap; - } - }); - this.notifications = this.notifications.filter(n => n.isConnected); - element.style.top = topPosition + 'px'; - this.notifications.push(element); - return element; - }, - remove: function(element) { - const index = this.notifications.indexOf(element); - if (index > -1) { - this.notifications.splice(index, 1); - } - this.updatePositions(); - }, - updatePositions: function() { - let topPosition = this.baseTop; - this.notifications.forEach(notification => { - if (notification.isConnected) { - notification.style.top = topPosition + 'px'; - topPosition += notification.offsetHeight + this.gap; - } - }); - } - }; - - // 添加样式到页面 - function addStyles() { - const styleSheet = document.createElement('style'); - styleSheet.textContent = ` - @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } - @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } - @keyframes fadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } - @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } } - @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } - @keyframes ripple { to { transform: scale(3); opacity: 0; } } - #dolphin-auto-btn { animation: slideInRight 0.5s ease-out; } - .dolphin-notification { animation: fadeIn 0.3s ease-out; display: flex; align-items: center; border-left: 4px solid; } - .dolphin-notification.hiding { animation: fadeOut 0.5s ease-in forwards; } - .notification-icon { margin-right: 12px; font-size: 20px; } - .loader { display: inline-block; width: 15px; height: 15px; border: 2px solid rgba(255,255,255,0.3); border-radius: 50%; border-top-color: #fff; animation: spin 0.8s linear infinite; margin-right: 8px; } - `; - document.head.appendChild(styleSheet); - } - - // 等待保存成功消息 - function waitForMessage(callback) { - const messageDiv = document.querySelector('.ivu-message'); - if (messageDiv && messageDiv.textContent.includes('保存成功')) { - console.log('保存成功'); - callback(); - } else { - setTimeout(() => waitForMessage(callback), 100); - } - } - - // 等待模态框并点击确认 - function waitForRestartModal() { - console.log('等待重启确认模态框...'); - const checkModal = setInterval(() => { - const modals = [...document.querySelectorAll('.ivu-modal')]; - const targetModal = modals.find(modal => - modal.textContent.includes('重新启动内核并重新运行整个笔记本') - ); - - if (targetModal) { - const confirmButton = targetModal.querySelector('.ivu-btn-primary'); - if (confirmButton) { - confirmButton.click(); - console.log('已点击"确定"按钮'); - clearInterval(checkModal); - // 执行完成后通知用户 - setTimeout(() => { - showNotification('自动化执行完成:代码已复制、保存并重启!若无警告,等待所有代码块执行完成后自行保存退出!', 'success', 6000); - }, 1000); - } - } - }, 200); - } - - // 查找所有目标代码块(包括“代码示例”和练习答案) - function findAllCodeBlocks() { - const textCellWraps = Array.from(document.querySelectorAll('.text-cell-wrap')); - - const allCodeBlocks = []; - function findCodeBlock(container) { - if (!container) return null; - const codeBlock = container.querySelector('pre code'); - return codeBlock || findCodeBlock(container.nextElementSibling); - } - - textCellWraps.forEach((cellWrap, index) => { - console.log(`处理容器 ${index + 1}:`, cellWrap); - - // 优先查找“代码示例”代码块 - const exampleMarker = cellWrap.querySelector('.alert.alert-success.alertsuccess'); - if (exampleMarker && exampleMarker.textContent.includes('代码示例')) { - const codeBlock = findCodeBlock(cellWrap); - if (codeBlock) { - allCodeBlocks.push(codeBlock); - console.log(`找到“代码示例”代码块内容:`, codeBlock.textContent.trim()); - } else { - console.warn(`未找到“代码示例”代码块!`); - } - } - - // 然后查找练习答案代码块 - const collapseDiv = cellWrap.querySelector('.collapse'); - if (collapseDiv) { - const codeBlocks = collapseDiv.querySelectorAll('pre code'); - if (codeBlocks.length > 0) { - codeBlocks.forEach((codeBlock) => { - allCodeBlocks.push(codeBlock); - console.log(`找到练习答案代码块内容:`, codeBlock.textContent.trim()); - }); - } else { - console.warn(`容器 ${index + 1} 中未找到练习答案代码块!`); - } - } - }); - - return allCodeBlocks; - } - - // 主函数:自动化流程 - function runAutomation() { - const button = document.getElementById('dolphin-auto-btn'); - setButtonState(button, 'running'); // 修改按钮状态为“执行中” - - try { - // 1. 查找所有目标代码块 - const allCodeBlocks = findAllCodeBlocks(); - console.log(`共找到 ${allCodeBlocks.length} 个有效代码块:`); - allCodeBlocks.forEach((codeBlock, index) => { - console.log(`代码块 ${index + 1}:`, codeBlock.textContent.trim()); - }); - - // 2. 获取所有 CodeMirror 编辑器实例 - const codeMirrors = Array.from(document.querySelectorAll('.CodeMirror')) - .map(cmElement => cmElement.CodeMirror) - .filter(cmInstance => !!cmInstance); - - console.log(`找到 ${codeMirrors.length} 个 CodeMirror 实例:`); - - if (allCodeBlocks.length === 0 || codeMirrors.length === 0) { - throw new Error("未找到足够的代码块或编辑器!"); - } - - // 3. 将代码块内容填充到 CodeMirror 编辑器 - showNotification(`正在填充 ${Math.min(allCodeBlocks.length, codeMirrors.length)} 个代码块...`, 'info'); - const minCount = Math.min(allCodeBlocks.length, codeMirrors.length); - for (let i = 0; i < minCount; i++) { - const codeText = allCodeBlocks[i].textContent.trim(); - const cmInstance = codeMirrors[i]; - if (cmInstance) { - cmInstance.setValue(codeText); // 使用 CodeMirror API 填充内容 - console.log(`已填充代码块 ${i + 1} 到 CodeMirror ${i + 1}`); - } else { - try { - const textarea = codeMirrors[i].querySelector('textarea'); - if (textarea) { - textarea.value = codeText; // 使用替代方法填充内容 - console.log(`使用替代方法填充代码块 ${i + 1}`); - } - } catch (e) { - console.error(`无法填充代码块 ${i + 1}:`, e); - } - } - } - - // 4. 检查多余的 CodeMirror 实例并通知用户 - if (codeMirrors.length > allCodeBlocks.length) { - const extraCount = codeMirrors.length - allCodeBlocks.length; - console.warn(`多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例`); - showNotification( - `多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例,请检查最后是否有练习,手动填充`, - 'warning', - 10000 // 通知停留时间设置为 10 秒 - ); - } - - // 5. 点击保存按钮 - console.log('准备点击保存按钮...'); - showNotification('正在保存笔记本...', 'info'); - const saveButton = findSaveButton(); - if (!saveButton) { - throw new Error("未找到保存按钮!"); - } - saveButton.click(); - console.log('已点击保存按钮'); - - // 6. 等待保存成功后重启 - waitForMessage(() => { - console.log('准备点击重启按钮...'); - showNotification('正在重启笔记本...', 'info'); - const restartButton = findRestartButton(); - if (!restartButton) { - throw new Error("未找到重启按钮!"); - } - restartButton.click(); - console.log('找到重启按钮,点击中...'); - waitForRestartModal(); // 等待模态框确认 - setButtonState(button, 'completed'); // 修改按钮状态为“已完成” - }); - - } catch (error) { - console.error(error.message); - showNotification(`自动化执行失败:${error.message}`, 'error'); // 显示错误通知 - setButtonState(button, 'failed'); // 修改按钮状态为“失败” - } - } - - // 辅助函数:查找保存按钮 - function findSaveButton() { - return document.querySelector('.btn-wrap .btn-name') || - document.querySelector('[title="保存"]') || - [...document.querySelectorAll('button')].find(btn => btn.textContent.includes('保存')); - } - - // 辅助函数:查找重启按钮 - function findRestartButton() { - const menuItems = [...document.querySelectorAll('.ivu-dropdown-item, [role="menuitem"], .menu-item')]; - const possibleTexts = ['重启 & 运行所有', '重启并运行所有', '重启&运行所有', '重启和运行所有']; - return menuItems.find(item => { - const text = item.textContent.trim(); - return possibleTexts.some(pt => text.includes(pt)); - }); - } - - // 设置按钮状态 - function setButtonState(button, state) { - if (!button) return; - const states = { - idle: { text: '运行自动化', backgroundColor: '#2196F3', disabled: false, html: '运行自动化' }, - running: { text: '执行中', backgroundColor: '#FFA000', disabled: true, html: '
执行中' }, - completed: { text: '已完成', backgroundColor: '#4CAF50', disabled: true, html: '✅ 已完成' }, - failed: { text: '执行失败', backgroundColor: '#F44336', disabled: false, html: '❌ 重试' } - }; - const newState = states[state]; - button.style.transition = 'all 0.3s ease'; - button.disabled = newState.disabled; - button.innerHTML = newState.html; - button.style.backgroundColor = newState.backgroundColor; - - if (state === 'completed') { - button.style.animation = 'pulse 0.5s ease-in-out'; - setTimeout(() => setButtonState(button, 'idle'), 3000); - } - } - - // 显示美化的通知 - function showNotification(message, type = 'info', duration = 3000) { - const notification = document.createElement('div'); - notification.className = 'dolphin-notification'; - let iconHTML = ''; - let borderColor = ''; - - if (type === 'success') { - iconHTML = '
'; - borderColor = '#4CAF50'; - } else if (type === 'error') { - iconHTML = '
'; - borderColor = '#F44336'; - } else if (type === 'warning') { - iconHTML = '
⚠️
'; - borderColor = '#FFA000'; - } else { - iconHTML = '
ℹ️
'; - borderColor = '#2196F3'; - } - - notification.innerHTML = iconHTML + `
${message}
`; - notification.style.cssText = ` - position: fixed; - right: 300px; - padding: 15px 20px; - background: white; - color: #333; - border-radius: 6px; - box-shadow: 0 4px 15px rgba(0,0,0,0.15); - z-index: 10000; - max-width: 350px; - font-size: 14px; - border-left-color: ${borderColor}; - display: flex; - align-items: center; - transition: top 0.3s ease; - `; - document.body.appendChild(notification); - NotificationManager.add(notification); - - let timeoutId; - notification.addEventListener('mouseenter', () => clearTimeout(timeoutId)); - notification.addEventListener('mouseleave', () => startHideTimeout()); - - function startHideTimeout() { - timeoutId = setTimeout(() => { - notification.classList.add('hiding'); - setTimeout(() => { - notification.remove(); - NotificationManager.remove(notification); - }, 500); - }, duration); // 使用传递的 duration 参数控制显示时间 - } - startHideTimeout(); - - notification.addEventListener('click', () => { - clearTimeout(timeoutId); - notification.classList.add('hiding'); - setTimeout(() => { - notification.remove(); - NotificationManager.remove(notification); - }, 500); - }); - return notification; - } - - // 创建悬浮按钮 - function createFloatingButton() { - const button = document.createElement('button'); - button.id = 'dolphin-auto-btn'; - button.innerHTML = '运行自动化'; - button.style.cssText = ` - position: fixed; - top: 0px; - right: 300px; - z-index: 10000; - padding: 12px 20px; - background-color: #2196F3; - color: white; - border: none; - border-radius: 6px; - cursor: pointer; - font-size: 14px; - box-shadow: 0 3px 10px rgba(33, 150, 243, 0.3); - transition: all 0.3s ease; - display: flex; - align-items: center; - justify-content: center; - min-width: 140px; - font-weight: 600; - `; - - // 鼠标悬停效果 - button.addEventListener('mouseover', () => { - button.style.transform = 'translateY(-2px)'; - button.style.boxShadow = '0 5px 15px rgba(33, 150, 243, 0.4)'; - button.style.backgroundColor = '#1976D2'; - }); - - button.addEventListener('mouseout', () => { - button.style.transform = ''; - button.style.boxShadow = '0 3px 10px rgba(33, 150, 243, 0.3)'; - if (!button.disabled) { - button.style.backgroundColor = '#2196F3'; - } - }); - - // 点击波纹效果 - button.addEventListener('mousedown', (e) => { - const ripple = document.createElement('span'); - const rect = button.getBoundingClientRect(); - const size = Math.max(rect.width, rect.height); - const x = e.clientX - rect.left - size / 2; - const y = e.clientY - rect.top - size / 2; - ripple.style.cssText = ` - position: absolute; - top: ${y}px; - left: ${x}px; - width: ${size}px; - height: ${size}px; - background-color: rgba(255, 255, 255, 0.7); - border-radius: 50%; - transform: scale(0); - animation: ripple 0.6s linear; - pointer-events: none; - `; - button.appendChild(ripple); - setTimeout(() => { - ripple.remove(); - }, 600); - }); - - // 点击事件 - button.addEventListener('click', () => { - if (!button.disabled) { - runAutomation(); - } - }); - - document.body.appendChild(button); - return button; - } - - // 初始化函数 - function init() { - addStyles(); - const button = createFloatingButton(); - // 显示欢迎通知 - setTimeout(() => { - showNotification('海豚自动化工具 v1.3 已加载,点击按钮开始自动化操作', 'info', 5000); // 通知显示 5 秒 - }, 1000); - } - - // 页面加载后初始化 - setTimeout(init, 1000); +// ==UserScript== +// @name 海豚自动化工具 +// @namespace http://tampermonkey.net/ +// @version 1.3 +// @description 自动从代码块复制内容到编辑器,保存并重启笔记本 +// @author Kakune55 Carryc +// @match https://labs.wd.dolphin-labs.com/data-analysis/* +// @match https://labs.wd.dilabs.cn/data-analysis/* +// @grant none +// @run-at document-idle +// ==/UserScript== + +(function() { + 'use strict'; + + // 通知管理器 - 管理多个通知的位置 + const NotificationManager = { + notifications: [], + baseTop: 45, // 初始顶部位置 + gap: 10, // 通知间距 + add: function(element) { + let topPosition = this.baseTop; + this.notifications.forEach(notification => { + if (notification.isConnected) { + const height = notification.offsetHeight; + topPosition += height + this.gap; + } + }); + this.notifications = this.notifications.filter(n => n.isConnected); + element.style.top = topPosition + 'px'; + this.notifications.push(element); + return element; + }, + remove: function(element) { + const index = this.notifications.indexOf(element); + if (index > -1) { + this.notifications.splice(index, 1); + } + this.updatePositions(); + }, + updatePositions: function() { + let topPosition = this.baseTop; + this.notifications.forEach(notification => { + if (notification.isConnected) { + notification.style.top = topPosition + 'px'; + topPosition += notification.offsetHeight + this.gap; + } + }); + } + }; + + // 添加样式到页面 + function addStyles() { + const styleSheet = document.createElement('style'); + styleSheet.textContent = ` + @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } + @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } + @keyframes fadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } + @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } } + @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } + @keyframes ripple { to { transform: scale(3); opacity: 0; } } + #dolphin-auto-btn { animation: slideInRight 0.5s ease-out; } + .dolphin-notification { animation: fadeIn 0.3s ease-out; display: flex; align-items: center; border-left: 4px solid; } + .dolphin-notification.hiding { animation: fadeOut 0.5s ease-in forwards; } + .notification-icon { margin-right: 12px; font-size: 20px; } + .loader { display: inline-block; width: 15px; height: 15px; border: 2px solid rgba(255,255,255,0.3); border-radius: 50%; border-top-color: #fff; animation: spin 0.8s linear infinite; margin-right: 8px; } + `; + document.head.appendChild(styleSheet); + } + + // 等待保存成功消息 + function waitForMessage(callback) { + const messageDiv = document.querySelector('.ivu-message'); + if (messageDiv && messageDiv.textContent.includes('保存成功')) { + console.log('保存成功'); + callback(); + } else { + setTimeout(() => waitForMessage(callback), 100); + } + } + + // 等待模态框并点击确认 + function waitForRestartModal() { + console.log('等待重启确认模态框...'); + const checkModal = setInterval(() => { + const modals = [...document.querySelectorAll('.ivu-modal')]; + const targetModal = modals.find(modal => + modal.textContent.includes('重新启动内核并重新运行整个笔记本') + ); + + if (targetModal) { + const confirmButton = targetModal.querySelector('.ivu-btn-primary'); + if (confirmButton) { + confirmButton.click(); + console.log('已点击"确定"按钮'); + clearInterval(checkModal); + // 执行完成后通知用户 + setTimeout(() => { + showNotification('自动化执行完成:代码已复制、保存并重启!若无警告,等待所有代码块执行完成后自行保存退出!', 'success', 6000); + }, 1000); + } + } + }, 200); + } + + // 查找所有目标代码块(包括“代码示例”和练习答案) + function findAllCodeBlocks() { + const textCellWraps = Array.from(document.querySelectorAll('.text-cell-wrap')); + + const allCodeBlocks = []; + function findCodeBlock(container) { + if (!container) return null; + const codeBlock = container.querySelector('pre code'); + return codeBlock || findCodeBlock(container.nextElementSibling); + } + + textCellWraps.forEach((cellWrap, index) => { + console.log(`处理容器 ${index + 1}:`, cellWrap); + + // 优先查找“代码示例”代码块 + const exampleMarker = cellWrap.querySelector('.alert.alert-success.alertsuccess'); + if (exampleMarker && exampleMarker.textContent.includes('代码示例')) { + const codeBlock = findCodeBlock(cellWrap); + if (codeBlock) { + allCodeBlocks.push(codeBlock); + console.log(`找到“代码示例”代码块内容:`, codeBlock.textContent.trim()); + } else { + console.warn(`未找到“代码示例”代码块!`); + } + } + + // 然后查找练习答案代码块 + const collapseDiv = cellWrap.querySelector('.collapse'); + if (collapseDiv) { + const codeBlocks = collapseDiv.querySelectorAll('pre code'); + if (codeBlocks.length > 0) { + codeBlocks.forEach((codeBlock) => { + allCodeBlocks.push(codeBlock); + console.log(`找到练习答案代码块内容:`, codeBlock.textContent.trim()); + }); + } else { + console.warn(`容器 ${index + 1} 中未找到练习答案代码块!`); + } + } + }); + + return allCodeBlocks; + } + + // 主函数:自动化流程 + function runAutomation() { + const button = document.getElementById('dolphin-auto-btn'); + setButtonState(button, 'running'); // 修改按钮状态为“执行中” + + try { + // 1. 查找所有目标代码块 + const allCodeBlocks = findAllCodeBlocks(); + console.log(`共找到 ${allCodeBlocks.length} 个有效代码块:`); + allCodeBlocks.forEach((codeBlock, index) => { + console.log(`代码块 ${index + 1}:`, codeBlock.textContent.trim()); + }); + + // 2. 获取所有 CodeMirror 编辑器实例 + const codeMirrors = Array.from(document.querySelectorAll('.CodeMirror')) + .map(cmElement => cmElement.CodeMirror) + .filter(cmInstance => !!cmInstance); + + console.log(`找到 ${codeMirrors.length} 个 CodeMirror 实例:`); + + if (allCodeBlocks.length === 0 || codeMirrors.length === 0) { + throw new Error("未找到足够的代码块或编辑器!"); + } + + // 3. 将代码块内容填充到 CodeMirror 编辑器 + showNotification(`正在填充 ${Math.min(allCodeBlocks.length, codeMirrors.length)} 个代码块...`, 'info'); + const minCount = Math.min(allCodeBlocks.length, codeMirrors.length); + for (let i = 0; i < minCount; i++) { + const codeText = allCodeBlocks[i].textContent.trim(); + const cmInstance = codeMirrors[i]; + if (cmInstance) { + cmInstance.setValue(codeText); // 使用 CodeMirror API 填充内容 + console.log(`已填充代码块 ${i + 1} 到 CodeMirror ${i + 1}`); + } else { + try { + const textarea = codeMirrors[i].querySelector('textarea'); + if (textarea) { + textarea.value = codeText; // 使用替代方法填充内容 + console.log(`使用替代方法填充代码块 ${i + 1}`); + } + } catch (e) { + console.error(`无法填充代码块 ${i + 1}:`, e); + } + } + } + + // 4. 检查多余的 CodeMirror 实例并通知用户 + if (codeMirrors.length > allCodeBlocks.length) { + const extraCount = codeMirrors.length - allCodeBlocks.length; + console.warn(`多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例`); + showNotification( + `多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例,请检查最后是否有练习,手动填充`, + 'warning', + 10000 // 通知停留时间设置为 10 秒 + ); + } + + // 5. 点击保存按钮 + console.log('准备点击保存按钮...'); + showNotification('正在保存笔记本...', 'info'); + const saveButton = findSaveButton(); + if (!saveButton) { + throw new Error("未找到保存按钮!"); + } + saveButton.click(); + console.log('已点击保存按钮'); + + // 6. 等待保存成功后重启 + waitForMessage(() => { + console.log('准备点击重启按钮...'); + showNotification('正在重启笔记本...', 'info'); + const restartButton = findRestartButton(); + if (!restartButton) { + throw new Error("未找到重启按钮!"); + } + restartButton.click(); + console.log('找到重启按钮,点击中...'); + waitForRestartModal(); // 等待模态框确认 + setButtonState(button, 'completed'); // 修改按钮状态为“已完成” + }); + + } catch (error) { + console.error(error.message); + showNotification(`自动化执行失败:${error.message}`, 'error'); // 显示错误通知 + setButtonState(button, 'failed'); // 修改按钮状态为“失败” + } + } + + // 辅助函数:查找保存按钮 + function findSaveButton() { + return document.querySelector('.btn-wrap .btn-name') || + document.querySelector('[title="保存"]') || + [...document.querySelectorAll('button')].find(btn => btn.textContent.includes('保存')); + } + + // 辅助函数:查找重启按钮 + function findRestartButton() { + const menuItems = [...document.querySelectorAll('.ivu-dropdown-item, [role="menuitem"], .menu-item')]; + const possibleTexts = ['重启 & 运行所有', '重启并运行所有', '重启&运行所有', '重启和运行所有']; + return menuItems.find(item => { + const text = item.textContent.trim(); + return possibleTexts.some(pt => text.includes(pt)); + }); + } + + // 设置按钮状态 + function setButtonState(button, state) { + if (!button) return; + const states = { + idle: { text: '运行自动化', backgroundColor: '#2196F3', disabled: false, html: '运行自动化' }, + running: { text: '执行中', backgroundColor: '#FFA000', disabled: true, html: '
执行中' }, + completed: { text: '已完成', backgroundColor: '#4CAF50', disabled: true, html: '✅ 已完成' }, + failed: { text: '执行失败', backgroundColor: '#F44336', disabled: false, html: '❌ 重试' } + }; + const newState = states[state]; + button.style.transition = 'all 0.3s ease'; + button.disabled = newState.disabled; + button.innerHTML = newState.html; + button.style.backgroundColor = newState.backgroundColor; + + if (state === 'completed') { + button.style.animation = 'pulse 0.5s ease-in-out'; + setTimeout(() => setButtonState(button, 'idle'), 3000); + } + } + + // 显示美化的通知 + function showNotification(message, type = 'info', duration = 3000) { + const notification = document.createElement('div'); + notification.className = 'dolphin-notification'; + let iconHTML = ''; + let borderColor = ''; + + if (type === 'success') { + iconHTML = '
'; + borderColor = '#4CAF50'; + } else if (type === 'error') { + iconHTML = '
'; + borderColor = '#F44336'; + } else if (type === 'warning') { + iconHTML = '
⚠️
'; + borderColor = '#FFA000'; + } else { + iconHTML = '
ℹ️
'; + borderColor = '#2196F3'; + } + + notification.innerHTML = iconHTML + `
${message}
`; + notification.style.cssText = ` + position: fixed; + right: 300px; + padding: 15px 20px; + background: white; + color: #333; + border-radius: 6px; + box-shadow: 0 4px 15px rgba(0,0,0,0.15); + z-index: 10000; + max-width: 350px; + font-size: 14px; + border-left-color: ${borderColor}; + display: flex; + align-items: center; + transition: top 0.3s ease; + `; + document.body.appendChild(notification); + NotificationManager.add(notification); + + let timeoutId; + notification.addEventListener('mouseenter', () => clearTimeout(timeoutId)); + notification.addEventListener('mouseleave', () => startHideTimeout()); + + function startHideTimeout() { + timeoutId = setTimeout(() => { + notification.classList.add('hiding'); + setTimeout(() => { + notification.remove(); + NotificationManager.remove(notification); + }, 500); + }, duration); // 使用传递的 duration 参数控制显示时间 + } + startHideTimeout(); + + notification.addEventListener('click', () => { + clearTimeout(timeoutId); + notification.classList.add('hiding'); + setTimeout(() => { + notification.remove(); + NotificationManager.remove(notification); + }, 500); + }); + return notification; + } + + // 创建悬浮按钮 + function createFloatingButton() { + const button = document.createElement('button'); + button.id = 'dolphin-auto-btn'; + button.innerHTML = '运行自动化'; + button.style.cssText = ` + position: fixed; + top: 0px; + right: 300px; + z-index: 10000; + padding: 12px 20px; + background-color: #2196F3; + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 14px; + box-shadow: 0 3px 10px rgba(33, 150, 243, 0.3); + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + min-width: 140px; + font-weight: 600; + `; + + // 鼠标悬停效果 + button.addEventListener('mouseover', () => { + button.style.transform = 'translateY(-2px)'; + button.style.boxShadow = '0 5px 15px rgba(33, 150, 243, 0.4)'; + button.style.backgroundColor = '#1976D2'; + }); + + button.addEventListener('mouseout', () => { + button.style.transform = ''; + button.style.boxShadow = '0 3px 10px rgba(33, 150, 243, 0.3)'; + if (!button.disabled) { + button.style.backgroundColor = '#2196F3'; + } + }); + + // 点击波纹效果 + button.addEventListener('mousedown', (e) => { + const ripple = document.createElement('span'); + const rect = button.getBoundingClientRect(); + const size = Math.max(rect.width, rect.height); + const x = e.clientX - rect.left - size / 2; + const y = e.clientY - rect.top - size / 2; + ripple.style.cssText = ` + position: absolute; + top: ${y}px; + left: ${x}px; + width: ${size}px; + height: ${size}px; + background-color: rgba(255, 255, 255, 0.7); + border-radius: 50%; + transform: scale(0); + animation: ripple 0.6s linear; + pointer-events: none; + `; + button.appendChild(ripple); + setTimeout(() => { + ripple.remove(); + }, 600); + }); + + // 点击事件 + button.addEventListener('click', () => { + if (!button.disabled) { + runAutomation(); + } + }); + + document.body.appendChild(button); + return button; + } + + // 初始化函数 + function init() { + addStyles(); + const button = createFloatingButton(); + // 显示欢迎通知 + setTimeout(() => { + showNotification('海豚自动化工具 v1.3 已加载,点击按钮开始自动化操作', 'info', 5000); // 通知显示 5 秒 + }, 1000); + } + + // 页面加载后初始化 + setTimeout(init, 1000); })(); \ No newline at end of file