forked from pu8crm6xf/analysiscode
Compare commits
25 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ed8ce4ed82 | 1 month ago |
|
|
a3e8eecbdb | 1 month ago |
|
|
1d1a63d094 | 1 month ago |
|
|
a61dec369b | 1 month ago |
|
|
246f1270d6 | 1 month ago |
|
|
7f23ec2e3a | 1 month ago |
|
|
f982b81cdd | 1 month ago |
|
|
76c7506a38 | 1 month ago |
|
|
26e954ffa7 | 1 month ago |
|
|
f0394511c5 | 1 month ago |
|
|
e026f6c143 | 1 month ago |
|
|
c9f7d55cbd | 1 month ago |
|
|
912c4e4e76 | 1 month ago |
|
|
fe92640a8b | 1 month ago |
|
|
e980d4e324 | 1 month ago |
|
|
c4c53db080 | 1 month ago |
|
|
52614e08a0 | 2 months ago |
|
|
26c132c871 | 2 months ago |
|
|
6703e51a1b | 2 months ago |
|
|
c46ec1827e | 2 months ago |
|
|
2c5f6f9ca3 | 2 months ago |
|
|
5562caab93 | 2 months ago |
|
|
7709dea698 | 2 months ago |
|
|
55d117d840 | 2 months ago |
|
|
0c5fb9f7e4 | 3 months ago |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,51 @@
|
||||
# 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
@ -0,0 +1,4 @@
|
||||
{
|
||||
"useLocalAi": false,
|
||||
"selectedModelId": null
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"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
@ -0,0 +1,202 @@
|
||||
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 };
|
||||
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** 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"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -1,370 +0,0 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** 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"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -1,370 +0,0 @@
|
||||
# 代码质量检查报告
|
||||
|
||||
**文件:** 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"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
# FortifyCode Python 依赖
|
||||
|
||||
# 代码质量检查工具
|
||||
pylint>=2.17.0
|
||||
flake8>=6.0.0
|
||||
bandit>=1.7.5
|
||||
|
||||
# 可选:增强功能
|
||||
pycodestyle>=2.10.0
|
||||
mccabe>=0.7.0
|
||||
|
||||
@ -0,0 +1,125 @@
|
||||
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
@ -1,31 +0,0 @@
|
||||
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();
|
||||
@ -1,8 +0,0 @@
|
||||
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()
|
||||
@ -1,347 +0,0 @@
|
||||
<!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>
|
||||
@ -1,193 +0,0 @@
|
||||
<!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>
|
||||
@ -0,0 +1,217 @@
|
||||
# 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