diff --git a/ai_knowledge_base_v2/apps/admin-web/src/App.vue b/ai_knowledge_base_v2/apps/admin-web/src/App.vue index f020405..c81582a 100644 --- a/ai_knowledge_base_v2/apps/admin-web/src/App.vue +++ b/ai_knowledge_base_v2/apps/admin-web/src/App.vue @@ -4,6 +4,7 @@ import { computed, onMounted, reactive, ref } from "vue"; import AdminLoginView from "./components/AdminLoginView.vue"; import KnowledgeManagementView from "./components/KnowledgeManagementView.vue"; +import TableRowActions from "./components/TableRowActions.vue"; import { systemSettingDefinitions, systemSettingSections, type SystemSettingValue } from "./config/systemSettings"; import { api, clearToken, getToken, saveToken } from "./services/api"; import type { @@ -27,6 +28,11 @@ const activeMenu = ref("dashboard"); const loading = ref(false); const stats = ref(null); +const storageStats = ref | null>(null); +const storageLoading = ref(false); +const cleanupBefore = ref(""); +const retentionDays = ref(90); +const retentionState = ref<{ lastRunAt: string | null; lastResult: string | null } | null>(null); const dashboardFilters = reactive({ start: "", end: "", @@ -249,8 +255,15 @@ async function previewKnowledge(knowledgeId: number) { async function loadDashboard() { stats.value = await api.dashboard(dashboardFilters.start, dashboardFilters.end); + storageLoading.value = true; + api.storageStats().then((value) => { storageStats.value = value; }).catch(() => { storageStats.value = null; }).finally(() => { storageLoading.value = false; }); } +async function refreshStorage() { storageLoading.value = true; try { storageStats.value = await api.storageStats(true); ElMessage.success("存储统计已刷新"); } finally { storageLoading.value = false; } } +function formatBytes(value: unknown) { if (typeof value !== "number") return "无法统计"; const units = ["B", "KB", "MB", "GB", "TB"]; let size = value, i = 0; while (size >= 1024 && i < units.length - 1) { size /= 1024; i += 1; } return `${size.toFixed(i ? 2 : 0)} ${units[i]}`; } +async function cleanupRetrievalLogs() { if (!cleanupBefore.value) return ElMessage.warning("请选择清理日期"); const estimate = await api.estimateRetrievalCleanup(cleanupBefore.value); await ElMessageBox.confirm(`预计清理 ${estimate.estimatedCount} 条检索日志及关联明细,操作日志不会被删除。`, "确认清理", { type: "warning" }); const result = await api.cleanupRetrievalLogs(cleanupBefore.value); ElMessage.success(`已清理 ${result.deleted} 条日志`); await loadCurrentMenu(); } +async function saveRetention() { await api.saveRetrievalRetention(retentionDays.value); ElMessage.success(retentionDays.value == null ? "已设为永久保留" : `已设为保留 ${retentionDays.value} 天`); await loadCurrentMenu(); } + async function loadCurrentMenu() { loading.value = true; try { @@ -262,6 +275,7 @@ async function loadCurrentMenu() { promptContent.value = prompt.promptContent; models.value = modelRows; knowledge.value = knowledgeRows; + agentForm.knowledgeIds = knowledgeRows.filter((item) => item.status === 1 && item.lifecycleStatus === "active").map((item) => item.id); if (!agentForm.modelId && modelRows.length) { agentForm.modelId = modelRows.find((model) => model.enabled === 1)?.id ?? modelRows[0].id; } @@ -276,7 +290,7 @@ async function loadCurrentMenu() { aiLogs.value = await api.aiLogs(); operationLogs.value = await api.operationLogs(); } - if (activeMenu.value === "retrievals") retrievalLogs.value = await api.retrievalLogs(); + if (activeMenu.value === "retrievals") { const [logs, retention] = await Promise.all([api.retrievalLogs(), api.retrievalRetention()]); retrievalLogs.value = logs; retentionDays.value = retention.retentionDays; retentionState.value = retention; } if (activeMenu.value === "attention") attentionRecords.value = await api.attentionList(); } finally { loading.value = false; @@ -937,6 +951,7 @@ function formatRecordDateTime(value: string, boundary: "start" | "end") { +

项目存储占用

数据库、Redis 与附件分别统计;无权限或不支持时显示“无法统计”。

手动刷新
项目总量{{ formatBytes(storageStats?.totalBytes) }}
数据库{{ formatBytes(storageStats?.detail?.database?.bytes) }}
Redis{{ formatBytes(storageStats?.detail?.redis?.bytes) }}
附件/文件{{ formatBytes(storageStats?.detail?.files?.bytes) }}
近7天增长{{ formatBytes(storageStats?.growth7DaysBytes) }}
近30天增长{{ formatBytes(storageStats?.growth30DaysBytes) }}
最后统计:{{ storageStats?.createdAt || '尚未统计' }}
@@ -986,8 +1001,8 @@ function formatRecordDateTime(value: string, boundary: "start" | "end") { - - + + @@ -1067,10 +1082,12 @@ function formatRecordDateTime(value: string, boundary: "start" | "end") {
-
- {{ index + 1 }}. {{ step.tool }} -
{{ JSON.stringify(step, null, 2) }}
-
+
+ {{ index + 1 }}. {{ step.tool }}{{ step.status || '完成' }}{{ step.durationMs ?? 0 }} ms +
请求
{{ JSON.stringify(step.request ?? {}, null, 2) }}
+
响应
{{ step.response == null ? '返回为空' : JSON.stringify(step.response, null, 2) }}
+ +
@@ -1180,12 +1197,9 @@ function formatRecordDateTime(value: string, boundary: "start" | "end") { - +
@@ -1232,7 +1246,8 @@ function formatRecordDateTime(value: string, boundary: "start" | "end") {