优化后台金山状态:登录后静默预取并在系统配置页复用缓存

This commit is contained in:
2026-02-16 01:42:47 +08:00
parent 1389ec7434
commit e725db79a9
25 changed files with 213 additions and 72 deletions

View File

@@ -17,6 +17,7 @@ import {
import { api } from '../api/client'
import { fetchFeedbackStats } from '../api/feedbacks'
import { fetchSystemStats } from '../api/stats'
import { clearCachedKdocsStatus, preloadKdocsStatus } from '../utils/kdocsStatusCache'
const route = useRoute()
const router = useRouter()
@@ -102,6 +103,9 @@ onMounted(async () => {
mediaQuery.addEventListener?.('change', syncIsMobile)
syncIsMobile()
// 后台登录后预加载金山文档登录状态,系统配置页可直接复用缓存。
void preloadKdocsStatus({ maxAgeMs: 60_000, silent: true }).catch(() => {})
await refreshStats()
await refreshNavBadges()
scheduleBadgePolling()
@@ -160,6 +164,7 @@ async function logout() {
try {
await api.post('/logout')
} finally {
clearCachedKdocsStatus()
window.location.href = '/yuyx'
}
}

View File

@@ -5,6 +5,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { fetchSystemConfig, updateSystemConfig } from '../api/system'
import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs'
import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy'
import { getCachedKdocsStatus, preloadKdocsStatus, updateCachedKdocsStatus } from '../utils/kdocsStatusCache'
const loading = ref(false)
@@ -33,14 +34,15 @@ const kdocsRowEnd = ref(0)
const kdocsAdminNotifyEnabled = ref(false)
const kdocsAdminNotifyEmail = ref('')
const kdocsStatus = ref({})
const initialKdocsStatus = getCachedKdocsStatus({ maxAgeMs: 10 * 60 * 1000 })
const kdocsStatus = ref(initialKdocsStatus || {})
const kdocsQrOpen = ref(false)
const kdocsQrImage = ref('')
const kdocsPolling = ref(false)
const kdocsStatusLoading = ref(false)
const kdocsQrLoading = ref(false)
const kdocsClearLoading = ref(false)
const kdocsSilentRefreshing = ref(false)
const kdocsSilentRefreshing = ref(!initialKdocsStatus)
const kdocsActionHint = ref('')
let kdocsPollingTimer = null
@@ -116,7 +118,13 @@ async function loadAll() {
loading.value = false
}
// 金山登录状态改为静默异步获取,避免阻塞系统配置首屏渲染
const cachedStatus = getCachedKdocsStatus({ maxAgeMs: 10 * 60 * 1000 })
if (cachedStatus) {
kdocsStatus.value = cachedStatus
kdocsSilentRefreshing.value = false
}
// 静默刷新金山登录状态,确保状态持续更新且不阻塞首屏。
void refreshKdocsStatusSilently()
}
@@ -124,14 +132,12 @@ async function refreshKdocsStatusSilently() {
if (kdocsSilentRefreshing.value || kdocsStatusLoading.value) return
kdocsSilentRefreshing.value = true
try {
const status = await fetchKdocsStatus(
{},
{
__silent: true,
__no_retry: true,
timeout: 8000,
},
)
const status = await preloadKdocsStatus({
force: false,
maxAgeMs: 60_000,
silent: true,
live: 0,
})
kdocsStatus.value = status || {}
} catch {
// silent mode
@@ -255,7 +261,9 @@ async function refreshKdocsStatus() {
kdocsStatusLoading.value = true
setKdocsHint('正在刷新状态')
try {
kdocsStatus.value = await fetchKdocsStatus({ live: 1 })
const status = await fetchKdocsStatus({ live: 1 })
kdocsStatus.value = status || {}
updateCachedKdocsStatus(kdocsStatus.value)
setKdocsHint('状态已刷新')
} catch {
setKdocsHint('刷新失败,请稍后重试')
@@ -267,7 +275,8 @@ async function refreshKdocsStatus() {
async function pollKdocsStatus() {
try {
const status = await fetchKdocsStatus({ live: 1 })
kdocsStatus.value = status
kdocsStatus.value = status || {}
updateCachedKdocsStatus(kdocsStatus.value)
const loggedIn = status?.logged_in === true || status?.last_login_ok === true
if (loggedIn) {
ElMessage.success('扫码成功,已登录')
@@ -332,6 +341,12 @@ async function onClearKdocsLogin() {
await clearKdocsLogin()
kdocsQrOpen.value = false
kdocsQrImage.value = ''
kdocsStatus.value = updateCachedKdocsStatus({
...(kdocsStatus.value || {}),
logged_in: false,
last_login_ok: false,
login_required: true,
})
ElMessage.success('登录态已清除')
setKdocsHint('登录态已清除')
await refreshKdocsStatus()

View File

@@ -0,0 +1,121 @@
import { fetchKdocsStatus } from '../api/kdocs'
const CACHE_KEY = 'admin:kdocs:status:v1'
const DEFAULT_MAX_AGE_MS = 5 * 60 * 1000
let memoryStatus = null
let memoryUpdatedAt = 0
let inflightPromise = null
function nowTs() {
return Date.now()
}
function normalizeStatus(raw) {
if (!raw || typeof raw !== 'object') return {}
return raw
}
function readSessionCache() {
try {
const raw = window.sessionStorage.getItem(CACHE_KEY)
if (!raw) return null
const parsed = JSON.parse(raw)
if (!parsed || typeof parsed !== 'object') return null
const updatedAt = Number(parsed.updated_at || 0)
const status = normalizeStatus(parsed.status)
if (!updatedAt) return null
return { status, updatedAt }
} catch {
return null
}
}
function writeSessionCache(status, updatedAt) {
try {
window.sessionStorage.setItem(
CACHE_KEY,
JSON.stringify({
status: normalizeStatus(status),
updated_at: Number(updatedAt || nowTs()),
}),
)
} catch {
// ignore
}
}
function hydrateFromSessionIfNeeded() {
if (memoryStatus !== null) return
const cached = readSessionCache()
if (!cached) return
memoryStatus = cached.status
memoryUpdatedAt = cached.updatedAt
}
function commitStatus(status) {
memoryStatus = normalizeStatus(status)
memoryUpdatedAt = nowTs()
writeSessionCache(memoryStatus, memoryUpdatedAt)
return memoryStatus
}
function isFresh(maxAgeMs) {
if (memoryStatus === null || !memoryUpdatedAt) return false
const ageLimit = Number(maxAgeMs)
if (!Number.isFinite(ageLimit) || ageLimit < 0) return true
return nowTs() - memoryUpdatedAt <= ageLimit
}
export function getCachedKdocsStatus(options = {}) {
hydrateFromSessionIfNeeded()
const maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS
if (!isFresh(maxAgeMs)) return null
return normalizeStatus(memoryStatus)
}
export function updateCachedKdocsStatus(status) {
return commitStatus(status)
}
export function clearCachedKdocsStatus() {
memoryStatus = null
memoryUpdatedAt = 0
inflightPromise = null
try {
window.sessionStorage.removeItem(CACHE_KEY)
} catch {
// ignore
}
}
export async function preloadKdocsStatus(options = {}) {
const {
force = false,
maxAgeMs = DEFAULT_MAX_AGE_MS,
silent = true,
live = 0,
} = options
if (!force) {
const cached = getCachedKdocsStatus({ maxAgeMs })
if (cached) return cached
}
if (inflightPromise) return inflightPromise
const params = live ? { live: 1 } : {}
const requestConfig = {
__silent: Boolean(silent),
__no_retry: true,
timeout: 8000,
}
inflightPromise = fetchKdocsStatus(params, requestConfig)
.then((status) => commitStatus(status || {}))
.finally(() => {
inflightPromise = null
})
return inflightPromise
}

View File

@@ -1,6 +1,6 @@
{
"_MetricGrid-BW8H4wTM.js": {
"file": "assets/MetricGrid-BW8H4wTM.js",
"_MetricGrid-BnihYB_8.js": {
"file": "assets/MetricGrid-BnihYB_8.js",
"name": "MetricGrid",
"imports": [
"index.html",
@@ -14,29 +14,29 @@
"file": "assets/MetricGrid-yP_dkP6X.css",
"src": "_MetricGrid-yP_dkP6X.css"
},
"_email-CZFN9gLR.js": {
"file": "assets/email-CZFN9gLR.js",
"_email-px7YBG2O.js": {
"file": "assets/email-px7YBG2O.js",
"name": "email",
"imports": [
"index.html"
]
},
"_system-CiDlQnoe.js": {
"file": "assets/system-CiDlQnoe.js",
"_system-ZDPnxnIu.js": {
"file": "assets/system-ZDPnxnIu.js",
"name": "system",
"imports": [
"index.html"
]
},
"_tasks-DqqATNe_.js": {
"file": "assets/tasks-DqqATNe_.js",
"_tasks-Bep0SUyu.js": {
"file": "assets/tasks-Bep0SUyu.js",
"name": "tasks",
"imports": [
"index.html"
]
},
"_users-BowyvQzr.js": {
"file": "assets/users-BowyvQzr.js",
"_users-te9ySk34.js": {
"file": "assets/users-te9ySk34.js",
"name": "users",
"imports": [
"index.html"
@@ -73,7 +73,7 @@
"name": "vendor-vue"
},
"index.html": {
"file": "assets/index-BNslg8wp.js",
"file": "assets/index-C1f9ticl.js",
"name": "index",
"src": "index.html",
"isEntry": true,
@@ -95,11 +95,11 @@
"src/pages/SettingsPage.vue"
],
"css": [
"assets/index-CVq5QfHO.css"
"assets/index-Dh0BbqTX.css"
]
},
"src/pages/AnnouncementsPage.vue": {
"file": "assets/AnnouncementsPage-C0u6p8a8.js",
"file": "assets/AnnouncementsPage-C6UgwLIT.js",
"name": "AnnouncementsPage",
"src": "src/pages/AnnouncementsPage.vue",
"isDynamicEntry": true,
@@ -115,14 +115,14 @@
]
},
"src/pages/EmailPage.vue": {
"file": "assets/EmailPage-DbZ8F1_b.js",
"file": "assets/EmailPage-CATruPK6.js",
"name": "EmailPage",
"src": "src/pages/EmailPage.vue",
"isDynamicEntry": true,
"imports": [
"_email-CZFN9gLR.js",
"_email-px7YBG2O.js",
"index.html",
"_MetricGrid-BW8H4wTM.js",
"_MetricGrid-BnihYB_8.js",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",
"_vendor-axios-B9ygI19o.js",
@@ -133,13 +133,13 @@
]
},
"src/pages/FeedbacksPage.vue": {
"file": "assets/FeedbacksPage-Dwzul2Z8.js",
"file": "assets/FeedbacksPage-BAnFKHSL.js",
"name": "FeedbacksPage",
"src": "src/pages/FeedbacksPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html",
"_MetricGrid-BW8H4wTM.js",
"_MetricGrid-BnihYB_8.js",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",
"_vendor-axios-B9ygI19o.js",
@@ -150,13 +150,13 @@
]
},
"src/pages/LogsPage.vue": {
"file": "assets/LogsPage-Bs3Ge-t3.js",
"file": "assets/LogsPage-DFPeq0bL.js",
"name": "LogsPage",
"src": "src/pages/LogsPage.vue",
"isDynamicEntry": true,
"imports": [
"_users-BowyvQzr.js",
"_tasks-DqqATNe_.js",
"_users-te9ySk34.js",
"_tasks-Bep0SUyu.js",
"index.html",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",
@@ -168,17 +168,17 @@
]
},
"src/pages/ReportPage.vue": {
"file": "assets/ReportPage-CqUGYZcC.js",
"file": "assets/ReportPage-fzVH-d9u.js",
"name": "ReportPage",
"src": "src/pages/ReportPage.vue",
"isDynamicEntry": true,
"imports": [
"_vendor-element-B5S5pUKo.js",
"index.html",
"_email-CZFN9gLR.js",
"_tasks-DqqATNe_.js",
"_system-CiDlQnoe.js",
"_MetricGrid-BW8H4wTM.js",
"_email-px7YBG2O.js",
"_tasks-Bep0SUyu.js",
"_system-ZDPnxnIu.js",
"_MetricGrid-BnihYB_8.js",
"_vendor-vue-CVxSw_oJ.js",
"_vendor-misc-BeoNyvBp.js",
"_vendor-axios-B9ygI19o.js"
@@ -188,13 +188,13 @@
]
},
"src/pages/SecurityPage.vue": {
"file": "assets/SecurityPage-BARcvvk8.js",
"file": "assets/SecurityPage-xwMQfhuh.js",
"name": "SecurityPage",
"src": "src/pages/SecurityPage.vue",
"isDynamicEntry": true,
"imports": [
"index.html",
"_MetricGrid-BW8H4wTM.js",
"_MetricGrid-BnihYB_8.js",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",
"_vendor-axios-B9ygI19o.js",
@@ -205,7 +205,7 @@
]
},
"src/pages/SettingsPage.vue": {
"file": "assets/SettingsPage-Bblx2O3L.js",
"file": "assets/SettingsPage-DRqlQLxJ.js",
"name": "SettingsPage",
"src": "src/pages/SettingsPage.vue",
"isDynamicEntry": true,
@@ -221,12 +221,12 @@
]
},
"src/pages/SystemPage.vue": {
"file": "assets/SystemPage-BVr94jQh.js",
"file": "assets/SystemPage-D3eBPCNe.js",
"name": "SystemPage",
"src": "src/pages/SystemPage.vue",
"isDynamicEntry": true,
"imports": [
"_system-CiDlQnoe.js",
"_system-ZDPnxnIu.js",
"index.html",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",
@@ -234,16 +234,16 @@
"_vendor-misc-BeoNyvBp.js"
],
"css": [
"assets/SystemPage-CfMGkvmW.css"
"assets/SystemPage-BhhEz4Qz.css"
]
},
"src/pages/UsersPage.vue": {
"file": "assets/UsersPage-CwfHMchI.js",
"file": "assets/UsersPage-DJZUCpfb.js",
"name": "UsersPage",
"src": "src/pages/UsersPage.vue",
"isDynamicEntry": true,
"imports": [
"_users-BowyvQzr.js",
"_users-te9ySk34.js",
"index.html",
"_vendor-element-B5S5pUKo.js",
"_vendor-vue-CVxSw_oJ.js",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{_}from"./index-BNslg8wp.js";import{aj as c,n as s,q as t,K as r,a3 as u,y as p,t as o,G as l,L as y,E as h,D as i,H as v,J as n,I as k,x as f}from"./vendor-vue-CVxSw_oJ.js";const b={class:"metric-top"},x={key:0,class:"metric-icon"},g={class:"metric-label"},B={class:"metric-value"},C={key:0,class:"metric-hint app-muted"},N={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,D)=>{const d=c("el-icon"),m=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(r,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",x,[y(d,null,{default:h(()=>[(t(),i(v(e.icon)))]),_:2},1024)])):l("",!0),o("div",g,n(e?.label||"-"),1)]),o("div",B,[a.loading?(t(),i(m,{key:0,rows:1,animated:""})):(t(),s(r,{key:1},[k(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",C,n(e?.hint||e?.sub),1)):l("",!0)],2))),128))],4)}}},w=_(N,[["__scopeId","data-v-00e217d4"]]);export{w as M};
import{_}from"./index-C1f9ticl.js";import{aj as c,n as s,q as t,K as r,a3 as u,y as p,t as o,G as l,L as y,E as h,D as i,H as v,J as n,I as k,x as f}from"./vendor-vue-CVxSw_oJ.js";const b={class:"metric-top"},x={key:0,class:"metric-icon"},g={class:"metric-label"},B={class:"metric-value"},C={key:0,class:"metric-hint app-muted"},N={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,D)=>{const d=c("el-icon"),m=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(r,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",x,[y(d,null,{default:h(()=>[(t(),i(v(e.icon)))]),_:2},1024)])):l("",!0),o("div",g,n(e?.label||"-"),1)]),o("div",B,[a.loading?(t(),i(m,{key:0,rows:1,animated:""})):(t(),s(r,{key:1},[k(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",C,n(e?.hint||e?.sub),1)):l("",!0)],2))),128))],4)}}},w=_(N,[["__scopeId","data-v-00e217d4"]]);export{w as M};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.page-stack[data-v-ca313705]{display:flex;flex-direction:column;gap:14px;min-width:0}.config-grid[data-v-ca313705]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.card[data-v-ca313705]{border-radius:var(--app-radius);border:1px solid var(--app-border);background:var(--app-card-bg);box-shadow:var(--app-shadow-soft)}.section-card[data-v-ca313705]{min-width:0}.section-title[data-v-ca313705]{margin:0;font-size:15px;font-weight:800;letter-spacing:.2px}.section-sub[data-v-ca313705]{margin-top:6px;margin-bottom:10px;font-size:12px}.section-head[data-v-ca313705]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:10px}.status-inline[data-v-ca313705]{font-size:12px;display:inline-flex;align-items:center;gap:6px}.status-chip[data-v-ca313705]{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border-radius:999px;font-size:12px;font-weight:700;border:1px solid transparent}.status-chip.is-checking[data-v-ca313705]{color:#1d4ed8;background:#dbeafe;border-color:#93c5fd}.status-chip.is-online[data-v-ca313705]{color:#065f46;background:#d1fae5;border-color:#6ee7b7}.status-chip.is-offline[data-v-ca313705]{color:#92400e;background:#fef3c7;border-color:#fcd34d}.status-chip.is-error[data-v-ca313705]{color:#991b1b;background:#fee2e2;border-color:#fca5a5}.status-chip.is-unknown[data-v-ca313705]{color:#374151;background:#f3f4f6;border-color:#d1d5db}.status-dots[data-v-ca313705]{display:inline-flex;align-items:center;gap:3px;margin-left:3px}.status-dots i[data-v-ca313705]{width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.25;animation:dotPulse-ca313705 1.2s infinite ease-in-out}.status-dots i[data-v-ca313705]:nth-child(2){animation-delay:.2s}.status-dots i[data-v-ca313705]:nth-child(3){animation-delay:.4s}@keyframes dotPulse-ca313705{0%,80%,to{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-1px)}}.kdocs-form[data-v-ca313705]{margin-top:6px}.kdocs-inline[data-v-ca313705]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;width:100%}.kdocs-range[data-v-ca313705]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.kdocs-qr[data-v-ca313705]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-ca313705]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-ca313705]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-ca313705]{display:flex;flex-wrap:wrap;gap:10px}@media(max-width:1200px){.config-grid[data-v-ca313705]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:768px){.config-grid[data-v-ca313705],.kdocs-inline[data-v-ca313705]{grid-template-columns:1fr}.kdocs-range[data-v-ca313705]{align-items:stretch}}

View File

@@ -1 +0,0 @@
.page-stack[data-v-cef111cd]{display:flex;flex-direction:column;gap:14px;min-width:0}.config-grid[data-v-cef111cd]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.card[data-v-cef111cd]{border-radius:var(--app-radius);border:1px solid var(--app-border);background:var(--app-card-bg);box-shadow:var(--app-shadow-soft)}.section-card[data-v-cef111cd]{min-width:0}.section-title[data-v-cef111cd]{margin:0;font-size:15px;font-weight:800;letter-spacing:.2px}.section-sub[data-v-cef111cd]{margin-top:6px;margin-bottom:10px;font-size:12px}.section-head[data-v-cef111cd]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:10px}.status-inline[data-v-cef111cd]{font-size:12px;display:inline-flex;align-items:center;gap:6px}.status-chip[data-v-cef111cd]{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border-radius:999px;font-size:12px;font-weight:700;border:1px solid transparent}.status-chip.is-checking[data-v-cef111cd]{color:#1d4ed8;background:#dbeafe;border-color:#93c5fd}.status-chip.is-online[data-v-cef111cd]{color:#065f46;background:#d1fae5;border-color:#6ee7b7}.status-chip.is-offline[data-v-cef111cd]{color:#92400e;background:#fef3c7;border-color:#fcd34d}.status-chip.is-error[data-v-cef111cd]{color:#991b1b;background:#fee2e2;border-color:#fca5a5}.status-chip.is-unknown[data-v-cef111cd]{color:#374151;background:#f3f4f6;border-color:#d1d5db}.status-dots[data-v-cef111cd]{display:inline-flex;align-items:center;gap:3px;margin-left:3px}.status-dots i[data-v-cef111cd]{width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.25;animation:dotPulse-cef111cd 1.2s infinite ease-in-out}.status-dots i[data-v-cef111cd]:nth-child(2){animation-delay:.2s}.status-dots i[data-v-cef111cd]:nth-child(3){animation-delay:.4s}@keyframes dotPulse-cef111cd{0%,80%,to{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-1px)}}.kdocs-form[data-v-cef111cd]{margin-top:6px}.kdocs-inline[data-v-cef111cd]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;width:100%}.kdocs-range[data-v-cef111cd]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.kdocs-qr[data-v-cef111cd]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-cef111cd]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-cef111cd]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-cef111cd]{display:flex;flex-wrap:wrap;gap:10px}@media(max-width:1200px){.config-grid[data-v-cef111cd]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:768px){.config-grid[data-v-cef111cd],.kdocs-inline[data-v-cef111cd]{grid-template-columns:1fr}.kdocs-range[data-v-cef111cd]{align-items:stretch}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{c as s,a as e}from"./index-BNslg8wp.js";const n=s(async()=>{const{data:a}=await e.get("/email/stats");return a},1e4);async function i(){const{data:a}=await e.get("/email/settings");return a}async function r(a){const{data:t}=await e.post("/email/settings",a);return n.clear(),t}async function o(a={}){return n.run(a)}async function l(a){const{data:t}=await e.get("/email/logs",{params:a});return t}async function u(a){const{data:t}=await e.post("/email/logs/cleanup",{days:a});return n.clear(),t}export{l as a,i as b,u as c,o as f,r as u};
import{c as s,a as e}from"./index-C1f9ticl.js";const n=s(async()=>{const{data:a}=await e.get("/email/stats");return a},1e4);async function i(){const{data:a}=await e.get("/email/settings");return a}async function r(a){const{data:t}=await e.post("/email/settings",a);return n.clear(),t}async function o(a={}){return n.run(a)}async function l(a){const{data:t}=await e.get("/email/logs",{params:a});return t}async function u(a){const{data:t}=await e.post("/email/logs/cleanup",{days:a});return n.clear(),t}export{l as a,i as b,u as c,o as f,r as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{c as s,a}from"./index-BNslg8wp.js";const e=s(async()=>{const{data:t}=await a.get("/system/config");return t},15e3);async function o(t={}){return e.run(t)}async function r(t){const{data:n}=await a.post("/system/config",t);return e.clear(),n}export{o as f,r as u};
import{c as s,a}from"./index-C1f9ticl.js";const e=s(async()=>{const{data:t}=await a.get("/system/config");return t},15e3);async function o(t={}){return e.run(t)}async function r(t){const{data:n}=await a.post("/system/config",t);return e.clear(),n}export{o as f,r as u};

View File

@@ -1 +1 @@
import{c as s,a}from"./index-BNslg8wp.js";const c=s(async()=>{const{data:t}=await a.get("/server/info");return t},3e4),o=s(async()=>{const{data:t}=await a.get("/docker_stats");return t},8e3),u=s(async()=>{const{data:t}=await a.get("/request_metrics");return t},1e4),i=s(async()=>{const{data:t}=await a.get("/slow_sql_metrics");return t},1e4),e=s(async()=>{const{data:t}=await a.get("/task/stats");return t},4e3),r=s(async()=>{const{data:t}=await a.get("/task/running");return t},2e3);async function g(t={}){return c.run(t)}async function y(t={}){return o.run(t)}async function d(t={}){return u.run(t)}async function k(t={}){return i.run(t)}async function l(t={}){return e.run(t)}async function w(t={}){return r.run(t)}async function _(t){const{data:n}=await a.get("/task/logs",{params:t});return n}async function h(t){const{data:n}=await a.post("/task/logs/clear",{days:t});return e.clear(),r.clear(),n}export{w as a,g as b,y as c,d,k as e,l as f,_ as g,h};
import{c as s,a}from"./index-C1f9ticl.js";const c=s(async()=>{const{data:t}=await a.get("/server/info");return t},3e4),o=s(async()=>{const{data:t}=await a.get("/docker_stats");return t},8e3),u=s(async()=>{const{data:t}=await a.get("/request_metrics");return t},1e4),i=s(async()=>{const{data:t}=await a.get("/slow_sql_metrics");return t},1e4),e=s(async()=>{const{data:t}=await a.get("/task/stats");return t},4e3),r=s(async()=>{const{data:t}=await a.get("/task/running");return t},2e3);async function g(t={}){return c.run(t)}async function y(t={}){return o.run(t)}async function d(t={}){return u.run(t)}async function k(t={}){return i.run(t)}async function l(t={}){return e.run(t)}async function w(t={}){return r.run(t)}async function _(t){const{data:n}=await a.get("/task/logs",{params:t});return n}async function h(t){const{data:n}=await a.post("/task/logs/clear",{days:t});return e.clear(),r.clear(),n}export{w as a,g as b,y as c,d,k as e,l as f,_ as g,h};

View File

@@ -1 +1 @@
import{a as t}from"./index-BNslg8wp.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s};
import{a as t}from"./index-C1f9ticl.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s};

View File

@@ -5,13 +5,13 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理 - 知识管理平台</title>
<script type="module" crossorigin src="./assets/index-BNslg8wp.js"></script>
<script type="module" crossorigin src="./assets/index-C1f9ticl.js"></script>
<link rel="modulepreload" crossorigin href="./assets/vendor-vue-CVxSw_oJ.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-misc-BeoNyvBp.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-element-B5S5pUKo.js">
<link rel="modulepreload" crossorigin href="./assets/vendor-axios-B9ygI19o.js">
<link rel="stylesheet" crossorigin href="./assets/vendor-element-C68yOrAy.css">
<link rel="stylesheet" crossorigin href="./assets/index-CVq5QfHO.css">
<link rel="stylesheet" crossorigin href="./assets/index-Dh0BbqTX.css">
</head>
<body>
<div id="app"></div>