feat(web): Login/MainLayout 从主题配置读取品牌信息
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- Login.tsx 从 /api/v1/public/brand 读取品牌名称/标语/特性/版权
- MainLayout 侧边栏 Logo 和 Footer 从 themeConfig 读取
- 启动时调用 loadThemeConfig 缓存主题配置
- 移除所有硬编码品牌文字(HMR Platform → 动态读取)
This commit is contained in:
iven
2026-05-01 17:39:21 +08:00
parent 669ca44360
commit ae1c9ccc77
2 changed files with 21 additions and 6 deletions

View File

@@ -95,6 +95,7 @@ const routeTitleFallback: Record<string, string> = {
'/health/alert-dashboard': '告警仪表盘',
'/health/alert-rules': '告警规则',
'/health/devices': '设备管理',
'/health/dialysis': '透析管理',
};
function getTitleFromMenus(path: string, menus: MenuInfo[]): string | undefined {
@@ -347,6 +348,8 @@ const DynamicMenuSection = memo(function DynamicMenuSection({
export default function MainLayout({ children }: { children: React.ReactNode }) {
const { sidebarCollapsed, toggleSidebar } = useAppStore();
const themeConfig = useAppStore((s) => s.themeConfig);
const loadThemeConfig = useAppStore((s) => s.loadThemeConfig);
const { user, logout } = useAuthStore();
const pluginMenuItems = usePluginStore((s) => s.pluginMenuItems);
const pluginMenuGroups = usePluginStore((s) => s.pluginMenuGroups);
@@ -379,6 +382,11 @@ export default function MainLayout({ children }: { children: React.ReactNode })
fetchPlugins(1, 'running');
}, [fetchPlugins]);
// 加载主题配置
useEffect(() => {
loadThemeConfig();
}, [loadThemeConfig]);
const handleLogout = useCallback(async () => {
await logout();
navigate('/login');
@@ -430,7 +438,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
<div className="erp-sidebar-logo" onClick={() => navigate('/')}>
<div className="erp-sidebar-logo-icon">H</div>
{!sidebarCollapsed && (
<span className="erp-sidebar-logo-text">HMS </span>
<span className="erp-sidebar-logo-text">{themeConfig?.brand_name || 'HMS 健康'}</span>
)}
</div>
@@ -523,7 +531,7 @@ export default function MainLayout({ children }: { children: React.ReactNode })
{/* 底部 */}
<Footer className="erp-footer">
HMS
{themeConfig?.brand_copyright || 'HMS 健康管理平台'}
</Footer>
</Layout>
</Layout>

View File

@@ -1,14 +1,21 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Form, Input, Button, message, Divider } from 'antd';
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
import { useAuthStore } from '../stores/auth';
import ThemeSwitcher from '../components/ThemeSwitcher';
import { getPublicBrand, type BrandConfig } from '../api/themes';
export default function Login() {
const navigate = useNavigate();
const login = useAuthStore((s) => s.login);
const loading = useAuthStore((s) => s.loading);
const [messageApi, contextHolder] = message.useMessage();
const [brand, setBrand] = useState<BrandConfig | null>(null);
useEffect(() => {
getPublicBrand().then(setBrand);
}, []);
const onFinish = async (values: { username: string; password: string }) => {
try {
@@ -37,9 +44,9 @@ export default function Login() {
<SafetyCertificateOutlined />
</div>
<h1 className="brand-title">HMR Platform</h1>
<p className="brand-desc"></p>
<p className="brand-sub-desc"> · · · </p>
<h1 className="brand-title">{brand?.brand_name || 'HMS 健康管理平台'}</h1>
<p className="brand-desc">{brand?.brand_slogan || '新一代健康管理平台'}</p>
<p className="brand-sub-desc">{brand?.brand_features || '患者管理 · 健康监测 · 随访管理 · AI 智能分析'}</p>
<div style={{ marginTop: 48, display: 'flex', gap: 32, justifyContent: 'center' }}>
{[
@@ -103,7 +110,7 @@ export default function Login() {
</Form>
<div className="form-footer">
HMR Platform · ©
{brand?.brand_copyright || 'HMS 健康管理平台 · ©汕头市智界科技有限公司'}
</div>
</div>
</main>