Compare commits
No commits in common. 'main' and 'main' have entirely different histories.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,51 +0,0 @@
|
||||
# Node.js
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# 项目特定
|
||||
projects_data/
|
||||
out/
|
||||
*.log
|
||||
|
||||
# 临时文件
|
||||
*.tmp
|
||||
*.temp
|
||||
temp_*.py
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# 环境变量
|
||||
.env
|
||||
.env.local
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
{
|
||||
"useLocalAi": false,
|
||||
"selectedModelId": null
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "model_1763556444768_81a9s6dh0",
|
||||
"name": "qwen:7b",
|
||||
"description": "测试",
|
||||
"apiUrl": "http://localhost:11434/v1",
|
||||
"createdAt": "2025-11-19T12:47:24.768Z",
|
||||
"filePath": null
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,202 +0,0 @@
|
||||
const API_BASE_URL = window.location.origin + '/api';
|
||||
|
||||
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 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 = `<i class="fas fa-check-circle"></i><span>${message}</span>`;
|
||||
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 = `<i class="fas fa-exclamation-circle"></i><span>${message}</span>`;
|
||||
document.body.appendChild(messageDiv);
|
||||
setTimeout(() => messageDiv.remove(), 5000);
|
||||
}
|
||||
|
||||
async function loadRules() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/rules`);
|
||||
const data = await response.json();
|
||||
if (!data.success) throw new Error(data.error || '加载失败');
|
||||
renderRulesList(data.data || []);
|
||||
} catch (e) {
|
||||
console.error('加载规则失败:', e);
|
||||
showErrorMessage('加载规则失败');
|
||||
}
|
||||
}
|
||||
|
||||
function renderRulesList(files) {
|
||||
const container = document.getElementById('rulesList');
|
||||
if (!container) return;
|
||||
container.innerHTML = '';
|
||||
if (!files.length) {
|
||||
container.innerHTML = '<div style="text-align:center; padding: 20px; color:#666;">暂无规则文件</div>';
|
||||
return;
|
||||
}
|
||||
files.forEach(f => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'project-card';
|
||||
const size = formatFileSize(f.size || 0);
|
||||
card.innerHTML = `
|
||||
<div class="project-header">
|
||||
<div>
|
||||
<div class="project-title">${f.name}</div>
|
||||
<div class="project-description">大小: ${size} | 更新: ${new Date(f.modified_at).toLocaleString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-actions">
|
||||
<button class="btn btn-secondary">编辑</button>
|
||||
<button class="btn btn-primary">下载</button>
|
||||
<button class="btn btn-danger">删除</button>
|
||||
</div>
|
||||
`;
|
||||
const [editBtn, downloadBtn, deleteBtn] = card.querySelectorAll('.project-actions .btn');
|
||||
editBtn.addEventListener('click', (e) => { e.stopPropagation(); editRule(f.name); });
|
||||
downloadBtn.addEventListener('click', (e) => { e.stopPropagation(); downloadRule(f.name); });
|
||||
deleteBtn.addEventListener('click', (e) => { e.stopPropagation(); deleteRule(f.name); });
|
||||
container.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function showRuleUploadDialog() {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.multiple = true;
|
||||
input.accept = '.cfg,.ini,.toml,.yaml,.yml,.json,.flake8,.pylintrc,setup.cfg,pyproject.toml,tox.ini';
|
||||
input.onchange = async (e) => {
|
||||
const files = Array.from(e.target.files || []);
|
||||
if (!files.length) return;
|
||||
const formData = new FormData();
|
||||
files.forEach(f => formData.append('files', f));
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE_URL}/rules/upload`, { method: 'POST', body: formData });
|
||||
const data = await resp.json();
|
||||
if (data.success) {
|
||||
showSuccessMessage('规则上传成功');
|
||||
loadRules();
|
||||
} else {
|
||||
showErrorMessage('规则上传失败:' + (data.error || ''));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('上传规则失败:', e);
|
||||
showErrorMessage('上传规则失败');
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
}
|
||||
|
||||
let currentEditingRule = '';
|
||||
|
||||
async function editRule(name) {
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE_URL}/rules/${encodeURIComponent(name)}`);
|
||||
const data = await resp.json();
|
||||
if (!data.success) throw new Error(data.error || '读取失败');
|
||||
currentEditingRule = name;
|
||||
document.getElementById('editRuleTitle').textContent = `编辑规则 - ${name}`;
|
||||
document.getElementById('editRuleTextarea').value = data.data.content || '';
|
||||
document.getElementById('editRuleModal').style.display = 'block';
|
||||
} catch (e) {
|
||||
console.error('读取规则失败:', e);
|
||||
showErrorMessage('读取规则失败');
|
||||
}
|
||||
}
|
||||
|
||||
function hideEditRuleModal() {
|
||||
const modal = document.getElementById('editRuleModal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
currentEditingRule = '';
|
||||
}
|
||||
|
||||
async function saveEditingRule() {
|
||||
if (!currentEditingRule) return;
|
||||
const content = document.getElementById('editRuleTextarea').value;
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE_URL}/rules/${encodeURIComponent(currentEditingRule)}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ content })
|
||||
});
|
||||
const data = await resp.json();
|
||||
if (data.success) {
|
||||
showSuccessMessage('保存成功');
|
||||
hideEditRuleModal();
|
||||
loadRules();
|
||||
} else {
|
||||
showErrorMessage('保存失败:' + (data.error || ''));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('保存规则失败:', e);
|
||||
showErrorMessage('保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteRule(name) {
|
||||
if (!confirm(`确定删除规则文件 "${name}" 吗?`)) return;
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE_URL}/rules/${encodeURIComponent(name)}`, { method: 'DELETE' });
|
||||
const data = await resp.json();
|
||||
if (data.success) {
|
||||
showSuccessMessage('删除成功');
|
||||
loadRules();
|
||||
} else {
|
||||
showErrorMessage('删除失败:' + (data.error || ''));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('删除规则失败:', e);
|
||||
showErrorMessage('删除失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadRule(name) {
|
||||
try {
|
||||
const resp = await fetch(`${API_BASE_URL}/rules/${encodeURIComponent(name)}`);
|
||||
const data = await resp.json();
|
||||
if (!data.success) throw new Error(data.error || '下载失败');
|
||||
const blob = new Blob([data.data.content || ''], { type: 'text/plain;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = name;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
a.remove();
|
||||
} catch (e) {
|
||||
console.error('下载规则失败:', e);
|
||||
showErrorMessage('下载失败');
|
||||
}
|
||||
}
|
||||
|
||||
function bindRulesEvents() {
|
||||
const uploadRuleBtn = document.getElementById('uploadRuleBtn');
|
||||
const refreshRuleBtn = document.getElementById('refreshRuleBtn');
|
||||
const closeEditRule = document.getElementById('closeEditRule');
|
||||
const cancelEditRule = document.getElementById('cancelEditRule');
|
||||
const saveRuleBtn = document.getElementById('saveRuleBtn');
|
||||
|
||||
if (uploadRuleBtn) uploadRuleBtn.addEventListener('click', showRuleUploadDialog);
|
||||
if (refreshRuleBtn) refreshRuleBtn.addEventListener('click', loadRules);
|
||||
if (closeEditRule) closeEditRule.addEventListener('click', hideEditRuleModal);
|
||||
if (cancelEditRule) cancelEditRule.addEventListener('click', hideEditRuleModal);
|
||||
if (saveRuleBtn) saveRuleBtn.addEventListener('click', saveEditingRule);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
bindRulesEvents();
|
||||
});
|
||||
|
||||
export { loadRules };
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** test_sample.py
|
||||
**检查时间:** 2025/9/18 14:28:54
|
||||
|
||||
## flake8 检查结果
|
||||
### 输出:
|
||||
```
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758176934520.py:3:1: E302 expected 2 blank lines, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758176934520.py:5:37: E261 at least two spaces before inline comment
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758176934520.py:7:1: E305 expected 2 blank lines after class or function definition, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758176934520.py:7:12: E225 missing whitespace around operator
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758176934520.py",
|
||||
"line": 3,
|
||||
"column": 1,
|
||||
"code": "E302",
|
||||
"message": "expected 2 blank lines, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758176934520.py",
|
||||
"line": 5,
|
||||
"column": 37,
|
||||
"code": "E261",
|
||||
"message": "at least two spaces before inline comment"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758176934520.py",
|
||||
"line": 7,
|
||||
"column": 1,
|
||||
"code": "E305",
|
||||
"message": "expected 2 blank lines after class or function definition, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758176934520.py",
|
||||
"line": 7,
|
||||
"column": 12,
|
||||
"code": "E225",
|
||||
"message": "missing whitespace around operator"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -0,0 +1,370 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** test_sample.py
|
||||
**检查时间:** 2025/9/18 14:33:21
|
||||
|
||||
## bandit 检查结果
|
||||
### 输出:
|
||||
```
|
||||
{
|
||||
"errors": [],
|
||||
"generated_at": "2025-09-18T06:33:19Z",
|
||||
"metrics": {
|
||||
"C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
},
|
||||
"_totals": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"code": "3 def bad_function():\n4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 34,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "MEDIUM",
|
||||
"issue_text": "Use of exec detected.",
|
||||
"line_number": 4,
|
||||
"line_range": [
|
||||
4
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b102_exec_used.html",
|
||||
"test_id": "B102",
|
||||
"test_name": "exec_used"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a shell: Seems safe, but may be changed in the future, consider rewriting without shell",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b605_start_process_with_a_shell.html",
|
||||
"test_id": "B605",
|
||||
"test_name": "start_process_with_a_shell"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a partial executable path",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b607_start_process_with_partial_path.html",
|
||||
"test_id": "B607",
|
||||
"test_name": "start_process_with_partial_path"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 错误:
|
||||
```
|
||||
[main] INFO profile include tests: None
|
||||
[main] INFO profile exclude tests: None
|
||||
[main] INFO cli include tests: None
|
||||
[main] INFO cli exclude tests: None
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
{
|
||||
"errors": [],
|
||||
"generated_at": "2025-09-18T06:33:19Z",
|
||||
"metrics": {
|
||||
"C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
},
|
||||
"_totals": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"code": "3 def bad_function():\n4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 34,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "MEDIUM",
|
||||
"issue_text": "Use of exec detected.",
|
||||
"line_number": 4,
|
||||
"line_range": [
|
||||
4
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b102_exec_used.html",
|
||||
"test_id": "B102",
|
||||
"test_name": "exec_used"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a shell: Seems safe, but may be changed in the future, consider rewriting without shell",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b605_start_process_with_a_shell.html",
|
||||
"test_id": "B605",
|
||||
"test_name": "start_process_with_a_shell"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a partial executable path",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b607_start_process_with_partial_path.html",
|
||||
"test_id": "B607",
|
||||
"test_name": "start_process_with_partial_path"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## flake8 检查结果
|
||||
### 输出:
|
||||
```
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177199898.py:3:1: E302 expected 2 blank lines, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177199898.py:5:37: E261 at least two spaces before inline comment
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177199898.py:7:1: E305 expected 2 blank lines after class or function definition, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177199898.py:7:12: E225 missing whitespace around operator
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177199898.py",
|
||||
"line": 3,
|
||||
"column": 1,
|
||||
"code": "E302",
|
||||
"message": "expected 2 blank lines, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177199898.py",
|
||||
"line": 5,
|
||||
"column": 37,
|
||||
"code": "E261",
|
||||
"message": "at least two spaces before inline comment"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177199898.py",
|
||||
"line": 7,
|
||||
"column": 1,
|
||||
"code": "E305",
|
||||
"message": "expected 2 blank lines after class or function definition, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177199898.py",
|
||||
"line": 7,
|
||||
"column": 12,
|
||||
"code": "E225",
|
||||
"message": "missing whitespace around operator"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## pylint 检查结果
|
||||
### 输出:
|
||||
```
|
||||
[
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "missing-module-docstring",
|
||||
"message": "Missing module docstring",
|
||||
"message-id": "C0114"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "invalid-name",
|
||||
"message": "Module name \"1758177199344-test_sample\" doesn't conform to snake_case naming style",
|
||||
"message-id": "C0103"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 3,
|
||||
"column": 0,
|
||||
"endLine": 3,
|
||||
"endColumn": 16,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "missing-function-docstring",
|
||||
"message": "Missing function or method docstring",
|
||||
"message-id": "C0116"
|
||||
},
|
||||
{
|
||||
"type": "warning",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 4,
|
||||
"column": 4,
|
||||
"endLine": 4,
|
||||
"endColumn": 34,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "exec-used",
|
||||
"message": "Use of exec",
|
||||
"message-id": "W0122"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "missing-module-docstring",
|
||||
"message": "Missing module docstring",
|
||||
"message-id": "C0114"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "invalid-name",
|
||||
"message": "Module name \"1758177199344-test_sample\" doesn't conform to snake_case naming style",
|
||||
"message-id": "C0103"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 3,
|
||||
"column": 0,
|
||||
"endLine": 3,
|
||||
"endColumn": 16,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "missing-function-docstring",
|
||||
"message": "Missing function or method docstring",
|
||||
"message-id": "C0116"
|
||||
},
|
||||
{
|
||||
"type": "warning",
|
||||
"module": "1758177199344-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 4,
|
||||
"column": 4,
|
||||
"endLine": 4,
|
||||
"endColumn": 34,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177199344-test_sample.py",
|
||||
"symbol": "exec-used",
|
||||
"message": "Use of exec",
|
||||
"message-id": "W0122"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -0,0 +1,370 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** test_sample.py
|
||||
**检查时间:** 2025/9/18 14:35:53
|
||||
|
||||
## bandit 检查结果
|
||||
### 输出:
|
||||
```
|
||||
{
|
||||
"errors": [],
|
||||
"generated_at": "2025-09-18T06:35:52Z",
|
||||
"metrics": {
|
||||
"C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
},
|
||||
"_totals": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"code": "3 def bad_function():\n4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 34,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "MEDIUM",
|
||||
"issue_text": "Use of exec detected.",
|
||||
"line_number": 4,
|
||||
"line_range": [
|
||||
4
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b102_exec_used.html",
|
||||
"test_id": "B102",
|
||||
"test_name": "exec_used"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a shell: Seems safe, but may be changed in the future, consider rewriting without shell",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b605_start_process_with_a_shell.html",
|
||||
"test_id": "B605",
|
||||
"test_name": "start_process_with_a_shell"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a partial executable path",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b607_start_process_with_partial_path.html",
|
||||
"test_id": "B607",
|
||||
"test_name": "start_process_with_partial_path"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 错误:
|
||||
```
|
||||
[main] INFO profile include tests: None
|
||||
[main] INFO profile exclude tests: None
|
||||
[main] INFO cli include tests: None
|
||||
[main] INFO cli exclude tests: None
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
{
|
||||
"errors": [],
|
||||
"generated_at": "2025-09-18T06:35:52Z",
|
||||
"metrics": {
|
||||
"C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
},
|
||||
"_totals": {
|
||||
"CONFIDENCE.HIGH": 3,
|
||||
"CONFIDENCE.LOW": 0,
|
||||
"CONFIDENCE.MEDIUM": 0,
|
||||
"CONFIDENCE.UNDEFINED": 0,
|
||||
"SEVERITY.HIGH": 0,
|
||||
"SEVERITY.LOW": 2,
|
||||
"SEVERITY.MEDIUM": 1,
|
||||
"SEVERITY.UNDEFINED": 0,
|
||||
"loc": 6,
|
||||
"nosec": 0,
|
||||
"skipped_tests": 0
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"code": "3 def bad_function():\n4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 34,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "MEDIUM",
|
||||
"issue_text": "Use of exec detected.",
|
||||
"line_number": 4,
|
||||
"line_range": [
|
||||
4
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b102_exec_used.html",
|
||||
"test_id": "B102",
|
||||
"test_name": "exec_used"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a shell: Seems safe, but may be changed in the future, consider rewriting without shell",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b605_start_process_with_a_shell.html",
|
||||
"test_id": "B605",
|
||||
"test_name": "start_process_with_a_shell"
|
||||
},
|
||||
{
|
||||
"code": "4 exec(\"print('Hello, world!')\") # Potential security risk\n5 os.system(\"echo This is a test\")# Missing space after comment\n6 \n",
|
||||
"col_offset": 4,
|
||||
"end_col_offset": 36,
|
||||
"filename": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"issue_confidence": "HIGH",
|
||||
"issue_cwe": {
|
||||
"id": 78,
|
||||
"link": "https://cwe.mitre.org/data/definitions/78.html"
|
||||
},
|
||||
"issue_severity": "LOW",
|
||||
"issue_text": "Starting a process with a partial executable path",
|
||||
"line_number": 5,
|
||||
"line_range": [
|
||||
5
|
||||
],
|
||||
"more_info": "https://bandit.readthedocs.io/en/1.8.6/plugins/b607_start_process_with_partial_path.html",
|
||||
"test_id": "B607",
|
||||
"test_name": "start_process_with_partial_path"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## flake8 检查结果
|
||||
### 输出:
|
||||
```
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177352260.py:3:1: E302 expected 2 blank lines, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177352260.py:5:37: E261 at least two spaces before inline comment
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177352260.py:7:1: E305 expected 2 blank lines after class or function definition, found 1
|
||||
D:\软件工程\代码质量检查\src\temp_check_1758177352260.py:7:12: E225 missing whitespace around operator
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177352260.py",
|
||||
"line": 3,
|
||||
"column": 1,
|
||||
"code": "E302",
|
||||
"message": "expected 2 blank lines, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177352260.py",
|
||||
"line": 5,
|
||||
"column": 37,
|
||||
"code": "E261",
|
||||
"message": "at least two spaces before inline comment"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177352260.py",
|
||||
"line": 7,
|
||||
"column": 1,
|
||||
"code": "E305",
|
||||
"message": "expected 2 blank lines after class or function definition, found 1"
|
||||
},
|
||||
{
|
||||
"file": "D:\\软件工程\\代码质量检查\\src\\temp_check_1758177352260.py",
|
||||
"line": 7,
|
||||
"column": 12,
|
||||
"code": "E225",
|
||||
"message": "missing whitespace around operator"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## pylint 检查结果
|
||||
### 输出:
|
||||
```
|
||||
[
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "missing-module-docstring",
|
||||
"message": "Missing module docstring",
|
||||
"message-id": "C0114"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "invalid-name",
|
||||
"message": "Module name \"1758177351895-test_sample\" doesn't conform to snake_case naming style",
|
||||
"message-id": "C0103"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 3,
|
||||
"column": 0,
|
||||
"endLine": 3,
|
||||
"endColumn": 16,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "missing-function-docstring",
|
||||
"message": "Missing function or method docstring",
|
||||
"message-id": "C0116"
|
||||
},
|
||||
{
|
||||
"type": "warning",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 4,
|
||||
"column": 4,
|
||||
"endLine": 4,
|
||||
"endColumn": 34,
|
||||
"path": "C:\\Users\\\u5f20\u6d0b\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "exec-used",
|
||||
"message": "Use of exec",
|
||||
"message-id": "W0122"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### 解析结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "missing-module-docstring",
|
||||
"message": "Missing module docstring",
|
||||
"message-id": "C0114"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "",
|
||||
"line": 1,
|
||||
"column": 0,
|
||||
"endLine": null,
|
||||
"endColumn": null,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "invalid-name",
|
||||
"message": "Module name \"1758177351895-test_sample\" doesn't conform to snake_case naming style",
|
||||
"message-id": "C0103"
|
||||
},
|
||||
{
|
||||
"type": "convention",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 3,
|
||||
"column": 0,
|
||||
"endLine": 3,
|
||||
"endColumn": 16,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "missing-function-docstring",
|
||||
"message": "Missing function or method docstring",
|
||||
"message-id": "C0116"
|
||||
},
|
||||
{
|
||||
"type": "warning",
|
||||
"module": "1758177351895-test_sample",
|
||||
"obj": "bad_function",
|
||||
"line": 4,
|
||||
"column": 4,
|
||||
"endLine": 4,
|
||||
"endColumn": 34,
|
||||
"path": "C:\\Users\\张洋\\AppData\\Local\\Temp\\1758177351895-test_sample.py",
|
||||
"symbol": "exec-used",
|
||||
"message": "Use of exec",
|
||||
"message-id": "W0122"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
# FortifyCode Python 依赖
|
||||
|
||||
# 代码质量检查工具
|
||||
pylint>=2.17.0
|
||||
flake8>=6.0.0
|
||||
bandit>=1.7.5
|
||||
|
||||
# 可选:增强功能
|
||||
pycodestyle>=2.10.0
|
||||
mccabe>=0.7.0
|
||||
|
||||
@ -1,125 +0,0 @@
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const multer = require('multer');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const RULE_DIR = path.join(__dirname, '..', '..', 'rule');
|
||||
if (!fs.existsSync(RULE_DIR)) {
|
||||
fs.mkdirSync(RULE_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
const ruleStorage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, RULE_DIR);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, file.originalname);
|
||||
}
|
||||
});
|
||||
|
||||
const ruleUpload = multer({
|
||||
storage: ruleStorage,
|
||||
limits: { fileSize: 5 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
const allowed = [
|
||||
'setup.cfg', '.pylintrc', '.flake8', 'pyproject.toml',
|
||||
'pylintrc', 'flake8.cfg', 'tox.ini'
|
||||
];
|
||||
const extAllowed = /\.(cfg|ini|toml|yaml|yml|json)$/i;
|
||||
if (allowed.includes(file.originalname) || extAllowed.test(file.originalname)) {
|
||||
return cb(null, true);
|
||||
}
|
||||
return cb(new Error('不支持的规则文件类型'));
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/rules/upload', ruleUpload.array('files'), (req, res) => {
|
||||
try {
|
||||
if (!req.files || req.files.length === 0) {
|
||||
return res.status(400).json({ success: false, error: '没有上传文件' });
|
||||
}
|
||||
const saved = req.files.map(f => f.originalname);
|
||||
res.json({ success: true, data: { saved_files: saved, directory: RULE_DIR } });
|
||||
} catch (error) {
|
||||
console.error('规则文件上传失败:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/rules', (req, res) => {
|
||||
try {
|
||||
if (!fs.existsSync(RULE_DIR)) {
|
||||
return res.json({ success: true, data: [] });
|
||||
}
|
||||
const files = fs.readdirSync(RULE_DIR).map(name => {
|
||||
const p = path.join(RULE_DIR, name);
|
||||
const stat = fs.statSync(p);
|
||||
return {
|
||||
name,
|
||||
size: stat.size,
|
||||
modified_at: stat.mtime.toISOString(),
|
||||
is_directory: stat.isDirectory()
|
||||
};
|
||||
}).filter(item => !item.is_directory);
|
||||
res.json({ success: true, data: files });
|
||||
} catch (error) {
|
||||
console.error('读取规则列表失败:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/rules/:name', (req, res) => {
|
||||
try {
|
||||
const name = req.params.name;
|
||||
const target = path.join(RULE_DIR, name);
|
||||
if (!fs.existsSync(target)) {
|
||||
return res.status(404).json({ success: false, error: '规则文件不存在' });
|
||||
}
|
||||
const content = fs.readFileSync(target, 'utf8');
|
||||
res.json({ success: true, data: { name, content } });
|
||||
} catch (error) {
|
||||
console.error('读取规则文件失败:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/rules/:name', (req, res) => {
|
||||
try {
|
||||
const name = req.params.name;
|
||||
const { content } = req.body || {};
|
||||
if (!name) {
|
||||
return res.status(400).json({ success: false, error: '规则文件名不能为空' });
|
||||
}
|
||||
const target = path.join(RULE_DIR, name);
|
||||
const dir = path.dirname(target);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(target, content ?? '', 'utf8');
|
||||
res.json({ success: true, message: '保存成功' });
|
||||
} catch (error) {
|
||||
console.error('保存规则文件失败:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/rules/:name', (req, res) => {
|
||||
try {
|
||||
const name = req.params.name;
|
||||
const target = path.join(RULE_DIR, name);
|
||||
if (!fs.existsSync(target)) {
|
||||
return res.status(404).json({ success: false, error: '规则文件不存在' });
|
||||
}
|
||||
fs.unlinkSync(target);
|
||||
res.json({ success: true, message: '已删除' });
|
||||
} catch (error) {
|
||||
console.error('删除规则文件失败:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// 模拟backend.js中的路径计算
|
||||
function testPathCalculation() {
|
||||
// 模拟__dirname的值 (view目录)
|
||||
const mockDirname = path.join(__dirname, 'view');
|
||||
|
||||
console.log('当前目录:', __dirname);
|
||||
console.log('模拟的__dirname:', mockDirname);
|
||||
|
||||
// 计算out目录路径
|
||||
const outDir = path.join(mockDirname, '..', 'out');
|
||||
console.log('计算出的out目录路径:', outDir);
|
||||
|
||||
// 规范化路径
|
||||
const normalizedOutDir = path.resolve(outDir);
|
||||
console.log('规范化后的out目录路径:', normalizedOutDir);
|
||||
|
||||
// 检查目录是否存在
|
||||
if (fs.existsSync(normalizedOutDir)) {
|
||||
console.log('目录存在');
|
||||
// 列出目录内容
|
||||
const files = fs.readdirSync(normalizedOutDir);
|
||||
console.log('目录内容:', files);
|
||||
} else {
|
||||
console.log('目录不存在');
|
||||
}
|
||||
}
|
||||
|
||||
testPathCalculation();
|
||||
@ -0,0 +1,8 @@
|
||||
import os
|
||||
|
||||
def bad_function():
|
||||
exec("print('Hello, world!')") # Potential security risk
|
||||
os.system("echo This is a test")# Missing space after comment
|
||||
|
||||
if __name__=="__main__": # Missing spaces around ==
|
||||
bad_function()
|
||||
@ -0,0 +1,347 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>简化的代码质量检查工具</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.container {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #2c3e50;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.tool-checkbox {
|
||||
margin: 15px 0;
|
||||
padding: 10px;
|
||||
background-color: #f1f8ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.file-upload {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.download-btn:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
#report-area {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
display: none;
|
||||
background-color: #e8f5e9;
|
||||
}
|
||||
|
||||
#result {
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 20px auto;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
background-color: #95a5a6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.debug-panel {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>简化的代码质量检查工具</h1>
|
||||
|
||||
<div id="toolContainer">
|
||||
<fieldset>
|
||||
<legend>选择工具:</legend>
|
||||
<div class="tool-checkbox">
|
||||
<input type="checkbox" id="bandit" name="tools" value="bandit" checked>
|
||||
<label for="bandit">Bandit</label>
|
||||
</div>
|
||||
<div class="tool-checkbox">
|
||||
<input type="checkbox" id="flake8" name="tools" value="flake8" checked>
|
||||
<label for="flake8">Flake8</label>
|
||||
</div>
|
||||
<div class="tool-checkbox">
|
||||
<input type="checkbox" id="pylint" name="tools" value="pylint" checked>
|
||||
<label for="pylint">Pylint</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="file-upload">
|
||||
<label for="file">上传代码文件:</label>
|
||||
<input type="file" id="file" name="file" accept=".py" aria-label="选择Python文件">
|
||||
</div>
|
||||
|
||||
<button type="button" id="submitBtn" class="btn">提交检查</button>
|
||||
</div>
|
||||
|
||||
<div class="loader" id="loader"></div>
|
||||
|
||||
<div id="report-area" aria-live="polite">
|
||||
<h2>检查报告</h2>
|
||||
<p>报告已生成,点击下载:</p>
|
||||
<a id="report-download" href="#" class="download-btn">下载报告</a>
|
||||
<button id="close-report" class="btn" style="margin-left: 10px;">关闭</button>
|
||||
</div>
|
||||
|
||||
<h2>结果:</h2>
|
||||
<pre id="result" role="log" aria-live="polite"></pre>
|
||||
|
||||
<div class="debug-panel">
|
||||
<strong>调试信息:</strong><br>
|
||||
<div id="debug-log"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 简单的调试日志函数
|
||||
function debugLog(message, data = null) {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
const logEntry = `[${timestamp}] ${message}`;
|
||||
if (data) {
|
||||
console.log(logEntry, data);
|
||||
} else {
|
||||
console.log(logEntry);
|
||||
}
|
||||
|
||||
const debugDiv = document.getElementById('debug-log');
|
||||
debugDiv.innerHTML += logEntry + '<br>';
|
||||
debugDiv.scrollTop = debugDiv.scrollHeight;
|
||||
}
|
||||
|
||||
// 页面加载
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
debugLog('页面DOM加载完成');
|
||||
|
||||
const submitBtn = document.getElementById('submitBtn');
|
||||
const resultPre = document.getElementById('result');
|
||||
const reportArea = document.getElementById('report-area');
|
||||
const reportLink = document.getElementById('report-download');
|
||||
const closeReportBtn = document.getElementById('close-report');
|
||||
const loader = document.getElementById('loader');
|
||||
const fileInput = document.getElementById('file');
|
||||
|
||||
let isProcessing = false;
|
||||
|
||||
// 初始隐藏报告区域
|
||||
reportArea.style.display = 'none';
|
||||
|
||||
// 关闭报告区域
|
||||
closeReportBtn.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
reportArea.style.display = 'none';
|
||||
debugLog('报告区域已关闭');
|
||||
});
|
||||
|
||||
// 提交按钮处理
|
||||
submitBtn.addEventListener('click', async function (event) {
|
||||
debugLog('提交按钮被点击');
|
||||
|
||||
// 阻止所有默认行为
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
debugLog('阻止了默认行为和冒泡');
|
||||
|
||||
// 防止重复提交
|
||||
if (isProcessing) {
|
||||
debugLog('正在处理中,忽略重复点击');
|
||||
return;
|
||||
}
|
||||
isProcessing = true;
|
||||
debugLog('开始处理请求');
|
||||
|
||||
// 更新UI状态
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '检查中...';
|
||||
loader.style.display = 'block';
|
||||
resultPre.textContent = '正在检查...';
|
||||
reportArea.style.display = 'none';
|
||||
|
||||
try {
|
||||
// 验证文件
|
||||
if (fileInput.files.length === 0) {
|
||||
throw new Error('请上传一个文件');
|
||||
}
|
||||
debugLog('文件验证通过');
|
||||
|
||||
// 获取选中的工具
|
||||
const tools = [];
|
||||
if (document.getElementById('bandit').checked) tools.push('bandit');
|
||||
if (document.getElementById('flake8').checked) tools.push('flake8');
|
||||
if (document.getElementById('pylint').checked) tools.push('pylint');
|
||||
|
||||
if (tools.length === 0) {
|
||||
throw new Error('请至少选择一个工具');
|
||||
}
|
||||
debugLog('工具选择:', tools);
|
||||
|
||||
// 准备表单数据
|
||||
const formData = new FormData();
|
||||
formData.append('file', fileInput.files[0]);
|
||||
formData.append('tools', tools.join(','));
|
||||
debugLog('表单数据准备完成');
|
||||
|
||||
// 发送请求
|
||||
debugLog('开始发送网络请求...');
|
||||
const response = await fetch('http://localhost:3000/check', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
debugLog('收到响应,状态码:', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP错误! 状态码: ${response.status}\n${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
debugLog('成功解析响应数据');
|
||||
debugLog('响应数据结构:', data);
|
||||
|
||||
// 显示结果
|
||||
resultPre.textContent = JSON.stringify(data, null, 2);
|
||||
debugLog('结果已显示在页面上');
|
||||
|
||||
// 显示报告下载区域
|
||||
if (data.reportUrl) {
|
||||
const downloadUrl = 'http://localhost:3000' + data.reportUrl;
|
||||
reportLink.href = downloadUrl;
|
||||
reportLink.download = `code_report_${Date.now()}.md`;
|
||||
reportArea.style.display = 'block';
|
||||
debugLog('报告下载链接已设置');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
debugLog('处理过程中发生错误:', error.message);
|
||||
resultPre.textContent = `错误: ${error.message}`;
|
||||
console.error('详细错误信息:', error);
|
||||
} finally {
|
||||
// 恢复UI状态
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = '提交检查';
|
||||
loader.style.display = 'none';
|
||||
isProcessing = false;
|
||||
debugLog('UI状态已恢复');
|
||||
}
|
||||
});
|
||||
|
||||
// 下载链接处理
|
||||
reportLink.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
debugLog('下载链接被点击');
|
||||
|
||||
// 使用简单的下载方式
|
||||
const link = document.createElement('a');
|
||||
link.href = reportLink.href;
|
||||
link.download = reportLink.download;
|
||||
link.style.display = 'none';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
debugLog('下载已启动');
|
||||
});
|
||||
|
||||
debugLog('事件监听器设置完成');
|
||||
});
|
||||
|
||||
// 全局错误处理
|
||||
window.addEventListener('error', function (event) {
|
||||
console.error('全局JavaScript错误:', event.error);
|
||||
debugLog('捕获到全局错误: ' + event.message);
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', function (event) {
|
||||
console.error('未处理的Promise错误:', event.reason);
|
||||
debugLog('捕获到未处理Promise错误: ' + event.reason);
|
||||
});
|
||||
|
||||
debugLog('脚本初始化完成');
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -0,0 +1,193 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>防刷新测试页面</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>防刷新测试页面</h1>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>防刷新状态控制</h2>
|
||||
<button id="toggleRefresh" class="btn">启用防刷新</button>
|
||||
<span id="refreshStatus">防刷新: 禁用</span>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>测试按钮</h2>
|
||||
<button id="testBtn1" class="btn">测试按钮1</button>
|
||||
<button id="testBtn2" class="btn">测试按钮2</button>
|
||||
<button id="testBtn3" class="btn">测试按钮3</button>
|
||||
<a id="testLink" href="#" class="btn" style="text-decoration: none;">测试链接</a>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>结果显示</h2>
|
||||
<div id="results" class="status">
|
||||
点击按钮查看结果...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>键盘测试</h2>
|
||||
<p>尝试按 F5 或 Ctrl+R 键测试防刷新功能</p>
|
||||
<div id="keyboardResults" class="status">
|
||||
键盘事件将在这里显示...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 防刷新状态
|
||||
let preventRefresh = false;
|
||||
let eventCount = 0;
|
||||
|
||||
// DOM元素
|
||||
const elements = {
|
||||
toggleRefresh: document.getElementById('toggleRefresh'),
|
||||
refreshStatus: document.getElementById('refreshStatus'),
|
||||
testBtn1: document.getElementById('testBtn1'),
|
||||
testBtn2: document.getElementById('testBtn2'),
|
||||
testBtn3: document.getElementById('testBtn3'),
|
||||
testLink: document.getElementById('testLink'),
|
||||
results: document.getElementById('results'),
|
||||
keyboardResults: document.getElementById('keyboardResults')
|
||||
};
|
||||
|
||||
// 全局防刷新拦截器
|
||||
function setupRefreshPrevention() {
|
||||
// 拦截所有点击事件
|
||||
document.addEventListener('click', function (event) {
|
||||
if (preventRefresh) {
|
||||
eventCount++;
|
||||
console.log(`拦截到点击事件 #${eventCount}:`, event.target.tagName, event.target.id || event.target.textContent);
|
||||
elements.results.innerHTML += `<br>点击事件 #${eventCount}: ${event.target.tagName} - ${event.target.id || event.target.textContent}`;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// 拦截键盘事件
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (preventRefresh) {
|
||||
console.log('拦截到键盘事件:', event.key, event.ctrlKey ? 'Ctrl+' : '');
|
||||
elements.keyboardResults.innerHTML += `<br>键盘事件: ${event.key}${event.ctrlKey ? ' (Ctrl)' : ''}`;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// 拦截链接点击
|
||||
document.addEventListener('click', function (event) {
|
||||
if (preventRefresh && event.target.tagName === 'A') {
|
||||
console.log('拦截到链接点击:', event.target.href);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
// 切换防刷新状态
|
||||
elements.toggleRefresh.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
preventRefresh = !preventRefresh;
|
||||
|
||||
if (preventRefresh) {
|
||||
elements.toggleRefresh.textContent = '禁用防刷新';
|
||||
elements.toggleRefresh.style.backgroundColor = '#27ae60';
|
||||
elements.refreshStatus.textContent = '防刷新: 启用';
|
||||
console.log('防刷新已启用');
|
||||
} else {
|
||||
elements.toggleRefresh.textContent = '启用防刷新';
|
||||
elements.toggleRefresh.style.backgroundColor = '#3498db';
|
||||
elements.refreshStatus.textContent = '防刷新: 禁用';
|
||||
eventCount = 0;
|
||||
elements.results.innerHTML = '点击按钮查看结果...';
|
||||
elements.keyboardResults.innerHTML = '键盘事件将在这里显示...';
|
||||
console.log('防刷新已禁用');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加测试按钮事件
|
||||
[elements.testBtn1, elements.testBtn2, elements.testBtn3].forEach((btn, index) => {
|
||||
btn.addEventListener('click', function (event) {
|
||||
if (!preventRefresh) {
|
||||
elements.results.innerHTML += `<br>按钮 ${index + 1} 被点击`;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 添加测试链接事件
|
||||
elements.testLink.addEventListener('click', function (event) {
|
||||
if (!preventRefresh) {
|
||||
elements.results.innerHTML += '<br>链接被点击';
|
||||
}
|
||||
});
|
||||
|
||||
// 页面事件监听器
|
||||
window.addEventListener('beforeunload', function (event) {
|
||||
console.log('页面即将被刷新或关闭');
|
||||
if (preventRefresh) {
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化
|
||||
setupRefreshPrevention();
|
||||
console.log('防刷新测试页面初始化完成');
|
||||
|
||||
// 添加页面加载时间戳
|
||||
const loadTime = new Date().toLocaleString();
|
||||
console.log('页面加载时间:', loadTime);
|
||||
document.body.insertAdjacentHTML('afterbegin',
|
||||
`<div style="background: #e8f5e9; padding: 10px; margin-bottom: 20px; border-radius: 4px;">
|
||||
页面加载时间: ${loadTime}
|
||||
</div>`
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -1,217 +0,0 @@
|
||||
# FortifyCode 快速开始指南
|
||||
|
||||
## 一键启动
|
||||
|
||||
### Windows 用户
|
||||
双击运行 `start_server.bat` 文件
|
||||
|
||||
### Linux/Mac 用户
|
||||
```bash
|
||||
chmod +x start_server.sh
|
||||
./start_server.sh
|
||||
```
|
||||
|
||||
### 使用 npm
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
## 首次使用前的准备
|
||||
|
||||
### 1. 安装 Node.js
|
||||
访问 https://nodejs.org/ 下载并安装 Node.js (推荐 LTS 版本)
|
||||
|
||||
验证安装:
|
||||
```bash
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
### 2. 安装 Python
|
||||
访问 https://www.python.org/ 下载并安装 Python 3.7+
|
||||
|
||||
**重要**: 安装时勾选 "Add Python to PATH"
|
||||
|
||||
验证安装:
|
||||
```bash
|
||||
python --version
|
||||
```
|
||||
|
||||
### 3. 安装项目依赖
|
||||
|
||||
#### Node.js 依赖
|
||||
```bash
|
||||
cd src
|
||||
npm install
|
||||
```
|
||||
|
||||
#### Python 代码检查工具
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
或手动安装:
|
||||
```bash
|
||||
pip install pylint flake8 bandit
|
||||
```
|
||||
|
||||
## 启动服务器
|
||||
|
||||
选择以下任一方式:
|
||||
|
||||
### 方式 1: 使用启动脚本(推荐)
|
||||
- Windows: 双击 `start_server.bat`
|
||||
- Linux/Mac: 运行 `./start_server.sh`
|
||||
|
||||
### 方式 2: 使用 npm
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
### 方式 3: 直接运行
|
||||
```bash
|
||||
node backend.js
|
||||
```
|
||||
|
||||
## 访问系统
|
||||
|
||||
启动成功后,浏览器访问:
|
||||
|
||||
```
|
||||
http://localhost:5000
|
||||
```
|
||||
|
||||
你会看到 FortifyCode 的主界面。
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例 1: 快速检查单个文件
|
||||
|
||||
1. 准备一个 Python 文件,例如 `test.py`:
|
||||
```python
|
||||
import os
|
||||
def test():
|
||||
x=1+2
|
||||
print(x)
|
||||
test()
|
||||
```
|
||||
|
||||
2. 在主页点击或拖拽文件到上传区域
|
||||
3. 点击"开始检查"按钮
|
||||
4. 查看检查结果
|
||||
|
||||
### 示例 2: 创建项目
|
||||
|
||||
1. 点击顶部导航栏的"项目管理"
|
||||
2. 点击"新建项目"按钮
|
||||
3. 填写项目信息:
|
||||
- 项目名称: 我的第一个项目
|
||||
- 项目描述: 测试项目
|
||||
- 来源类型: 选择"文件上传"
|
||||
4. 选择要上传的文件或文件夹
|
||||
5. 点击"创建项目"
|
||||
|
||||
### 示例 3: 查看项目详情
|
||||
|
||||
1. 在项目列表中点击项目卡片
|
||||
2. 查看项目信息和文件浏览器
|
||||
3. 点击"运行检查"进行代码检查
|
||||
4. 在"检查历史"中查看历史记录
|
||||
|
||||
## 常见问题快速解决
|
||||
|
||||
### ❌ 提示 "未找到 Node.js"
|
||||
**解决**: 安装 Node.js 并确保添加到系统 PATH
|
||||
|
||||
### ❌ 提示 "未找到 Python"
|
||||
**解决**: 安装 Python 并确保添加到系统 PATH
|
||||
|
||||
### ❌ 提示 "pylint 未安装"
|
||||
**解决**:
|
||||
```bash
|
||||
pip install pylint
|
||||
```
|
||||
|
||||
### ❌ 提示 "端口 5000 被占用"
|
||||
**解决**:
|
||||
- 方案 1: 关闭占用端口的程序
|
||||
- 方案 2: 修改端口号
|
||||
编辑 `backend.js` 第 10 行:
|
||||
```javascript
|
||||
const PORT = process.env.PORT || 8080; // 改为其他端口
|
||||
```
|
||||
|
||||
### ❌ 上传文件失败
|
||||
**解决**:
|
||||
- 确保文件是 .py, .pyx, .pyi 格式
|
||||
- 确保文件大小不超过 100MB
|
||||
- 检查磁盘空间是否充足
|
||||
|
||||
## 系统架构
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ 浏览器 │ http://localhost:5000
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Express 服务器 (Node.js) │
|
||||
│ - 提供前端页面 │
|
||||
│ - 处理API请求 │
|
||||
│ - 文件管理 │
|
||||
└──────┬──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────┐
|
||||
│ 代码检查工具 (Python) │
|
||||
│ - Pylint (代码质量) │
|
||||
│ - Flake8 (代码规范) │
|
||||
│ - Bandit (安全检查) │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
## 功能概览
|
||||
|
||||
### 🏠 仪表板
|
||||
- 查看系统统计信息
|
||||
- 快捷文件上传和检查
|
||||
- Agent 状态监控
|
||||
|
||||
### 📁 项目管理
|
||||
- 创建和管理多个项目
|
||||
- 支持 GitHub/Gitee 克隆
|
||||
- 支持本地文件上传
|
||||
|
||||
### 📝 文件浏览器
|
||||
- 浏览项目文件
|
||||
- 在线编辑代码
|
||||
- 文件上传和管理
|
||||
|
||||
### 🔍 代码检查
|
||||
- 多工具协同检查
|
||||
- 问题分类显示
|
||||
- 修复建议提供
|
||||
|
||||
### 📊 检查报告
|
||||
- 详细的问题列表
|
||||
- 问题统计分析
|
||||
- 历史记录查看
|
||||
|
||||
## 下一步
|
||||
|
||||
- 📖 阅读完整的 [README.md](README.md)
|
||||
- 📚 查看 [API 文档](view/API.md)
|
||||
- 🔧 了解 [军工软件Python编码指南](../doc/军工软件python编码指南.docx)
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如果遇到问题:
|
||||
1. 检查控制台输出的错误信息
|
||||
2. 查看浏览器开发者工具的 Console 选项卡
|
||||
3. 参考 README.md 中的"常见问题"部分
|
||||
|
||||
---
|
||||
|
||||
祝使用愉快! 🚀
|
||||
|
||||
Loading…
Reference in new issue