diff --git a/config/config.ts b/config/config.ts index 7579aca..0e795a2 100644 --- a/config/config.ts +++ b/config/config.ts @@ -20,9 +20,9 @@ export default defineConfig({ hash: true, mock: false, antd: {}, - // dva: { - // hmr: true - // }, + dva: { + hmr: true + }, history: { type: REACT_APP_ENV === 'dev' ? "hash" : "memory", // type: "hash" @@ -36,7 +36,7 @@ export default defineConfig({ baseNavigator: true, }, dynamicImport: { - loading: '@/components/SmartLoading/index', + loading: '@/components/PageLoading/index', }, targets: { ie: 11, diff --git a/src/app.ts b/src/app.ts index 07c98e6..96a4c39 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,7 +7,6 @@ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ import globalState from './globalState'; -import { routePreloader } from './utils/routePreloader'; // import { getMicroAppRouteComponent } from 'umi'; @@ -30,22 +29,6 @@ export const qiankun = { } -// 应用启动时的初始化配置 -export async function getInitialState() { - // 预加载关键路由以优化首屏加载 - setTimeout(() => { - routePreloader.preloadCriticalRoutes().then(() => { - console.log('关键路由预加载完成'); - }).catch(error => { - console.warn('关键路由预加载失败:', error); - }); - }, 1000); // 延迟1秒后开始预加载,避免影响首屏渲染 - - return { - preloadEnabled: true, - }; -} - // export const patchRoutes = ({ routes }: any) => { // console.info('routes', routes); // routes[0].routes[1].routes[0].routes.forEach((item: any, index: number) => { @@ -58,4 +41,4 @@ export async function getInitialState() { // }))() // } // }); -// } \ No newline at end of file +// } diff --git a/src/components/PageLoading/index.less b/src/components/PageLoading/index.less deleted file mode 100644 index d8adfe4..0000000 --- a/src/components/PageLoading/index.less +++ /dev/null @@ -1,7 +0,0 @@ -.page-loading-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - width: 100%; -} \ No newline at end of file diff --git a/src/components/PageLoading/index.tsx b/src/components/PageLoading/index.tsx index dbd4884..096c58f 100644 --- a/src/components/PageLoading/index.tsx +++ b/src/components/PageLoading/index.tsx @@ -1,13 +1,5 @@ -// import { PageLoading } from '@ant-design/pro-layout'; +import { PageLoading } from '@ant-design/pro-layout'; -// // loading components from code split -// // https://umijs.org/plugin/umi-plugin-react.html#dynamicimport -// export default PageLoading; -import React from 'react'; -import SkeletonLoading from '../SkeletonLoading'; - -const PageLoading: React.FC = () => { - return ; -}; - -export default PageLoading; \ No newline at end of file +// loading components from code split +// https://umijs.org/plugin/umi-plugin-react.html#dynamicimport +export default PageLoading; diff --git a/src/components/PageTransition/index.less b/src/components/PageTransition/index.less index 925adb4..37fd1b7 100644 --- a/src/components/PageTransition/index.less +++ b/src/components/PageTransition/index.less @@ -3,7 +3,13 @@ // 默认不播放动画,只有带animate类时才播放 &.animate { animation: pageEnter 0.5s cubic-bezier(0.4, 0, 0.2, 1); - will-change: opacity, transform; + // 移除will-change避免HMR时样式冲突 + // will-change: opacity, transform; + } + + // 动画结束后重置will-change,避免持续占用GPU资源 + &.animate:not(:hover):not(:focus) { + animation-fill-mode: forwards; } } @@ -11,12 +17,12 @@ from { opacity: 0; transform: translateY(30px) scale(0.96); - filter: blur(4px); + // filter: blur(4px); // 注释掉filter属性,可能导致HMR问题 } to { opacity: 1; transform: translateY(0) scale(1); - filter: blur(0); + // filter: blur(0); // 注释掉filter属性 } } diff --git a/src/components/PageTransition/index.tsx b/src/components/PageTransition/index.tsx index 08c02e7..498f84b 100644 --- a/src/components/PageTransition/index.tsx +++ b/src/components/PageTransition/index.tsx @@ -41,32 +41,37 @@ const PageTransition: React.FC = ({ ); }; -// 简化版本 - 仅使用CSS动画 -export const SimplePageTransition: React.FC<{ - children: React.ReactNode; +// 简化版本 - 禁用所有动画 +export const SimplePageTransition: React.FC<{ + children: React.ReactNode; className?: string; enableAnimation?: boolean; onAnimationEnd?: () => void; }> = ({ children, className = '', - enableAnimation = true, + enableAnimation = false, // 强制禁用动画 onAnimationEnd, }) => { - const handleAnimationEnd = () => { - if (enableAnimation && onAnimationEnd) { - onAnimationEnd(); - } + // 立即执行回调,不等待动画 + const handleAnimationEnd = () => { + if (onAnimationEnd) { + onAnimationEnd(); + } + }; + + // 立即执行动画结束回调 + React.useEffect(() => { + if (onAnimationEnd) { + onAnimationEnd(); + } + }, [onAnimationEnd]); + + return ( +
+ {children} +
+ ); }; - return ( -
- {children} -
- ); -}; - export default PageTransition; \ No newline at end of file diff --git a/src/global.less b/src/global.less index d6430a2..0b57e94 100644 --- a/src/global.less +++ b/src/global.less @@ -1,5 +1,4 @@ -// @import '~antd/es/style/themes/default.less'; -@import '~antd/dist/antd.less'; +@import '~antd/es/style/themes/default.less'; html, body, @@ -25,51 +24,6 @@ body { -moz-osx-font-smoothing: grayscale; } -// 骨架屏优化样式 -.ant-skeleton { - .ant-skeleton-content { - - .ant-skeleton-title, - .ant-skeleton-paragraph>li { - background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%); - background-size: 200% 100%; - animation: loading 1.4s ease-in-out infinite; - } - } - - .ant-skeleton-avatar { - background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%); - background-size: 200% 100%; - animation: loading 1.4s ease-in-out infinite; - } - - .ant-skeleton-input, - .ant-skeleton-button { - background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 50%, #f2f2f2 75%); - background-size: 200% 100%; - animation: loading 1.4s ease-in-out infinite; - } -} - -@keyframes loading { - 0% { - background-position: 200% 0; - } - - 100% { - background-position: -200% 0; - } -} - -// 页面切换动画优化 -.ant-layout-content { - transition: opacity 0.2s ease-in-out; - - &.loading { - opacity: 0.7; - } -} - ul, ol { list-style: none; @@ -101,18 +55,4 @@ ol { body .ant-design-pro>.ant-layout { min-height: 100vh; } -} - -// 页面过渡优化 -* { - box-sizing: border-box; -} - -// 增强页面切换体验 -.ant-tabs-content-holder { - overflow: hidden; -} - -.ant-tabs-tabpane { - outline: none; } \ No newline at end of file diff --git a/src/layouts/BasicLayout.less b/src/layouts/BasicLayout.less index d9491bd..8383d42 100644 --- a/src/layouts/BasicLayout.less +++ b/src/layouts/BasicLayout.less @@ -1,5 +1,4 @@ @import '~antd/es/style/themes/default.less'; -@import '../components/PageTransition/index.less'; .ant-pro-global-header { box-shadow: none !important; diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index c9cb979..3489719 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -28,9 +28,6 @@ import * as Icon from '@ant-design/icons' import IconFont from '@/components/IconFont'; import type { CurrentUser } from '@/models/user' import session from '@/utils/session'; -import { SimplePageTransition } from '@/components/PageTransition'; -import TabVirtualizer from '@/components/TabVirtualizer'; -import { tabPerformanceManager, DEFAULT_CONFIG } from '@/utils/tabPerformanceManager'; import upMenu from '../assets/tab/upMenu.png' import { getFieldEnum, getFieldEnumTravel, getFieldEnumTree, getFieldGetFieEnumList, getTravelFieldEnumTree, handleGetFieldEnumTreeTravel, handleGetNestingFIELDENUMList } from "@/services/options"; import { handleGetServerpartTree } from '@/pages/basicManage/serverpartAssets/service'; @@ -95,10 +92,7 @@ const BasicLayout: React.FC = (props) => { const [activeKey, setActiveKey] = useState(location?.pathname || '/') - const [animatedPages, setAnimatedPages] = useState>(new Set()); - const [reloadingTabs, setReloadingTabs] = useState>(new Set()); const menuDataRef = useRef([]); - const checkTimerRef = useRef(null); const { formatMessage } = useIntl(); useEffect(() => { @@ -146,57 +140,13 @@ const BasicLayout: React.FC = (props) => { // 改变panes const handleTabsPanes = (payload: any): void => { if (dispatch) { - // 检查是否为新页面(从未打开过的页面才需要动画) - const isNewPage = !tabsPanes.some(tab => tab.path === payload.path); - if (isNewPage) { - // 标记新页面需要播放动画 - setAnimatedPages(prev => new Set(prev).add(payload.path)); - } - - // 更新访问时间 - const updatedPayload = { - ...payload, - lastAccessTime: Date.now(), - isLoaded: true, - isLoading: false, - }; - dispatch({ type: 'global/changeTabsRoutes', - payload: { data: updatedPayload, action: 'add' }, + payload: { data: payload, action: 'add' }, }); } }; - // 处理标签页重新加载 - const handleTabReload = (tabPath: string): void => { - if (dispatch) { - // 标记为加载中 - setReloadingTabs(prev => new Set(prev).add(tabPath)); - - // 重新加载时也要播放动画 - setAnimatedPages(prev => new Set(prev).add(tabPath)); - - dispatch({ - type: 'global/reloadTab', - payload: { tabPath }, - }); - - // 模拟加载过程 - setTimeout(() => { - setReloadingTabs(prev => { - const newSet = new Set(prev); - newSet.delete(tabPath); - return newSet; - }); - - // 切换到该标签页 - history.push(tabPath); - setActiveKey(tabPath); - }, 800); // 800ms的加载时间 - } - }; - // 关闭当前标签 const handleEdit = (targetKey: string | React.MouseEvent | React.KeyboardEvent, action: "add" | "remove"): void => { @@ -210,13 +160,6 @@ const BasicLayout: React.FC = (props) => { history.push(nextkey || '/') setActiveKey(nextkey) - // 从动画记录中移除关闭的页面 - setAnimatedPages(prev => { - const newSet = new Set(prev); - newSet.delete(targetKey as string); - return newSet; - }); - // 缓存路由栈数据 dispatch({ type: 'global/changeTabsRoutes', @@ -927,31 +870,6 @@ const BasicLayout: React.FC = (props) => { }) } - // 启动标签页性能管理 - useEffect(() => { - // 启动定时检查 - checkTimerRef.current = setInterval(() => { - if (dispatch && tabsPanes.length > 0) { - const tabsToUnload = tabPerformanceManager.getTabsToUnload(tabsPanes, activeKey); - if (tabsToUnload.length > 0) { - // 批量卸载标签页 - tabsToUnload.forEach(tabPath => { - dispatch({ - type: 'global/unloadTab', - payload: { tabPath }, - }); - }); - } - } - }, DEFAULT_CONFIG.checkIntervalMinutes * 60 * 1000); - - return () => { - if (checkTimerRef.current) { - clearInterval(checkTimerRef.current); - } - }; - }, [dispatch, tabsPanes, activeKey]); - // 显示就调用 useEffect(() => { handleGetAllFieldEnum() @@ -1064,14 +982,6 @@ const BasicLayout: React.FC = (props) => { onChange={(value) => { history.push(value) setActiveKey(value) - - // 更新标签页访问时间 - if (dispatch) { - dispatch({ - type: 'global/updateTabAccessTime', - payload: { tabPath: value }, - }); - } }} activeKey={activeKey} onEdit={handleEdit} @@ -1096,13 +1006,6 @@ const BasicLayout: React.FC = (props) => { break; } - // 从动画记录中移除关闭的页面 - setAnimatedPages(prev => { - const newSet = new Set(prev); - closeTabKeys.forEach(key => newSet.delete(key)); - return newSet; - }); - dispatch({ type: 'global/changeTabsRoutes', payload: { data: closeTabKeys, action: 'remove' }, @@ -1132,53 +1035,17 @@ const BasicLayout: React.FC = (props) => { } moreIcon={} > - {tabsPanes && tabsPanes.map((item: tabsRoute) => { - const shouldAnimate = animatedPages.has(item.path); - const isActive = activeKey === item.path; - const isLoaded = item.isLoaded !== false; // 默认为已加载状态 - const isLoading = reloadingTabs.has(item.path) || item.isLoading === true; - - return ( - - {/* 如果页面未加载或正在加载,显示TabVirtualizer */} - {(!isLoaded || isLoading) ? ( - - {/* 空内容,TabVirtualizer会处理显示 */} - - ) : ( - /* 页面已加载,直接显示内容,根据需要播放动画 */ - { - // 动画播放完成后,移除动画标记 - setAnimatedPages(prev => { - const newSet = new Set(prev); - newSet.delete(item.path); - return newSet; - }); - }} - > - - - {item.children} - - - - )} - - ); - })} + {tabsPanes && tabsPanes.map((item: tabsRoute) => + + Loading...}> + + {item.children} + + + ) + } {/* 不要标签栏,删除tabs的代码,使用下方的代码就可以 */} {/* diff --git a/src/layouts/SecurityLayout.tsx b/src/layouts/SecurityLayout.tsx index f2cd8db..e208fb0 100644 --- a/src/layouts/SecurityLayout.tsx +++ b/src/layouts/SecurityLayout.tsx @@ -15,101 +15,68 @@ type SecurityLayoutProps = { type SecurityLayoutState = { isReady: boolean; - shouldShowLoading: boolean; - initialLoadComplete: boolean; }; class SecurityLayout extends React.Component { state: SecurityLayoutState = { isReady: false, - shouldShowLoading: false, - initialLoadComplete: false, + }; - private loadingTimer?: NodeJS.Timeout; - componentDidMount() { - const { location } = history; - const { dispatch } = this.props; - - // 检查是否有缓存的用户信息,避免不必要的加载状态 - const cachedUser = session.get("currentUser"); - - // 设置防闪烁定时器,只有加载时间超过300ms才显示loading - this.loadingTimer = setTimeout(() => { - if (!this.state.isReady && !this.state.initialLoadComplete) { - this.setState({ - shouldShowLoading: true, - }); - } - }, 300); + const { location } = history + + const { dispatch } = this.props; if (dispatch) { + dispatch({ - type: 'user/fetch', - callback: (user) => { - // 清除定时器 - if (this.loadingTimer) { - clearTimeout(this.loadingTimer); - } + type: 'user/fetch', callback: (user) => { if (user.code && location.pathname !== '/user/login') { history.push('/user/login'); - return; + return } - + console.log('secur') dispatch({ - type: 'global/getMenuData', - payload: user.ID, - callback: (menu) => { + type: 'global/getMenuData', payload: user.ID, callback: (menu) => { if (menu) { + this.setState({ isReady: true, - shouldShowLoading: false, - initialLoadComplete: true, }); } } - }); + }) + } - }); + }) + } else { - // 清除定时器 - if (this.loadingTimer) { - clearTimeout(this.loadingTimer); - } - this.setState({ isReady: true, - shouldShowLoading: false, - initialLoadComplete: true, }); } - } - componentWillUnmount() { - if (this.loadingTimer) { - clearTimeout(this.loadingTimer); - } } render() { - const { isReady, shouldShowLoading, initialLoadComplete } = this.state; - const { children, currentUser } = this.props; - - // 用户认证规则 + const { isReady } = this.state; + const { children, loading, currentUser } = this.props; + // const { location } = history; + + + // You can replace it to your authentication rule (such as check token exists) + // You can replace it with your own login authentication rules (such as judging whether the token exists) const isLogin = currentUser && currentUser.ID; - - // 如果初始化未完成且需要显示加载状态,才显示骨架屏 - if (!isReady && shouldShowLoading) { + + + if ((!isLogin && loading) || !isReady) { return ; } - - // 如果还在初始化过程中,但不需要显示loading,返回null(避免闪烁) - if (!isReady && !shouldShowLoading) { - return null; - } - + // if (!isLogin && location.pathname !== '/user/login') { + // history.push('/user/login'); + // } return children; } } diff --git a/src/layouts/UserLayout.tsx b/src/layouts/UserLayout.tsx index 0c0b323..7ce4964 100644 --- a/src/layouts/UserLayout.tsx +++ b/src/layouts/UserLayout.tsx @@ -61,7 +61,7 @@ const UserLayout: React.FC = (props) => {
- {children} + {children}
; @@ -185,26 +179,10 @@ const GlobalModel: GlobalModelType = { const index = state.global.tabsRoutes.findIndex(n => n.path === data.path) if (index === -1) { // 没缓存 则添加 - return [...state.global.tabsRoutes, { - ...data, - index: state.global.tabsRoutes.length, - lastAccessTime: data.lastAccessTime || Date.now(), - isLoaded: data.isLoaded !== false, - isLoading: data.isLoading || false, - }] + return [...state.global.tabsRoutes, { ...data, index: state.global.tabsRoutes.length }] } - // 否则更新现有标签页信息 - return state.global.tabsRoutes.map(tab => - tab.path === data.path - ? { - ...tab, - ...data, - lastAccessTime: data.lastAccessTime || Date.now(), - isLoaded: data.isLoaded !== false, - isLoading: data.isLoading || false, - } - : tab - ); + // 否则不操作 + return [...state.global.tabsRoutes] } if (payload.action === 'removeAll') { return [] @@ -221,57 +199,8 @@ const GlobalModel: GlobalModelType = { type: 'saveTabsRoutes', payload: tabsRoutes, }); - }, - // 更新标签页访问时间 - * updateTabAccessTime({ payload }, { put, select }) { - const { tabPath } = payload; - const tabsRoutes: tabsRoute[] = yield select((state: ConnectState) => - state.global.tabsRoutes.map(tab => - tab.path === tabPath - ? { ...tab, lastAccessTime: Date.now(), isLoaded: true, isLoading: false } - : tab - ) - ); - yield put({ - type: 'saveTabsRoutes', - payload: tabsRoutes, - }); - }, - - // 卸载标签页 - * unloadTab({ payload }, { put, select }) { - const { tabPath } = payload; - const tabsRoutes: tabsRoute[] = yield select((state: ConnectState) => - state.global.tabsRoutes.map(tab => - tab.path === tabPath - ? { ...tab, isLoaded: false, isLoading: false } - : tab - ) - ); - - yield put({ - type: 'saveTabsRoutes', - payload: tabsRoutes, - }); - }, - - // 重新加载标签页 - * reloadTab({ payload }, { put, select }) { - const { tabPath } = payload; - const tabsRoutes: tabsRoute[] = yield select((state: ConnectState) => - state.global.tabsRoutes.map(tab => - tab.path === tabPath - ? { ...tab, isLoaded: true, isLoading: false, lastAccessTime: Date.now() } - : tab - ) - ); - - yield put({ - type: 'saveTabsRoutes', - payload: tabsRoutes, - }); } }, diff --git a/src/pages/ahjgPage/shopProcurement/index.tsx b/src/pages/ahjgPage/shopProcurement/index.tsx index 632dcde..ab8eb2e 100644 --- a/src/pages/ahjgPage/shopProcurement/index.tsx +++ b/src/pages/ahjgPage/shopProcurement/index.tsx @@ -221,9 +221,9 @@ const shopProcurement: React.FC<{ currentUser: CurrentUser }> = (props) => { // ellipsis: true, // }, { - title:
入库总数
, + title:
入库总数
, dataIndex: "RECEIVE_TOTALCOUNT", - align: 'right', + align: 'right', valueType: 'digit', width: 120, sorter: true, diff --git a/src/services/login.ts b/src/services/login.ts index 5ac8b50..dd6971e 100644 --- a/src/services/login.ts +++ b/src/services/login.ts @@ -53,7 +53,7 @@ export async function accountLogin(params: LoginParamsType): Promise