You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
eh-fastapi/static/script.js

300 lines
11 KiB

class DownloadTool {
constructor() {
this.form = document.getElementById('downloadForm');
this.output = document.getElementById('output');
this.loadUrlsBtn = document.getElementById('loadUrls');
this.urlListTextarea = document.getElementById('urlList');
this.downloadUrlBtn = document.getElementById('downloadUrl');
this.cleanFilesBtn = document.getElementById('cleanFiles');
this.downloadImageBtn = document.getElementById('downloadImage');
this.checkIncompleteBtn = document.getElementById('checkIncomplete');
this.clearOutputBtn = document.getElementById('clearOutput');
this.proxySelect = document.getElementById('proxy');
this.websocket = null;
this.isConnected = false;
this.initEvents();
this.connectWebSocket();
}
initEvents() {
// 读取URL按钮
this.loadUrlsBtn.addEventListener('click', () => {
this.loadTargetUrls();
});
// 下载URL按钮
this.downloadUrlBtn.addEventListener('click', () => {
this.downloadUrls()
});
// 下载图片按钮
this.downloadImageBtn.addEventListener('click', () => {
this.downloadImages()
});
// 检查未完成按钮
this.checkIncompleteBtn.addEventListener('click', () => {
this.checkIncomplete();
});
// 清理文件按钮
this.cleanFilesBtn.addEventListener('click', () => {
this.cleanFiles();
});
// 清除输出按钮
this.clearOutputBtn.addEventListener('click', () => {
this.clearOutput();
});
}
connectWebSocket() {
try {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/ws`;
this.websocket = new WebSocket(wsUrl);
this.websocket.onopen = () => {
this.isConnected = true;
this.showOutput('WebSocket连接已建立,可以接收实时日志', 'success');
console.log('WebSocket连接已建立');
};
this.websocket.onmessage = (event) => {
try {
const logEntry = JSON.parse(event.data);
this.appendRealtimeLog(logEntry);
} catch (e) {
console.error('解析WebSocket消息失败:', e);
}
};
this.websocket.onclose = () => {
this.isConnected = false;
this.showOutput('WebSocket连接已断开,正在尝试重连...', 'error');
console.log('WebSocket连接已断开');
// 5秒后尝试重连
setTimeout(() => this.connectWebSocket(), 5000);
};
this.websocket.onerror = (error) => {
console.error('WebSocket错误:', error);
this.showOutput('WebSocket连接错误', 'error');
};
} catch (error) {
console.error('创建WebSocket连接失败:', error);
this.showOutput('WebSocket连接失败', 'error');
}
}
appendRealtimeLog(logEntry) {
const timestamp = logEntry.time || new Date().toLocaleTimeString();
const level = logEntry.level || 'INFO';
const source = logEntry.source || 'system';
const message = logEntry.message || '';
const logLine = `[${timestamp}] [${level}] [${source}] ${message}`;
// 追加到输出框
if (this.output.textContent) {
this.output.textContent += '\n' + logLine;
} else {
this.output.textContent = logLine;
}
// 自动滚动到底部
this.output.scrollTop = this.output.scrollHeight;
// 根据日志级别设置样式
if (level === 'ERROR') {
this.output.classList.add('error');
} else if (level === 'SUCCESS') {
this.output.classList.add('success');
} else {
this.output.classList.remove('error', 'success');
}
}
async loadTargetUrls() {
try {
this.setLoading(true);
this.showOutput('正在读取 targets.txt...', 'info');
const response = await fetch('/load_urls', {
method: 'POST'
});
const result = await response.json();
if (result.success) {
// 在URL列表文本框中显示读取的URL
this.urlListTextarea.value = result.urls.join('\n');
this.showOutput(`成功读取 ${result.urls.length} 个URL\n\nURL列表:\n${result.urls.join('\n')}`, 'success');
} else {
this.showOutput(`读取失败: ${result.message}`, 'error');
}
} catch (error) {
this.showOutput(`读取URL时出错: ${error.message}`, 'error');
} finally {
this.setLoading(false);
}
}
async clearOutput() {
try {
const response = await fetch('/clear', {
method: 'POST'
});
const result = await response.json();
if (result.success) {
this.showOutput('', 'success');
this.urlListTextarea.value = ''; // 同时清空URL列表
}
} catch (error) {
this.showOutput(`清除失败: ${error.message}`, 'error');
}
}
async downloadUrls() {
try {
const proxy = this.proxySelect.value;
this.showOutput(`正在抓取画廊链接...\n代理: ${proxy}\n\n注意:此操作可能需要较长时间,请耐心等待...`, 'info');
// 使用setTimeout确保UI不被阻塞
setTimeout(async () => {
try {
const res = await fetch('/download_urls', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ proxy })
});
const data = await res.json();
this.showOutput(data.message, data.success ? 'success' : 'error');
} catch (error) {
this.showOutput(`抓取画廊链接时出错: ${error.message}`, 'error');
}
}, 100);
} catch (error) {
this.showOutput(`抓取画廊链接时出错: ${error.message}`, 'error');
}
}
async downloadImages() {
try {
const proxy = this.proxySelect.value;
this.showOutput(`正在下载图片...\n代理: ${proxy}\n\n注意:此操作可能需要较长时间,请耐心等待...`, 'info');
// 使用setTimeout确保UI不被阻塞
setTimeout(async () => {
try {
const res = await fetch('/download_images', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ proxy })
});
const data = await res.json();
this.showOutput(data.message, data.success ? 'success' : 'error');
} catch (error) {
this.showOutput(`下载图片时出错: ${error.message}`, 'error');
}
}, 100);
} catch (error) {
this.showOutput(`下载图片时出错: ${error.message}`, 'error');
}
}
async checkIncomplete() {
try {
this.setLoading(true);
this.showOutput('正在检查未完成文件...', 'info');
const response = await fetch('/check_incomplete', {
method: 'POST'
});
const result = await response.json();
if (result.success) {
let message = `检查完成!\n\n`;
message += `${result.data}`;
this.showOutput(message, 'success');
} else {
this.showOutput(`检查失败: ${result.message}`, 'error');
}
} catch (error) {
this.showOutput(`检查未完成文件时出错: ${error.message}`, 'error');
} finally {
this.setLoading(false);
}
}
async cleanFiles() {
try {
this.setLoading(true);
this.showOutput('正在清理日志和JSON文件...', 'info');
const response = await fetch('/clean_files', {
method: 'POST'
});
const result = await response.json();
if (result.success) {
let message = `清理完成!成功删除 ${result.deleted_count} 个文件\n\n`;
if (result.deleted_files && result.deleted_files.length > 0) {
message += "已删除的文件:\n" + result.deleted_files.join('\n');
}
this.showOutput(message, 'success');
} else {
let message = `清理完成,但有 ${result.error_count} 个文件删除失败\n\n`;
if (result.deleted_files && result.deleted_files.length > 0) {
message += "已删除的文件:\n" + result.deleted_files.join('\n') + '\n\n';
}
if (result.error_files && result.error_files.length > 0) {
message += "删除失败的文件:\n" + result.error_files.join('\n');
}
this.showOutput(message, 'error');
}
} catch (error) {
this.showOutput(`清理文件时出错: ${error.message}`, 'error');
} finally {
this.setLoading(false);
}
}
showOutput(message, type = '') {
this.output.textContent = message;
this.output.className = 'output-area';
if (type) {
this.output.classList.add(type);
}
// 自动滚动到底部
this.output.scrollTop = this.output.scrollHeight;
}
setLoading(loading) {
const buttons = this.form.querySelectorAll('button');
buttons.forEach(button => {
button.disabled = loading;
});
if (loading) {
document.body.classList.add('loading');
} else {
document.body.classList.remove('loading');
}
}
}
// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
new DownloadTool();
});