feat: harden recording lifecycle and refresh fnOS UI

This commit is contained in:
2026-08-03 23:45:26 +08:00
parent e5b50ea85c
commit ecc737f0bd
90 changed files with 6995 additions and 1826 deletions
+27 -12
View File
@@ -7,7 +7,9 @@ import { logLevelLabelMap } from "@/types";
const AUTO_REFRESH_INTERVAL_MS = 15000;
const loading = ref(false);
const initialLoading = ref(false);
const refreshing = ref(false);
const requestInFlight = ref(false);
const logs = ref<SystemLog[]>([]);
const loadError = ref("");
const { isMobile } = useViewport();
@@ -31,13 +33,25 @@ const newestLogTime = computed(() => (logs.value[0] ? formatDate(logs.value[0].c
let autoRefreshTimer: number | null = null;
async function loadLogs() {
if (loading.value) {
function mergeLogs(nextLogs: SystemLog[]) {
const previousById = new Map(logs.value.map((item) => [item.id, item]));
return nextLogs.map((item) => {
const previous = previousById.get(item.id);
return previous && JSON.stringify(previous) === JSON.stringify(item) ? previous : item;
});
}
async function loadLogs(background = false) {
if (requestInFlight.value) {
return;
}
loading.value = true;
loadError.value = "";
requestInFlight.value = true;
initialLoading.value = !background && logs.value.length === 0;
refreshing.value = !initialLoading.value;
if (!background) {
loadError.value = "";
}
try {
const { data } = await apiClient.get<SystemLog[]>("/logs", {
@@ -50,11 +64,13 @@ async function loadLogs() {
}
});
logs.value = data;
logs.value = mergeLogs(data);
} catch (error) {
loadError.value = getApiErrorMessage(error, "系统日志加载失败,请稍后重试。");
} finally {
loading.value = false;
requestInFlight.value = false;
initialLoading.value = false;
refreshing.value = false;
}
}
@@ -63,7 +79,7 @@ async function autoRefreshLogs() {
return;
}
await loadLogs();
await loadLogs(true);
}
function startAutoRefresh() {
@@ -126,7 +142,7 @@ onBeforeUnmount(() => {
</div>
<div class="page-toolbar">
<el-button @click="loadLogs">刷新日志</el-button>
<el-button :loading="refreshing" @click="loadLogs(false)">刷新日志</el-button>
</div>
</div>
@@ -187,7 +203,7 @@ onBeforeUnmount(() => {
<el-input-number v-model="filters.take" :min="1" :max="500" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadLogs">应用筛选</el-button>
<el-button type="primary" @click="loadLogs(false)">应用筛选</el-button>
</el-form-item>
</el-form>
</el-card>
@@ -230,8 +246,7 @@ onBeforeUnmount(() => {
<div v-else class="table-scroll-shell logs-table-shell">
<el-table
:data="logs"
v-loading="loading"
:height="720"
v-loading="initialLoading"
class="premium-table logs-table"
table-layout="auto"
>