增加企微旧包刷新护栏(07-27-yang-jun-reimbursement-readiness)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-31 17:40:25 +08:00
父节点 39c3e808a3
当前提交 e123d50f86
共修改 9 个文件,包含 308 行新增和 1 行删除
+85
查看文件
@@ -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;