从 Pinterest 风格切换到 Soft UI Evolution 设计系统,使用 UI UX Pro Max 推理引擎生成适合跨行业 ERP 业务用户的专业设计方案。 设计变更: - 主色从 Pinterest Red (#e60023) 切换到 Trust Blue (#2563EB) - 字体从系统默认切换到 Noto Sans SC(中文优先) - 圆角从 16-20px 调整到 10-12px(专业但不夸张) - 中性色从暖橄榄调切换到 Slate 石板蓝调 - 成功色 #103c25 → #059669,警告色 #b56e1a → #d97706 - 暗色模式从暖黑 (#1a1a18) 切换到深海军蓝 (#0f172a) 涉及文件:DESIGN.md + index.css + App.tsx + 24 个组件文件
169 lines
6.0 KiB
TypeScript
169 lines
6.0 KiB
TypeScript
import { useEffect, lazy, Suspense } from 'react';
|
|
import { HashRouter, Routes, Route, Navigate } from 'react-router-dom';
|
|
import { ConfigProvider, theme as antdTheme, Spin } from 'antd';
|
|
import zhCN from 'antd/locale/zh_CN';
|
|
import MainLayout from './layouts/MainLayout';
|
|
import Login from './pages/Login';
|
|
import { ErrorBoundary } from './components/ErrorBoundary';
|
|
import { useAuthStore } from './stores/auth';
|
|
import { useAppStore } from './stores/app';
|
|
|
|
const Home = lazy(() => import('./pages/Home'));
|
|
const Users = lazy(() => import('./pages/Users'));
|
|
const Roles = lazy(() => import('./pages/Roles'));
|
|
const Organizations = lazy(() => import('./pages/Organizations'));
|
|
const Workflow = lazy(() => import('./pages/Workflow'));
|
|
const Messages = lazy(() => import('./pages/Messages'));
|
|
const Settings = lazy(() => import('./pages/Settings'));
|
|
const PluginAdmin = lazy(() => import('./pages/PluginAdmin'));
|
|
const PluginMarket = lazy(() => import('./pages/PluginMarket'));
|
|
const PluginCRUDPage = lazy(() => import('./pages/PluginCRUDPage'));
|
|
const PluginTabsPage = lazy(() => import('./pages/PluginTabsPage').then((m) => ({ default: m.PluginTabsPage })));
|
|
const PluginTreePage = lazy(() => import('./pages/PluginTreePage').then((m) => ({ default: m.PluginTreePage })));
|
|
const PluginGraphPage = lazy(() => import('./pages/PluginGraphPage').then((m) => ({ default: m.PluginGraphPage })));
|
|
const PluginDashboardPage = lazy(() => import('./pages/PluginDashboardPage').then((m) => ({ default: m.PluginDashboardPage })));
|
|
const PluginKanbanPage = lazy(() => import('./pages/PluginKanbanPage'));
|
|
|
|
function PrivateRoute({ children }: { children: React.ReactNode }) {
|
|
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
return isAuthenticated ? <>{children}</> : <Navigate to="/login" replace />;
|
|
}
|
|
|
|
const themeConfig = {
|
|
token: {
|
|
colorPrimary: '#2563eb',
|
|
colorSuccess: '#059669',
|
|
colorWarning: '#d97706',
|
|
colorError: '#dc2626',
|
|
colorInfo: '#0284c7',
|
|
colorBgLayout: '#f8fafc',
|
|
colorBgContainer: '#ffffff',
|
|
colorBgElevated: '#ffffff',
|
|
colorBorder: '#e2e8f0',
|
|
colorBorderSecondary: '#f1f5f9',
|
|
borderRadius: 10,
|
|
borderRadiusLG: 12,
|
|
borderRadiusSM: 6,
|
|
fontFamily: "'Noto Sans SC', -apple-system, system-ui, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', Helvetica, Arial, sans-serif",
|
|
fontSize: 14,
|
|
fontSizeHeading4: 20,
|
|
controlHeight: 40,
|
|
controlHeightLG: 44,
|
|
controlHeightSM: 32,
|
|
boxShadow: 'none',
|
|
boxShadowSecondary: '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',
|
|
},
|
|
components: {
|
|
Button: {
|
|
primaryShadow: 'none',
|
|
fontWeight: 500,
|
|
},
|
|
Card: {
|
|
paddingLG: 20,
|
|
},
|
|
Table: {
|
|
headerBg: '#f1f5f9',
|
|
headerColor: '#475569',
|
|
rowHoverBg: '#f1f5f9',
|
|
fontSize: 14,
|
|
},
|
|
Menu: {
|
|
itemBorderRadius: 10,
|
|
itemMarginInline: 8,
|
|
itemHeight: 40,
|
|
},
|
|
Modal: {
|
|
borderRadiusLG: 16,
|
|
},
|
|
Tag: {
|
|
borderRadiusSM: 6,
|
|
},
|
|
},
|
|
};
|
|
|
|
const darkThemeConfig = {
|
|
...themeConfig,
|
|
token: {
|
|
...themeConfig.token,
|
|
colorBgLayout: '#0f172a',
|
|
colorBgContainer: '#1e293b',
|
|
colorBgElevated: '#334155',
|
|
colorBorder: '#334155',
|
|
colorBorderSecondary: 'rgba(255, 255, 255, 0.06)',
|
|
boxShadow: 'none',
|
|
boxShadowSecondary: '0 2px 8px rgba(0,0,0,0.3), 0 1px 3px rgba(0,0,0,0.2)',
|
|
},
|
|
components: {
|
|
...themeConfig.components,
|
|
Table: {
|
|
headerBg: '#1e293b',
|
|
headerColor: '#94a3b8',
|
|
rowHoverBg: '#1e293b',
|
|
},
|
|
},
|
|
};
|
|
|
|
export default function App() {
|
|
const loadFromStorage = useAuthStore((s) => s.loadFromStorage);
|
|
const themeMode = useAppStore((s) => s.theme);
|
|
|
|
useEffect(() => {
|
|
loadFromStorage();
|
|
}, [loadFromStorage]);
|
|
|
|
useEffect(() => {
|
|
document.documentElement.setAttribute('data-theme', themeMode);
|
|
}, [themeMode]);
|
|
|
|
const isDark = themeMode === 'dark';
|
|
|
|
return (
|
|
<>
|
|
<a href="#root" className="erp-skip-link">跳转到主要内容</a>
|
|
<ConfigProvider
|
|
locale={zhCN}
|
|
theme={{
|
|
...isDark ? darkThemeConfig : themeConfig,
|
|
algorithm: isDark ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,
|
|
}}
|
|
>
|
|
<HashRouter>
|
|
<Routes>
|
|
<Route path="/login" element={<Login />} />
|
|
<Route
|
|
path="/*"
|
|
element={
|
|
<PrivateRoute>
|
|
<MainLayout>
|
|
<ErrorBoundary>
|
|
<Suspense fallback={<div style={{ display: 'flex', justifyContent: 'center', padding: 100 }}><Spin size="large" /></div>}>
|
|
<Routes>
|
|
<Route path="/" element={<Home />} />
|
|
<Route path="/users" element={<Users />} />
|
|
<Route path="/roles" element={<Roles />} />
|
|
<Route path="/organizations" element={<Organizations />} />
|
|
<Route path="/workflow" element={<Workflow />} />
|
|
<Route path="/messages" element={<Messages />} />
|
|
<Route path="/settings" element={<Settings />} />
|
|
<Route path="/plugins/admin" element={<PluginAdmin />} />
|
|
<Route path="/plugins/market" element={<PluginMarket />} />
|
|
<Route path="/plugins/:pluginId/tabs/:pageLabel" element={<PluginTabsPage />} />
|
|
<Route path="/plugins/:pluginId/tree/:entityName" element={<PluginTreePage />} />
|
|
<Route path="/plugins/:pluginId/graph/:entityName" element={<PluginGraphPage />} />
|
|
<Route path="/plugins/:pluginId/dashboard" element={<PluginDashboardPage />} />
|
|
<Route path="/plugins/:pluginId/kanban/:entityName" element={<PluginKanbanPage />} />
|
|
<Route path="/plugins/:pluginId/:entityName" element={<PluginCRUDPage />} />
|
|
</Routes>
|
|
</Suspense>
|
|
</ErrorBoundary>
|
|
</MainLayout>
|
|
</PrivateRoute>
|
|
}
|
|
/>
|
|
</Routes>
|
|
</HashRouter>
|
|
</ConfigProvider>
|
|
</>
|
|
);
|
|
}
|