前端热更新
This commit is contained in:
1 parent
af88732a07
commit
5b95fe8f40
3 files changed
+19
-16
No files matched your search
+11
-4
@@ -8,6 +8,13 @@ import {
|
|||||||
refreshIfNeeded,
|
refreshIfNeeded,
|
||||||
} from '../auth/session'
|
} from '../auth/session'
|
||||||
|
|
||||||
|
declare module 'axios' {
|
||||||
|
export interface AxiosRequestConfig {
|
||||||
|
// Public kiosk pages must remain usable when this browser has an expired login session.
|
||||||
|
skipAuthSession?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const http = axios.create({
|
const http = axios.create({
|
||||||
baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api',
|
baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api',
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
@@ -20,12 +27,12 @@ http.interceptors.request.use(async (config) => {
|
|||||||
config.url?.endsWith('/auth/logout') ||
|
config.url?.endsWith('/auth/logout') ||
|
||||||
config.url?.endsWith('/auth/sso/exchange') ||
|
config.url?.endsWith('/auth/sso/exchange') ||
|
||||||
config.url?.endsWith('/auth/sso/bind')
|
config.url?.endsWith('/auth/sso/bind')
|
||||||
if (!isAuthenticationRequest) {
|
if (!isAuthenticationRequest && !config.skipAuthSession) {
|
||||||
const activeToken = await refreshIfNeeded(true)
|
const activeToken = await refreshIfNeeded(true)
|
||||||
if (activeToken) markActivity()
|
if (activeToken) markActivity()
|
||||||
}
|
}
|
||||||
const token = localStorage.getItem(authStorageKeys.token)
|
const token = localStorage.getItem(authStorageKeys.token)
|
||||||
if (token) config.headers.Authorization = `Bearer ${token}`
|
if (token && !config.skipAuthSession) config.headers.Authorization = `Bearer ${token}`
|
||||||
return config
|
return config
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -40,7 +47,7 @@ http.interceptors.response.use(
|
|||||||
error.config?.url?.endsWith('/auth/sso/bind')
|
error.config?.url?.endsWith('/auth/sso/bind')
|
||||||
const retryableConfig = error.config as
|
const retryableConfig = error.config as
|
||||||
(typeof error.config & { _jiaowuRetried?: boolean }) | undefined
|
(typeof error.config & { _jiaowuRetried?: boolean }) | undefined
|
||||||
if (error.response?.status === 401 && !isAuthenticationRequest &&
|
if (error.response?.status === 401 && !isAuthenticationRequest && !error.config?.skipAuthSession &&
|
||||||
!retryableConfig?._jiaowuRetried) {
|
!retryableConfig?._jiaowuRetried) {
|
||||||
const token = await refreshAuthSession()
|
const token = await refreshAuthSession()
|
||||||
if (token && retryableConfig) {
|
if (token && retryableConfig) {
|
||||||
@@ -49,7 +56,7 @@ http.interceptors.response.use(
|
|||||||
return http.request(retryableConfig)
|
return http.request(retryableConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (error.response?.status === 401 && !isAuthenticationRequest) {
|
if (error.response?.status === 401 && !isAuthenticationRequest && !error.config?.skipAuthSession) {
|
||||||
clearAuthSession()
|
clearAuthSession()
|
||||||
goLogin(location.pathname + location.search + location.hash)
|
goLogin(location.pathname + location.search + location.hash)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,8 @@ interface AppUpdateCheckResponse {
|
|||||||
|
|
||||||
const updateChannel =
|
const updateChannel =
|
||||||
import.meta.env.VITE_APP_UPDATE_CHANNEL?.trim() || 'production'
|
import.meta.env.VITE_APP_UPDATE_CHANNEL?.trim() || 'production'
|
||||||
const foregroundCheckInterval = 5 * 60 * 1000
|
|
||||||
|
|
||||||
let checkInProgress: Promise<void> | undefined
|
let checkInProgress: Promise<void> | undefined
|
||||||
let lastCheckedAt = 0
|
|
||||||
|
|
||||||
function absoluteApiUrl(relativePath: string) {
|
function absoluteApiUrl(relativePath: string) {
|
||||||
const configuredBase = String(http.defaults.baseURL ?? '/api')
|
const configuredBase = String(http.defaults.baseURL ?? '/api')
|
||||||
@@ -36,9 +34,7 @@ function absoluteApiUrl(relativePath: string) {
|
|||||||
|
|
||||||
async function checkForAppUpdate() {
|
async function checkForAppUpdate() {
|
||||||
if (checkInProgress) return checkInProgress
|
if (checkInProgress) return checkInProgress
|
||||||
if (!navigator.onLine || Date.now() - lastCheckedAt < foregroundCheckInterval) {
|
if (!navigator.onLine) return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checkInProgress = (async () => {
|
checkInProgress = (async () => {
|
||||||
try {
|
try {
|
||||||
@@ -64,6 +60,9 @@ async function checkForAppUpdate() {
|
|||||||
nativeVersion: current.native,
|
nativeVersion: current.native,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
},
|
},
|
||||||
|
// Update discovery is deliberately public. Do not delay startup for a
|
||||||
|
// token refresh or send a stale Authorization header to this endpoint.
|
||||||
|
skipAuthSession: true,
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -96,7 +95,6 @@ async function checkForAppUpdate() {
|
|||||||
// OTA failure must never stop users from entering the bundled application.
|
// OTA failure must never stop users from entering the bundled application.
|
||||||
console.warn('[app-update] update check failed', error)
|
console.warn('[app-update] update check failed', error)
|
||||||
} finally {
|
} finally {
|
||||||
lastCheckedAt = Date.now()
|
|
||||||
checkInProgress = undefined
|
checkInProgress = undefined
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
@@ -116,10 +114,8 @@ export async function initializeAppUpdates() {
|
|||||||
console.warn('[app-update] bundle readiness confirmation failed', error)
|
console.warn('[app-update] bundle readiness confirmation failed', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every cold start checks the latest public release immediately. A bundle
|
||||||
|
// downloaded here is activated when the app is next launched.
|
||||||
void checkForAppUpdate()
|
void checkForAppUpdate()
|
||||||
window.addEventListener('visibilitychange', () => {
|
window.addEventListener('online', () => void checkForAppUpdate())
|
||||||
if (document.visibilityState === 'visible') {
|
|
||||||
void checkForAppUpdate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ async function load() {
|
|||||||
if (loading) return
|
if (loading) return
|
||||||
loading = true
|
loading = true
|
||||||
try {
|
try {
|
||||||
data.value = (await http.get(`/venue-displays/${type.value}s/${id.value}`)).data
|
data.value = (await http.get(`/venue-displays/${type.value}s/${id.value}`, { skipAuthSession: true })).data
|
||||||
await nextTick()
|
await nextTick()
|
||||||
fitPage()
|
fitPage()
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in new issue
Block a user