增加企微旧包刷新护栏(07-27-yang-jun-reimbursement-readiness)
这个提交包含在:
@@ -6,6 +6,15 @@ const MOBILE_APPROVAL_TASK_PATH = /^\/workflow\/tasks\/([^/]+)$/i;
|
||||
const OFFLINE_ALLOWED_PATHS = ["/mobile/approvals"];
|
||||
const CLEARABLE_CACHE_PREFIXES = ["app-api-runtime", "app-static-runtime", "workbox-precache"];
|
||||
const AUTH_INPUT_PATHS = ["/login", "/change-password", "/forgot-password", "/reset-password"];
|
||||
const BUILD_SHA_DISPLAY_LENGTH = 12;
|
||||
|
||||
type ReadyResponse = {
|
||||
data?: {
|
||||
buildSha?: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
let buildFreshnessMonitorInstalled = false;
|
||||
|
||||
function isAuthInputPath(pathname: string) {
|
||||
return AUTH_INPUT_PATHS.some((path) => pathname === path || pathname.startsWith(`${path}/`));
|
||||
@@ -34,6 +43,82 @@ function bindServiceWorkerUpdateCleanup(registration: ServiceWorkerRegistration
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeBuildSha(value: unknown) {
|
||||
const normalized = String(value ?? "").trim().toLowerCase();
|
||||
if (
|
||||
!normalized ||
|
||||
normalized === "unknown" ||
|
||||
normalized === "development" ||
|
||||
!/^[a-f0-9]{7,64}$/.test(normalized)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return normalized.slice(0, BUILD_SHA_DISPLAY_LENGTH);
|
||||
}
|
||||
|
||||
function buildUserControlledRefresh() {
|
||||
return () => {
|
||||
void clearPwaRuntimeCaches()
|
||||
.catch(() => undefined)
|
||||
.finally(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function installBuildFreshnessMonitor() {
|
||||
if (!canUseWindow() || buildFreshnessMonitorInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
buildFreshnessMonitorInstalled = true;
|
||||
let checkInFlight = false;
|
||||
let mismatchNotified = false;
|
||||
|
||||
const checkBuildFreshness = async () => {
|
||||
if (document.visibilityState !== "visible" || checkInFlight || mismatchNotified) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clientBuildSha = normalizeBuildSha(document.documentElement.dataset.buildSha);
|
||||
if (!clientBuildSha) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkInFlight = true;
|
||||
try {
|
||||
const response = await window.fetch("/ready", {
|
||||
cache: "no-store",
|
||||
credentials: "same-origin",
|
||||
headers: { accept: "application/json" },
|
||||
});
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = await response.json() as ReadyResponse;
|
||||
const serverBuildSha = normalizeBuildSha(payload.data?.buildSha);
|
||||
if (!serverBuildSha || serverBuildSha === clientBuildSha) {
|
||||
return;
|
||||
}
|
||||
|
||||
mismatchNotified = true;
|
||||
window.dispatchEvent(new CustomEvent(PWA_UPDATE_READY_EVENT, {
|
||||
detail: { applyUpdate: buildUserControlledRefresh() },
|
||||
}));
|
||||
} catch {
|
||||
} finally {
|
||||
checkInFlight = false;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
void checkBuildFreshness();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function registerPwaIfEnabled() {
|
||||
if (import.meta.env.DEV) {
|
||||
return;
|
||||
|
||||
在新工单中引用
屏蔽一个用户