继续更新 update 门户站点界面和功能
This commit is contained in:
@@ -59,10 +59,12 @@ const toast = ref<ToastState | null>(null);
|
||||
const autoRefreshPaused = ref(false);
|
||||
let refreshTimer: number | undefined;
|
||||
let toastTimer: number | undefined;
|
||||
let events: EventSource | null = null;
|
||||
|
||||
const captcha = ref<Captcha | null>(null);
|
||||
const authBootstrap = ref<AuthBootstrap | null>(null);
|
||||
const dashboard = ref<any>({});
|
||||
const sourceCheckJobs = ref<any[]>([]);
|
||||
const feedbackPage = ref<any>({ items: [], total: 0, page: 1, perPage: 20 });
|
||||
const selectedFeedback = ref<any | null>(null);
|
||||
const releases = ref<any>(null);
|
||||
@@ -303,6 +305,7 @@ const viewContext = computed(() => ({
|
||||
selectedFeedback: selectedFeedback.value,
|
||||
selectedNotice: selectedNotice.value,
|
||||
sourceCategories: sourceCategories.value,
|
||||
sourceCheckJobs: sourceCheckJobs.value,
|
||||
sourceDraft,
|
||||
statusTone,
|
||||
syncDatabase,
|
||||
@@ -385,6 +388,7 @@ async function login() {
|
||||
});
|
||||
csrf.value = data.csrfToken;
|
||||
localStorage.setItem("ymhut.csrf", csrf.value);
|
||||
connectAdminEvents();
|
||||
navigate("/admin/dashboard");
|
||||
});
|
||||
}
|
||||
@@ -393,6 +397,8 @@ async function logout() {
|
||||
await api("/api/admin/auth/logout", { method: "POST", body: "{}" }).catch(() => undefined);
|
||||
csrf.value = "";
|
||||
localStorage.removeItem("ymhut.csrf");
|
||||
events?.close();
|
||||
events = null;
|
||||
navigate("/admin/login");
|
||||
}
|
||||
|
||||
@@ -716,13 +722,19 @@ async function saveSource() {
|
||||
|
||||
async function checkSources() {
|
||||
await guarded(async () => {
|
||||
await api("/api/admin/sources/check", { method: "POST", body: "{}" });
|
||||
setToast("接口心跳检测已进入队列");
|
||||
const data = await api<{ jobId: string; job: any }>("/api/admin/sources/check", { method: "POST", body: "{}" });
|
||||
if (data.job) sourceCheckJobs.value = [data.job, ...sourceCheckJobs.value.filter((item) => item.id !== data.job.id)].slice(0, 5);
|
||||
setToast(`接口心跳检测已进入队列:${data.jobId}`);
|
||||
if (currentPath.value === "/admin/dashboard") await loadDashboard();
|
||||
if (currentPath.value === "/admin/sources") await loadSources();
|
||||
});
|
||||
}
|
||||
|
||||
async function loadSourceCheckJobs() {
|
||||
const data = await api<{ items: any[] }>("/api/admin/sources/check/status");
|
||||
sourceCheckJobs.value = data.items || [];
|
||||
}
|
||||
|
||||
async function loadEndpoints() {
|
||||
const data = await api<{ items: any[] }>("/api/admin/endpoints");
|
||||
endpoints.value = data.items || [];
|
||||
@@ -795,10 +807,11 @@ async function loadAudit() {
|
||||
|
||||
async function changePassword() {
|
||||
await guarded(async () => {
|
||||
await api("/api/admin/auth/password", { method: "POST", body: JSON.stringify(passwordForm) });
|
||||
const data = await api<{ isDefaultPassword: boolean; warning?: string }>("/api/admin/auth/password", { method: "POST", body: JSON.stringify(passwordForm) });
|
||||
passwordForm.currentPassword = "";
|
||||
passwordForm.newPassword = "";
|
||||
setToast("后台密码已修改,登录页将不再提示默认密码");
|
||||
if (authBootstrap.value) authBootstrap.value.isDefaultPassword = data.isDefaultPassword;
|
||||
setToast(data.warning || "后台密码已修改,登录页将不再提示默认密码", data.warning ? "warn" : "success");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -909,6 +922,7 @@ function splitList(value: string) {
|
||||
|
||||
onMounted(() => {
|
||||
void load();
|
||||
connectAdminEvents();
|
||||
refreshTimer = window.setInterval(() => {
|
||||
if (!autoRefreshPaused.value && currentPath.value === "/admin/dashboard" && csrf.value) void loadDashboard();
|
||||
}, 15000);
|
||||
@@ -916,7 +930,30 @@ onMounted(() => {
|
||||
|
||||
onUnmounted(() => {
|
||||
if (refreshTimer) window.clearInterval(refreshTimer);
|
||||
events?.close();
|
||||
events = null;
|
||||
});
|
||||
|
||||
function connectAdminEvents() {
|
||||
if (!csrf.value || events) return;
|
||||
events = new EventSource("/api/admin/events", { withCredentials: true });
|
||||
const refreshCurrent = () => {
|
||||
if (autoRefreshPaused.value) return;
|
||||
if (currentPath.value === "/admin/dashboard") void Promise.all([loadDashboard(), loadSourceCheckJobs().catch(() => undefined)]);
|
||||
if (currentPath.value === "/admin/sources") void Promise.all([loadSources(), loadSourceCheckJobs().catch(() => undefined)]);
|
||||
if (currentPath.value === "/admin/endpoints") void loadEndpoints();
|
||||
if (currentPath.value === "/admin/audit") void loadAudit();
|
||||
if (currentPath.value === "/admin/database") void loadDatabase();
|
||||
};
|
||||
for (const name of ["source_check.item", "source_check.progress", "source_check.completed", "heartbeat"]) {
|
||||
events.addEventListener(name, refreshCurrent);
|
||||
}
|
||||
events.onerror = () => {
|
||||
events?.close();
|
||||
events = null;
|
||||
window.setTimeout(connectAdminEvents, 5000);
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user