From 9eb44acd18a66b34b2969b96d0d600a67468bd23 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 29 May 2026 15:15:22 +0800 Subject: [PATCH] fix: apply qiming theme in settings shell --- qiming/src/app.tsx | 8 ++ .../src/constants/openAppTheme.constants.ts | 9 ++ qiming/src/layouts/Setting/index.less | 109 ++++++++++++++++++ qiming/src/layouts/Setting/index.tsx | 26 +++++ 4 files changed, 152 insertions(+) diff --git a/qiming/src/app.tsx b/qiming/src/app.tsx index d57c8b4c..687bc40d 100644 --- a/qiming/src/app.tsx +++ b/qiming/src/app.tsx @@ -4,6 +4,10 @@ import React, { useEffect, useRef } from 'react'; import { history, useAntdConfigSetter } from 'umi'; import { SUCCESS_CODE } from './constants/codes.constants'; import { ACCESS_TOKEN } from './constants/home.constants'; +import { + applyOpenAppThemeToDocument, + getInitialOpenAppTheme, +} from './constants/openAppTheme.constants'; import { darkThemeTokens, themeTokens } from './constants/theme.constants'; import { APP_NAME, APP_VERSION } from './constants/version'; import useEventPolling from './hooks/useEventPolling'; @@ -78,6 +82,10 @@ const AppContainer: React.FC<{ children: React.ReactElement }> = ({ ); }, []); + useEffect(() => { + applyOpenAppThemeToDocument(getInitialOpenAppTheme()); + }, []); + // 全局错误处理,捕获Monaco Editor的CanceledError useEffect(() => { const isChunkLoadError = (error: any): boolean => { diff --git a/qiming/src/constants/openAppTheme.constants.ts b/qiming/src/constants/openAppTheme.constants.ts index 40859c60..b5d7656e 100644 --- a/qiming/src/constants/openAppTheme.constants.ts +++ b/qiming/src/constants/openAppTheme.constants.ts @@ -38,12 +38,21 @@ export const getInitialOpenAppTheme = (): OpenAppTheme => { : DEFAULT_OPEN_APP_THEME; }; +export const applyOpenAppThemeToDocument = (theme: OpenAppTheme) => { + if (typeof document === 'undefined') { + return; + } + + document.documentElement.setAttribute('data-open-app-theme', theme); +}; + export const setOpenAppThemePreference = (theme: OpenAppTheme) => { if (typeof window === 'undefined') { return; } window.localStorage.setItem(OPEN_APP_THEME_STORAGE_KEY, theme); + applyOpenAppThemeToDocument(theme); window.dispatchEvent( new CustomEvent(OPEN_APP_THEME_CHANGED_EVENT, { detail: theme, diff --git a/qiming/src/layouts/Setting/index.less b/qiming/src/layouts/Setting/index.less index ad466bf3..953c1536 100644 --- a/qiming/src/layouts/Setting/index.less +++ b/qiming/src/layouts/Setting/index.less @@ -61,6 +61,115 @@ top: 24px; z-index: 2; } + + &.open-app-theme-light { + background: linear-gradient(135deg, #ffffff 0%, #f3fbf8 100%); + + .left { + background: #f4fbf8; + border-right: 1px solid rgba(0, 101, 105, 0.12); + + h3 { + color: #006569; + } + + ul .item { + color: #395254; + + &:hover:not(.checked) { + background-color: rgba(0, 101, 105, 0.08); + } + + &.checked { + background-color: #ffffff; + color: #006569; + box-shadow: inset 3px 0 0 #006569; + } + } + } + + .right { + background: linear-gradient(135deg, #ffffff 0%, #f8fcfb 100%); + } + } + + &.open-app-theme-dispatch { + background: #062f30; + + .left { + background: linear-gradient(180deg, #003f42 0%, #02292b 100%); + border-right: 1px solid rgba(0, 166, 122, 0.28); + + h3 { + color: #f1fffb; + } + + ul .item { + color: rgba(241, 255, 251, 0.76); + + &:hover:not(.checked) { + background-color: rgba(0, 166, 122, 0.16); + color: #ffffff; + } + + &.checked { + background: linear-gradient(90deg, #00a67a 0%, #0b7775 100%); + color: #ffffff; + box-shadow: 0 10px 24px rgba(0, 32, 34, 0.28); + } + } + } + + .right { + background: linear-gradient( + 180deg, + rgba(0, 166, 122, 0.08), + transparent 220px + ), + #f4faf8; + } + + .close { + color: rgba(255, 255, 255, 0.88); + } + } + + &.open-app-theme-portal { + background: #ffffff; + + .left { + background: #eef8f5; + border-right: 1px solid #cde5df; + + h3 { + color: #00575a; + } + + ul .item { + color: #355b5c; + border-radius: 6px; + + &:hover:not(.checked) { + background-color: rgba(0, 101, 105, 0.08); + } + + &.checked { + background-color: #006569; + color: #ffffff; + } + } + } + + .right { + background: linear-gradient( + 90deg, + rgba(0, 101, 105, 0.05) 0 1px, + transparent 1px + ), + #ffffff; + background-size: 28px 28px; + } + } } .loading { diff --git a/qiming/src/layouts/Setting/index.tsx b/qiming/src/layouts/Setting/index.tsx index 182e40ba..a1d3918d 100644 --- a/qiming/src/layouts/Setting/index.tsx +++ b/qiming/src/layouts/Setting/index.tsx @@ -1,4 +1,9 @@ import { SETTING_ACTIONS } from '@/constants/menus.constants'; +import { + getInitialOpenAppTheme, + OPEN_APP_THEME_CHANGED_EVENT, + OpenAppTheme, +} from '@/constants/openAppTheme.constants'; import { dict } from '@/services/i18nRuntime'; import { getTenantThemeConfig } from '@/services/tenant'; import { SettingActionEnum } from '@/types/enums/menus'; @@ -29,6 +34,26 @@ const Setting: React.FC = () => { const [tenantThemeConfig, setTenantThemeConfig] = useState(null); const [loading, setLoading] = useState(false); + const [openAppTheme, setOpenAppTheme] = useState( + getInitialOpenAppTheme, + ); + + useEffect(() => { + const handleOpenAppThemeChange = (event: Event) => { + setOpenAppTheme((event as CustomEvent).detail); + }; + + window.addEventListener( + OPEN_APP_THEME_CHANGED_EVENT, + handleOpenAppThemeChange, + ); + return () => { + window.removeEventListener( + OPEN_APP_THEME_CHANGED_EVENT, + handleOpenAppThemeChange, + ); + }; + }, []); // 获取租户主题配置 useEffect(() => { @@ -123,6 +148,7 @@ const Setting: React.FC = () => {