// ==UserScript==
// @name T1Down - 百度网盘不限速 - 稳定加速⚡⚡⚡
// @namespace https://g.zuba.lat
// @version 1.0.0
// @description 加速百度网盘下载,无视黑号等问题,提高下载体验,使用高速下载链接,服务稳定,极速下载中⚡⚡⚡
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBhcmlhLWhpZGRlbj0idHJ1ZSIgcm9sZT0iaW1nIiBjbGFzcz0iaWNvbmlmeSBpY29uaWZ5LS1sb2dvcyIgd2lkdGg9IjMxLjg4IiBoZWlnaHQ9IjMyIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMjU2IDI1NyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJJY29uaWZ5SWQxODEzMDg4ZmUxZmJjMDFmYjQ2NiIgeDE9Ii0uODI4JSIgeDI9IjU3LjYzNiUiIHkxPSI3LjY1MiUiIHkyPSI3OC40MTElIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNDFEMUZGIj48L3N0b3A+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjQkQzNEZFIj48L3N0b3A+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9Ikljb25pZnlJZDE4MTMwODhmZTFmYmMwMWZiNDY3IiB4MT0iNDMuMzc2JSIgeDI9IjUwLjMxNiUiIHkxPSIyLjI0MiUiIHkyPSI4OS4wMyUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNGRkVBODMiPjwvc3RvcD48c3RvcCBvZmZzZXQ9IjguMzMzJSIgc3RvcC1jb2xvcj0iI0ZGREQzNSI+PC9zdG9wPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI0ZGQTgwMCI+PC9zdG9wPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGZpbGw9InVybCgjSWNvbmlmeUlkMTgxMzA4OGZlMWZiYzAxZmI0NjYpIiBkPSJNMjU1LjE1MyAzNy45MzhMMTM0Ljg5NyAyNTIuOTc2Yy0yLjQ4MyA0LjQ0LTguODYyIDQuNDY2LTExLjM4Mi4wNDhMLjg3NSAzNy45NThjLTIuNzQ2LTQuODE0IDEuMzcxLTEwLjY0NiA2LjgyNy05LjY3bDEyMC4zODUgMjEuNTE3YTYuNTM3IDYuNTM3IDAgMCAwIDIuMzIyLS4wMDRsMTE3Ljg2Ny0yMS40ODNjNS40MzgtLjk5MSA5LjU3NCA0Ljc5NiA2Ljg3NyA5LjYyWiI+PC9wYXRoPjxwYXRoIGZpbGw9InVybCgjSWNvbmlmeUlkMTgxMzA4OGZlMWZiYzAxZmI0NjcpIiBkPSJNMTg1LjQzMi4wNjNMOTYuNDQgMTcuNTAxYTMuMjY4IDMuMjY4IDAgMCAwLTIuNjM0IDMuMDE0bC01LjQ3NCA5Mi40NTZhMy4yNjggMy4yNjggMCAwIDAgMy45OTcgMy4zNzhsMjQuNzc3LTUuNzE4YzIuMzE4LS41MzUgNC40MTMgMS41MDcgMy45MzYgMy44MzhsLTcuMzYxIDM2LjA0N2MtLjQ5NSAyLjQyNiAxLjc4MiA0LjUgNC4xNTEgMy43OGwxNS4zMDQtNC42NDljMi4zNzItLjcyIDQuNjUyIDEuMzYgNC4xNSAzLjc4OGwtMTEuNjk4IDU2LjYyMWMtLjczMiAzLjU0MiAzLjk3OSA1LjQ3MyA1Ljk0MyAyLjQzN2wxLjMxMy0yLjAyOGw3Mi41MTYtMTQ0LjcyYzEuMjE1LTIuNDIzLS44OC01LjE4Ni0zLjU0LTQuNjcybC0yNS41MDUgNC45MjJjLTIuMzk2LjQ2Mi00LjQzNS0xLjc3LTMuNzU5LTQuMTE0bDE2LjY0Ni01Ny43MDVjLjY3Ny0yLjM1LTEuMzctNC41ODMtMy43NjktNC4xMTNaIj48L3BhdGg+PC9zdmc+
// @author Check Out
// @license MIT
// @match https://pan.baidu.com/disk/*
// @grant GM_addStyle
// @grant GM_getResourceText
// @require https://lib.baomitu.com/layui/2.8.18/layui.min.js
// @resource LAYUI_CSS https://lib.baomitu.com/layui/2.8.18/css/layui.css
// @resource LAYUI_WOFF2 https://lib.baomitu.com/layui/2.8.18/font/iconfont.woff2
// @resource LAYUI_WOFF https://lib.baomitu.com/layui/2.8.18/font/iconfont.woff
// @resource LAYUI_TTF https://lib.baomitu.com/layui/2.8.18/font/iconfont.ttf
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @connect localhost
// @connect 127.0.0.1
// @connect baidu.com
// @connect gitee.com
// @connect zuba.lat
// ==/UserScript==
(function() {
'use strict';
// 在文件开头添加全局配置变量(在 'use strict' 后面)
let globalConfig = null;
// 在文件开头添加全局变量
let fileListResult = null;
// 在文件开头添加全局变量
let currentPassword = null;
// 在文件开头添加 Aria2 配置变量
const aria2Config = {
rpcUrl: GM_getValue('aria2RpcUrl', 'http://localhost:6800/jsonrpc'),
token: GM_getValue('aria2Token', '')
};
// 修改 CSS 中的字体路径
const layuiCSS = GM_getResourceText('LAYUI_CSS')
.replace(/url\([^)]+iconfont\.woff2[^)]*\)/g, `url(https://lib.baomitu.com/layui/2.8.18/font/iconfont.woff2)`)
.replace(/url\([^)]+iconfont\.woff[^)]*\)/g, `url(https://lib.baomitu.com/layui/2.8.18/font/iconfont.woff)`)
.replace(/url\([^)]+iconfont\.ttf[^)]*\)/g, `url(https://lib.baomitu.com/layui/2.8.18/font/iconfont.ttf)`);
// 添加修改后的样式
GM_addStyle(layuiCSS);
// 在文件开头添加防抖函数
const debounce = (fn, delay) => {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
// 检查选中的文件
const checkSelectedFiles = () => {
const selectedElements = document.querySelectorAll(
".wp-s-pan-table__body-row.mouse-choose-item.selected, " +
".wp-s-file-grid-list__item.text-center.cursor-p.mouse-choose-item.is-checked, " +
".wp-s-file-contain-list__item.text-center.cursor-p.mouse-choose-item.is-checked"
);
const selectedIds = Array.from(selectedElements).map(item => item.getAttribute("data-id"));
console.log("Selected elements:", selectedElements);
console.log("Selected IDs:", selectedIds);
// 检查是否有选中文件
if (selectedIds.length === 0) {
layer.msg('请选择需要处理的文件', {
icon: 2,
time: 2000
});
return false;
}
// 检查是否选中多个文件
if (selectedIds.length > 1) {
layer.msg('暂时只能处理一个文件', {
icon: 2,
time: 2000
});
return false;
}
// 检查是否选中了文件夹
const selectedItems = Array.from(selectedElements);
if (selectedItems.some(item => {
const sizeSection = item.querySelector('.wp-format-size section');
return sizeSection?.textContent.trim() === '-';
})) {
layer.msg('请不要选择文件夹,暂不支持处理', {
icon: 2,
time: 2000
});
return false;
}
return {
id: selectedIds[0],
element: selectedElements[0]
};
};
// 添加按钮样式
GM_addStyle(`
.wp-s-agile-tool-bar__h-action-button.is-disabled {
cursor: not-allowed;
opacity: 0.4;
}
.wp-s-agile-tool-bar__h-action-button:hover {
background-color: #f5f5f5;
border-radius: 4px;
}
.wp-s-agile-tool-bar__h-action-button i {
font-size: 16px;
margin-right: 4px;
}
`);
// 修改查找下载按钮的函数
const findDownloadButton = () => {
// 尝试多种可能选择器
const selectors = [
'button[title="下载"]',
'.u-button-group button[title="下载"]',
'.wp-s-agile-tool-bar__h-action button',
'.nd-file-list-toolbar-action-item'
];
for (const selector of selectors) {
const btn = document.querySelector(selector);
if (btn) return btn;
}
return null;
};
// 修改等待函数
const waitForDownloadButton = () => {
return new Promise((resolve) => {
const checkButton = () => {
const downloadBtn = findDownloadButton();
if (downloadBtn) {
resolve(downloadBtn);
return true;
}
return false;
};
if (checkButton()) return;
const observer = new MutationObserver(() => {
if (checkButton()) {
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
};
// 修改配获取函数(替换原来的 getConfig 函数)
const getConfig = () => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: 'https://gitee.com/Mo_Net/T1down/raw/master/server',
timeout: 5000,
onload: function(response) {
if (response.status === 200) {
try {
const config = JSON.parse(response.responseText);
// 保存配置到全局变量
globalConfig = config;
// 如果按钮已存在,更新按钮文字
const customBtn = document.getElementById('CustomBtn');
if (customBtn) {
const textSpan = customBtn.querySelector('span');
if (textSpan) {
textSpan.textContent = config?.tabs?.[0]?.raw || '自定义功能';
}
}
resolve(config);
} catch (error) {
console.error('解析配置失败:', error);
reject(error);
}
} else {
reject(new Error('请求失败: ' + response.status));
}
},
onerror: function(error) {
console.error('请求配置失败:', error);
reject(error);
},
ontimeout: function() {
reject(new Error('请求超时'));
}
});
});
};
// 修改 addCustomButton 函数
const addCustomButton = () => {
if (document.getElementById('CustomBtn')) {
return true;
}
// 找到主按钮组
const mainButtonGroup = document.querySelector('.u-button-group.wp-s-agile-tool-bar__h-button-group.is-main');
if (!mainButtonGroup) {
console.log('未找到主按钮组');
return false;
}
// 建按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.className = 'wp-s-agile-tool-bar__h-action';
buttonContainer.style.cssText = `
margin-left: 8px;
background: none;
padding: 0;
`;
// 创建按钮 - 默认紫色样式
const button = document.createElement('button');
button.id = 'CustomBtn';
button.className = 'u-button u-button--primary u-button--small is-round';
button.title = '自定义功能';
// 默认紫色样式
const purpleStyle = `
background-color: #9c27b0;
border-color: #9c27b0;
height: 32px;
padding: 0 16px;
font-size: 14px;
color: #fff;
display: inline-flex;
align-items: center;
justify-content: center;
margin-left: 4px;
`;
button.style.cssText = purpleStyle;
// 创建图标
const icon = document.createElement('i');
icon.className = 'u-icon-download';
icon.style.marginRight = '4px';
// 创建文本
const textSpan = document.createElement('span');
textSpan.textContent = globalConfig?.tabs?.[0]?.raw || '自定义功能';
// 组装按钮
button.appendChild(icon);
button.appendChild(textSpan);
buttonContainer.appendChild(button);
// 监听文件选择状态变化
const updateButtonStyle = () => {
const hasSelection = document.querySelector('.wp-s-pan-table__header-th .content span')?.textContent.includes('已选中');
const downloadButton = document.querySelector('button[title="下载"]');
if (hasSelection && downloadButton) {
// 选中文件时:复制下载按钮的样式和位置
const downloadContainer = downloadButton.closest('.wp-s-agile-tool-bar__h-action');
buttonContainer.className = downloadContainer.className;
buttonContainer.style.cssText = '';
button.className = downloadButton.className;
button.style.cssText = downloadButton.style.cssText;
// 移动到下载按钮前面
if (buttonContainer.parentNode !== downloadContainer.parentNode) {
downloadContainer.parentNode.insertBefore(buttonContainer, downloadContainer);
}
} else {
// 未选中文件时:恢复紫色样式和原位置
buttonContainer.className = 'wp-s-agile-tool-bar__h-action';
buttonContainer.style.cssText = `
margin-left: 8px;
background: none;
padding: 0;
`;
button.className = 'u-button u-button--primary u-button--small is-round';
button.style.cssText = purpleStyle;
// 移回主按钮组
if (buttonContainer.parentNode !== mainButtonGroup) {
mainButtonGroup.appendChild(buttonContainer);
}
}
};
// 使用防抖包装更新函数
const debouncedUpdate = debounce(updateButtonStyle, 100);
// 监听文件选择态变化
const observer = new MutationObserver(debouncedUpdate);
observer.observe(document.body, {
childList: true,
subtree: true
});
// 修改按钮的点击事件
button.onclick = async (e) => {
if (e.shiftKey) {
GM_setValue('initialized', false);
layer.confirm('初始化状态已重置,是否刷新页面?<br><small style="color: #666;">提示:刷新后将重新显示初始化页面</small>', {
btn: ['是','否'],
icon: 3,
title: '重置确认'
}, function(){
location.reload();
});
return;
}
const fileInfo = checkSelectedFiles();
if (!fileInfo) return;
// 获取配置
const config = await getConfig();
if (!config) {
layer.msg('获取配置失败', {icon: 2});
return;
}
// 直接显示主页对话框
layer.open({
type: 1,
title: '文件处理',
area: ['800px', '600px'],
content: `
<div class="custom-dialog">
<!-- 顶部广告 -->
<div class="top-banner">
<div class="banner-left">
<i class="layui-icon layui-icon-speaker"></i>
${config.tabs?.[0]?.label || '欢迎使用'}
</div>
<button class="layui-btn layui-btn-normal layui-btn-sm" data-url="${config.tabs?.[0]?.url || '#'}">了解详情</button>
</div>
<!-- 当前文件信息和解析按钮 -->
<div class="file-info">
<div class="file-info-header">
<div class="file-name">
<span class="label">当前文件:</span>
<span class="value">${fileInfo.element.querySelector('.wp-s-pan-list__file-name-title-text')?.textContent.trim() || '未获取到文件名'}</span>
</div>
<button class="layui-btn layui-btn-normal" id="parseFile">
<i class="layui-icon layui-icon-release"></i> 解析
</button>
</div>
</div>
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 左侧二维码区域 -->
<div class="qrcode-section">
<div class="qrcode-title">扫一扫获取解析密码</div>
<div class="qrcode-image">
<img src="${config.config?.quark_share_base64 || ''}" alt="QR Code">
</div>
<div class="qrcode-tip">扫码获取解析密码</div>
<div class="qrcode-actions">
<button class="layui-btn layui-btn-primary">https://pan.quark.cn/s/11d137f012ef</button>
<button class="layui-btn layui-btn-primary">从网盘获取解析密码</button>
</div>
</div>
<!-- 右侧使用帮助 -->
<div class="help-section">
<!-- 解析使用帮助 -->
<div class="help-block">
<div class="help-title">解析使用帮助</div>
<div class="help-content">
<ol>
<li>扫描左侧二维码获取解析密码</li>
<li>点击解析按钮开始解析文件</li>
<li>使用获取的密码完成解析</li>
<li>获得高速下载链接</li>
</ol>
</div>
</div>
<!-- IDM使用教程 -->
<div class="help-block">
<div class="help-title">IDM使用教程</div>
<div class="help-content">
<ol>
<li>打开IDM,进入选项->下载</li>
<li>找到用户代理(UA)设置</li>
<li>在解析完成后复制UA并填入</li>
<li>使用IDM新建任务载文件</li>
</ol>
</div>
</div>
</div>
</div>
</div>
`,
success: function(layero, index) {
// 添加自定义样式
GM_addStyle(`
.custom-dialog {
padding: 0;
background: #fff;
}
.top-banner {
background: #e8f4ff;
padding: 12px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e8e8e8;
}
.banner-left {
display: flex;
align-items: center;
color: #1890ff;
font-size: 13px;
}
.banner-left i {
margin-right: 6px;
font-size: 14px;
}
.file-info {
padding: 15px 20px;
border-bottom: 1px solid #f0f0f0;
background: #fafafa;
}
.file-info-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.file-name {
flex: 1;
margin-right: 15px;
}
.file-name .label {
color: #666;
font-size: 13px;
}
.file-name .value {
color: #333;
font-size: 13px;
margin-left: 5px;
}
.main-content {
display: flex;
padding: 0;
height: 450px;
}
.qrcode-section {
flex: 1;
padding: 30px;
text-align: center;
border-right: 1px solid #f0f0f0;
display: flex;
flex-direction: column;
align-items: center;
}
.qrcode-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.qrcode-image {
width: 200px;
height: 200px;
margin: 0 auto 15px;
padding: 10px;
border: 1px solid #f0f0f0;
border-radius: 4px;
}
.qrcode-image img {
width: 100%;
height: 100%;
}
.qrcode-tip {
color: #666;
font-size: 13px;
margin-bottom: 20px;
}
.qrcode-actions {
width: 100%;
max-width: 280px;
display: flex;
flex-direction: column;
gap: 10px;
}
.qrcode-actions .layui-btn {
width: 100%;
height: 36px;
line-height: 34px;
border: 1px solid #e8e8e8;
background: #fff;
color: #333;
}
.qrcode-actions .layui-btn:hover {
border-color: #1890ff;
color: #1890ff;
}
.help-section {
flex: 1;
padding: 20px;
}
.help-block {
background: #fff;
padding: 20px;
margin-bottom: 15px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.help-block:last-child {
margin-bottom: 0;
}
.help-title {
font-size: 15px;
font-weight: bold;
color: #333;
margin-bottom: 15px;
padding-left: 10px;
border-left: 3px solid #1890ff;
}
.help-content ol {
margin: 0;
padding-left: 20px;
}
.help-content li {
color: #666;
font-size: 13px;
line-height: 2;
padding-left: 5px;
}
`);
// 修改解按钮事件处
layero.find('#parseFile').on('click', async function() {
// 显示加载提示
const loadingIndex = layer.load(1, {
shade: [0.3, '#fff'],
content: '正在生成分享链接...'
});
try {
// 获取分享链接
const bdstoken = getBdsToken();
if (!bdstoken) {
throw new Error('获取 bdstoken 失败');
}
// 分享文件获取链接
const shareResult = await shareFiles(bdstoken, [fileInfo.id]);
if (shareResult.errno !== 0) {
throw new Error(shareResult.show_msg || '分享失败');
}
// 提取短链接
const shorturl = extractShortUrl(shareResult.link);
if (!shorturl) {
throw new Error('提取分享链接失败');
}
// 关闭加载提示
layer.close(loadingIndex);
// 显示密码输入��
layer.open({
type: 1,
title: '输入解析密码',
area: ['400px', '240px'],
content: `
<div class="parse-password-dialog">
<div class="password-tip">请输入6位数字解析密码</div>
<div class="password-input-group">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
<input type="text" maxlength="1" class="password-input" autocomplete="off">
</div>
<div class="password-actions">
<button type="button" class="layui-btn layui-btn-primary" onclick="layer.closeAll()">取消</button>
<button type="button" class="layui-btn" id="confirmParse">确认解析</button>
</div>
</div>
`,
success: function(layero) {
// 添加密码输入框样式
GM_addStyle(`
.parse-password-dialog {
padding: 20px;
text-align: center;
}
.password-tip {
font-size: 14px;
color: #666;
margin-bottom: 20px;
}
.password-input-group {
display: flex;
justify-content: center;
gap: 8px;
margin-bottom: 30px;
}
.password-input {
width: 40px;
height: 40px;
text-align: center;
font-size: 18px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
}
.password-input:focus {
border-color: #1890ff;
outline: none;
box-shadow: 0 0 0 2px rgba(24,144,255,0.2);
}
.password-actions {
display: flex;
justify-content: center;
gap: 20px;
}
`);
// 获取所有密���输入框
const inputs = layero.find('.password-input');
// 添加输入框事处理
inputs.on('input', function(e) {
const value = e.target.value;
// 只允许输入数字
if (!/^\d*$/.test(value)) {
e.target.value = '';
return;
}
// 自动跳转到下一个输入框
const index = inputs.index(this);
if (value && index < inputs.length - 1) {
inputs[index + 1].focus();
}
});
// 支持删除键跳转到上一输入框
inputs.on('keydown', function(e) {
if (e.key === 'Backspace' && !this.value) {
const index = inputs.index(this);
if (index > 0) {
inputs[index - 1].focus();
}
}
});
// 修改确认解析按钮事件
layero.find('#confirmParse').on('click', async function() {
const password = Array.from(layero.find('.password-input')).map(input => input.value).join('');
currentPassword = password;
if (password.length !== 6) {
layer.msg('请输入完整的6位数字密码', {icon: 2});
return;
}
// 显示加载提示
const loadingIndex = layer.load(1, {
shade: [0.3, '#fff'],
content: '正在获取文件列表...'
});
try {
const server = config.config.server[0];
const fileListResult = await getFileList(server, shorturl, password);
if (fileListResult.code !== 200) {
throw new Error(fileListResult.message || '获取文件列表失败');
}
// 闭密码输入框
layer.closeAll();
// 显示文件列表
layer.open({
type: 1,
title: '文件列表',
area: ['800px', '600px'],
content: `
<div class="file-list-dialog">
<div class="file-list-header">
<div class="header-checkbox">
<input type="checkbox" class="select-all" title="全选">
</div>
<div class="header-name">文件名</div>
<div class="header-size">大小</div>
<div class="header-action">操作</div>
</div>
<div class="file-list-body">
${fileListResult.data.list.map(file => `
<div class="file-item" data-fs-id="${file.fs_id}">
<div class="item-checkbox">
<input type="checkbox" class="file-select">
</div>
<div class="item-name" title="${file.server_filename}">
<i class="layui-icon ${file.isdir ? 'layui-icon-folder' : 'layui-icon-file'}"></i>
${file.server_filename}
</div>
<div class="item-size">${formatSize(file.size)}</div>
<div class="item-action">
<button class="layui-btn layui-btn-sm get-link">获取直链</button>
</div>
</div>
`).join('')}
</div>
<div class="file-list-footer">
<div class="footer-info">
已选择 <span class="selected-count">0</span> 个文件
</div>
<div class="footer-actions">
<button class="layui-btn" id="batchGetLinks">
<i class="layui-icon layui-icon-download"></i>批量获取直链
</button>
</div>
</div>
</div>
`,
success: function(layero) {
// 添加文件列表样式
GM_addStyle(`
.file-list-dialog {
padding: 20px;
display: flex;
flex-direction: column;
height: calc(100% - 40px);
}
.file-list-header {
display: flex;
padding: 12px 15px;
background: #f8f8f8;
border-radius: 4px 4px 0 0;
font-weight: bold;
border-bottom: 1px solid #e6e6e6;
}
.file-list-body {
flex: 1;
overflow-y: auto;
background: #fff;
border: 1px solid #e6e6e6;
border-top: none;
}
.file-item {
display: flex;
padding: 12px 15px;
border-bottom: 1px solid #f0f0f0;
align-items: center;
transition: background-color 0.2s;
}
.file-item:hover {
background-color: #f8f8f8;
}
.header-checkbox, .item-checkbox {
width: 40px;
text-align: center;
}
.header-name, .item-name {
flex: 1;
padding-right: 15px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.item-name i {
margin-right: 5px;
color: #666;
}
.header-size, .item-size {
width: 100px;
text-align: right;
}
.header-action, .item-action {
width: 100px;
text-align: center;
}
.file-list-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 15px;
padding: 10px 0;
}
.footer-info {
color: #666;
}
.selected-count {
color: #1890ff;
font-weight: bold;
}
`);
// 更新选中文件数量
const updateSelectedCount = () => {
const count = layero.find('.file-select:checked').length;
layero.find('.selected-count').text(count);
};
// 全选功能
layero.find('.select-all').on('change', function() {
const checked = this.checked;
layero.find('.file-select').prop('checked', checked);
updateSelectedCount();
});
// 单选更新
layero.find('.file-select').on('change', updateSelectedCount);
// 获取直链按钮事件
layero.find('.get-link').on('click', async function(e) {
// 使用 jQuery 获取当前按钮和相关元素
const $button = $(this); // 改用 this 而不是 e.currentTarget
const $fileItem = $button.closest('.file-item');
const fsId = $fileItem.data('fs-id');
const fileInfo = fileListResult.data.list.find(f => f.fs_id.toString() === fsId.toString());
if (!fileInfo) {
layer.msg('未找到文件信息', {icon: 2});
return;
}
// 显示加载提示
const loadingIndex = layer.load(1, {
shade: [0.3, '#fff'],
content: '正在获取直链...'
});
try {
const linkInfo = await getFileLink(server, fileInfo, shorturl, password);
// 显示直链信息对话框
layer.open({
type: 1,
title: '文件直链',
area: ['600px', '400px'],
content: `
<div class="file-link-dialog">
<div class="file-info-section">
<div class="info-item">
<label>文件名:</label>
<div class="info-content">
<span class="file-name-text">${fileInfo.server_filename}</span>
</div>
</div>
<div class="info-item">
<label>UA:</label>
<div class="info-content">
<input type="text" class="layui-input ua-input" value="${linkInfo.ua}" readonly>
<button class="layui-btn layui-btn-sm copy-ua">复制UA</button>
</div>
</div>
<div class="info-item">
<label>直链地址:</label>
<div class="info-content link-content">
<div class="link-wrapper">
<input type="text" class="layui-input link-input" value="${linkInfo.dlink}" readonly>
<button class="layui-btn layui-btn-sm copy-link">复制链接</button>
</div>
<button class="layui-btn layui-btn-sm change-link">
<i class="layui-icon layui-icon-refresh"></i> 更换链接
</button>
</div>
</div>
</div>
<div class="action-section">
<button class="layui-btn config-aria2">
<i class="layui-icon layui-icon-set"></i> 配置Aria2
</button>
<button class="layui-btn send-to-aria2">
<i class="layui-icon layui-icon-download-circle"></i> 发送到Aria2
</button>
</div>
</div>
`,
success: function(layero) {
// 添加样式
GM_addStyle(`
.file-link-dialog {
padding: 20px;
font-family: Arial, sans-serif;
}
.file-info-section {
margin-bottom: 20px;
}
.info-item {
display: flex;
margin-bottom: 15px;
align-items: center;
}
.info-item label {
width: 100px;
color: #666;
line-height: 32px;
flex-shrink: 0;
}
.info-content {
flex: 1;
display: flex;
gap: 10px;
align-items: center;
}
.file-name-text {
line-height: 32px;
color: #333;
}
.ua-input, .link-input {
flex: 1;
background-color: #f8f8f8;
border: 1px solid #ddd;
padding: 5px;
border-radius: 4px;
}
.link-wrapper {
display: flex;
gap: 10px;
flex: 1;
}
.link-content {
flex-direction: column;
gap: 10px;
}
.action-section {
display: flex;
justify-content: center;
gap: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
}
.layui-btn {
display: inline-flex;
align-items: center;
gap: 5px;
background-color: #5FB878;
color: #fff;
border: none;
border-radius: 4px;
padding: 8px 16px;
cursor: pointer;
transition: background-color 0.3s;
}
.layui-btn:hover {
background-color: #4E9A6E;
}
.layui-btn i {
font-size: 16px;
}
`);
// 复制UA按钮事件
layero.find('.copy-ua').on('click', function() {
navigator.clipboard.writeText(linkInfo.ua).then(() => {
layer.msg('UA已复制到剪贴板', {icon: 1});
}).catch(() => {
layer.msg('复制失败,请手动复制', {icon: 2});
});
});
// 复制链接按钮事件
layero.find('.copy-link').on('click', function() {
navigator.clipboard.writeText(linkInfo.dlink).then(() => {
layer.msg('直链已复制到剪贴板', {icon: 1});
}).catch(() => {
layer.msg('复制失败,请手动复制', {icon: 2});
});
});
// 更换链接按钮事件
layero.find('.change-link').on('click', async function() {
const loadingIndex = layer.load(1, {
shade: [0.3, '#fff']
});
try {
if (!linkInfo.urls || linkInfo.urls.length === 0) {
throw new Error('没有可用的备用链接');
}
// 轮询urls数组
const currentLink = layero.find('.link-input').val();
const currentIndex = linkInfo.urls.indexOf(currentLink);
const nextIndex = (currentIndex + 1) % linkInfo.urls.length;
const newLink = linkInfo.urls[nextIndex];
layero.find('.link-input').val(newLink);
linkInfo.dlink = newLink;
layer.msg('已更换为新链接', {icon: 1});
} catch (error) {
layer.msg(error.message, {icon: 2});
} finally {
layer.close(loadingIndex);
}
});
// 配置Aria2按钮事件
layero.find('.config-aria2').on('click', function() {
const currentLayerIndex = layer.index; // 保存当前层的索引
showAria2Config(currentLayerIndex);
});
// 发送到Aria2按钮事件
layero.find('.send-to-aria2').on('click', function() {
sendToAria2(linkInfo.dlink, fileInfo.server_filename, linkInfo.ua);
});
}
});
} catch (error) {
console.error('获取直链失败:', error);
layer.msg(error.message || '获取直链失败,请重试', {icon: 2});
} finally {
layer.close(loadingIndex);
}
});
// 全选功能
layero.find('.select-all').on('change', function() {
const checked = this.checked;
layero.find('.file-select').prop('checked', checked);
updateSelectedCount();
});
}
});
} catch (error) {
console.error('处理失败:', error);
layer.msg(error.message || '处理失败,请重试', {icon: 2});
} finally {
layer.close(loadingIndex);
}
});
// 自动聚焦第一个输入框
inputs[0].focus();
}
});
} catch (error) {
console.error('处理失败:', error);
layer.msg(error.message || '处理失败,请重试', {icon: 2});
layer.close(loadingIndex);
}
});
// 顶部广��按钮点击事件
layero.find('.top-banner button').on('click', function() {
const url = $(this).data('url');
if (url) {
window.open(url, '_blank');
}
});
}
});
};
try {
// 初始添加到主按钮组
mainButtonGroup.appendChild(buttonContainer);
// 初始状态检查
updateButtonStyle();
// 验证按钮是否真正添加成功
if (document.getElementById('CustomBtn')) {
console.log('按钮真正添加成功');
return true;
} else {
console.log('按钮添加失败:DOM中未找到按钮');
return false;
}
} catch (error) {
console.error('添加按钮时发生错误:', error);
return false;
}
};
// 将重试计数器移到函数外部,作为模块级变量
const MAX_RETRIES = 10;
const state = {
retryCount: 0,
isInitialized: false
};
// 修改 checkAndAddButton 函数
const checkAndAddButton = () => {
if (state.retryCount >= MAX_RETRIES) {
console.log('已达到最��重试次数,停止尝试');
return;
}
const existingButton = document.getElementById('CustomBtn');
if (!existingButton) {
state.retryCount++;
console.log(`按钮不存在第 ${state.retryCount} 次尝试添加`);
// 尝试添加按钮并验证结果
const success = addCustomButton();
if (success && document.getElementById('CustomBtn')) {
console.log('按钮添加并验证成功');
state.retryCount = 0;
state.isInitialized = true;
} else {
console.log('按钮添加失败或验证失败');
}
} else {
console.log('按钮已存在,无需添加');
state.isInitialized = true;
}
};
// 等待工具栏加载完成
const waitForToolbar = () => {
return new Promise((resolve) => {
const check = () => {
const toolbar = document.querySelector('.wp-s-agile-tool-bar__h-button-group');
if (toolbar) {
resolve(toolbar);
return true;
}
return false;
};
if (check()) return;
const observer = new MutationObserver(() => {
if (check()) {
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
};
// 修改移动按钮的函数
const moveButtonsToMore = () => {
// 要留在工具栏的按钮标题列表
const keepButtons = ['下载', '删除', '自定义功能'];
// 监听文件选择状态变化
const observer = new MutationObserver(() => {
// 检查是否有文件选中
const hasSelection = document.querySelector('.wp-s-pan-table__header-th .content span')?.textContent.includes('已选中');
if (!hasSelection) return;
// 找到百度网盘原生的更多菜单内容区域
const moreMenu = document.querySelector('.wp-s-inner-popover__content .wp-s-agile-tool-bar__v-button-group');
if (!moreMenu) return;
// 找到操作按钮组
const actionButtons = document.querySelectorAll('.wp-s-agile-tool-bar__h-action button[title]');
if (!actionButtons.length) return;
// 遍历所有按钮
actionButtons.forEach(button => {
const title = button.getAttribute('title');
const container = button.closest('.wp-s-agile-tool-bar__h-action');
if (!keepButtons.includes(title) && container && !container.dataset.moved) {
// 移动按钮到更多菜单
const menuItem = document.createElement('div');
menuItem.className = 'wp-s-agile-tool-bar__item';
const actionWrapper = document.createElement('div');
actionWrapper.className = 'wp-s-agile-tool-bar__v-action is-list';
// 复制原按钮并调整样式
const newButton = button.cloneNode(true);
newButton.className = 'u-button wp-s-agile-tool-bar__v-action-button u-button--text u-button--small';
newButton.style.height = '30px';
// 保持原有的点击事件
newButton.onclick = button.onclick;
actionWrapper.appendChild(newButton);
menuItem.appendChild(actionWrapper);
moreMenu.appendChild(menuItem);
// 隐藏原按钮
container.style.display = 'none';
container.dataset.moved = 'true';
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class']
});
};
// 添加初始化系统相关代码
const initSystem = {
// 检查是否首次运行
isFirstRun: () => {
return !GM_getValue('initialized', false);
},
// 显示初始化协议
showInitDialog: () => {
return new Promise((resolve) => {
layer.open({
type: 1,
title: '欢迎使用',
area: ['600px', '500px'],
closeBtn: 0,
shadeClose: false,
content: `
<div class="init-dialog">
<div class="init-header">
<i class="layui-icon layui-icon-app"></i>
<h2>T1down 网盘助手</h2>
<p class="version">版本 1.0.0</p>
</div>
<div class="init-content">
<div class="feature-section">
<h3><i class="layui-icon layui-icon-star"></i>主要功能</h3>
<ul>
<li>支持文件直链解析</li>
<li>支持 Aria2 下载集成</li>
<li>支持批量任务处理</li>
<li>智能 UA 获取与更新</li>
</ul>
</div>
<div class="terms-section">
<h3><i class="layui-icon layui-icon-about"></i>使用条款</h3>
<div class="terms-content">
<p><strong>使用须知:</strong></p>
<ul>
<li>本脚本完全免费,仅供学习交流使用</li>
<li>请勿用于任何商业用途或非法行为</li>
<li>使用本脚本产生的任何后果由用户自行承担</li>
</ul>
<p><strong>隐私说明:</strong></p>
<ul>
<li>脚本不会收集任何个人隐私信息</li>
<li>所有操作均在本地执行</li>
<li>不会向任何第三方传输用户数据</li>
</ul>
</div>
</div>
</div>
<div class="init-footer">
<button class="layui-btn layui-btn-primary" id="rejectInit">暂不使用</button>
<button class="layui-btn" id="acceptInit">同意并开始使用</button>
</div>
</div>
`,
success: function(layero) {
// 添加样式
GM_addStyle(`
.init-dialog {
padding: 0;
background: #fff;
}
.init-header {
background: linear-gradient(135deg, #9c27b0, #673ab7);
color: #fff;
padding: 30px;
text-align: center;
border-radius: 2px 2px 0 0;
}
.init-header i {
font-size: 48px;
margin-bottom: 10px;
}
.init-header h2 {
font-size: 24px;
margin: 10px 0;
font-weight: normal;
}
.version {
font-size: 14px;
opacity: 0.8;
}
.init-content {
padding: 20px 30px;
max-height: 300px;
overflow-y: auto;
}
.feature-section, .terms-section {
margin-bottom: 20px;
}
.feature-section h3, .terms-section h3 {
font-size: 16px;
color: #333;
margin-bottom: 15px;
display: flex;
align-items: center;
}
.feature-section h3 i, .terms-section h3 i {
margin-right: 8px;
color: #9c27b0;
}
.feature-section ul, .terms-section ul {
padding-left: 20px;
margin: 10px 0;
}
.feature-section li, .terms-section li {
line-height: 1.8;
color: #666;
position: relative;
padding-left: 5px;
}
.terms-content {
background: #f8f8f8;
padding: 15px;
border-radius: 4px;
font-size: 13px;
}
.terms-content p {
margin: 10px 0;
}
.init-footer {
padding: 20px 30px;
text-align: center;
border-top: 1px solid #eee;
}
.init-footer .layui-btn {
height: 38px;
line-height: 38px;
padding: 0 25px;
font-size: 14px;
}
.init-footer .layui-btn-primary {
margin-right: 15px;
}
.init-footer .layui-btn:not(.layui-btn-primary) {
background: #9c27b0;
}
.init-footer .layui-btn:not(.layui-btn-primary):hover {
background: #7b1fa2;
}
`);
// 添加按钮事件
layero.find('#acceptInit').on('click', function() {
GM_setValue('initialized', true);
layer.closeAll();
resolve(true);
});
layero.find('#rejectInit').on('click', function() {
GM_setValue('initialized', false);
layer.closeAll();
resolve(false);
});
},
end: function() {
if (!GM_getValue('initialized', false)) {
resolve(false);
}
}
});
});
},
// 初始化流程
init: async () => {
if (initSystem.isFirstRun()) {
console.log('首次运行,显示初始化页面');
// 等待确保样式加载完成
await new Promise(resolve => setTimeout(resolve, 1000));
// 显示初始化对话框
const accepted = await initSystem.showInitDialog();
if (!accepted) {
console.log('用户拒绝初始化');
layer.msg('您已拒绝使用本脚本,脚本将不会运行', {
icon: 2,
time: 3000
});
return false;
}
console.log('用户接受初始化');
layer.msg('初始化成功,欢迎使用!', {
icon: 1,
time: 2000
});
}
return true;
}
};
// 添加初始化标志
let isInitialized = false;
// 修改初始化函数
const init = async () => {
// 防止重��初始化
if (isInitialized) return;
isInitialized = true;
try {
console.log('开始初始化');
// 先获取配置
try {
await getConfig();
console.log('配置获取成');
} catch (error) {
console.error('获取配置失败,但继续执行其他初始化:', error);
}
const initResult = await initSystem.init();
if (!initResult) return;
await waitForToolbar();
// 等待页面完全加载
setTimeout(() => {
console.log('页面加载完成,开始处理');
// 首次添加按钮
const success = addCustomButton();
if (!success) {
console.log('首次添加按钮失败,将开始重试');
state.retryCount++;
} else {
state.isInitialized = true;
}
// 期检查按钮是否存在(每5秒检查一次)
const checkInterval = setInterval(() => {
if (state.retryCount >= MAX_RETRIES || state.isInitialized) {
console.log('停止定期检查');
clearInterval(checkInterval);
return;
}
checkAndAddButton();
}, 5000);
// 监听页面变化
const observer = new MutationObserver(() => {
if (!state.isInitialized && state.retryCount < MAX_RETRIES) {
checkAndAddButton();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// 移动按钮到更多菜单
moveButtonsToMore();
}, 1000);
} catch (error) {
console.error('初始化失败:', error);
isInitialized = false; // 初始化失败时重置标志
}
};
// 添加获取 bdstoken 的函数
const getBdsToken = () => {
try {
// 方法1:从页面全局变量获取
if (window.locals && window.locals.bdstoken) {
return window.locals.bdstoken;
}
// 方法2:从 HTML 内容中提取
const htmlString = document.documentElement.innerHTML;
const regex = /"bdstoken":"([^"]+)"/;
const match = regex.exec(htmlString);
if (match) {
return match[1];
}
// 方法3:从 URL 参数获取
const urlParams = new URLSearchParams(window.location.search);
const urlToken = urlParams.get('bdstoken');
if (urlToken) {
return urlToken;
}
throw new Error('无法获取 bdstoken');
} catch (error) {
console.error('获取 bdstoken 失败:', error);
return null;
}
};
// 添加分享文件的函数
const shareFiles = async (bdstoken, selectedIds) => {
try {
const formData = new URLSearchParams({
period: '1',
pwd: '7777', // 固定提取码
eflag_disable: 'true',
channel_list: '[]',
schannel: '4',
fid_list: JSON.stringify(selectedIds)
});
const response = await fetch(`https://pan.baidu.com/share/set?channel=chunlei&bdstoken=${bdstoken}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
credentials: 'include'
});
const result = await response.json();
console.log('分享结果:', result);
return result;
} catch (error) {
console.error('分享文件失败:', error);
throw error;
}
};
// 添加提取短链接的函数
const extractShortUrl = (link) => {
try {
const regex = /https:\/\/pan\.baidu\.com\/s\/([a-zA-Z0-9-_]+)/;
const match = regex.exec(link);
console.log("提取的短链接:", match ? match[1] : null);
return match ? match[1] : null;
} catch (error) {
console.error('提取短链接失败:', error);
return null;
}
};
// 修改获取文件列表的函数
const getFileList = async (server, shorturl, password) => {
return new Promise((resolve, reject) => {
// 构建JSON请求体
const requestData = {
surl: shorturl,
dir: '/',
password: password,
pwd: '7777' // 固定提取码
};
GM_xmlhttpRequest({
method: 'POST',
url: `${server}/api/v0/list`,
headers: {
'Content-Type': 'application/json',
'Origin': 'https://pan.baidu.com',
'Referer': 'https://pan.baidu.com/'
},
data: JSON.stringify(requestData),
onload: function(response) {
if (response.status === 200) {
try {
const result = JSON.parse(response.responseText);
// 保存响应结果到全局变量
fileListResult = result;
console.log('解析后的响应结果:', result);
resolve(result);
} catch (error) {
console.error('解析响应失败:', error);
reject(new Error('解析响应失败: ' + error.message));
}
} else {
reject(new Error(`请求失败: HTTP ${response.status}`));
}
},
onerror: function(error) {
console.error('请求错误:', error);
reject(error);
}
});
});
};
// 添加文件大小格式化函数
const formatSize = (size) => {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let index = 0;
while (size >= 1024 && index < units.length - 1) {
size /= 1024;
index++;
}
return `${size.toFixed(2)} ${units[index]}`;
};
// 添加时间格式化函数
const formatTime = (timestamp) => {
const date = new Date(timestamp * 1000);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
};
// 修改获取直链的函数
const getFileLink = async (server, fileInfo, surl, password) => {
return new Promise((resolve, reject) => {
// 检查 fileListResult 是否存在
if (!fileListResult || !fileListResult.data || !fileListResult.data.info) {
reject(new Error('获取文件列表信息失败'));
return;
}
// 从 fileListResult.data.info 中获取必要参数
const info = fileListResult.data.info;
// 构建JSON请求体,确保数字类型的参数不带引号
const requestData = {
fsidlist: Number(fileInfo.fs_id), // 确保是数字
sekey: info.randsk, // 使用 randsk 作为 sekey
shareid: Number(info.shareid), // 确保是数字
uk: Number(info.uk), // 确保是数字
surl: surl,
size: Number(fileInfo.size), // 确保是数字
password: password // 添加密码参数
};
console.log('获取直链请求体:', requestData);
GM_xmlhttpRequest({
method: 'POST',
url: `${server}/api/v0/parse`,
headers: {
'Content-Type': 'application/json',
'Origin': 'https://pan.baidu.com',
'Referer': 'https://pan.baidu.com/'
},
data: JSON.stringify(requestData),
onload: function(response) {
console.log('获取直链响应状态:', response.status);
console.log('获取直链响应体:', response.responseText);
if (response.status === 200) {
try {
const result = JSON.parse(response.responseText);
if (result.code === 200) {
resolve(result.data);
} else {
reject(new Error(result.message || '获取直链失败'));
}
} catch (error) {
console.error('解析直链响应失败:', error);
reject(new Error('解析直链响应失败'));
}
} else {
reject(new Error(`获取直链请求失败: HTTP ${response.status}`));
}
},
onerror: function(error) {
console.error('获取直链请求错误:', error);
reject(error);
}
});
});
};
// 添加 Aria2 配置对话框函数
const showAria2Config = (parentLayerIndex) => {
layer.open({
type: 1,
title: 'Aria2 配置',
area: ['500px', '300px'],
content: `
<div class="aria2-config-dialog">
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">RPC地址</label>
<div class="layui-input-block">
<input type="text" id="aria2RpcUrl" class="layui-input" value="${aria2Config.rpcUrl}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Token</label>
<div class="layui-input-block">
<input type="text" id="aria2Token" class="layui-input" value="${aria2Config.token}">
</div>
</div>
<div class="layui-form-item">
<div class="button-group">
<button class="layui-btn layui-btn-primary" id="cancelAria2Config">取消</button>
<button class="layui-btn" id="saveAria2Config">保存配置</button>
</div>
</div>
</div>
</div>
`,
success: function(layero) {
// 添加样式
GM_addStyle(`
.aria2-config-dialog {
padding: 20px;
}
.button-group {
text-align: center;
margin-top: 30px;
}
.button-group .layui-btn {
margin: 0 10px;
}
`);
// 保存配置按钮事件
layero.find('#saveAria2Config').on('click', function() {
const newRpcUrl = layero.find('#aria2RpcUrl').val();
const newToken = layero.find('#aria2Token').val();
aria2Config.rpcUrl = newRpcUrl;
aria2Config.token = newToken;
GM_setValue('aria2RpcUrl', newRpcUrl);
GM_setValue('aria2Token', newToken);
layer.msg('配置已保存', {icon: 1});
if (parentLayerIndex) {
layer.close(layer.index); // 关闭配置窗口
} else {
layer.closeAll(); // 如果没有父层,关闭所有窗口
}
});
// 取消按钮事件
layero.find('#cancelAria2Config').on('click', function() {
layer.close(layer.index);
});
}
});
};
// 修改发送到 Aria2 函数
const sendToAria2 = async (dlink, filename, ua) => {
if (!aria2Config.rpcUrl) {
layer.msg('请先配置Aria2', {icon: 2});
return;
}
const jsonPayload = {
jsonrpc: '2.0',
id: 'BaiduPan-Helper',
method: 'aria2.addUri',
params: [
`token:${aria2Config.token}`,
[dlink],
{
out: filename,
header: [`User-Agent: ${ua}`]
}
]
};
try {
const response = await fetch(aria2Config.rpcUrl, {
method: 'POST',
body: JSON.stringify(jsonPayload),
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('Aria2 response:', data);
if (data.result) {
layer.msg('下载任务已添加到Aria2', {icon: 1});
} else {
throw new Error(data.error?.message || '添加任务失败');
}
} catch (error) {
console.error('Error:', error);
layer.msg('连接到Aria2失败: ' + error.message, {icon: 2});
}
};
// 确保在页面加载完成后执行
if (document.readyState === 'complete') {
console.log('页面已加载完成,直接执行');
init();
} else {
console.log('等待页面加载完成');
window.addEventListener('load', init);
}
})();