refactor(company): extract ExpireOrApp guard component from app.tsx
- Move ExpireOrApp logic into standalone component under components/ExpireOrApp - Remove unused React hooks and CompanyExpireGuard import from app.tsx - Use dayjs.utc for validity date to prevent timezone offset issues - Remove stale console.log from CompanyExpireWarning
This commit is contained in:
12
src/app.tsx
12
src/app.tsx
@@ -3,6 +3,7 @@ import { PageLoading } from '@ant-design/pro-components';
|
|||||||
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
|
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
|
||||||
import { history, Link, useAccess, useModel } from '@umijs/max';
|
import { history, Link, useAccess, useModel } from '@umijs/max';
|
||||||
import '@ant-design/v5-patch-for-react-19';
|
import '@ant-design/v5-patch-for-react-19';
|
||||||
|
import React from 'react';
|
||||||
import { App } from 'antd';
|
import { App } from 'antd';
|
||||||
import { AvatarDropdown, AvatarName, SelectLang } from '@/components';
|
import { AvatarDropdown, AvatarName, SelectLang } from '@/components';
|
||||||
import { currentUser as queryCurrentUser } from '@/services/api';
|
import { currentUser as queryCurrentUser } from '@/services/api';
|
||||||
@@ -17,7 +18,7 @@ import ServerErrorPage from './pages/500';
|
|||||||
import { errorConfig } from './requestErrorConfig';
|
import { errorConfig } from './requestErrorConfig';
|
||||||
import { getDeviceId } from './utils/fp';
|
import { getDeviceId } from './utils/fp';
|
||||||
import './utils/sentry';
|
import './utils/sentry';
|
||||||
import CompanyExpireGuard from './components/CompanyExpireGuard';
|
import ExpireOrApp from './components/ExpireOrApp';
|
||||||
import CompanyExpireWarning from './components/CompanyExpireWarning';
|
import CompanyExpireWarning from './components/CompanyExpireWarning';
|
||||||
import GlobalErrorBoundary from './components/GlobalErrorBoundary';
|
import GlobalErrorBoundary from './components/GlobalErrorBoundary';
|
||||||
import PermissionGuard from './components/PermissionGuard';
|
import PermissionGuard from './components/PermissionGuard';
|
||||||
@@ -106,6 +107,10 @@ export function rootContainer(container: React.ReactNode) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function innerProvider(container: React.ReactNode) {
|
||||||
|
return <ExpireOrApp>{container}</ExpireOrApp>;
|
||||||
|
}
|
||||||
|
|
||||||
// ProLayout support API https://procomponents.ant.design/components/layout
|
// ProLayout support API https://procomponents.ant.design/components/layout
|
||||||
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
||||||
const { fetchUnread, initialized } = useModel('useMenuNoticeNum');
|
const { fetchUnread, initialized } = useModel('useMenuNoticeNum');
|
||||||
@@ -201,11 +206,6 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
|||||||
childrenRender: (children) => {
|
childrenRender: (children) => {
|
||||||
if (initialState?.loading) return <PageLoading />;
|
if (initialState?.loading) return <PageLoading />;
|
||||||
|
|
||||||
const { company } = currentUser ?? {};
|
|
||||||
|
|
||||||
if (company?.special !== 0 && company?.validityStatus === 2) {
|
|
||||||
return <CompanyExpireGuard />;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentUser && (
|
{currentUser && (
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ const CompanyExpireWarning: React.FC = () => {
|
|||||||
dayjs().utc(),
|
dayjs().utc(),
|
||||||
'day',
|
'day',
|
||||||
);
|
);
|
||||||
console.log(
|
|
||||||
expireInDays,
|
|
||||||
validityEndTime,
|
|
||||||
dayjs().utc().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
);
|
|
||||||
|
|
||||||
const tipsNode = (
|
const tipsNode = (
|
||||||
<Alert
|
<Alert
|
||||||
|
|||||||
58
src/components/ExpireOrApp/index.tsx
Normal file
58
src/components/ExpireOrApp/index.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { PageLoading } from '@ant-design/pro-components';
|
||||||
|
import { history, useModel } from '@umijs/max';
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import { LOGIN_URL } from '@/access';
|
||||||
|
import CompanyExpireGuard from '@/components/CompanyExpireGuard';
|
||||||
|
|
||||||
|
const ExpireOrApp: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
|
const { initialState, loading } = useModel('@@initialState');
|
||||||
|
const [location, setLocation] = useState(history.location);
|
||||||
|
const company = initialState?.currentUser?.company;
|
||||||
|
const guardRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return history.listen((update) => {
|
||||||
|
setLocation(update.location);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const isExpired = company?.special !== 0 && company?.validityStatus === 2;
|
||||||
|
const isLoginPage = location.pathname === LOGIN_URL;
|
||||||
|
const shouldBlock = isExpired && !isLoginPage;
|
||||||
|
|
||||||
|
const shouldBlockRef = useRef(shouldBlock);
|
||||||
|
shouldBlockRef.current = shouldBlock;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!shouldBlock) return;
|
||||||
|
const el = guardRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
if (!shouldBlockRef.current) return;
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
for (const node of Array.from(mutation.removedNodes)) {
|
||||||
|
if (node === el) {
|
||||||
|
window.location.reload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, { childList: true });
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [shouldBlock]);
|
||||||
|
|
||||||
|
if (loading) return <PageLoading />;
|
||||||
|
if (shouldBlock) {
|
||||||
|
return (
|
||||||
|
<div ref={guardRef} id="company-expire-guard-root">
|
||||||
|
<CompanyExpireGuard />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExpireOrApp;
|
||||||
@@ -50,7 +50,7 @@ export default (props: {
|
|||||||
|
|
||||||
if (isSuperAdmin) {
|
if (isSuperAdmin) {
|
||||||
values.validityEndTime = values.validityEndTime
|
values.validityEndTime = values.validityEndTime
|
||||||
? dayjs(values.validityEndTime).endOf('day').format('YYYY-MM-DD')
|
? dayjs.utc(values.validityEndTime).format('YYYY-MM-DD')
|
||||||
: '';
|
: '';
|
||||||
values.validityStartTime = values.validityEndTime ? '2026-01-01' : '';
|
values.validityStartTime = values.validityEndTime ? '2026-01-01' : '';
|
||||||
}
|
}
|
||||||
@@ -118,26 +118,29 @@ export default (props: {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{isSuperAdmin && (
|
|
||||||
<ProFormDatePicker
|
|
||||||
hidden={formValues?.id === void 0}
|
|
||||||
name="validityEndTime"
|
|
||||||
label={`${$t('form.company.validityEndTime')} (${$t('form.company.validityEndTime.tips')})`}
|
|
||||||
placeholder={$t('form.company.validityEndTime.placeholder')}
|
|
||||||
convertValue={(value: string | Dayjs | null | undefined) =>
|
|
||||||
value ? value : undefined
|
|
||||||
}
|
|
||||||
fieldProps={{
|
|
||||||
style: { width: '100%' },
|
|
||||||
disabledDate: (current: Dayjs) =>
|
|
||||||
current?.isBefore(dayjs().startOf('day')),
|
|
||||||
}}
|
|
||||||
// extra={<Text type="danger">{$t('pages.company.expired')}</Text>}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{formValues?.id !== void 0 && (
|
{formValues?.id !== void 0 && (
|
||||||
<>
|
<>
|
||||||
|
{isSuperAdmin && (
|
||||||
|
<ProFormDatePicker
|
||||||
|
name="validityEndTime"
|
||||||
|
label={`${$t('form.company.validityEndTime')} (${$t('form.company.validityEndTime.tips')})`}
|
||||||
|
placeholder={$t('form.company.validityEndTime.placeholder')}
|
||||||
|
convertValue={(value: string | Dayjs | null | undefined) =>
|
||||||
|
value ? dayjs.utc(value) : undefined
|
||||||
|
}
|
||||||
|
fieldProps={{
|
||||||
|
style: { width: '100%' },
|
||||||
|
disabledDate: (current: Dayjs) => {
|
||||||
|
// return current?.isBefore(dayjs().startOf('day'));
|
||||||
|
return (
|
||||||
|
current?.format('YYYY-MM-DD') <
|
||||||
|
dayjs.utc().format('YYYY-MM-DD')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Divider size="small" />
|
<Divider size="small" />
|
||||||
|
|
||||||
<Text strong style={{ lineHeight: '40px', fontSize: 16 }}>
|
<Text strong style={{ lineHeight: '40px', fontSize: 16 }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user