341 lines
12 KiB
HTML
341 lines
12 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>开源项目质量分析系统 - 红山开源平台</title>
|
|||
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|||
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
|||
|
|
<style>
|
|||
|
|
:root {
|
|||
|
|
--primary-color: #4a90e2;
|
|||
|
|
--success-color: #28a745;
|
|||
|
|
--warning-color: #ffc107;
|
|||
|
|
--danger-color: #dc3545;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
body {
|
|||
|
|
background: linear-gradient(135deg, #3f275fff 0%, #e5bb6dff 100%);
|
|||
|
|
min-height: 100vh;
|
|||
|
|
font-family: 'Microsoft YaHei', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hero-section {
|
|||
|
|
padding: 60px 0;
|
|||
|
|
color: white;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hero-section h1 {
|
|||
|
|
font-size: 3rem;
|
|||
|
|
font-weight: bold;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hero-section p {
|
|||
|
|
font-size: 1.3rem;
|
|||
|
|
opacity: 0.9;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.main-card {
|
|||
|
|
background: white;
|
|||
|
|
border-radius: 15px;
|
|||
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|||
|
|
padding: 40px;
|
|||
|
|
margin-bottom: 30px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.feature-box {
|
|||
|
|
text-align: center;
|
|||
|
|
padding: 30px;
|
|||
|
|
margin: 20px 0;
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
transition: transform 0.3s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.feature-box:hover {
|
|||
|
|
transform: translateY(-5px);
|
|||
|
|
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.feature-box i {
|
|||
|
|
font-size: 3rem;
|
|||
|
|
color: var(--primary-color);
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn-analyze {
|
|||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|||
|
|
border: none;
|
|||
|
|
padding: 15px 40px;
|
|||
|
|
font-size: 1.1rem;
|
|||
|
|
font-weight: bold;
|
|||
|
|
border-radius: 50px;
|
|||
|
|
color: white;
|
|||
|
|
transition: all 0.3s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn-analyze:hover {
|
|||
|
|
transform: translateY(-2px);
|
|||
|
|
box-shadow: 0 5px 20px rgba(0,0,0,0.3);
|
|||
|
|
color: white;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.analysis-type-card {
|
|||
|
|
border: 2px solid #e0e0e0;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
padding: 20px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.3s;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.analysis-type-card:hover {
|
|||
|
|
border-color: var(--primary-color);
|
|||
|
|
background: #f8f9ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.analysis-type-card.active {
|
|||
|
|
border-color: var(--primary-color);
|
|||
|
|
background: #f0f4ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading-overlay {
|
|||
|
|
position: fixed;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
background: rgba(0,0,0,0.7);
|
|||
|
|
display: none;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
z-index: 9999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading-content {
|
|||
|
|
text-align: center;
|
|||
|
|
color: white;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.spinner {
|
|||
|
|
border: 5px solid #f3f3f3;
|
|||
|
|
border-top: 5px solid var(--primary-color);
|
|||
|
|
border-radius: 50%;
|
|||
|
|
width: 60px;
|
|||
|
|
height: 60px;
|
|||
|
|
animation: spin 1s linear infinite;
|
|||
|
|
margin: 0 auto 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@keyframes spin {
|
|||
|
|
0% { transform: rotate(0deg); }
|
|||
|
|
100% { transform: rotate(360deg); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.footer {
|
|||
|
|
background: rgba(0,0,0,0.2);
|
|||
|
|
color: white;
|
|||
|
|
padding: 30px 0;
|
|||
|
|
margin-top: 50px;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<!-- Hero Section -->
|
|||
|
|
<div class="hero-section">
|
|||
|
|
<div class="container">
|
|||
|
|
<h1><i class="bi bi-graph-up-arrow"></i> 开源项目质量分析系统</h1>
|
|||
|
|
<p>基于九格大模型的智能分析 · 为红山开源平台赋能</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Main Content -->
|
|||
|
|
<div class="container">
|
|||
|
|
<div class="main-card">
|
|||
|
|
<h2 class="text-center mb-4">开始分析您的项目</h2>
|
|||
|
|
|
|||
|
|
<form id="analysisForm">
|
|||
|
|
<div class="row">
|
|||
|
|
<div class="col-md-6">
|
|||
|
|
<div class="analysis-type-card" data-type="github" onclick="selectAnalysisType('github')">
|
|||
|
|
<i class="bi bi-github" style="font-size: 3rem; color: #333;"></i>
|
|||
|
|
<h4>GitHub 仓库分析</h4>
|
|||
|
|
<p class="text-muted">输入GitHub仓库URL进行在线分析</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-6">
|
|||
|
|
<div class="analysis-type-card" data-type="upload" onclick="selectAnalysisType('upload')">
|
|||
|
|
<i class="bi bi-cloud-upload" style="font-size: 3rem; color: var(--primary-color);"></i>
|
|||
|
|
<h4>上传项目文件</h4>
|
|||
|
|
<p class="text-muted">上传项目压缩包进行本地分析</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<input type="hidden" id="analysisType" name="analysis_type" value="">
|
|||
|
|
|
|||
|
|
<!-- GitHub Input -->
|
|||
|
|
<div id="githubInput" style="display: none;">
|
|||
|
|
<div class="mb-3">
|
|||
|
|
<label for="repoUrl" class="form-label">GitHub 仓库 URL</label>
|
|||
|
|
<input type="url" class="form-control form-control-lg" id="repoUrl" name="repo_url"
|
|||
|
|
placeholder="https://github.com/username/repository">
|
|||
|
|
<div class="form-text">示例: https://github.com/flask/flask</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- File Upload -->
|
|||
|
|
<div id="uploadInput" style="display: none;">
|
|||
|
|
<div class="mb-3">
|
|||
|
|
<label for="fileUpload" class="form-label">选择项目压缩包</label>
|
|||
|
|
<input type="file" class="form-control form-control-lg" id="fileUpload" name="file"
|
|||
|
|
accept=".zip,.tar,.tar.gz,.tgz">
|
|||
|
|
<div class="form-text">支持 .zip, .tar, .tar.gz 格式,最大100MB</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="text-center mt-4">
|
|||
|
|
<button type="submit" class="btn btn-analyze" id="analyzeBtn">
|
|||
|
|
<i class="bi bi-play-circle"></i> 开始分析
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Features -->
|
|||
|
|
<div class="row mt-5">
|
|||
|
|
<div class="col-md-3">
|
|||
|
|
<div class="feature-box">
|
|||
|
|
<i class="bi bi-code-square"></i>
|
|||
|
|
<h5>代码质量</h5>
|
|||
|
|
<p>深度分析代码结构和可维护性</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-3">
|
|||
|
|
<div class="feature-box">
|
|||
|
|
<i class="bi bi-book"></i>
|
|||
|
|
<h5>文档完整性</h5>
|
|||
|
|
<p>评估文档的完整性和规范性</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-3">
|
|||
|
|
<div class="feature-box">
|
|||
|
|
<i class="bi bi-activity"></i>
|
|||
|
|
<h5>项目活跃度</h5>
|
|||
|
|
<p>分析提交频率和社区参与度</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-3">
|
|||
|
|
<div class="feature-box">
|
|||
|
|
<i class="bi bi-robot"></i>
|
|||
|
|
<h5>AI智能建议</h5>
|
|||
|
|
<p>基于九格大模型提供改进建议</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Loading Overlay -->
|
|||
|
|
<div class="loading-overlay" id="loadingOverlay">
|
|||
|
|
<div class="loading-content">
|
|||
|
|
<div class="spinner"></div>
|
|||
|
|
<h3>正在分析项目...</h3>
|
|||
|
|
<p>这可能需要几分钟时间,请耐心等待</p>
|
|||
|
|
<div id="loadingStatus">初始化分析...</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Footer -->
|
|||
|
|
<div class="footer">
|
|||
|
|
<div class="container text-center">
|
|||
|
|
<p>© 2025 红山开源平台 - 开源项目质量分析系统</p>
|
|||
|
|
<p>基于九格大模型技术支持</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
|||
|
|
<script>
|
|||
|
|
function selectAnalysisType(type) {
|
|||
|
|
// 更新选中状态
|
|||
|
|
document.querySelectorAll('.analysis-type-card').forEach(card => {
|
|||
|
|
card.classList.remove('active');
|
|||
|
|
});
|
|||
|
|
document.querySelector(`[data-type="${type}"]`).classList.add('active');
|
|||
|
|
|
|||
|
|
// 设置分析类型
|
|||
|
|
document.getElementById('analysisType').value = type;
|
|||
|
|
|
|||
|
|
// 显示对应的输入区域
|
|||
|
|
document.getElementById('githubInput').style.display = type === 'github' ? 'block' : 'none';
|
|||
|
|
document.getElementById('uploadInput').style.display = type === 'upload' ? 'block' : 'none';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
document.getElementById('analysisForm').addEventListener('submit', async function(e) {
|
|||
|
|
e.preventDefault();
|
|||
|
|
|
|||
|
|
const analysisType = document.getElementById('analysisType').value;
|
|||
|
|
if (!analysisType) {
|
|||
|
|
alert('请选择分析类型');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (analysisType === 'github') {
|
|||
|
|
const repoUrl = document.getElementById('repoUrl').value;
|
|||
|
|
if (!repoUrl) {
|
|||
|
|
alert('请输入GitHub仓库URL');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
} else if (analysisType === 'upload') {
|
|||
|
|
const fileUpload = document.getElementById('fileUpload').files[0];
|
|||
|
|
if (!fileUpload) {
|
|||
|
|
alert('请选择要上传的文件');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示加载动画
|
|||
|
|
document.getElementById('loadingOverlay').style.display = 'flex';
|
|||
|
|
|
|||
|
|
// 构建FormData
|
|||
|
|
const formData = new FormData(this);
|
|||
|
|
|
|||
|
|
// 更新加载状态
|
|||
|
|
updateLoadingStatus('正在上传项目文件...');
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const response = await fetch('/analyze', {
|
|||
|
|
method: 'POST',
|
|||
|
|
body: formData
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
updateLoadingStatus('正在分析代码质量...');
|
|||
|
|
|
|||
|
|
const result = await response.json();
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
updateLoadingStatus('分析完成!正在跳转到报告页面...');
|
|||
|
|
// 跳转到报告页面
|
|||
|
|
setTimeout(() => {
|
|||
|
|
window.location.href = '/report/' + result.project_name;
|
|||
|
|
}, 1000);
|
|||
|
|
} else {
|
|||
|
|
alert('分析失败: ' + (result.error || '未知错误'));
|
|||
|
|
document.getElementById('loadingOverlay').style.display = 'none';
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Error:', error);
|
|||
|
|
alert('分析过程中出现错误: ' + error.message);
|
|||
|
|
document.getElementById('loadingOverlay').style.display = 'none';
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
function updateLoadingStatus(status) {
|
|||
|
|
document.getElementById('loadingStatus').textContent = status;
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|