diff --git a/.changeset/afraid-adults-whisper.md b/.changeset/afraid-adults-whisper.md new file mode 100644 index 0000000000..44358ac500 --- /dev/null +++ b/.changeset/afraid-adults-whisper.md @@ -0,0 +1,5 @@ +--- +"@scow/portal-web": patch +--- + +修复了本地开发环境出现 Hydration 报错的问题 diff --git a/apps/portal-web/src/pages/_app.tsx b/apps/portal-web/src/pages/_app.tsx index daa79cf50e..1b228827e6 100644 --- a/apps/portal-web/src/pages/_app.tsx +++ b/apps/portal-web/src/pages/_app.tsx @@ -147,6 +147,8 @@ interface ExtraProps { initialLanguage: string; clusterConfigs: { [clusterId: string]: ClusterConfigSchema }; initialCurrentClusters: Cluster[]; + // 用于获取桌面功能是否可用,如集群配置文件中没有配置则判断门户的配置文件,需要通过SSR进行传递 + initialPortalRuntimeDesktopEnabled: boolean; } type Props = AppProps & { extra: ExtraProps }; @@ -162,7 +164,11 @@ function MyApp({ Component, pageProps, extra }: Props) { }); const clusterInfoStore = useConstant(() => { - return createStore(ClusterInfoStore, extra.clusterConfigs, extra.initialCurrentClusters); + return createStore(ClusterInfoStore, + extra.clusterConfigs, + extra.initialCurrentClusters, + extra.initialPortalRuntimeDesktopEnabled, + ); }); const loginNodeStore = useConstant(() => createStore(LoginNodeStore, loginNodes, @@ -233,6 +239,9 @@ MyApp.getInitialProps = async (appContext: AppContext) => { initialLanguage: "", clusterConfigs: {}, initialCurrentClusters: [], + // 通过SSR获取门户系统配置文件中是否可用桌面功能 + // enabled: Type.Boolean({ description: "是否启动登录节点上的桌面功能", default: true }), + initialPortalRuntimeDesktopEnabled: true, }; // This is called on server on first load, and on client on every page transition @@ -264,6 +273,9 @@ MyApp.getInitialProps = async (appContext: AppContext) => { if (clusterConfigs && Object.keys(clusterConfigs).length > 0) { extra.clusterConfigs = clusterConfigs; + + extra.initialPortalRuntimeDesktopEnabled = runtimeConfig.PORTAL_CONFIG.loginDesktop.enabled; + const publicConfigClusters = Object.values(getPublicConfigClusters(clusterConfigs)); diff --git a/apps/portal-web/src/stores/ClusterInfoStore.ts b/apps/portal-web/src/stores/ClusterInfoStore.ts index 783b81f79c..92abb76c07 100644 --- a/apps/portal-web/src/stores/ClusterInfoStore.ts +++ b/apps/portal-web/src/stores/ClusterInfoStore.ts @@ -14,7 +14,7 @@ import { ClusterConfigSchema } from "@scow/config/build/cluster"; import { getSortedClusterIds } from "@scow/lib-web/build/utils/cluster"; import { useLocalStorage } from "@scow/lib-web/build/utils/hooks"; import { useEffect, useState } from "react"; -import { Cluster, getDesktopEnabled, getPublicConfigClusters } from "src/utils/cluster"; +import { Cluster, getDesktopEnabled, getFileTransferEnabled, getPublicConfigClusters } from "src/utils/cluster"; import { publicConfig } from "src/utils/config"; const SCOW_DEFAULT_CLUSTER_ID = "SCOW_DEFAULT_CLUSTER_ID"; @@ -22,6 +22,8 @@ const SCOW_DEFAULT_CLUSTER_ID = "SCOW_DEFAULT_CLUSTER_ID"; export function ClusterInfoStore( clusterConfigs: {[clusterId: string]: ClusterConfigSchema}, initialCurrentClusters: Cluster[], + // 用于获取桌面功能是否可用,如集群配置文件中没有配置则判断门户的配置文件 + portalRuntimeDesktopEnabled: boolean, ) { // 配置文件集群信息 @@ -57,13 +59,41 @@ export function ClusterInfoStore( } }; + // ENABLE_LOGIN_DESKTOP + const initialEnableLoginDesktop = getDesktopEnabled(clusterConfigs, portalRuntimeDesktopEnabled); + const [enableLoginDesktop, setEnableLoginDesktop] = useState(initialEnableLoginDesktop); + + + // CROSS_CLUSTER_FILE_TRANSFER_ENABLED + const initialEnableFileTransfer = getFileTransferEnabled(clusterConfigs); + const [crossClusterFileTransferEnabled, setCrossClusterFileTransferEnabled] + = useState(initialEnableFileTransfer); + + useEffect(() => { if (publicConfig.MIS_DEPLOYED) { // 可用集群不存在时 if (currentClusters.length === 0) { setDefaultCluster(undefined); + setEnableLoginDesktop(false); + setCrossClusterFileTransferEnabled(false); } else { + + const currentClusterIds = currentClusters.map((x) => x.id); + const specifiedClusterConfigs = Object.fromEntries( + Object.entries(clusterConfigs).filter(([clusterId]) => currentClusterIds.includes(clusterId)), + ); + + // set桌面功能是否可用 + const currentEnableLoginDesktop = getDesktopEnabled(clusterConfigs, portalRuntimeDesktopEnabled); + setEnableLoginDesktop(currentEnableLoginDesktop); + + // set文件传输功能是否可用 + const currentCrossClusterFileTransferEnabled = getFileTransferEnabled(specifiedClusterConfigs); + setCrossClusterFileTransferEnabled(currentCrossClusterFileTransferEnabled); + + // set默认集群 // 上一次记录的集群为undefined的情况,使用可用集群中的某一个集群作为新的默认集群 if (!defaultCluster?.id) { setDefaultCluster(currentClusters[0]); @@ -78,14 +108,7 @@ export function ClusterInfoStore( } } - }, [currentClusters]); - - // ENABLE_LOGIN_DESKTOP - const enableLoginDesktop = getDesktopEnabled(clusterConfigs); - - // CROSS_CLUSTER_FILE_TRANSFER_ENABLED - const crossClusterFileTransferEnabled = Object.values(clusterConfigs).filter( - (cluster) => cluster.crossClusterFileTransfer?.enabled).length > 1; + }, [currentClusters, clusterConfigs, portalRuntimeDesktopEnabled]); return { publicConfigClusters, diff --git a/apps/portal-web/src/utils/cluster.ts b/apps/portal-web/src/utils/cluster.ts index 940c6c4a9b..f0b3ceee9e 100644 --- a/apps/portal-web/src/utils/cluster.ts +++ b/apps/portal-web/src/utils/cluster.ts @@ -24,14 +24,13 @@ import { runtimeConfig } from "./config"; * @returns {boolean} desktop login enable */ export function getDesktopEnabled( - clusters: Record) { - + clusters: Record, + portalRuntimeDesktopEnabled: boolean) { const clusterDesktopEnabled = Object.keys(clusters).reduce( ((pre, cur) => { const curClusterDesktopEnabled = clusters?.[cur]?.loginDesktop?.enabled !== undefined ? !!clusters[cur]?.loginDesktop?.enabled - : runtimeConfig.PORTAL_CONFIG?.loginDesktop?.enabled; - + : portalRuntimeDesktopEnabled; return pre || curClusterDesktopEnabled; }), false, ); @@ -39,7 +38,19 @@ export function getDesktopEnabled( return clusterDesktopEnabled; } +/** + * 当两个以上(含两个)集群下都配置了文件传输功能时,才开启 + * @param {Record} clusters + * @returns {boolean} fileTransferEnabled + */ +export function getFileTransferEnabled( + clusters: Record) { + const fileTransferEnabled = Object.values(clusters).filter( + (cluster) => cluster.crossClusterFileTransfer?.enabled).length > 1; + + return fileTransferEnabled; +} export type Cluster = { id: string; name: I18nStringType; }