Compare commits
No commits in common. 'main' and 'yangwengui' have entirely different histories.
main
...
yangwengui
Binary file not shown.
Binary file not shown.
Binary file not shown.
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
@ -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,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>
|
||||
Loading…
Reference in new issue