diff --git a/web/app.py b/web/app.py index fbc3579..b3d3023 100644 --- a/web/app.py +++ b/web/app.py @@ -47,6 +47,50 @@ def get_safe_path(requested_path): if is_path_allowed(requested_path): return requested_path return ALLOWED_BASE_DIR +def kill_all_services(): + """ + 杀死所有frpc_linux和python ./p2pfile.py相关的进程 + """ + killed_processes = [] + + try: + # 查找并杀死所有frpc_linux进程 + for proc in psutil.process_iter(['pid', 'name', 'cmdline']): + try: + if proc.info['cmdline'] and any('frpc_linux' in part for part in proc.info['cmdline']): + proc.terminate() + killed_processes.append(f"frpc_linux (PID: {proc.info['pid']})") + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + # 查找并杀死所有python p2pfile.py进程 + for proc in psutil.process_iter(['pid', 'name', 'cmdline']): + try: + if (proc.info['cmdline'] and + 'python' in proc.info['cmdline'] and + any('p2pfile.py' in part for part in proc.info['cmdline'])): + proc.terminate() + killed_processes.append(f"p2pfile.py (PID: {proc.info['pid']})") + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + # 等待一段时间让进程结束 + time.sleep(1) + + # 强制杀死任何仍然运行的进程 + for proc in psutil.process_iter(['pid', 'name', 'cmdline']): + try: + if (proc.info['cmdline'] and + (any('frpc_linux' in part for part in proc.info['cmdline']) or + ('python' in proc.info['cmdline'] and any('p2pfile.py' in part for part in proc.info['cmdline'])))): + proc.kill() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + return killed_processes + + except Exception as e: + return [f"错误: {str(e)}"] @app.route('/') def index(): @@ -665,6 +709,7 @@ def check_file(): except Exception as e: return jsonify({'status': 'error', 'message': f'检查文件失败: {str(e)}'}) + if __name__ == '__main__': print("启动蜗牛文件传输Web服务...") print(f"允许访问的目录: {ALLOWED_BASE_DIR}") diff --git a/web/static/css/style.css b/web/static/css/style.css index 8c05af9..ce8e7a1 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -514,4 +514,27 @@ body { .button-group .btn { width: 100%; } + + /* 添加停止所有服务按钮样式 */ + .btn-warning { + background-color: #ffc107; + color: #212529; + } + + .btn-warning:hover { + background-color: #e0a800; + color: #212529; + } + + /* 按钮组样式调整 */ + .button-group { + display: flex; + gap: 10px; + margin: 20px 0; + flex-wrap: wrap; + } + + .button-group .btn { + margin: 5px 0; + } } \ No newline at end of file diff --git a/web/static/css/style.css.bak b/web/static/css/style.css.bak deleted file mode 100644 index 9a2195b..0000000 --- a/web/static/css/style.css.bak +++ /dev/null @@ -1,517 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Microsoft YaHei', sans-serif; - background-color: white; - color: #2c3e50; - line-height: 1.6; -} - -.container { - max-width: 1000px; - margin: 0 auto; - padding: 20px; -} - -.screen { - display: none; -} - -.screen.active { - display: block; -} - -.logo-area { - text-align: center; - margin: 30px 0; -} - -.logo-area h1 { - font-size: 24px; - font-weight: bold; - margin-bottom: 5px; -} - -.logo-area p { - font-size: 14px; - color: #7f8c8d; -} - -.card-container { - display: flex; - justify-content: center; - gap: 30px; - margin: 40px 0; -} - -.card { - background-color: #f8f9fa; - border: 1px solid #ddd; - border-radius: 8px; - padding: 25px; - margin-top: 10px; -} - -.card-icon { - font-size: 40px; - margin-bottom: 15px; -} - -.card h3 { - font-size: 18px; - margin-bottom: 10px; -} - -.card p { - font-size: 12px; - color: #7f8c8d; - margin-bottom: 20px; -} - -.footer { - text-align: center; - margin-top: 40px; - color: #bdc3c7; - font-size: 12px; -} - -.header { - display: flex; - align-items: center; - margin-bottom: 20px; -} - -.header h2 { - margin-left: 15px; -} - -.input-group { - display: flex; - align-items: center; - margin-bottom: 15px; -} - -.input-group label { - width: 100px; - font-weight: bold; -} - -.input-group input { - flex: 1; - padding: 8px 12px; - border: 1px solid #ddd; - border-radius: 4px; - margin: 0 10px; -} - -.button-group { - display: flex; - gap: 10px; - margin: 20px 0; -} - -.status { - margin: 15px 0; -} - -.output-container { - background-color: #ffffff; - border: 1px solid #ddd; - border-radius: 4px; - padding: 15px; - max-height: 500px; - overflow-y: auto; -} - -.output-container pre { - white-space: pre-wrap; - font-family: Consolas, monospace; - font-size: 12px; -} - -.btn { - padding: 10px 15px; - border: none; - border-radius: 4px; - cursor: pointer; - font-weight: bold; - font-family: 'Microsoft YaHei', sans-serif; -} - -.btn-primary { - background-color: #3498db; - color: white; -} - -.btn-success { - background-color: #2ecc71; - color: white; -} - -.btn-danger { - background-color: #e74c3c; - color: white; -} - -.btn-secondary { - background-color: #95a5a6; - color: white; -} - -.btn-purple { - background-color: #8e44ad; - color: white; -} - -.btn-small { - padding: 5px 10px; - font-size: 12px; -} - -.btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.modal { - display: none; - position: fixed; - z-index: 1000; - left: 0; - top: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); -} - - -.modal-content { - background-color: white; - margin: 5% auto; - padding: 0; - border-radius: 8px; - width: 80%; - max-width: 600px; -} - -.modal-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px 20px; - border-bottom: 1px solid #ddd; -} - -.modal-header h3 { - margin: 0; -} - -.close { - font-size: 24px; - font-weight: bold; - cursor: pointer; -} - -.modal-body { - padding: 20px; - max-height: 400px; - overflow-y: auto; -} - -.path-navigation { - display: flex; - align-items: center; - margin-bottom: 15px; -} - -.path-navigation span { - margin-left: 15px; - font-family: monospace; -} - -.file-list { - border: 1px solid #ddd; - border-radius: 4px; - max-height: 300px; - overflow-y: auto; -} - -.file-item { - padding: 10px; - border-bottom: 1px solid #eee; - cursor: pointer; -} - -.file-item:hover { - background-color: #f5f5f5; -} - -.file-item.selected { - background-color: #e3f2fd; -} - -.file-item:last-child { - border-bottom: none; -} - -.modal-footer { - padding: 15px 20px; - border-top: 1px solid #ddd; - text-align: right; -} -/* 原有样式保持不变 */ - -.search-controls { - margin-bottom: 20px; - padding: 15px; - background-color: #f8f9fa; - border-radius: 4px; -} - -.search-controls .input-group { - margin-bottom: 10px; -} - -.search-results { - margin-top: 20px; -} - -.search-results h4 { - margin-bottom: 10px; - color: #2c3e50; -} - -.file-item { - padding: 10px; - border-bottom: 1px solid #eee; - cursor: pointer; -} - -.file-item:hover { - background-color: #f5f5f5; -} - -.file-item.selected { - background-color: #e3f2fd; -} - -.file-item .file-path { - font-size: 12px; - color: #7f8c8d; - margin-top: 5px; -} - -.file-item:last-child { - border-bottom: none; -} - - -/* 添加文件信息显示样式 */ -.file-info { - margin: 15px 0; - padding: 12px; - background-color: #f8f9fa; - border-radius: 4px; - border: 1px solid #e9ecef; -} - -.file-info-item { - margin: 5px 0; - font-size: 13px; - color: #6c757d; - display: flex; - justify-content: space-between; -} - -.file-info-item span { - font-weight: 500; - color: #495057; -} - -.file-status-valid { - color: #28a745 !important; -} - -.file-status-invalid { - color: #dc3545 !important; -} - -.file-status-unknown { - color: #6c757d !important; -} - -/* 输入框组样式调整 */ -.input-group { - display: flex; - align-items: center; - margin-bottom: 12px; -} - -.input-group label { - width: 100px; - font-weight: bold; - margin-right: 10px; - flex-shrink: 0; -} - -.input-group input { - flex: 1; - padding: 8px 12px; - border: 1px solid #ced4da; - border-radius: 4px; - margin: 0 10px; - font-family: 'Microsoft YaHei', sans-serif; -} - -.input-group input:focus { - outline: none; - border-color: #80bdff; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); -} - -.input-group .btn-small { - padding: 8px 12px; - font-size: 12px; - white-space: nowrap; -} - -/* 按钮样式调整 */ -.btn { - padding: 10px 16px; - border: none; - border-radius: 4px; - cursor: pointer; - font-weight: bold; - font-family: 'Microsoft YaHei', sans-serif; - transition: all 0.2s; -} - -.btn:hover { - opacity: 0.9; - transform: translateY(-1px); -} - -.btn:active { - transform: translateY(0); -} - -.btn-small { - padding: 6px 12px; - font-size: 12px; -} - -/* 模态框样式调整 */ -.modal-content { - max-width: 900px; - max-height: 80vh; - display: flex; - flex-direction: column; -} - -.modal-body { - flex: 1; - overflow-y: auto; - max-height: 60vh; - padding: 20px; -} - -/* 文件列表样式 */ -.file-list { - max-height: 300px; - overflow-y: auto; - border: 1px solid #dee2e6; - border-radius: 4px; - margin-top: 10px; -} - -.file-item { - padding: 10px 12px; - border-bottom: 1px solid #e9ecef; - cursor: pointer; - transition: background-color 0.15s; -} - -.file-item:hover { - background-color: #f8f9fa; -} - -.file-item.selected { - background-color: #e3f2fd; - border-left: 4px solid #2196f3; -} - -.file-item:last-child { - border-bottom: none; -} - -/* 搜索结果显示 */ -.file-name { - font-weight: 600; - color: #2c3e50; - margin-bottom: 4px; -} - -.file-details { - display: flex; - justify-content: space-between; - font-size: 12px; - color: #6c757d; -} - -.file-path { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.file-size { - margin-left: 10px; - color: #495057; - font-weight: 500; -} - -/* 加载状态 */ -.loading { - text-align: center; - padding: 30px; - color: #6c757d; - font-style: italic; -} - -.no-results { - text-align: center; - padding: 30px; - color: #6c757d; - font-style: italic; -} - -/* 响应式设计 */ -@media (max-width: 768px) { - .input-group { - flex-direction: column; - align-items: stretch; - } - - .input-group label { - width: auto; - margin-bottom: 5px; - } - - .input-group input { - margin: 5px 0; - } - - .button-group { - flex-direction: column; - gap: 8px; - } - - .button-group .btn { - width: 100%; - } -} \ No newline at end of file diff --git a/web/static/js/script.js b/web/static/js/script.js index e56f374..e29273f 100644 --- a/web/static/js/script.js +++ b/web/static/js/script.js @@ -37,7 +37,13 @@ document.addEventListener('DOMContentLoaded', function() { const filePathInput = document.getElementById('send-file-path'); filePathInput.addEventListener('input', updateFileInfo); filePathInput.addEventListener('change', updateFileInfo); - + + // 确保停止所有服务按钮在所有页面都可用 + const stopAllButtons = document.querySelectorAll('[onclick="stopAllServices()"]'); + stopAllButtons.forEach(btn => { + btn.addEventListener('click', stopAllServices); + }); + // 初始更新文件信息 updateFileInfo(); }); @@ -518,4 +524,53 @@ function selectItem() { document.getElementById('search-path').value = path; closeModal(); } -} \ No newline at end of file +} + + +// 停止所有服务 +function stopAllServices() { + if (confirm('确定要停止所有服务吗?这将终止所有文件传输和连接进程。')) { + fetch('/stop/all', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + alert('所有服务已停止'); + // 更新按钮状态 + document.getElementById('send-connect-btn').disabled = false; + document.getElementById('send-file-btn').disabled = true; + document.getElementById('send-stop-btn').disabled = true; + document.getElementById('receive-connect-btn').disabled = false; + document.getElementById('receive-stop-btn').disabled = true; + + // 更新状态显示 + document.getElementById('send-status').textContent = '已停止'; + document.getElementById('receive-status').textContent = '已停止'; + } else { + alert('停止服务失败: ' + data.message); + } + }) + .catch(error => { + console.error('Error:', error); + alert('停止服务失败: ' + error); + }); + } +} + +// 监听服务停止事件 +socket.on('service_stopped', function(data) { + // 更新按钮状态 + document.getElementById('send-connect-btn').disabled = false; + document.getElementById('send-file-btn').disabled = true; + document.getElementById('send-stop-btn').disabled = true; + document.getElementById('receive-connect-btn').disabled = false; + document.getElementById('receive-stop-btn').disabled = true; + + // 更新状态显示 + document.getElementById('send-status').textContent = '已停止'; + document.getElementById('receive-status').textContent = '已停止'; +}); diff --git a/web/static/js/script.js.bak b/web/static/js/script.js.bak deleted file mode 100644 index 9a5561e..0000000 --- a/web/static/js/script.js.bak +++ /dev/null @@ -1,521 +0,0 @@ -// 全局变量 -let socket = null; -let currentModalType = ''; -let selectedItem = null; -let currentPath = ''; -let searchResults = []; - -// 初始化Socket连接 -document.addEventListener('DOMContentLoaded', function() { - socket = io(); - - // 监听发送输出 - socket.on('send_output', function(data) { - const output = document.getElementById('send-output'); - output.textContent += data.message; - output.scrollTop = output.scrollHeight; - }); - - // 监听发送状态 - socket.on('send_status', function(data) { - document.getElementById('send-status').textContent = data.status; - }); - - // 监听接收输出 - socket.on('receive_output', function(data) { - const output = document.getElementById('receive-output'); - output.textContent += data.message; - output.scrollTop = output.scrollHeight; - }); - - // 监听接收状态 - socket.on('receive_status', function(data) { - document.getElementById('receive-status').textContent = data.status; - }); - - // 监听文件路径输入变化 - const filePathInput = document.getElementById('send-file-path'); - filePathInput.addEventListener('input', updateFileInfo); - filePathInput.addEventListener('change', updateFileInfo); - - // 初始更新文件信息 - updateFileInfo(); -}); - -// 更新文件信息 -function updateFileInfo() { - const filePath = document.getElementById('send-file-path').value.trim(); - const fileSizeElement = document.getElementById('file-size'); - const fileMtimeElement = document.getElementById('file-mtime'); - const fileStatusElement = document.getElementById('file-status'); - - if (!filePath) { - fileSizeElement.textContent = '-'; - fileMtimeElement.textContent = '-'; - fileStatusElement.textContent = '未选择'; - fileStatusElement.className = 'file-status-unknown'; - return; - } - - // 检查文件是否存在 - fetch('/check/file', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - body: JSON.stringify({ file_path: filePath }) - }) - .then(response => { - const contentType = response.headers.get('content-type'); - if (!contentType || !contentType.includes('application/json')) { - return response.text().then(text => { - throw new Error('服务器返回了非JSON响应'); - }); - } - return response.json(); - }) - .then(data => { - if (data.status === 'success') { - fileSizeElement.textContent = formatFileSize(data.size); - fileMtimeElement.textContent = new Date(data.mtime * 1000).toLocaleString(); - fileStatusElement.textContent = '文件有效'; - fileStatusElement.className = 'file-status-valid'; - } else { - fileSizeElement.textContent = '-'; - fileMtimeElement.textContent = '-'; - fileStatusElement.textContent = '文件不存在或无法访问'; - fileStatusElement.className = 'file-status-invalid'; - } - }) - .catch(error => { - console.error('检查文件错误:', error); - fileSizeElement.textContent = '-'; - fileMtimeElement.textContent = '-'; - fileStatusElement.textContent = '检查失败'; - fileStatusElement.className = 'file-status-invalid'; - }); -} - -// 手动浏览文件 -function browseFileManually() { - currentModalType = 'send'; - currentPath = document.getElementById('send-file-path').value || '/'; - const filePath = document.getElementById('send-file-path').value; - - if (filePath) { - try { - const dirPath = require('path').dirname(filePath); - if (require('fs').existsSync(dirPath)) { - currentPath = dirPath; - } - } catch (e) { - // 忽略错误,使用默认路径 - } - } - - fetchFileList(currentPath, 'file'); - document.getElementById('file-browser-modal').style.display = 'block'; -} - - -// 显示指定界面 -function showScreen(screenId) { - document.querySelectorAll('.screen').forEach(screen => { - screen.classList.remove('active'); - }); - document.getElementById(screenId).classList.add('active'); -} - - -// 发送连接 -function sendConnect() { - const key = document.getElementById('send-key').value; - - fetch('/send/connect', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ key: key }) - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - document.getElementById('send-connect-btn').disabled = true; - document.getElementById('send-stop-btn').disabled = false; - // 3秒后启用发送文件按钮 - setTimeout(() => { - document.getElementById('send-file-btn').disabled = false; - }, 3000); - } else { - alert('错误: ' + data.message); - } - }) - .catch(error => { - console.error('Error:', error); - alert('连接失败: ' + error); - }); -} - -// 发送文件 -function sendFile() { - const filePath = document.getElementById('send-file-path').value; - const key = document.getElementById('send-key').value; - const parts = key.split('|'); - const psk = parts.length >= 3 ? parts[2].trim() : ''; - - fetch('/send/file', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - file_path: filePath, - psk: psk - }) - }) - .then(response => response.json()) - .then(data => { - if (data.status !== 'success') { - alert('错误: ' + data.message); - } - }) - .catch(error => { - console.error('Error:', error); - alert('发送失败: ' + error); - }); -} - -// 停止发送 -function sendStop() { - fetch('/send/stop', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - } - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - document.getElementById('send-connect-btn').disabled = false; - document.getElementById('send-file-btn').disabled = true; - document.getElementById('send-stop-btn').disabled = true; - } - }) - .catch(error => { - console.error('Error:', error); - }); -} - -// 接收连接 -function receiveConnect() { - const key = document.getElementById('receive-key').value; - const savePath = document.getElementById('receive-save-path').value; - - fetch('/receive/connect', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - key: key, - save_path: savePath - }) - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - document.getElementById('receive-connect-btn').disabled = true; - document.getElementById('receive-stop-btn').disabled = false; - } else { - alert('错误: ' + data.message); - } - }) - .catch(error => { - console.error('Error:', error); - alert('连接失败: ' + error); - }); -} - -// 停止接收 -function receiveStop() { - fetch('/receive/stop', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - } - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - document.getElementById('receive-connect-btn').disabled = false; - document.getElementById('receive-stop-btn').disabled = true; - } - }) - .catch(error => { - console.error('Error:', error); - }); -} - -// 打开搜索模态框 -function openSearchModal() { - document.getElementById('file-search-modal').style.display = 'block'; - document.getElementById('search-path').value = '/'; - document.getElementById('search-keyword').value = '*'; - document.getElementById('search-results-list').innerHTML = ''; - document.getElementById('result-count').textContent = '0'; - document.getElementById('search-select-btn').disabled = true; - selectedItem = null; - searchResults = []; -} - -// 关闭搜索模态框 -function closeSearchModal() { - document.getElementById('file-search-modal').style.display = 'none'; -} - -// 浏览搜索路径 -function browseSearchPath() { - currentModalType = 'search_path'; - currentPath = document.getElementById('search-path').value || '/'; - - fetchFileList(currentPath, 'folder'); - document.getElementById('file-browser-modal').style.display = 'block'; -} - -// 开始搜索 -function startSearch() { - const searchPath = document.getElementById('search-path').value; - const keyword = document.getElementById('search-keyword').value; - const maxResults = document.getElementById('max-results').value; - - if (!keyword) { - alert('请输入搜索关键词'); - return; - } - - // 显示加载状态 - const resultsList = document.getElementById('search-results-list'); - resultsList.innerHTML = '
搜索中...
'; - - fetch('/search/files', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - body: JSON.stringify({ - path: searchPath, - pattern: keyword, - max_results: parseInt(maxResults) - }) - }) - .then(response => { - const contentType = response.headers.get('content-type'); - if (!contentType || !contentType.includes('application/json')) { - return response.text().then(text => { - throw new Error(`服务器返回了非JSON响应: ${text.substring(0, 100)}...`); - }); - } - return response.json(); - }) - .then(data => { - if (data.status === 'success') { - searchResults = data.results; - displaySearchResults(data.results); - document.getElementById('result-count').textContent = data.count; - } else { - alert('搜索失败: ' + data.message); - resultsList.innerHTML = '
搜索失败
'; - } - }) - .catch(error => { - console.error('搜索错误:', error); - alert('搜索失败: ' + error.message); - resultsList.innerHTML = '
搜索错误
'; - }); -} - -// 显示搜索结果 -function displaySearchResults(results) { - const resultsList = document.getElementById('search-results-list'); - resultsList.innerHTML = ''; - - if (results.length === 0) { - resultsList.innerHTML = '
未找到匹配的文件
'; - return; - } - - results.forEach(result => { - const div = document.createElement('div'); - div.className = 'file-item'; - - const fileSize = formatFileSize(result.size || 0); - - div.innerHTML = ` -
📄 ${result.name}
-
- ${result.relative_path} - ${fileSize} -
- `; - div.dataset.path = result.path; - - div.addEventListener('click', function() { - // 取消之前的选择 - document.querySelectorAll('.file-item.selected').forEach(el => { - el.classList.remove('selected'); - }); - - // 选择当前项 - this.classList.add('selected'); - selectedItem = this; - document.getElementById('search-select-btn').disabled = false; - }); - - resultsList.appendChild(div); - }); -} - - -// 格式化文件大小 -function formatFileSize(bytes) { - if (bytes === 0) return '0 B'; - const k = 1024; - const sizes = ['B', 'KB', 'MB', 'GB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; -} - -// 选择搜索结果 -function selectSearchResult() { - if (!selectedItem) { - alert('请先选择一个文件'); - return; - } - - const filePath = selectedItem.dataset.path; - document.getElementById('send-file-path').value = filePath; - closeSearchModal(); - updateFileInfo(); // 更新文件信息显示 -} - -// 获取文件列表 -function fetchFileList(path, type) { - fetch('/browse', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - body: JSON.stringify({ - path: path, - type: type - }) - }) - .then(response => { - const contentType = response.headers.get('content-type'); - if (!contentType || !contentType.includes('application/json')) { - return response.text().then(text => { - throw new Error(`服务器返回了非JSON响应: ${text.substring(0, 100)}...`); - }); - } - return response.json(); - }) - .then(data => { - if (data.status === 'success') { - currentPath = data.current_path; - document.getElementById('current-path').textContent = currentPath; - - const fileList = document.getElementById('file-list'); - fileList.innerHTML = ''; - - data.items.forEach(item => { - const div = document.createElement('div'); - div.className = 'file-item'; - div.innerHTML = item.type === 'folder' ? - `📁 ${item.name}` : `📄 ${item.name}`; - div.dataset.path = item.path; - div.dataset.type = item.type; - - div.addEventListener('click', function() { - // 取消之前的选择 - document.querySelectorAll('.file-item.selected').forEach(el => { - el.classList.remove('selected'); - }); - - // 选择当前项 - this.classList.add('selected'); - selectedItem = this; - - // 如果是文件夹,双击进入 - this.addEventListener('dblclick', function() { - if (item.type === 'folder') { - if (currentModalType === 'search_path') { - document.getElementById('search-path').value = item.path; - closeModal(); - } else { - fetchFileList(item.path, type); - } - } - }); - }); - - fileList.appendChild(div); - }); - } else { - alert('错误: ' + data.message); - } - }) - .catch(error => { - console.error('Error:', error); - alert('获取文件列表失败: ' + error.message); - }); -} - -// 导航到上级目录 -function navigateUp() { - const parentPath = currentPath.split('/').slice(0, -1).join('/'); - if (parentPath === '') { - currentPath = '/'; - } else { - currentPath = parentPath; - } - - const type = currentModalType === 'send' ? 'file' : 'folder'; - fetchFileList(currentPath, type); -} - -// 关闭模态框 -function closeModal() { - document.getElementById('file-browser-modal').style.display = 'none'; - selectedItem = null; -} - -// 选择文件或文件夹 -function selectItem() { - if (!selectedItem) { - alert('请先选择一个项目'); - return; - } - - const path = selectedItem.dataset.path; - const type = selectedItem.dataset.type; - - if (currentModalType === 'send') { - if (type === 'file') { - document.getElementById('send-file-path').value = path; - closeModal(); - updateFileInfo(); // 更新文件信息显示 - } else { - alert('请选择一个文件'); - } - } else if (currentModalType === 'folder') { - document.getElementById('receive-save-path').value = path; - closeModal(); - } else if (currentModalType === 'search_path') { - document.getElementById('search-path').value = path; - closeModal(); - } -} \ No newline at end of file diff --git a/web/templates/index.html b/web/templates/index.html index 8c59e99..b8e83c5 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -73,6 +73,7 @@ +
@@ -111,6 +112,7 @@
+
diff --git a/web/templates/index.html.bak b/web/templates/index.html.bak deleted file mode 100644 index 2617e2d..0000000 --- a/web/templates/index.html.bak +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - 蜗牛创造的高速文件传输 - - - - - -
- -
-
-

🐌 欢迎来到蜗牛创造的高速世界

-

安全、高速的文件传输解决方案

-
- -
-
-
📤
-

发送文件

-

快速安全地发送文件

- -
- -
-
📥
-

接收文件

-

安全可靠地接收文件

- -
-
- - -
- - -
-
- -

📤 文件发送

-
- -
-
- - -
- -
- - - -
- -
- - - -
- -
-
文件大小: -
-
修改时间: -
-
文件状态: 未选择
-
- -
- - - -
- -
-

📊 状态: 等待连接

-
-
- -
-

📋 发送日志:

-
-
等待输入密钥并选择文件...
-密钥格式应为: token|sk|psk|sern
-
-
-
- - -
-
- -

📥 文件接收

-
- -
-
- - -
- -
- - - -
- -
- - -
- -
-

📊 状态: 等待连接

-
-
- -
-

📋 接收日志:

-
-
等待输入密钥并连接...
-密钥格式应为: token|sk|psk|sern
-文件将保存到: 网络挂载/本地存储/下载/
-
-
-
- - - - - - -
- - - - \ No newline at end of file