优化后台金山状态:登录后静默预取并在系统配置页复用缓存
This commit is contained in:
@@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
121
admin-frontend/src/utils/kdocsStatusCache.js
Normal file
121
admin-frontend/src/utils/kdocsStatusCache.js
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user