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