Compare commits

...

3 Commits
v1.0 ... main

Author SHA1 Message Date
78c67cd097 update:更新海豚实验室域名 2025-05-20 14:49:30 +08:00
a3032692b2 fix:修复了部分bug 2025-03-27 18:38:10 +08:00
40a27eaa09 fix:修复了部分bug 2025-03-27 16:18:37 +08:00

View File

@ -1,503 +1,432 @@
// ==UserScript== // ==UserScript==
// @name 海豚自动化工具 // @name 海豚自动化工具
// @namespace http://tampermonkey.net/ // @namespace http://tampermonkey.net/
// @version 1.2 // @version 1.3
// @description 自动从代码块复制内容到编辑器,保存并重启笔记本 // @description 自动从代码块复制内容到编辑器,保存并重启笔记本
// @author Kakune55 Carryc // @author Kakune55 Carryc
// @match https://labs.wd.dolphin-labs.com/data-analysis/* // @match https://labs.wd.dolphin-labs.com/data-analysis/*
// @grant none // @match https://labs.wd.dilabs.cn/data-analysis/*
// @run-at document-end // @grant none
// ==/UserScript== // @run-at document-idle
// ==/UserScript==
(function() {
'use strict'; (function() {
'use strict';
// 通知管理器 - 管理多个通知的位置
const NotificationManager = { // 通知管理器 - 管理多个通知的位置
notifications: [], const NotificationManager = {
baseTop: 70, // 初始顶部位置 notifications: [],
gap: 10, // 通知间距 baseTop: 45, // 初始顶部位置
gap: 10, // 通知间距
// 添加通知到管理器 add: function(element) {
add: function(element) { let topPosition = this.baseTop;
// 计算新通知的顶部位置 this.notifications.forEach(notification => {
let topPosition = this.baseTop; if (notification.isConnected) {
const height = notification.offsetHeight;
// 为已有的每个通知增加高度和间隔 topPosition += height + this.gap;
this.notifications.forEach(notification => { }
if (notification.isConnected) { // 确保通知仍在DOM中 });
const height = notification.offsetHeight; this.notifications = this.notifications.filter(n => n.isConnected);
topPosition += height + this.gap; element.style.top = topPosition + 'px';
} this.notifications.push(element);
}); return element;
},
// 过滤掉已移除的通知 remove: function(element) {
this.notifications = this.notifications.filter(n => n.isConnected); const index = this.notifications.indexOf(element);
if (index > -1) {
// 设置新通知位置 this.notifications.splice(index, 1);
element.style.top = topPosition + 'px'; }
this.updatePositions();
// 添加到管理器 },
this.notifications.push(element); updatePositions: function() {
let topPosition = this.baseTop;
return element; this.notifications.forEach(notification => {
}, if (notification.isConnected) {
notification.style.top = topPosition + 'px';
// 从管理器移除通知 topPosition += notification.offsetHeight + this.gap;
remove: function(element) { }
const index = this.notifications.indexOf(element); });
if (index > -1) { }
this.notifications.splice(index, 1); };
}
// 添加样式到页面
// 重新计算剩余通知的位置 function addStyles() {
this.updatePositions(); 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); } }
updatePositions: function() { @keyframes fadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
let topPosition = this.baseTop; @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } }
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
this.notifications.forEach(notification => { @keyframes ripple { to { transform: scale(3); opacity: 0; } }
if (notification.isConnected) { #dolphin-auto-btn { animation: slideInRight 0.5s ease-out; }
notification.style.top = topPosition + 'px'; .dolphin-notification { animation: fadeIn 0.3s ease-out; display: flex; align-items: center; border-left: 4px solid; }
topPosition += notification.offsetHeight + this.gap; .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 addStyles() { // 等待保存成功消息
const styleSheet = document.createElement('style'); function waitForMessage(callback) {
styleSheet.textContent = ` const messageDiv = document.querySelector('.ivu-message');
@keyframes slideInRight { if (messageDiv && messageDiv.textContent.includes('保存成功')) {
from { transform: translateX(100%); opacity: 0; } console.log('保存成功');
to { transform: translateX(0); opacity: 1; } callback();
} } else {
setTimeout(() => waitForMessage(callback), 100);
@keyframes pulse { }
0% { transform: scale(1); } }
50% { transform: scale(1.05); }
100% { transform: scale(1); } // 等待模态框并点击确认
} function waitForRestartModal() {
console.log('等待重启确认模态框...');
@keyframes fadeIn { const checkModal = setInterval(() => {
from { opacity: 0; transform: translateY(-20px); } const modals = [...document.querySelectorAll('.ivu-modal')];
to { opacity: 1; transform: translateY(0); } const targetModal = modals.find(modal =>
} modal.textContent.includes('重新启动内核并重新运行整个笔记本')
);
@keyframes fadeOut {
from { opacity: 1; transform: translateY(0); } if (targetModal) {
to { opacity: 0; transform: translateY(-20px); } const confirmButton = targetModal.querySelector('.ivu-btn-primary');
} if (confirmButton) {
confirmButton.click();
@keyframes spin { console.log('已点击"确定"按钮');
0% { transform: rotate(0deg); } clearInterval(checkModal);
100% { transform: rotate(360deg); } // 执行完成后通知用户
} setTimeout(() => {
showNotification('自动化执行完成:代码已复制、保存并重启!若无警告,等待所有代码块执行完成后自行保存退出!', 'success', 6000);
@keyframes ripple { }, 1000);
to { }
transform: scale(3); }
opacity: 0; }, 200);
} }
}
// 查找所有目标代码块(包括“代码示例”和练习答案)
#dolphin-auto-btn { function findAllCodeBlocks() {
animation: slideInRight 0.5s ease-out; const textCellWraps = Array.from(document.querySelectorAll('.text-cell-wrap'));
}
const allCodeBlocks = [];
.dolphin-notification { function findCodeBlock(container) {
animation: fadeIn 0.3s ease-out; if (!container) return null;
display: flex; const codeBlock = container.querySelector('pre code');
align-items: center; return codeBlock || findCodeBlock(container.nextElementSibling);
border-left: 4px solid; }
}
textCellWraps.forEach((cellWrap, index) => {
.dolphin-notification.hiding { console.log(`处理容器 ${index + 1}`, cellWrap);
animation: fadeOut 0.5s ease-in forwards;
} // 优先查找“代码示例”代码块
const exampleMarker = cellWrap.querySelector('.alert.alert-success.alertsuccess');
.notification-icon { if (exampleMarker && exampleMarker.textContent.includes('代码示例')) {
margin-right: 12px; const codeBlock = findCodeBlock(cellWrap);
font-size: 20px; if (codeBlock) {
} allCodeBlocks.push(codeBlock);
console.log(`找到“代码示例”代码块内容:`, codeBlock.textContent.trim());
.loader { } else {
display: inline-block; console.warn(`未找到“代码示例”代码块!`);
width: 15px; }
height: 15px; }
border: 2px solid rgba(255,255,255,0.3);
border-radius: 50%; // 然后查找练习答案代码块
border-top-color: #fff; const collapseDiv = cellWrap.querySelector('.collapse');
animation: spin 0.8s linear infinite; if (collapseDiv) {
margin-right: 8px; const codeBlocks = collapseDiv.querySelectorAll('pre code');
} if (codeBlocks.length > 0) {
`; codeBlocks.forEach((codeBlock) => {
document.head.appendChild(styleSheet); allCodeBlocks.push(codeBlock);
} console.log(`找到练习答案代码块内容:`, codeBlock.textContent.trim());
});
// 等待保存成功消息 } else {
function waitForMessage(callback) { console.warn(`容器 ${index + 1} 中未找到练习答案代码块!`);
const messageDiv = document.querySelector('.ivu-message'); }
if (messageDiv && messageDiv.textContent.includes('保存成功')) { }
console.log('保存成功'); });
callback();
} else { return allCodeBlocks;
setTimeout(() => waitForMessage(callback), 100); }
}
} // 主函数:自动化流程
function runAutomation() {
// 等待模态框并点击确认 const button = document.getElementById('dolphin-auto-btn');
function waitForRestartModal() { setButtonState(button, 'running'); // 修改按钮状态为“执行中”
console.log('等待重启确认模态框...');
const checkModal = setInterval(() => { try {
const modals = [...document.querySelectorAll('.ivu-modal')]; // 1. 查找所有目标代码块
const targetModal = modals.find(modal => const allCodeBlocks = findAllCodeBlocks();
modal.textContent.includes('重新启动内核并重新运行整个笔记本')); console.log(`共找到 ${allCodeBlocks.length} 个有效代码块:`);
allCodeBlocks.forEach((codeBlock, index) => {
if (targetModal) { console.log(`代码块 ${index + 1}:`, codeBlock.textContent.trim());
const confirmButton = targetModal.querySelector('.ivu-btn-primary'); });
if (confirmButton) {
confirmButton.click(); // 2. 获取所有 CodeMirror 编辑器实例
console.log('已点击"确定"按钮'); const codeMirrors = Array.from(document.querySelectorAll('.CodeMirror'))
clearInterval(checkModal); .map(cmElement => cmElement.CodeMirror)
.filter(cmInstance => !!cmInstance);
// 执行完成后通知用户
setTimeout(() => { console.log(`找到 ${codeMirrors.length} 个 CodeMirror 实例:`);
showNotification('自动化执行完成:代码已复制、保存并重启', 'success');
}, 1000); if (allCodeBlocks.length === 0 || codeMirrors.length === 0) {
} throw new Error("未找到足够的代码块或编辑器!");
} }
}, 200);
} // 3. 将代码块内容填充到 CodeMirror 编辑器
showNotification(`正在填充 ${Math.min(allCodeBlocks.length, codeMirrors.length)} 个代码块...`, 'info');
// 提取代码文本 const minCount = Math.min(allCodeBlocks.length, codeMirrors.length);
function extractCodeText(codeBlock) { for (let i = 0; i < minCount; i++) {
return codeBlock.innerText || const codeText = allCodeBlocks[i].textContent.trim();
[...codeBlock.querySelectorAll('span')].reduce((text, span) => const cmInstance = codeMirrors[i];
text + span.textContent, ''); if (cmInstance) {
} cmInstance.setValue(codeText); // 使用 CodeMirror API 填充内容
console.log(`已填充代码块 ${i + 1} 到 CodeMirror ${i + 1}`);
// 显示美化的通知 } else {
function showNotification(message, type = 'info') { try {
const notification = document.createElement('div'); const textarea = codeMirrors[i].querySelector('textarea');
notification.className = 'dolphin-notification'; if (textarea) {
textarea.value = codeText; // 使用替代方法填充内容
let iconHTML = ''; console.log(`使用替代方法填充代码块 ${i + 1}`);
let borderColor = ''; }
} catch (e) {
// 根据类型设置不同的图标和颜色 console.error(`无法填充代码块 ${i + 1}:`, e);
if (type === 'success') { }
iconHTML = '<div class="notification-icon">✅</div>'; }
borderColor = '#4CAF50'; }
} else if (type === 'error') {
iconHTML = '<div class="notification-icon">❌</div>'; // 4. 检查多余的 CodeMirror 实例并通知用户
borderColor = '#F44336'; if (codeMirrors.length > allCodeBlocks.length) {
} else { const extraCount = codeMirrors.length - allCodeBlocks.length;
iconHTML = '<div class="notification-icon"></div>'; console.warn(`多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例`);
borderColor = '#2196F3'; showNotification(
} `多余的 CodeMirror 实例未被填充: 多出 ${extraCount} 个实例,请检查最后是否有练习,手动填充`,
'warning',
notification.innerHTML = iconHTML + `<div>${message}</div>`; 10000 // 通知停留时间设置为 10 秒
notification.style.cssText = ` );
position: fixed; }
right: 300px;
padding: 15px 20px; // 5. 点击保存按钮
background: white; console.log('准备点击保存按钮...');
color: #333; showNotification('正在保存笔记本...', 'info');
border-radius: 6px; const saveButton = findSaveButton();
box-shadow: 0 4px 15px rgba(0,0,0,0.15); if (!saveButton) {
z-index: 10000; throw new Error("未找到保存按钮!");
max-width: 350px; }
font-size: 14px; saveButton.click();
border-left-color: ${borderColor}; console.log('已点击保存按钮');
display: flex;
align-items: center; // 6. 等待保存成功后重启
transition: top 0.3s ease; waitForMessage(() => {
`; console.log('准备点击重启按钮...');
showNotification('正在重启笔记本...', 'info');
document.body.appendChild(notification); const restartButton = findRestartButton();
if (!restartButton) {
// 通过通知管理器添加并定位通知 throw new Error("未找到重启按钮!");
NotificationManager.add(notification); }
restartButton.click();
// 鼠标悬停时停止自动隐藏 console.log('找到重启按钮,点击中...');
let timeoutId; waitForRestartModal(); // 等待模态框确认
setButtonState(button, 'completed'); // 修改按钮状态为“已完成”
notification.addEventListener('mouseenter', () => { });
clearTimeout(timeoutId);
}); } catch (error) {
console.error(error.message);
notification.addEventListener('mouseleave', () => { showNotification(`自动化执行失败:${error.message}`, 'error'); // 显示错误通知
startHideTimeout(); setButtonState(button, 'failed'); // 修改按钮状态为“失败”
}); }
}
function startHideTimeout() {
timeoutId = setTimeout(() => { // 辅助函数:查找保存按钮
notification.classList.add('hiding'); function findSaveButton() {
setTimeout(() => { return document.querySelector('.btn-wrap .btn-name') ||
notification.remove(); document.querySelector('[title="保存"]') ||
// 从管理器中移除并重新排列其他通知 [...document.querySelectorAll('button')].find(btn => btn.textContent.includes('保存'));
NotificationManager.remove(notification); }
}, 500);
}, 3000); // 辅助函数:查找重启按钮
} function findRestartButton() {
const menuItems = [...document.querySelectorAll('.ivu-dropdown-item, [role="menuitem"], .menu-item')];
// 开始隐藏倒计时 const possibleTexts = ['重启 & 运行所有', '重启并运行所有', '重启&运行所有', '重启和运行所有'];
startHideTimeout(); return menuItems.find(item => {
const text = item.textContent.trim();
// 添加点击关闭功能 return possibleTexts.some(pt => text.includes(pt));
notification.addEventListener('click', () => { });
clearTimeout(timeoutId); }
notification.classList.add('hiding');
setTimeout(() => { // 设置按钮状态
notification.remove(); function setButtonState(button, state) {
NotificationManager.remove(notification); if (!button) return;
}, 500); const states = {
}); idle: { text: '运行自动化', backgroundColor: '#2196F3', disabled: false, html: '运行自动化' },
running: { text: '执行中', backgroundColor: '#FFA000', disabled: true, html: '<div class="loader"></div> 执行中' },
return notification; completed: { text: '已完成', backgroundColor: '#4CAF50', disabled: true, html: '✅ 已完成' },
} failed: { text: '执行失败', backgroundColor: '#F44336', disabled: false, html: '❌ 重试' }
};
// 设置按钮状态 const newState = states[state];
function setButtonState(button, state) { button.style.transition = 'all 0.3s ease';
if (!button) return; button.disabled = newState.disabled;
button.innerHTML = newState.html;
// 定义不同状态的样式 button.style.backgroundColor = newState.backgroundColor;
const states = {
idle: { if (state === 'completed') {
text: '运行自动化', button.style.animation = 'pulse 0.5s ease-in-out';
backgroundColor: '#2196F3', setTimeout(() => setButtonState(button, 'idle'), 3000);
disabled: false, }
html: '运行自动化' }
},
running: { // 显示美化的通知
text: '执行中', function showNotification(message, type = 'info', duration = 3000) {
backgroundColor: '#FFA000', const notification = document.createElement('div');
disabled: true, notification.className = 'dolphin-notification';
html: '<div class="loader"></div> 执行中' let iconHTML = '';
}, let borderColor = '';
completed: {
text: '已完成', if (type === 'success') {
backgroundColor: '#4CAF50', iconHTML = '<div class="notification-icon">✅</div>';
disabled: true, borderColor = '#4CAF50';
html: '✅ 已完成' } else if (type === 'error') {
}, iconHTML = '<div class="notification-icon">❌</div>';
failed: { borderColor = '#F44336';
text: '执行失败', } else if (type === 'warning') {
backgroundColor: '#F44336', iconHTML = '<div class="notification-icon">⚠️</div>';
disabled: false, borderColor = '#FFA000';
html: '❌ 重试' } else {
} iconHTML = '<div class="notification-icon"></div>';
}; borderColor = '#2196F3';
}
const newState = states[state];
notification.innerHTML = iconHTML + `<div>${message}</div>`;
// 应用过渡效果 notification.style.cssText = `
button.style.transition = 'all 0.3s ease'; position: fixed;
button.disabled = newState.disabled; right: 300px;
button.innerHTML = newState.html; padding: 15px 20px;
button.style.backgroundColor = newState.backgroundColor; background: white;
color: #333;
// 如果是完成状态,添加脉冲动画 border-radius: 6px;
if (state === 'completed') { box-shadow: 0 4px 15px rgba(0,0,0,0.15);
button.style.animation = 'pulse 0.5s ease-in-out'; z-index: 10000;
// 3秒后恢复到初始状态 max-width: 350px;
setTimeout(() => setButtonState(button, 'idle'), 3000); font-size: 14px;
} border-left-color: ${borderColor};
} display: flex;
align-items: center;
// 主函数 transition: top 0.3s ease;
function runAutomation() { `;
// 修改按钮状态 document.body.appendChild(notification);
const button = document.getElementById('dolphin-auto-btn'); NotificationManager.add(notification);
setButtonState(button, 'running');
let timeoutId;
// 1. 查找代码块 notification.addEventListener('mouseenter', () => clearTimeout(timeoutId));
let codeBlocks = document.querySelectorAll('pre > code.cm-s-ipython[class*="language-"]') || notification.addEventListener('mouseleave', () => startHideTimeout());
document.querySelectorAll('pre > code[class*="language-"]') ||
document.querySelectorAll('pre > code'); function startHideTimeout() {
timeoutId = setTimeout(() => {
console.log(`找到 ${codeBlocks.length} 个代码块`); notification.classList.add('hiding');
setTimeout(() => {
// 2. 查找编辑器 notification.remove();
const codeMirrors = document.querySelectorAll('.CodeMirror'); NotificationManager.remove(notification);
console.log(`找到 ${codeMirrors.length} 个编辑器`); }, 500);
}, duration); // 使用传递的 duration 参数控制显示时间
if (codeBlocks.length > 0 && codeMirrors.length > 0) { }
showNotification(`正在填充 ${Math.min(codeBlocks.length, codeMirrors.length)} 个代码块...`, 'info'); startHideTimeout();
// 3. 将代码块内容复制到编辑器 notification.addEventListener('click', () => {
codeBlocks.forEach((codeBlock, index) => { clearTimeout(timeoutId);
if (index < codeMirrors.length) { notification.classList.add('hiding');
const codeText = extractCodeText(codeBlock); setTimeout(() => {
const cm = codeMirrors[index].CodeMirror; notification.remove();
NotificationManager.remove(notification);
if (cm) { }, 500);
cm.setValue(codeText); });
console.log(`已填充代码块 ${index + 1}`); return notification;
} else { }
try {
const textarea = codeMirrors[index].querySelector('textarea'); // 创建悬浮按钮
if (textarea) { function createFloatingButton() {
textarea.value = codeText; const button = document.createElement('button');
console.log(`使用替代方法填充代码块 ${index + 1}`); button.id = 'dolphin-auto-btn';
} button.innerHTML = '运行自动化';
} catch (e) { button.style.cssText = `
console.error(`无法填充代码块 ${index + 1}:`, e); position: fixed;
} top: 0px;
} right: 300px;
} z-index: 10000;
}); padding: 12px 20px;
background-color: #2196F3;
// 4. 点击保存按钮 color: white;
console.log('准备点击保存按钮...'); border: none;
showNotification('正在保存笔记本...', 'info'); border-radius: 6px;
cursor: pointer;
const saveButton = document.querySelector('.btn-wrap .btn-name') || font-size: 14px;
document.querySelector('[title="保存"]') || box-shadow: 0 3px 10px rgba(33, 150, 243, 0.3);
[...document.querySelectorAll('button')].find(btn => transition: all 0.3s ease;
btn.textContent.includes('保存')); display: flex;
align-items: center;
if (saveButton) { justify-content: center;
saveButton.click(); min-width: 140px;
console.log('已点击保存按钮'); font-weight: 600;
`;
// 5. 等待保存成功后重启
waitForMessage(() => { // 鼠标悬停效果
console.log('准备点击重启按钮...'); button.addEventListener('mouseover', () => {
showNotification('正在重启笔记本...', 'info'); button.style.transform = 'translateY(-2px)';
button.style.boxShadow = '0 5px 15px rgba(33, 150, 243, 0.4)';
const menuItems = [...document.querySelectorAll('.ivu-dropdown-item, [role="menuitem"], .menu-item')]; button.style.backgroundColor = '#1976D2';
const possibleTexts = ['重启 & 运行所有', '重启并运行所有', '重启&运行所有', '重启和运行所有']; });
const restartButton = menuItems.find(item => { button.addEventListener('mouseout', () => {
const text = item.textContent.trim(); button.style.transform = '';
return possibleTexts.some(pt => text.includes(pt)); button.style.boxShadow = '0 3px 10px rgba(33, 150, 243, 0.3)';
}); if (!button.disabled) {
button.style.backgroundColor = '#2196F3';
if (restartButton) { }
console.log('找到重启按钮,点击中...'); });
restartButton.click();
waitForRestartModal(); // 点击波纹效果
setButtonState(button, 'completed'); button.addEventListener('mousedown', (e) => {
} else { const ripple = document.createElement('span');
console.error('未找到重启按钮!'); const rect = button.getBoundingClientRect();
console.log('可用菜单项:'); const size = Math.max(rect.width, rect.height);
menuItems.forEach((item, i) => console.log(`${i+1}. "${item.textContent.trim()}"`)); const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
// 执行遇到错误,通知用户 ripple.style.cssText = `
showNotification('自动化执行失败:未找到重启按钮!', 'error'); position: absolute;
setButtonState(button, 'failed'); top: ${y}px;
} left: ${x}px;
}); width: ${size}px;
} else { height: ${size}px;
console.error('未找到保存按钮!'); background-color: rgba(255, 255, 255, 0.7);
// 执行遇到错误,通知用户 border-radius: 50%;
showNotification('自动化执行失败:未找到保存按钮!', 'error'); transform: scale(0);
setButtonState(button, 'failed'); animation: ripple 0.6s linear;
} pointer-events: none;
} else { `;
console.error("未找到足够的代码块或编辑器!"); button.appendChild(ripple);
// 执行遇到错误,通知用户 setTimeout(() => {
showNotification('自动化执行失败:未找到足够的代码块或编辑器!', 'error'); ripple.remove();
setButtonState(button, 'failed'); }, 600);
} });
}
// 点击事件
// 创建悬浮按钮 button.addEventListener('click', () => {
function createFloatingButton() { if (!button.disabled) {
const button = document.createElement('button'); runAutomation();
button.id = 'dolphin-auto-btn'; }
button.innerHTML = '运行自动化'; });
button.style.cssText = `
position: fixed; document.body.appendChild(button);
top: 20px; return button;
right: 300px; /* 距离右侧300像素 */ }
z-index: 10000;
padding: 12px 20px; // 初始化函数
background-color: #2196F3; function init() {
color: white; addStyles();
border: none; const button = createFloatingButton();
border-radius: 6px; // 显示欢迎通知
cursor: pointer; setTimeout(() => {
font-size: 14px; showNotification('海豚自动化工具 v1.3 已加载,点击按钮开始自动化操作', 'info', 5000); // 通知显示 5 秒
box-shadow: 0 3px 10px rgba(33, 150, 243, 0.3); }, 1000);
transition: all 0.3s ease; }
display: flex;
align-items: center; // 页面加载后初始化
justify-content: center; setTimeout(init, 1000);
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('海豚自动化工具已加载,点击按钮开始自动化操作', 'info');
}, 1000);
}
// 页面加载后初始化
setTimeout(init, 1000);
})(); })();