feat: 全量功能模块开发与集成测试修复

- 新增后端模块:Alert、APIAsset、Compliance、Lineage、Masking、Risk、SchemaChange、Unstructured、Watermark
- 新增前端模块页面与API接口
- 新增Alembic迁移脚本(002-014)覆盖全量业务表
- 新增测试数据生成脚本与集成测试脚本
- 修复metadata模型JSON类型导入缺失导致启动失败的问题
- 修复前端Alert/APIAsset页面request模块路径错误
- 更新docker-compose与开发计划文档
This commit is contained in:
hiderfong
2026-04-25 08:51:38 +08:00
parent 8b2bc84399
commit 6d70520e79
110 changed files with 6125 additions and 87 deletions
+69
View File
@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>报告预览</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 40px; color: #333; background: #f5f7fa; }
.page { max-width: 800px; margin: 0 auto; background: #fff; padding: 48px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); }
h1 { text-align: center; font-size: 24px; margin-bottom: 32px; }
h2 { font-size: 16px; border-left: 4px solid #409eff; padding-left: 8px; margin-top: 24px; }
table { width: 100%; border-collapse: collapse; margin-top: 12px; }
th, td { border: 1px solid #dcdfe6; padding: 8px 12px; text-align: left; }
th { background: #f5f7fa; }
.highlight { background: #fde2e2; }
.info { color: #909399; font-size: 12px; margin-top: 4px; }
.print-btn { position: fixed; top: 20px; right: 20px; padding: 8px 16px; background: #409eff; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
@media print { .print-btn { display: none; } body { margin: 0; background: #fff; } .page { box-shadow: none; } }
</style>
</head>
<body>
<button class="print-btn" onclick="window.print()">打印 / 保存为PDF</button>
<div class="page">
<h1>数据分类分级项目报告</h1>
<div id="content">加载中...</div>
</div>
<script>
const params = new URLSearchParams(location.search);
const projectId = params.get('projectId');
const apiBase = '/api/v1';
async function load() {
if (!projectId) { document.getElementById('content').innerText = '缺少项目ID'; return; }
try {
const res = await fetch(`${apiBase}/reports/projects/${projectId}/summary`);
const json = await res.json();
const d = json.data;
let html = '';
html += '<h2>一、项目基本信息</h2>';
html += '<table><tr><th>项目名称</th><td>' + (d.project_name || '') + '</td></tr>';
html += '<tr><th>报告生成时间</th><td>' + (d.generated_at || '').slice(0,19).replace('T',' ') + '</td></tr>';
html += '<tr><th>项目状态</th><td>' + (d.status || '') + '</td></tr>';
html += '<tr><th>模板版本</th><td>' + (d.template_version || '') + '</td></tr></table>';
html += '<h2>二、分类分级统计</h2>';
html += '<p>总字段数: ' + d.total + ' | 自动识别: ' + d.auto + ' | 人工打标: ' + d.manual + '</p>';
html += '<h2>三、分级分布</h2><table><tr><th>分级</th><th>数量</th><th>占比</th></tr>';
d.level_distribution.forEach(item => {
const pct = d.total ? (item.count / d.total * 100).toFixed(1) + '%' : '0%';
const cls = item.name.includes('L4') || item.name.includes('L5') ? 'highlight' : '';
html += '<tr class="' + cls + '"><td>' + item.name + '</td><td>' + item.count + '</td><td>' + pct + '</td></tr>';
});
html += '</table>';
html += '<h2>四、高敏感数据清单(L4/L5</h2>';
if (d.high_risk && d.high_risk.length) {
html += '<table><tr><th>字段名</th><th>所属表</th><th>分类</th><th>分级</th><th>来源</th></tr>';
d.high_risk.forEach(r => {
html += '<tr class="highlight"><td>' + r.column_name + '</td><td>' + r.table_name + '</td><td>' + r.category_name + '</td><td>' + r.level_name + '</td><td>' + r.source + '</td></tr>';
});
html += '</table>';
} else {
html += '<p>暂无L4/L5级高敏感数据。</p>';
}
document.getElementById('content').innerHTML = html;
} catch (e) {
document.getElementById('content').innerText = '加载失败: ' + e.message;
}
}
load();
</script>
</body>
</html>