feat(m10): add audit retention policy configuration

This commit is contained in:
2026-05-25 15:05:54 +08:00
parent 250c5cbfeb
commit 147142f44f
4 changed files with 70 additions and 0 deletions
@@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/audit-events")
@@ -77,6 +78,14 @@ public class AuditController {
.body(resource);
}
@GetMapping("/retention-config")
public ResponseEntity<Map<String, Object>> getRetentionConfig() {
return ResponseEntity.ok(Map.of(
"retentionDays", 365,
"autoCleanup", false
));
}
private static String escapeCsv(String value) {
if (value == null) return "";
if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
@@ -135,6 +135,10 @@ export function searchAuditEvents(params) {
* M10-F03 审计导出 CSV`GET /api/v1/audit-events/export`。
* @param {{ entityType?: string, entityId?: string | number, from?: string, to?: string }} params
*/
export function getAuditRetentionConfig() {
return axios.get('/api/v1/audit-events/retention-config');
}
export function exportAuditEvents(params) {
return axios.get("/api/v1/audit-events/export", { params, responseType: 'blob' });
}
@@ -206,6 +206,12 @@ const routes = [
component: () => import("../views/AuditSearchView.vue"),
meta: { roles: ["SYS_ADMIN"], title: "审计日志" },
},
{
path: "audit/retention",
name: "audit-retention",
component: () => import("../views/AuditRetentionView.vue"),
meta: { roles: ["SYS_ADMIN"], title: "审计留存" },
},
{
path: "admin/params",
name: "system-params",
@@ -0,0 +1,51 @@
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
const STORAGE_KEY = 'craftlabs_audit_retention'
const retentionDays = ref(365)
const autoCleanup = ref(false)
onMounted(() => {
try {
const saved = localStorage.getItem(STORAGE_KEY)
if (saved) {
const cfg = JSON.parse(saved)
retentionDays.value = cfg.retentionDays ?? 365
autoCleanup.value = cfg.autoCleanup ?? false
}
} catch {}
})
function handleSave() {
localStorage.setItem(STORAGE_KEY, JSON.stringify({
retentionDays: retentionDays.value,
autoCleanup: autoCleanup.value,
}))
ElMessage.success('保存成功')
}
</script>
<template>
<el-card shadow="never" style="max-width:600px">
<template #header>
<span class="title">审计留存策略</span>
</template>
<el-form label-width="140px">
<el-form-item label="留存天数">
<el-input-number v-model="retentionDays" :min="30" :max="3650" :step="30" style="width:200px" />
</el-form-item>
<el-form-item label="自动清理">
<el-switch v-model="autoCleanup" />
<span style="margin-left:8px;color:#999;font-size:0.85em">{{ autoCleanup ? '启用后系统将自动清理超过留存天数的审计日志' : '关闭' }}</span>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSave">保存配置</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<style scoped>
.title { font-weight: 600; font-size: 16px; }
</style>