R29-1 R29-6: 重构海音达工作台壳层与高频页面

这个提交包含在:
2026-03-23 09:59:35 +08:00
父节点 f9198a781a
当前提交 7e183c0cdc
共修改 33 个文件,包含 2193 行新增和 1564 行删除
+37 -12
查看文件
@@ -143,6 +143,7 @@ export function AuthProvider({ children }: PropsWithChildren) {
const [state, setState] = useState<AuthState>(EMPTY_STATE);
const [offlineAccessMode, setOfflineAccessMode] = useState(false);
const tokenRef = useRef<string | null>(null);
const bootstrapPromiseRef = useRef<Promise<string | null> | null>(null);
useEffect(() => {
tokenRef.current = state.accessToken;
@@ -195,18 +196,28 @@ export function AuthProvider({ children }: PropsWithChildren) {
return;
}
try {
const refreshed = await refreshSession();
const me = await fetchCurrentEmployee(refreshed.accessToken);
const mustChangePassword = readMustChangePasswordFromStorage();
commitAuthenticatedUser(refreshed.accessToken, me, mustChangePassword);
} catch {
if (isWindowAvailable() && window.navigator.onLine === false && offlineSnapshot) {
activateOfflineSnapshot(offlineSnapshot);
return;
}
clearSession();
if (!bootstrapPromiseRef.current) {
bootstrapPromiseRef.current = (async () => {
try {
const refreshed = await refreshSession();
const me = await fetchCurrentEmployee(refreshed.accessToken);
const mustChangePassword = readMustChangePasswordFromStorage();
commitAuthenticatedUser(refreshed.accessToken, me, mustChangePassword);
return refreshed.accessToken;
} catch {
if (isWindowAvailable() && window.navigator.onLine === false && offlineSnapshot) {
activateOfflineSnapshot(offlineSnapshot);
return null;
}
clearSession();
return null;
} finally {
bootstrapPromiseRef.current = null;
}
})();
}
await bootstrapPromiseRef.current;
}, [activateOfflineSnapshot, clearSession, commitAuthenticatedUser]);
const login = useCallback(
@@ -241,8 +252,22 @@ export function AuthProvider({ children }: PropsWithChildren) {
configureHttpAuth({
getAccessToken: () => tokenRef.current,
refreshAccessToken: async () => {
if (bootstrapPromiseRef.current) {
const bootstrappedToken = await bootstrapPromiseRef.current;
if (bootstrappedToken) {
return bootstrappedToken;
}
}
try {
const refreshed = await refreshSession();
if (!state.me) {
const me = await fetchCurrentEmployee(refreshed.accessToken);
const mustChangePassword = readMustChangePasswordFromStorage();
commitAuthenticatedUser(refreshed.accessToken, me, mustChangePassword);
return refreshed.accessToken;
}
tokenRef.current = refreshed.accessToken;
setOfflineAccessMode(false);
setState((previous) => ({
@@ -258,7 +283,7 @@ export function AuthProvider({ children }: PropsWithChildren) {
},
clearSession,
});
}, [clearSession]);
}, [clearSession, commitAuthenticatedUser, state.me]);
useEffect(() => {
void bootstrapByRefresh();