From 318728b121bbf01122881757bf4722f05b58e514 Mon Sep 17 00:00:00 2001
From: Johnton Chen <504071088@qq.com>
Date: Thu, 30 Jul 2026 21:33:48 +0800
Subject: [PATCH] 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
---
src/app.tsx | 12 ++--
src/components/CompanyExpireWarning/index.tsx | 5 --
src/components/ExpireOrApp/index.tsx | 58 +++++++++++++++++++
src/pages/company/Popup.tsx | 39 +++++++------
4 files changed, 85 insertions(+), 29 deletions(-)
create mode 100644 src/components/ExpireOrApp/index.tsx
diff --git a/src/app.tsx b/src/app.tsx
index 15380ea..ace44e6 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -3,6 +3,7 @@ import { PageLoading } from '@ant-design/pro-components';
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
import { history, Link, useAccess, useModel } from '@umijs/max';
import '@ant-design/v5-patch-for-react-19';
+import React from 'react';
import { App } from 'antd';
import { AvatarDropdown, AvatarName, SelectLang } from '@/components';
import { currentUser as queryCurrentUser } from '@/services/api';
@@ -17,7 +18,7 @@ import ServerErrorPage from './pages/500';
import { errorConfig } from './requestErrorConfig';
import { getDeviceId } from './utils/fp';
import './utils/sentry';
-import CompanyExpireGuard from './components/CompanyExpireGuard';
+import ExpireOrApp from './components/ExpireOrApp';
import CompanyExpireWarning from './components/CompanyExpireWarning';
import GlobalErrorBoundary from './components/GlobalErrorBoundary';
import PermissionGuard from './components/PermissionGuard';
@@ -106,6 +107,10 @@ export function rootContainer(container: React.ReactNode) {
);
}
+export function innerProvider(container: React.ReactNode) {
+ return {container};
+}
+
// ProLayout support API https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
const { fetchUnread, initialized } = useModel('useMenuNoticeNum');
@@ -201,11 +206,6 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
childrenRender: (children) => {
if (initialState?.loading) return ;
- const { company } = currentUser ?? {};
-
- if (company?.special !== 0 && company?.validityStatus === 2) {
- return ;
- }
return (
<>
{currentUser && (
diff --git a/src/components/CompanyExpireWarning/index.tsx b/src/components/CompanyExpireWarning/index.tsx
index 56e158e..6bdc844 100644
--- a/src/components/CompanyExpireWarning/index.tsx
+++ b/src/components/CompanyExpireWarning/index.tsx
@@ -19,11 +19,6 @@ const CompanyExpireWarning: React.FC = () => {
dayjs().utc(),
'day',
);
- console.log(
- expireInDays,
- validityEndTime,
- dayjs().utc().format('YYYY-MM-DD HH:mm:ss'),
- );
const tipsNode = (
= ({ children }) => {
+ const { initialState, loading } = useModel('@@initialState');
+ const [location, setLocation] = useState(history.location);
+ const company = initialState?.currentUser?.company;
+ const guardRef = useRef(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 ;
+ if (shouldBlock) {
+ return (
+
+
+
+ );
+ }
+ return <>{children}>;
+};
+
+export default ExpireOrApp;
diff --git a/src/pages/company/Popup.tsx b/src/pages/company/Popup.tsx
index 1363f20..cb64839 100644
--- a/src/pages/company/Popup.tsx
+++ b/src/pages/company/Popup.tsx
@@ -50,7 +50,7 @@ export default (props: {
if (isSuperAdmin) {
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' : '';
}
@@ -118,26 +118,29 @@ export default (props: {
},
]}
/>
- {isSuperAdmin && (
-
- value ? value : undefined
- }
- fieldProps={{
- style: { width: '100%' },
- disabledDate: (current: Dayjs) =>
- current?.isBefore(dayjs().startOf('day')),
- }}
- // extra={{$t('pages.company.expired')}}
- />
- )}
{formValues?.id !== void 0 && (
<>
+ {isSuperAdmin && (
+
+ 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')
+ );
+ },
+ }}
+ />
+ )}