|
|
|
|
@ -23,10 +23,268 @@ class OpenRankDashboard {
|
|
|
|
|
this.updateLastUpdateTime();
|
|
|
|
|
this.setupTabNavigation();
|
|
|
|
|
this.setupModeSwitch();
|
|
|
|
|
this.setupCodeReviewPage();
|
|
|
|
|
// 默认显示开发者分析数据
|
|
|
|
|
this.displayDeveloperAnalysis(this.mockData.developers);
|
|
|
|
|
this.hydrateFromURL();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置代码测评页面功能
|
|
|
|
|
setupCodeReviewPage() {
|
|
|
|
|
// 运行Pylint测评按钮
|
|
|
|
|
document.getElementById('run-lint-btn')?.addEventListener('click', () => {
|
|
|
|
|
this.runCodeLinting();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 清空代码按钮
|
|
|
|
|
document.getElementById('clear-code-btn')?.addEventListener('click', () => {
|
|
|
|
|
const codeInput = document.getElementById('python-code-input');
|
|
|
|
|
if (codeInput) {
|
|
|
|
|
codeInput.value = '';
|
|
|
|
|
this.resetCodeReviewResults();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 加载示例按钮
|
|
|
|
|
document.getElementById('load-example-btn')?.addEventListener('click', () => {
|
|
|
|
|
this.loadExampleCode();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载示例代码
|
|
|
|
|
loadExampleCode() {
|
|
|
|
|
const exampleCode = `def calculate_average(numbers):
|
|
|
|
|
"""计算数字列表的平均值"""
|
|
|
|
|
if not numbers:
|
|
|
|
|
return 0
|
|
|
|
|
total = sum(numbers)
|
|
|
|
|
return total / len(numbers)
|
|
|
|
|
|
|
|
|
|
def get_user_name():
|
|
|
|
|
name = input("请输入您的名字: ")
|
|
|
|
|
print(f"你好, {name}!")
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
# 主程序
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
user = get_user_name()
|
|
|
|
|
scores = [85, 90, 78, 92, 88]
|
|
|
|
|
avg = calculate_average(scores)
|
|
|
|
|
print(f"平均分数是: {avg}")`;
|
|
|
|
|
|
|
|
|
|
const codeInput = document.getElementById('python-code-input');
|
|
|
|
|
if (codeInput) {
|
|
|
|
|
codeInput.value = exampleCode;
|
|
|
|
|
this.resetCodeReviewResults();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重置代码测评结果
|
|
|
|
|
resetCodeReviewResults() {
|
|
|
|
|
document.getElementById('code-score').textContent = '0';
|
|
|
|
|
document.getElementById('score-quality').textContent = '待评分';
|
|
|
|
|
document.getElementById('score-quality').className = 'score-quality';
|
|
|
|
|
document.getElementById('issues-count').textContent = '0';
|
|
|
|
|
document.getElementById('issues-list').innerHTML = '<p class="empty-message">请运行测评查看代码中的问题</p>';
|
|
|
|
|
document.getElementById('lint-summary').innerHTML = '<p class="empty-message">请运行测评查看代码质量总结</p>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 运行代码测评
|
|
|
|
|
runCodeLinting() {
|
|
|
|
|
const codeInput = document.getElementById('python-code-input');
|
|
|
|
|
if (!codeInput || !codeInput.value.trim()) {
|
|
|
|
|
this.showNotification('请先输入Python代码', 'error');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 模拟Pylint测评过程
|
|
|
|
|
this.simulatePylintAnalysis(codeInput.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 模拟Pylint分析(由于浏览器限制,使用模拟数据)
|
|
|
|
|
simulatePylintAnalysis(code) {
|
|
|
|
|
// 这里使用模拟数据,实际项目中应该调用后端API
|
|
|
|
|
const codeLines = code.split('\n');
|
|
|
|
|
|
|
|
|
|
// 根据代码内容生成模拟的Pylint问题
|
|
|
|
|
const issues = [];
|
|
|
|
|
|
|
|
|
|
// 检查是否有未使用的导入(模拟)
|
|
|
|
|
if (code.includes('import') && !code.includes('from ')) {
|
|
|
|
|
issues.push({
|
|
|
|
|
type: 'info',
|
|
|
|
|
message: '导入了模块但未使用',
|
|
|
|
|
line: 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否有函数缺少文档字符串(模拟)
|
|
|
|
|
let inFunction = false;
|
|
|
|
|
let functionStartLine = 0;
|
|
|
|
|
codeLines.forEach((line, index) => {
|
|
|
|
|
if (line.trim().startsWith('def ')) {
|
|
|
|
|
inFunction = true;
|
|
|
|
|
functionStartLine = index + 1;
|
|
|
|
|
} else if (inFunction && line.trim().startsWith('#') || line.trim().startsWith('"""')) {
|
|
|
|
|
inFunction = false;
|
|
|
|
|
} else if (inFunction && line.trim() && !line.trim().startsWith(' ') && !line.trim().startsWith('#')) {
|
|
|
|
|
issues.push({
|
|
|
|
|
type: 'warning',
|
|
|
|
|
message: '缺少函数文档字符串',
|
|
|
|
|
line: functionStartLine
|
|
|
|
|
});
|
|
|
|
|
inFunction = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查行长度(模拟)
|
|
|
|
|
codeLines.forEach((line, index) => {
|
|
|
|
|
if (line.length > 79) {
|
|
|
|
|
issues.push({
|
|
|
|
|
type: 'warning',
|
|
|
|
|
message: '行长度超过79个字符',
|
|
|
|
|
line: index + 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查是否有print语句(模拟)
|
|
|
|
|
codeLines.forEach((line, index) => {
|
|
|
|
|
if (line.includes('print(') && !line.includes('"""') && !line.includes("''")) {
|
|
|
|
|
issues.push({
|
|
|
|
|
type: 'info',
|
|
|
|
|
message: '考虑使用logging模块替代print语句',
|
|
|
|
|
line: index + 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查是否有input语句(模拟)
|
|
|
|
|
codeLines.forEach((line, index) => {
|
|
|
|
|
if (line.includes('input(')) {
|
|
|
|
|
issues.push({
|
|
|
|
|
type: 'warning',
|
|
|
|
|
message: '生产环境中应避免使用input()函数',
|
|
|
|
|
line: index + 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 生成随机的额外问题(增加模拟真实性)
|
|
|
|
|
const randomIssues = [
|
|
|
|
|
{ type: 'info', message: '考虑添加类型提示以提高代码可读性', line: Math.floor(Math.random() * codeLines.length) + 1 },
|
|
|
|
|
{ type: 'warning', message: '变量名可以更具描述性', line: Math.floor(Math.random() * codeLines.length) + 1 },
|
|
|
|
|
{ type: 'info', message: '考虑添加单元测试', line: 1 }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// 随机添加1-2个额外问题
|
|
|
|
|
const additionalIssues = Math.floor(Math.random() * 2) + 1;
|
|
|
|
|
for (let i = 0; i < additionalIssues; i++) {
|
|
|
|
|
issues.push(randomIssues[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算分数(基于问题数量和严重性)
|
|
|
|
|
let score = 10;
|
|
|
|
|
issues.forEach(issue => {
|
|
|
|
|
if (issue.type === 'error') score -= 3;
|
|
|
|
|
else if (issue.type === 'warning') score -= 1;
|
|
|
|
|
else if (issue.type === 'info') score -= 0.5;
|
|
|
|
|
});
|
|
|
|
|
score = Math.max(0, Math.min(10, score));
|
|
|
|
|
score = Math.round(score * 10) / 10; // 保留一位小数
|
|
|
|
|
|
|
|
|
|
// 显示结果
|
|
|
|
|
this.displayLintResults(score, issues);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 显示测评结果
|
|
|
|
|
displayLintResults(score, issues) {
|
|
|
|
|
// 更新分数显示
|
|
|
|
|
const scoreElement = document.getElementById('code-score');
|
|
|
|
|
const qualityElement = document.getElementById('score-quality');
|
|
|
|
|
|
|
|
|
|
scoreElement.textContent = score.toString();
|
|
|
|
|
|
|
|
|
|
// 设置质量等级
|
|
|
|
|
let qualityText = '优秀';
|
|
|
|
|
let qualityClass = 'excellent';
|
|
|
|
|
|
|
|
|
|
if (score >= 9) {
|
|
|
|
|
qualityText = '优秀';
|
|
|
|
|
qualityClass = 'excellent';
|
|
|
|
|
} else if (score >= 7) {
|
|
|
|
|
qualityText = '良好';
|
|
|
|
|
qualityClass = 'good';
|
|
|
|
|
} else if (score >= 5) {
|
|
|
|
|
qualityText = '一般';
|
|
|
|
|
qualityClass = 'average';
|
|
|
|
|
} else {
|
|
|
|
|
qualityText = '需改进';
|
|
|
|
|
qualityClass = 'poor';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qualityElement.textContent = qualityText;
|
|
|
|
|
qualityElement.className = `score-quality ${qualityClass}`;
|
|
|
|
|
|
|
|
|
|
// 更新CSS样式以反映不同的质量等级
|
|
|
|
|
if (qualityClass === 'excellent') {
|
|
|
|
|
qualityElement.style.background = 'rgba(0, 255, 0, 0.2)';
|
|
|
|
|
qualityElement.style.border = '1px solid rgba(0, 255, 0, 0.3)';
|
|
|
|
|
qualityElement.style.color = '#66ff99';
|
|
|
|
|
} else if (qualityClass === 'good') {
|
|
|
|
|
qualityElement.style.background = 'rgba(0, 212, 255, 0.2)';
|
|
|
|
|
qualityElement.style.border = '1px solid rgba(0, 212, 255, 0.3)';
|
|
|
|
|
qualityElement.style.color = '#00d4ff';
|
|
|
|
|
} else if (qualityClass === 'average') {
|
|
|
|
|
qualityElement.style.background = 'rgba(255, 165, 0, 0.2)';
|
|
|
|
|
qualityElement.style.border = '1px solid rgba(255, 165, 0, 0.3)';
|
|
|
|
|
qualityElement.style.color = '#ffcc66';
|
|
|
|
|
} else {
|
|
|
|
|
qualityElement.style.background = 'rgba(255, 0, 0, 0.2)';
|
|
|
|
|
qualityElement.style.border = '1px solid rgba(255, 0, 0, 0.3)';
|
|
|
|
|
qualityElement.style.color = '#ff6b6b';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新问题列表
|
|
|
|
|
document.getElementById('issues-count').textContent = issues.length.toString();
|
|
|
|
|
const issuesList = document.getElementById('issues-list');
|
|
|
|
|
|
|
|
|
|
if (issues.length === 0) {
|
|
|
|
|
issuesList.innerHTML = '<p class="empty-message">代码质量良好,未发现问题</p>';
|
|
|
|
|
} else {
|
|
|
|
|
// 按行号排序
|
|
|
|
|
issues.sort((a, b) => a.line - b.line);
|
|
|
|
|
|
|
|
|
|
issuesList.innerHTML = issues.map(issue => `
|
|
|
|
|
<div class="issue-item">
|
|
|
|
|
<div class="issue-header">
|
|
|
|
|
<span class="issue-type ${issue.type}">${issue.type === 'error' ? '错误' : issue.type === 'warning' ? '警告' : '信息'}</span>
|
|
|
|
|
<span class="issue-line">第 ${issue.line} 行</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="issue-message">${issue.message}</div>
|
|
|
|
|
</div>
|
|
|
|
|
`).join('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成总结
|
|
|
|
|
const summaryElement = document.getElementById('lint-summary');
|
|
|
|
|
const errorCount = issues.filter(i => i.type === 'error').length;
|
|
|
|
|
const warningCount = issues.filter(i => i.type === 'warning').length;
|
|
|
|
|
const infoCount = issues.filter(i => i.type === 'info').length;
|
|
|
|
|
|
|
|
|
|
summaryElement.innerHTML = `
|
|
|
|
|
<ul>
|
|
|
|
|
<li><i class="fas fa-check-circle"></i> 代码评分: ${score}/10 (${qualityText})</li>
|
|
|
|
|
<li><i class="fas fa-exclamation-circle"></i> 发现 ${errorCount} 个错误</li>
|
|
|
|
|
<li><i class="fas fa-exclamation-triangle"></i> 发现 ${warningCount} 个警告</li>
|
|
|
|
|
<li><i class="fas fa-info-circle"></i> 发现 ${infoCount} 个建议</li>
|
|
|
|
|
<li><i class="fas fa-code"></i> 代码行数: ${document.getElementById('python-code-input').value.split('\n').length}</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<p style="margin-top: 1rem;">
|
|
|
|
|
${score >= 7 ? '代码整体质量良好,继续保持!' : '建议根据提示改进代码质量。'}
|
|
|
|
|
</p>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置事件监听器
|
|
|
|
|
setupEventListeners() {
|
|
|
|
|
|