// 全局变量 let uploadedFiles = []; let isChecking = false; let checkProgress = 0; let currentProject = null; let projects = []; // API 基础URL const API_BASE_URL = 'http://localhost:5000/api'; // DOM 元素 const uploadArea = document.getElementById('uploadArea'); const fileInput = document.getElementById('fileInput'); const progressContainer = document.getElementById('progressContainer'); const progressFill = document.getElementById('progressFill'); const progressText = document.getElementById('progressText'); const startCheckBtn = document.getElementById('startCheckBtn'); const stopCheckBtn = document.getElementById('stopCheckBtn'); const resultsSection = document.getElementById('resultsSection'); const resultsContent = document.getElementById('resultsContent'); // 页面切换功能 const navLinks = document.querySelectorAll('.nav-link'); const pageContents = document.querySelectorAll('.page-content'); navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetPage = link.getAttribute('href').substring(1); showPage(targetPage); // 更新导航状态 navLinks.forEach(l => l.classList.remove('active')); link.classList.add('active'); }); }); function showPage(pageId) { pageContents.forEach(page => { page.classList.remove('active'); }); const targetPage = document.getElementById(pageId + '-page'); if (targetPage) { targetPage.classList.add('active'); // 根据页面加载相应数据 switch(pageId) { case 'dashboard': loadDashboardData(); break; case 'projects': loadProjects(); break; } } } // 文件上传处理 uploadArea.addEventListener('click', () => fileInput.click()); uploadArea.addEventListener('dragover', handleDragOver); uploadArea.addEventListener('dragleave', handleDragLeave); uploadArea.addEventListener('drop', handleDrop); fileInput.addEventListener('change', handleFileSelect); function handleDragOver(e) { e.preventDefault(); uploadArea.classList.add('dragover'); } function handleDragLeave(e) { e.preventDefault(); uploadArea.classList.remove('dragover'); } function handleDrop(e) { e.preventDefault(); uploadArea.classList.remove('dragover'); const files = Array.from(e.dataTransfer.files); processFiles(files); } function handleFileSelect(e) { const files = Array.from(e.target.files); processFiles(files); } function processFiles(files) { const validFiles = files.filter(file => file.name.endsWith('.py') || file.name.endsWith('.pyx') || file.name.endsWith('.pyi') ); if (validFiles.length === 0) { alert('请选择有效的 Python 文件!'); return; } uploadedFiles = validFiles; updateUploadArea(); startCheckBtn.style.display = 'inline-block'; } function updateUploadArea() { if (uploadedFiles.length > 0) { uploadArea.innerHTML = `
已选择 ${uploadedFiles.length} 个文件
${uploadedFiles.map(f => f.name).join(', ')}
`; } } // 开始检查 startCheckBtn.addEventListener('click', startCheck); stopCheckBtn.addEventListener('click', stopCheck); async function startCheck() { if (uploadedFiles.length === 0) { alert('请先上传文件!'); return; } isChecking = true; startCheckBtn.style.display = 'none'; stopCheckBtn.style.display = 'inline-block'; progressContainer.style.display = 'block'; resultsSection.style.display = 'none'; // 更新 Agent 状态 updateAgentStatus('working'); try { // 第一步:上传文件 updateProgress(10, '正在上传文件...'); const uploadResult = await uploadFiles(); if (!uploadResult || !uploadResult.success) { throw new Error(uploadResult?.error || '文件上传失败'); } // 第二步:开始代码检查 updateProgress(30, '开始代码检查...'); const checkResult = await runCodeCheck(uploadResult.data.temp_path); if (!checkResult || !checkResult.success) { throw new Error(checkResult?.error || '代码检查失败'); } // 第三步:处理检查结果 updateProgress(90, '处理检查结果...'); await processCheckResults(checkResult.data); // 第四步:完成检查 updateProgress(100, '检查完成!'); completeCheck(); } catch (error) { console.error('检查过程出错:', error); alert('检查失败:' + error.message); stopCheck(); } } function stopCheck() { isChecking = false; startCheckBtn.style.display = 'inline-block'; stopCheckBtn.style.display = 'none'; progressContainer.style.display = 'none'; // 更新 Agent 状态 updateAgentStatus('idle'); } function updateAgentStatus(status) { const agentItems = document.querySelectorAll('.agent-item'); agentItems.forEach(item => { const badge = item.querySelector('.agent-status-badge'); badge.className = `agent-status-badge status-${status}`; badge.textContent = status === 'working' ? '工作中' : status === 'completed' ? '完成' : '空闲'; }); } // 更新进度条 function updateProgress(progress, text) { progressFill.style.width = progress + '%'; progressText.textContent = text; } // 上传文件到服务器 async function uploadFiles() { try { if (uploadedFiles.length === 0) { throw new Error('没有选择要上传的文件'); } const formData = new FormData(); uploadedFiles.forEach(file => { formData.append('files', file); }); const response = await fetch(`${API_BASE_URL}/upload`, { method: 'POST', body: formData }); if (!response.ok) { throw new Error(`HTTP错误: ${response.status} ${response.statusText}`); } const result = await response.json(); return result; } catch (error) { console.error('上传文件时发生错误:', error); return { success: false, error: error.message || '网络连接失败,请检查后端服务是否正常运行' }; } } // 运行代码检查 async function runCodeCheck(tempPath) { try { const response = await fetch(`${API_BASE_URL}/check`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ temp_path: tempPath }) }); if (!response.ok) { throw new Error(`HTTP错误: ${response.status} ${response.statusText}`); } const result = await response.json(); return result; } catch (error) { console.error('代码检查时发生错误:', error); return { success: false, error: error.message || '代码检查失败,请检查后端服务是否正常运行' }; } } // 处理检查结果 async function processCheckResults(data) { // 更新统计信息 updateStatistics(data); // 更新工具状态 updateToolsStatus(data.tools_status); // 显示检查结果 displayResults(data.all_issues); // 更新Agent状态 updateAgentStatus('completed'); } // 更新统计信息 function updateStatistics(data) { // 更新仪表板上的统计数据 const totalFilesElement = document.getElementById('totalFiles'); const complianceRateElement = document.getElementById('complianceRate'); const pendingIssuesElement = document.getElementById('pendingIssues'); const highRiskIssuesElement = document.getElementById('highRiskIssues'); if (totalFilesElement) { // 这里可以计算实际检查的文件数 totalFilesElement.textContent = uploadedFiles.length; } if (pendingIssuesElement) { pendingIssuesElement.textContent = data.warning_count || 0; } if (highRiskIssuesElement) { highRiskIssuesElement.textContent = data.error_count || 0; } if (complianceRateElement) { const totalIssues = data.total_issues || 0; const complianceRate = totalIssues === 0 ? 100 : Math.max(0, 100 - (totalIssues * 2)); complianceRateElement.textContent = complianceRate.toFixed(1) + '%'; } console.log('检查结果统计:', { total_issues: data.total_issues, error_count: data.error_count, warning_count: data.warning_count, info_count: data.info_count }); } // 更新工具状态 function updateToolsStatus(toolsStatus) { const agentItems = document.querySelectorAll('.agent-item'); const toolNames = ['pylint', 'flake8', 'bandit']; agentItems.forEach((item, index) => { const badge = item.querySelector('.agent-status-badge'); const toolName = toolNames[index]; const status = toolsStatus && toolsStatus[toolName] ? toolsStatus[toolName] : 'error'; badge.className = `agent-status-badge status-${status}`; switch(status) { case 'completed': badge.textContent = '完成'; break; case 'error': badge.textContent = '错误'; break; case 'timeout': badge.textContent = '超时'; break; default: badge.textContent = '空闲'; } }); } // 查看问题详情 function viewIssueDetail(rule, message) { const detailModal = document.createElement('div'); detailModal.className = 'modal'; detailModal.style.display = 'block'; detailModal.innerHTML = ` `; document.body.appendChild(detailModal); } // 显示修复建议 function showFixSuggestion(rule, message) { const suggestions = { 'B608': '使用参数化查询替代字符串拼接,例如使用 cursor.execute("SELECT * FROM table WHERE id = %s", (user_id,))', 'E501': '将长行拆分为多行,使用括号或反斜杠进行换行', 'C0114': '为函数添加文档字符串,描述函数的功能、参数和返回值', 'W0613': '移除未使用的参数,或使用下划线前缀表示故意未使用的参数', 'default': '请参考相关代码规范文档,确保代码符合军事项目标准' }; const suggestion = suggestions[rule] || suggestions['default']; const suggestionModal = document.createElement('div'); suggestionModal.className = 'modal'; suggestionModal.style.display = 'block'; suggestionModal.innerHTML = ` `; document.body.appendChild(suggestionModal); } // 模拟检查函数已被真实的API调用替代 function completeCheck() { isChecking = false; startCheckBtn.style.display = 'inline-block'; stopCheckBtn.style.display = 'none'; progressContainer.style.display = 'none'; // 更新 Agent 状态 updateAgentStatus('completed'); // 显示结果区域 resultsSection.style.display = 'block'; } function showResults() { resultsSection.style.display = 'block'; // 结果现在通过 processCheckResults 函数处理 } function displayResults(results) { resultsContent.innerHTML = ''; if (!results || results.length === 0) { resultsContent.innerHTML = `

检查完成!

未发现任何问题,代码质量良好。

`; return; } // 添加结果摘要 const summaryHtml = createResultsSummary(results); resultsContent.innerHTML = summaryHtml; // 添加具体问题列表 const issuesContainer = document.createElement('div'); issuesContainer.style.marginTop = '20px'; results.forEach(result => { const resultItem = document.createElement('div'); resultItem.className = 'result-item'; // 根据问题类型确定图标和样式 const iconClass = result.type === 'error' ? 'times' : result.type === 'warning' ? 'exclamation-triangle' : 'info-circle'; // 格式化文件路径,只显示文件名 const fileName = result.file ? result.file.split('/').pop() : '未知文件'; const location = `${fileName}:${result.line}:${result.column || 0}`; resultItem.innerHTML = `
${result.message || '代码问题'}
规则: ${result.rule || '未知规则'} | 严重程度: ${result.severity || 'medium'} ${result.confidence ? ` | 置信度: ${result.confidence}` : ''}
${location}
`; issuesContainer.appendChild(resultItem); }); resultsContent.appendChild(issuesContainer); } // 创建结果摘要 function createResultsSummary(results) { const errorCount = results.filter(r => r.type === 'error').length; const warningCount = results.filter(r => r.type === 'warning').length; const infoCount = results.filter(r => r.type === 'info').length; const totalCount = results.length; return `

检查结果摘要

${errorCount}
错误
${warningCount}
警告
${infoCount}
信息
${totalCount}
总计
`; } // 结果过滤 const filterTabs = document.querySelectorAll('.filter-tab[data-filter]'); filterTabs.forEach(tab => { tab.addEventListener('click', () => { filterTabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); const filter = tab.dataset.filter; filterResults(filter); }); }); function filterResults(filter) { const resultItems = document.querySelectorAll('.result-item'); resultItems.forEach(item => { if (filter === 'all') { item.style.display = 'flex'; } else { const icon = item.querySelector('.result-icon'); const hasClass = icon.classList.contains(filter); item.style.display = hasClass ? 'flex' : 'none'; } }); } // 项目管理功能 async function loadProjects() { try { const response = await fetch(`${API_BASE_URL}/projects`); const data = await response.json(); if (data.success) { projects = data.data; displayProjects(projects); } else { console.error('加载项目失败:', data.error); // 显示模拟数据 displayMockProjects(); } } catch (error) { console.error('加载项目失败:', error); // 显示模拟数据 displayMockProjects(); } } function displayProjects(projects) { const projectsGrid = document.getElementById('projectsGrid'); if (!projectsGrid) return; projectsGrid.innerHTML = ''; projects.forEach(project => { const projectCard = document.createElement('div'); projectCard.className = 'project-card'; projectCard.addEventListener('click', () => showProjectDetail(project)); const statusText = project.status === 'active' ? '进行中' : project.status === 'completed' ? '已完成' : '待处理'; const latestCheck = project.latest_check; const totalIssues = latestCheck ? latestCheck.total_issues : 0; const errorCount = latestCheck ? latestCheck.error_count : 0; const lastCheckDate = latestCheck && latestCheck.completed_at ? new Date(latestCheck.completed_at).toLocaleDateString() : '从未检查'; projectCard.innerHTML = `
${project.name}
${project.description || '暂无描述'}
${statusText}
${totalIssues}
问题数
${errorCount}
错误数
${lastCheckDate}
最后检查
`; projectsGrid.appendChild(projectCard); }); } function displayMockProjects() { const mockProjects = [ { id: 1, name: '军事指挥系统', description: '基于Python的军事指挥控制系统,包含用户管理、权限控制、数据加密等模块', status: 'active', source_type: 'github', source_url: 'https://github.com/example/military-command-system.git', created_at: '2024-01-15T10:30:00Z', latest_check: { status: 'completed', total_issues: 12, error_count: 3, warning_count: 7, info_count: 2, completed_at: '2024-01-15T14:20:00Z' } }, { id: 2, name: '安全通信模块', description: '军用安全通信协议实现,支持端到端加密和身份验证', status: 'completed', source_type: 'gitee', source_url: 'https://gitee.com/example/secure-communication.git', created_at: '2024-01-14T09:15:00Z', latest_check: { status: 'completed', total_issues: 3, error_count: 0, warning_count: 2, info_count: 1, completed_at: '2024-01-14T16:45:00Z' } }, { id: 3, name: '数据分析平台', description: '军事数据分析和可视化平台,支持实时数据处理和报告生成', status: 'pending', source_type: 'upload', source_url: '', created_at: '2024-01-13T14:20:00Z', latest_check: { status: 'completed', total_issues: 28, error_count: 8, warning_count: 15, info_count: 5, completed_at: '2024-01-13T18:30:00Z' } } ]; displayProjects(mockProjects); } // 项目搜索功能 const projectSearch = document.getElementById('projectSearch'); if (projectSearch) { projectSearch.addEventListener('input', (e) => { const searchTerm = e.target.value.toLowerCase(); const filteredProjects = projects.filter(project => project.name.toLowerCase().includes(searchTerm) || (project.description && project.description.toLowerCase().includes(searchTerm)) ); displayProjects(filteredProjects); }); } // 新建项目功能 const createProjectBtn = document.getElementById('createProjectBtn'); const createProjectModal = document.getElementById('createProjectModal'); const cancelCreateProject = document.getElementById('cancelCreateProject'); const confirmCreateProject = document.getElementById('confirmCreateProject'); const closeModal = document.querySelector('.close'); if (createProjectBtn) { createProjectBtn.addEventListener('click', () => { createProjectModal.style.display = 'block'; }); } if (cancelCreateProject) { cancelCreateProject.addEventListener('click', () => { createProjectModal.style.display = 'none'; }); } if (closeModal) { closeModal.addEventListener('click', () => { createProjectModal.style.display = 'none'; }); } // 项目来源类型切换 const sourceTypeRadios = document.querySelectorAll('input[name="source_type"]'); const gitUrlGroup = document.getElementById('gitUrlGroup'); const fileUploadGroup = document.getElementById('fileUploadGroup'); sourceTypeRadios.forEach(radio => { radio.addEventListener('change', (e) => { if (e.target.value === 'upload') { gitUrlGroup.style.display = 'none'; fileUploadGroup.style.display = 'block'; } else { gitUrlGroup.style.display = 'block'; fileUploadGroup.style.display = 'none'; } }); }); // 文件上传选择反馈 const fileUploadInput = document.getElementById('fileUpload'); if (fileUploadInput) { fileUploadInput.addEventListener('change', (e) => { const files = e.target.files; if (files.length > 0) { // 显示选择的文件信息 const fileInfo = document.createElement('div'); fileInfo.className = 'file-info'; fileInfo.style.cssText = ` margin-top: 10px; padding: 10px; background: #f8f9fa; border-radius: 4px; border-left: 4px solid #28a745; `; let fileList = ''; for (let i = 0; i < Math.min(files.length, 5); i++) { fileList += `
• ${files[i].webkitRelativePath || files[i].name}
`; } if (files.length > 5) { fileList += `
... 还有 ${files.length - 5} 个文件
`; } fileInfo.innerHTML = `
已选择 ${files.length} 个文件
${fileList}
`; // 移除之前的文件信息 const existingInfo = fileUploadGroup.querySelector('.file-info'); if (existingInfo) { existingInfo.remove(); } fileUploadGroup.appendChild(fileInfo); } }); } // 确认创建项目 if (confirmCreateProject) { confirmCreateProject.addEventListener('click', async () => { const form = document.getElementById('createProjectForm'); const formData = new FormData(form); const projectData = { name: formData.get('name'), description: formData.get('description'), source_type: formData.get('source_type'), source_url: formData.get('source_url') }; if (!projectData.name) { alert('请输入项目名称!'); return; } if (projectData.source_type !== 'upload' && !projectData.source_url) { alert('请输入Git URL!'); return; } // 检查文件上传 const fileInput = document.getElementById('fileUpload'); const files = fileInput.files; if (projectData.source_type === 'upload' && files.length === 0) { alert('请选择要上传的文件或文件夹!'); return; } try { // 第一步:创建项目 const response = await fetch(`${API_BASE_URL}/projects`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(projectData) }); const data = await response.json(); if (data.success) { // 第二步:如果是文件上传方式,上传文件到项目 if (projectData.source_type === 'upload' && files.length > 0) { const uploadFormData = new FormData(); for (let i = 0; i < files.length; i++) { uploadFormData.append('files', files[i]); } const uploadResponse = await fetch(`${API_BASE_URL}/projects/${data.data.id}/upload-files`, { method: 'POST', body: uploadFormData }); const uploadData = await uploadResponse.json(); if (uploadData.success) { alert(`项目创建成功!已上传 ${uploadData.uploaded_count} 个文件。`); } else { alert(`项目创建成功,但文件上传失败:${uploadData.error}`); } } else { alert('项目创建成功!'); } createProjectModal.style.display = 'none'; form.reset(); loadProjects(); // 重新加载项目列表 } else { alert('项目创建失败:' + data.error); } } catch (error) { console.error('创建项目失败:', error); alert('项目创建失败,请检查网络连接!'); } }); } // 显示项目详情 function showProjectDetail(project) { currentProject = project; // 更新页面标题 document.getElementById('projectDetailTitle').textContent = project.name; document.getElementById('projectDetailSubtitle').textContent = project.description || '查看项目信息和运行代码检查'; // 显示项目信息 const projectInfoContent = document.getElementById('projectInfoContent'); projectInfoContent.innerHTML = `
${project.name}
${project.description || '暂无描述'}
${project.source_type === 'github' ? 'GitHub' : project.source_type === 'gitee' ? 'Gitee' : '文件上传'}
${project.source_url || '无'}
${new Date(project.created_at).toLocaleString()}
${project.status === 'active' ? '进行中' : project.status === 'completed' ? '已完成' : '待处理'}
`; // 显示检查历史 displayCheckHistory(project); // 加载文件浏览器 loadProjectFiles(); // 切换到项目详情页面 showPage('project-detail'); } // 显示检查历史 function displayCheckHistory(project) { const checkHistoryContent = document.getElementById('checkHistoryContent'); // 模拟检查历史数据 const mockChecks = [ { id: 1, check_type: 'combined', status: 'completed', started_at: '2024-01-15T14:20:00Z', completed_at: '2024-01-15T14:25:00Z', total_issues: 12, error_count: 3, warning_count: 7, info_count: 2 }, { id: 2, check_type: 'combined', status: 'completed', started_at: '2024-01-14T10:15:00Z', completed_at: '2024-01-14T10:20:00Z', total_issues: 15, error_count: 5, warning_count: 8, info_count: 2 } ]; checkHistoryContent.innerHTML = ''; mockChecks.forEach(check => { const checkItem = document.createElement('div'); checkItem.className = 'check-history-item'; checkItem.innerHTML = `
${check.check_type} 检查
${new Date(check.started_at).toLocaleString()} - 发现问题: ${check.total_issues} (错误: ${check.error_count}, 警告: ${check.warning_count})
`; checkHistoryContent.appendChild(checkItem); }); } // 运行项目检查 async function runProjectCheck(projectId) { try { const response = await fetch(`${API_BASE_URL}/projects/${projectId}/check`, { method: 'POST' }); const data = await response.json(); if (data.success) { alert('检查已开始,请稍候查看结果!'); // 刷新项目详情 if (currentProject && currentProject.id === projectId) { showProjectDetail(currentProject); } } else { alert('检查启动失败:' + data.error); } } catch (error) { console.error('运行检查失败:', error); alert('检查启动失败,请检查网络连接!'); } } // 删除项目 async function deleteProject(projectId, projectName) { // 显示确认对话框 showDeleteConfirmDialog(projectId, projectName); } // 显示删除确认对话框 function showDeleteConfirmDialog(projectId, projectName) { const confirmModal = document.createElement('div'); confirmModal.className = 'modal'; confirmModal.style.display = 'block'; confirmModal.innerHTML = ` `; document.body.appendChild(confirmModal); } // 确认删除项目 async function confirmDeleteProject(projectId, projectName) { try { const response = await fetch(`${API_BASE_URL}/projects/${projectId}`, { method: 'DELETE' }); const data = await response.json(); if (data.success) { // 显示成功消息 showSuccessMessage('项目删除成功!'); // 重新加载项目列表 loadProjects(); // 如果当前查看的是被删除的项目,返回项目列表页面 if (currentProject && currentProject.id === projectId) { showPage('projects'); } } else { showErrorMessage('项目删除失败:' + data.error); } } catch (error) { console.error('删除项目失败:', error); showErrorMessage('删除项目失败,请检查网络连接!'); } } // 显示成功消息 function showSuccessMessage(message) { const messageDiv = document.createElement('div'); messageDiv.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 6px; padding: 15px 20px; z-index: 3000; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: flex; align-items: center; gap: 10px; `; messageDiv.innerHTML = ` ${message} `; document.body.appendChild(messageDiv); setTimeout(() => { messageDiv.remove(); }, 3000); } // 显示错误消息 function showErrorMessage(message) { const messageDiv = document.createElement('div'); messageDiv.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; border-radius: 6px; padding: 15px 20px; z-index: 3000; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: flex; align-items: center; gap: 10px; `; messageDiv.innerHTML = ` ${message} `; document.body.appendChild(messageDiv); setTimeout(() => { messageDiv.remove(); }, 5000); } // 查看检查结果 function viewCheckResults(checkId) { // 模拟检查结果数据 const mockResults = [ { id: 1, file_path: 'src/database.py', line_number: 45, column_number: 12, issue_type: 'error', severity: 'high', rule_id: 'B608', message: 'SQL注入风险:使用字符串拼接构建SQL查询', suggestion: '建议使用参数化查询或ORM' }, { id: 2, file_path: 'src/utils.py', line_number: 23, column_number: 1, issue_type: 'warning', severity: 'medium', rule_id: 'E501', message: '行长度超过120字符限制', suggestion: '建议将长行拆分为多行' } ]; const checkResultsContent = document.getElementById('checkResultsContent'); checkResultsContent.innerHTML = ''; mockResults.forEach(result => { const resultItem = document.createElement('div'); resultItem.className = 'result-item'; resultItem.innerHTML = `
${result.message}
${result.suggestion}
${result.file_path}:${result.line_number}:${result.column_number}
`; checkResultsContent.appendChild(resultItem); }); // 显示检查结果面板 document.getElementById('checkResultsPanel').style.display = 'block'; } // 返回项目列表 const backToProjectsBtn = document.getElementById('backToProjectsBtn'); if (backToProjectsBtn) { backToProjectsBtn.addEventListener('click', () => { showPage('projects'); }); } // 运行检查按钮 const runCheckBtn = document.getElementById('runCheckBtn'); if (runCheckBtn) { runCheckBtn.addEventListener('click', () => { if (currentProject) { runProjectCheck(currentProject.id); } }); } // 删除项目按钮 const deleteProjectBtn = document.getElementById('deleteProjectBtn'); if (deleteProjectBtn) { deleteProjectBtn.addEventListener('click', () => { if (currentProject) { deleteProject(currentProject.id, currentProject.name); } }); } // 仪表板数据加载 function loadDashboardData() { // 这里可以加载真实的统计数据 // 目前使用模拟数据 console.log('加载仪表板数据'); } // 文件浏览器相关变量 let currentFilePath = ''; let currentFileContent = ''; let isFileModified = false; // 加载项目文件 async function loadProjectFiles(path = '') { if (!currentProject) return; try { const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files?path=${encodeURIComponent(path)}`); const data = await response.json(); if (data.success) { displayFileTree(data.data); updateCurrentPath(path); } else { showErrorMessage('加载文件列表失败:' + data.error); } } catch (error) { console.error('加载文件列表失败:', error); showErrorMessage('加载文件列表失败,请检查网络连接!'); } } // 显示文件树 function displayFileTree(files) { const fileTree = document.getElementById('fileTree'); fileTree.innerHTML = ''; if (files.length === 0) { fileTree.innerHTML = '
此目录为空
'; return; } files.forEach(file => { const fileItem = document.createElement('div'); fileItem.className = 'file-item'; fileItem.onclick = () => handleFileClick(file); const iconClass = getFileIconClass(file.name, file.is_directory); fileItem.innerHTML = `
${file.name}
${file.is_directory ? '' : formatFileSize(file.size)}
`; fileTree.appendChild(fileItem); }); } // 获取文件图标类 function getFileIconClass(fileName, isDirectory) { if (isDirectory) return 'folder'; const ext = fileName.split('.').pop().toLowerCase(); switch (ext) { case 'py': return 'python'; case 'js': return 'js'; case 'css': return 'css'; case 'html': case 'htm': return 'html'; default: return 'file'; } } // 格式化文件大小 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(1)) + ' ' + sizes[i]; } // 处理文件点击 function handleFileClick(file) { if (file.is_directory) { // 如果是目录,进入目录 loadProjectFiles(file.path); } else { // 如果是文件,打开文件 openFile(file.path); } } // 打开文件 async function openFile(filePath) { if (!currentProject) return; try { const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files/content?path=${encodeURIComponent(filePath)}`); const data = await response.json(); if (data.success) { currentFilePath = filePath; currentFileContent = data.data.content; isFileModified = false; // 显示代码编辑器 showCodeEditor(filePath, data.data.content); } else { showErrorMessage('打开文件失败:' + data.error); } } catch (error) { console.error('打开文件失败:', error); showErrorMessage('打开文件失败,请检查网络连接!'); } } // 显示代码编辑器 function showCodeEditor(filePath, content) { const editorPanel = document.getElementById('codeEditorPanel'); const editor = document.getElementById('codeEditor'); const editorTitle = document.getElementById('editorTitle'); const currentFilePathSpan = document.getElementById('currentFilePath'); editor.value = content; editorTitle.textContent = `编辑文件 - ${filePath.split('/').pop()}`; currentFilePathSpan.textContent = filePath; editorPanel.style.display = 'block'; // 监听内容变化 editor.oninput = () => { isFileModified = true; }; } // 更新当前路径显示 function updateCurrentPath(path) { const currentPathSpan = document.getElementById('currentPath'); currentPathSpan.textContent = path || '/'; } // 保存文件 async function saveFile() { if (!currentProject || !currentFilePath) return; const editor = document.getElementById('codeEditor'); const content = editor.value; try { const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files/content`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ path: currentFilePath, content: content }) }); const data = await response.json(); if (data.success) { isFileModified = false; showSuccessMessage('文件保存成功!'); } else { showErrorMessage('保存文件失败:' + data.error); } } catch (error) { console.error('保存文件失败:', error); showErrorMessage('保存文件失败,请检查网络连接!'); } } // 关闭编辑器 function closeEditor() { if (isFileModified) { const confirmed = confirm('文件已修改,确定要关闭吗?未保存的更改将丢失。'); if (!confirmed) return; } const editorPanel = document.getElementById('codeEditorPanel'); editorPanel.style.display = 'none'; currentFilePath = ''; currentFileContent = ''; isFileModified = false; } // 页面加载动画 document.addEventListener('DOMContentLoaded', () => { const fadeElements = document.querySelectorAll('.fade-in'); fadeElements.forEach((element, index) => { setTimeout(() => { element.style.opacity = '1'; element.style.transform = 'translateY(0)'; }, index * 200); }); // 默认显示仪表板页面 showPage('dashboard'); // 初始化各个页面 loadProjects(); // 绑定文件浏览器事件 bindFileBrowserEvents(); }); // 绑定文件浏览器事件 function bindFileBrowserEvents() { // 保存文件按钮 const saveFileBtn = document.getElementById('saveFileBtn'); if (saveFileBtn) { saveFileBtn.addEventListener('click', saveFile); } // 关闭编辑器按钮 const closeEditorBtn = document.getElementById('closeEditorBtn'); if (closeEditorBtn) { closeEditorBtn.addEventListener('click', closeEditor); } // 上传文件按钮 const uploadFileBtn = document.getElementById('uploadFileBtn'); if (uploadFileBtn) { uploadFileBtn.addEventListener('click', showUploadDialog); } // 新建文件按钮 const createFileBtn = document.getElementById('createFileBtn'); if (createFileBtn) { createFileBtn.addEventListener('click', showCreateFileDialog); } // 新建文件夹按钮 const createFolderBtn = document.getElementById('createFolderBtn'); if (createFolderBtn) { createFolderBtn.addEventListener('click', showCreateFolderDialog); } // 键盘快捷键 document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 's') { e.preventDefault(); if (currentFilePath) { saveFile(); } } }); } // 显示上传文件对话框 function showUploadDialog() { const input = document.createElement('input'); input.type = 'file'; input.multiple = true; input.onchange = (e) => { const files = Array.from(e.target.files); if (files.length > 0) { uploadProjectFiles(files); } }; input.click(); } // 上传文件到项目 async function uploadProjectFiles(files) { if (!currentProject) return; const currentPath = document.getElementById('currentPath').textContent; const targetPath = currentPath === '/' ? '' : currentPath; for (const file of files) { const formData = new FormData(); formData.append('file', file); formData.append('path', targetPath); try { const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files/upload`, { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { showSuccessMessage(`文件 ${file.name} 上传成功!`); } else { showErrorMessage(`文件 ${file.name} 上传失败:${data.error}`); } } catch (error) { console.error('上传文件失败:', error); showErrorMessage(`文件 ${file.name} 上传失败,请检查网络连接!`); } } // 刷新文件列表 loadProjectFiles(targetPath); } // 显示新建文件对话框 function showCreateFileDialog() { const fileName = prompt('请输入文件名(包含扩展名):'); if (fileName) { createFile(fileName); } } // 创建文件 async function createFile(fileName) { if (!currentProject) return; const currentPath = document.getElementById('currentPath').textContent; const filePath = currentPath === '/' ? fileName : `${currentPath}/${fileName}`; try { const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files/content`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ path: filePath, content: '' }) }); const data = await response.json(); if (data.success) { showSuccessMessage('文件创建成功!'); loadProjectFiles(currentPath); } else { showErrorMessage('文件创建失败:' + data.error); } } catch (error) { console.error('创建文件失败:', error); showErrorMessage('创建文件失败,请检查网络连接!'); } } // 显示新建文件夹对话框 function showCreateFolderDialog() { const folderName = prompt('请输入文件夹名称:'); if (folderName) { createFolder(folderName); } } // 创建文件夹 async function createFolder(folderName) { if (!currentProject) return; const currentPath = document.getElementById('currentPath').textContent; const folderPath = currentPath === '/' ? folderName : `${currentPath}/${folderName}`; try { // 通过创建一个隐藏文件来创建文件夹 const response = await fetch(`${API_BASE_URL}/projects/${currentProject.id}/files/content`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ path: `${folderPath}/.gitkeep`, content: '' }) }); const data = await response.json(); if (data.success) { showSuccessMessage('文件夹创建成功!'); loadProjectFiles(currentPath); } else { showErrorMessage('文件夹创建失败:' + data.error); } } catch (error) { console.error('创建文件夹失败:', error); showErrorMessage('创建文件夹失败,请检查网络连接!'); } } // 通知功能 const notification = document.querySelector('.notification'); if (notification) { notification.addEventListener('click', () => { alert('您有 3 条新通知:\n1. 检查任务已完成\n2. 发现 5 个高危漏洞\n3. 系统维护通知'); }); } // 点击模态框外部关闭 window.addEventListener('click', (e) => { const modal = document.getElementById('createProjectModal'); if (e.target === modal) { modal.style.display = 'none'; } });