@chenhui996/gg-cli 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/index.js +8 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/template/main-app/.env.development +7 -0
  4. package/dist/template/main-app/.env.production +7 -0
  5. package/dist/template/{zhiguan → main-app}/README.md +13 -10
  6. package/dist/template/main-app/docs//345/276/256/345/211/215/347/253/257/346/236/266/346/236/204/350/256/276/350/256/241/344/270/216/345/274/200/345/217/221/346/214/207/345/215/227.md +285 -0
  7. package/dist/template/{zhiguan → main-app}/docs//351/241/271/347/233/256/347/233/256/345/275/225/347/273/223/346/236/204/350/247/204/350/214/203.md +24 -15
  8. package/dist/template/{zhiguan → main-app}/package.json +4 -2
  9. package/dist/template/{zhiguan → main-app}/src/api/user.ts +1 -1
  10. package/dist/template/main-app/src/components/AuthRoute/index.tsx +25 -0
  11. package/dist/template/{zhiguan → main-app}/src/layouts/BasicLayout.tsx +15 -7
  12. package/dist/template/main-app/src/main.tsx +36 -0
  13. package/dist/template/{zhiguan → main-app}/src/pages/404.test.tsx +1 -1
  14. package/dist/template/{zhiguan → main-app}/src/pages/home/index.tsx +2 -68
  15. package/dist/template/main-app/src/pages/login/index.tsx +97 -0
  16. package/dist/template/main-app/src/pages/micro-app/index.tsx +12 -0
  17. package/dist/template/{zhiguan → main-app}/src/router/index.tsx +18 -2
  18. package/dist/template/main-app/src/store/useGlobalStore.ts +29 -0
  19. package/dist/template/main-app/src/style.less +40 -0
  20. package/dist/template/main-app/src/utils/request/index.ts +113 -0
  21. package/dist/template/{zhiguan → main-app}/src/vite-env.d.ts +1 -0
  22. package/dist/template/{zhiguan → main-app}/vite.config.ts +28 -0
  23. package/dist/template/micro-app/.editorconfig +16 -0
  24. package/dist/template/micro-app/.env +1 -0
  25. package/dist/template/micro-app/.env.test +4 -0
  26. package/dist/template/micro-app/.prettierignore +34 -0
  27. package/dist/template/micro-app/.prettierrc +14 -0
  28. package/dist/template/micro-app/README.md +186 -0
  29. package/dist/template/micro-app/eslint.config.js +27 -0
  30. package/dist/template/micro-app/package-lock.json +7274 -0
  31. package/dist/template/micro-app/package.json +63 -0
  32. package/dist/template/micro-app/src/api/user.ts +21 -0
  33. package/dist/template/micro-app/src/assets/Frame 20.png +0 -0
  34. package/dist/template/micro-app/src/components/Chart/index.tsx +22 -0
  35. package/dist/template/micro-app/src/components/ErrorBoundary/index.tsx +82 -0
  36. package/dist/template/micro-app/src/layouts/BasicLayout.tsx +21 -0
  37. package/dist/template/micro-app/src/main.tsx +47 -0
  38. package/dist/template/micro-app/src/pages/404.test.tsx +20 -0
  39. package/dist/template/micro-app/src/pages/404.tsx +32 -0
  40. package/dist/template/micro-app/src/pages/home/index.less +59 -0
  41. package/dist/template/micro-app/src/pages/home/index.tsx +165 -0
  42. package/dist/template/micro-app/src/router/index.tsx +62 -0
  43. package/dist/template/micro-app/src/setupTests.ts +1 -0
  44. package/dist/template/micro-app/src/store/useGlobalStore.ts +20 -0
  45. package/dist/template/micro-app/src/vite-env.d.ts +16 -0
  46. package/dist/template/{react19 → micro-app}/tsconfig.app.json +7 -1
  47. package/dist/template/micro-app/vite.config.ts +116 -0
  48. package/dist/template/operations-tem/gitignore +24 -0
  49. package/package.json +1 -1
  50. package/dist/template/react19/README.md +0 -75
  51. package/dist/template/react19/eslint.config.js +0 -23
  52. package/dist/template/react19/package.json +0 -34
  53. package/dist/template/react19/src/App.css +0 -184
  54. package/dist/template/react19/src/App.tsx +0 -121
  55. package/dist/template/react19/src/assets/hero.png +0 -0
  56. package/dist/template/react19/src/assets/vite.svg +0 -1
  57. package/dist/template/react19/src/index.css +0 -111
  58. package/dist/template/react19/src/main.tsx +0 -10
  59. package/dist/template/react19/vite.config.ts +0 -11
  60. package/dist/template/zhiguan/src/main.tsx +0 -38
  61. package/dist/template/zhiguan/src/store/useCounterStore.ts +0 -24
  62. /package/dist/template/{zhiguan → main-app}/.editorconfig +0 -0
  63. /package/dist/template/{zhiguan → main-app}/.env +0 -0
  64. /package/dist/template/{zhiguan → main-app}/.env.test +0 -0
  65. /package/dist/template/{zhiguan → main-app}/.prettierignore +0 -0
  66. /package/dist/template/{zhiguan → main-app}/.prettierrc +0 -0
  67. /package/dist/template/{zhiguan → main-app}/docs/Git/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
  68. /package/dist/template/{zhiguan → main-app}/docs/React/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
  69. /package/dist/template/{zhiguan → main-app}/docs/TypeScript/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
  70. /package/dist/template/{zhiguan → main-app}/docs//345/211/215/347/253/257/346/227/245/345/277/227/344/270/216/347/233/221/346/216/247/345/237/213/347/202/271/350/247/204/350/214/203.md" +0 -0
  71. /package/dist/template/{zhiguan → main-app}/docs//345/215/225/345/205/203/346/265/213/350/257/225/350/247/204/350/214/203.md" +0 -0
  72. /package/dist/template/{zhiguan → main-app}/eslint.config.js +0 -0
  73. /package/dist/template/{react19 → main-app}/index.html +0 -0
  74. /package/dist/template/{react19 → main-app}/public/favicon.svg +0 -0
  75. /package/dist/template/{react19 → main-app}/public/icons.svg +0 -0
  76. /package/dist/template/{zhiguan → main-app}/src/assets/Frame 20.png +0 -0
  77. /package/dist/template/{react19 → main-app}/src/assets/react.svg +0 -0
  78. /package/dist/template/{zhiguan → main-app}/src/components/Chart/index.tsx +0 -0
  79. /package/dist/template/{zhiguan → main-app}/src/components/ErrorBoundary/index.tsx +0 -0
  80. /package/dist/template/{zhiguan → main-app}/src/pages/404.tsx +0 -0
  81. /package/dist/template/{zhiguan → main-app}/src/pages/about/index.tsx +0 -0
  82. /package/dist/template/{zhiguan → main-app}/src/pages/calendar/index.tsx +0 -0
  83. /package/dist/template/{zhiguan → main-app}/src/pages/dashboard/index.tsx +0 -0
  84. /package/dist/template/{zhiguan → main-app}/src/pages/home/index.less +0 -0
  85. /package/dist/template/{zhiguan → main-app}/src/pages/settings/index.tsx +0 -0
  86. /package/dist/template/{zhiguan → main-app}/src/pages/workspace/index.tsx +0 -0
  87. /package/dist/template/{zhiguan → main-app}/src/setupTests.ts +0 -0
  88. /package/dist/template/{zhiguan → main-app}/tsconfig.app.json +0 -0
  89. /package/dist/template/{react19 → main-app}/tsconfig.json +0 -0
  90. /package/dist/template/{react19 → main-app}/tsconfig.node.json +0 -0
  91. /package/dist/template/{zhiguan → micro-app}/.env.development +0 -0
  92. /package/dist/template/{zhiguan → micro-app}/.env.production +0 -0
  93. /package/dist/template/{zhiguan → micro-app}/index.html +0 -0
  94. /package/dist/template/{zhiguan → micro-app}/public/favicon.svg +0 -0
  95. /package/dist/template/{zhiguan → micro-app}/public/icons.svg +0 -0
  96. /package/dist/template/{zhiguan → micro-app}/src/assets/react.svg +0 -0
  97. /package/dist/template/{zhiguan → micro-app}/src/style.less +0 -0
  98. /package/dist/template/{zhiguan → micro-app}/src/utils/request/index.ts +0 -0
  99. /package/dist/template/{zhiguan → micro-app}/tsconfig.json +0 -0
  100. /package/dist/template/{zhiguan → micro-app}/tsconfig.node.json +0 -0
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "micro-app",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite --mode development",
8
+ "build:test": "tsc -b && vite build --mode test",
9
+ "build:prod": "tsc -b && vite build --mode production",
10
+ "build": "npm run build:prod",
11
+ "test": "vitest",
12
+ "test:ui": "vitest --ui",
13
+ "test:coverage": "vitest run --coverage",
14
+ "analyze": "cross-env ANALYZE=true npm run build:prod",
15
+ "lint": "eslint .",
16
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,less,css,json,md}\"",
17
+ "preview": "vite preview"
18
+ },
19
+ "dependencies": {
20
+ "@ant-design/icons": "^6.1.0",
21
+ "@garfish/bridge-react-v18": "^1.19.8",
22
+ "antd": "^6.3.3",
23
+ "axios": "^1.13.6",
24
+ "echarts": "^6.0.0",
25
+ "echarts-for-react": "^3.0.6",
26
+ "react": "^19.2.4",
27
+ "react-dom": "^19.2.4",
28
+ "react-router-dom": "^7.13.1",
29
+ "tslib": "^2.8.1",
30
+ "zustand": "^5.0.12"
31
+ },
32
+ "devDependencies": {
33
+ "@babel/core": "^7.29.0",
34
+ "@eslint/js": "^9.39.4",
35
+ "@rolldown/plugin-babel": "^0.2.0",
36
+ "@testing-library/dom": "^10.4.1",
37
+ "@testing-library/jest-dom": "^6.9.1",
38
+ "@testing-library/react": "^16.3.2",
39
+ "@types/babel__core": "^7.20.5",
40
+ "@types/node": "^24.12.0",
41
+ "@types/react": "^19.2.14",
42
+ "@types/react-dom": "^19.2.3",
43
+ "@vitejs/plugin-react": "^6.0.0",
44
+ "@vitest/coverage-v8": "^4.1.4",
45
+ "babel-plugin-react-compiler": "^1.0.0",
46
+ "cross-env": "^10.1.0",
47
+ "eslint": "^9.39.4",
48
+ "eslint-plugin-react-hooks": "^7.0.1",
49
+ "eslint-plugin-react-refresh": "^0.5.2",
50
+ "globals": "^17.4.0",
51
+ "jsdom": "^29.0.2",
52
+ "less": "^4.6.4",
53
+ "prettier": "^3.8.1",
54
+ "rollup-plugin-visualizer": "^7.0.1",
55
+ "terser": "^5.46.1",
56
+ "typescript": "~5.9.3",
57
+ "typescript-eslint": "^8.56.1",
58
+ "vite": "^8.0.0",
59
+ "vite-plugin-cdn-import": "^1.0.1",
60
+ "vite-plugin-garfish-mf": "^1.0.4",
61
+ "vitest": "^4.1.4"
62
+ }
63
+ }
@@ -0,0 +1,21 @@
1
+ import { request } from '../utils/request';
2
+
3
+ // 定义接口返回的数据类型
4
+ export interface UserInfo {
5
+ id: number;
6
+ name: string;
7
+ email: string;
8
+ }
9
+
10
+ // 示例 API 服务
11
+ export const userService = {
12
+ // 获取用户信息
13
+ getUserInfo: (userId: number) => {
14
+ return request.get<UserInfo>(`/users/${userId}`);
15
+ },
16
+
17
+ // 更新用户信息
18
+ updateUserInfo: (userId: number, data: Partial<UserInfo>) => {
19
+ return request.put<UserInfo>(`/users/${userId}`, data);
20
+ },
21
+ };
@@ -0,0 +1,22 @@
1
+ import ReactECharts from 'echarts-for-react';
2
+ import type { EChartsOption } from 'echarts';
3
+
4
+ interface ChartProps {
5
+ option: EChartsOption;
6
+ style?: React.CSSProperties;
7
+ className?: string;
8
+ loading?: boolean;
9
+ }
10
+
11
+ export default function Chart({ option, style, className, loading = false }: ChartProps) {
12
+ return (
13
+ <ReactECharts
14
+ option={option}
15
+ style={{ height: '100%', width: '100%', ...style }}
16
+ className={className}
17
+ showLoading={loading}
18
+ notMerge={true}
19
+ lazyUpdate={true}
20
+ />
21
+ );
22
+ }
@@ -0,0 +1,82 @@
1
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
2
+ import { Result, Button } from 'antd';
3
+
4
+ interface Props {
5
+ children?: ReactNode;
6
+ fallback?: ReactNode;
7
+ }
8
+
9
+ interface State {
10
+ hasError: boolean;
11
+ error?: Error;
12
+ }
13
+
14
+ /**
15
+ * 全局错误边界组件 (Error Boundary)
16
+ * 用于捕获 React 组件树中的渲染错误,防止整个应用白屏崩溃
17
+ * 同时可在此处进行错误日志上报
18
+ */
19
+ export class ErrorBoundary extends Component<Props, State> {
20
+ public state: State = {
21
+ hasError: false,
22
+ };
23
+
24
+ public static getDerivedStateFromError(error: Error): State {
25
+ // 更新 state 以致于下一次渲染能够显示降级后的 UI
26
+ return { hasError: true, error };
27
+ }
28
+
29
+ public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
30
+ // 在这里你可以将错误日志上报给服务器
31
+ console.error('Uncaught error in React component tree:', error, errorInfo);
32
+
33
+ // 示例:如果在生产环境,调用监控 SDK
34
+ // if (import.meta.env.PROD) {
35
+ // logService.error('REACT_RENDER_ERROR', { error, errorInfo });
36
+ // }
37
+ }
38
+
39
+ private handleReset = () => {
40
+ // 重置错误状态,尝试恢复组件渲染
41
+ this.setState({ hasError: false, error: undefined });
42
+ // 也可以选择刷新整个页面
43
+ // window.location.reload();
44
+ };
45
+
46
+ public render() {
47
+ if (this.state.hasError) {
48
+ // 渲染自定义的降级 UI,或者使用默认的 500 页面
49
+ if (this.props.fallback) {
50
+ return this.props.fallback;
51
+ }
52
+
53
+ return (
54
+ <Result
55
+ status="500"
56
+ title="抱歉,页面加载出错了"
57
+ subTitle={
58
+ import.meta.env.DEV
59
+ ? this.state.error?.message
60
+ : "我们正在努力修复此问题,请稍后再试。"
61
+ }
62
+ extra={
63
+ <Button type="primary" onClick={this.handleReset}>
64
+ 重试
65
+ </Button>
66
+ }
67
+ style={{
68
+ height: '100%',
69
+ display: 'flex',
70
+ flexDirection: 'column',
71
+ justifyContent: 'center',
72
+ background: '#fff',
73
+ borderRadius: 8,
74
+ margin: 24,
75
+ }}
76
+ />
77
+ );
78
+ }
79
+
80
+ return this.props.children;
81
+ }
82
+ }
@@ -0,0 +1,21 @@
1
+ import { Outlet } from 'react-router-dom';
2
+
3
+ /**
4
+ * 子应用基础布局组件 (BasicLayout)
5
+ *
6
+ * 作为微前端的业务模块,子应用不需要包含侧边栏 (Sider) 和顶栏 (Header)。
7
+ * 它只需要作为一个纯粹的视图容器,将自身的路由内容渲染到主应用的 Content 区域中。
8
+ */
9
+ export default function BasicLayout() {
10
+ return (
11
+ <div className="micro-app-container" style={{ minHeight: '100%', backgroundColor: '#fff', borderRadius: 8 }}>
12
+ {/*
13
+ 此处可以放置子应用全局共享的逻辑,例如:
14
+ - 子应用级别的 ErrorBoundary
15
+ - 子应用级别的权限校验
16
+ - 子应用特有的水印等
17
+ */}
18
+ <Outlet />
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,47 @@
1
+ import { createRoot } from 'react-dom/client';
2
+ import { RouterProvider } from 'react-router-dom';
3
+ import { reactBridge } from '@garfish/bridge-react-v18';
4
+ import { ConfigProvider } from 'antd';
5
+ import { router } from '@/router';
6
+ import { useGlobalStore } from '@/store/useGlobalStore';
7
+ import './style.less';
8
+
9
+ // 微前端环境下,由于主应用已经引入了 reset.css 或类似的全局重置样式,
10
+ // 子应用再引入会导致切换时样式的重复挂载和卸载,从而引发全局界面的重绘闪烁。
11
+ if (!window.__GARFISH__) {
12
+ import('antd/dist/reset.css');
13
+ }
14
+
15
+ // 定义子应用专属的样式前缀
16
+ const MICRO_PREFIX_CLS = 'micro1';
17
+
18
+ export const provider = reactBridge({
19
+ el: '#root',
20
+ // Garfish 会将主应用传递的 appInfo 作为参数传入
21
+ rootComponent: (appInfo: any) => {
22
+ console.log('appInfo', appInfo);
23
+
24
+ // 拦截主应用传来的数据,并同步到子应用的全局状态中
25
+ if (appInfo?.props?.globalState) {
26
+ // 避免 React render 阶段直接触发 zustand 更新警告,我们利用微任务或者只在初始化时设置
27
+ useGlobalStore.getState().setGlobalState(appInfo.props.globalState);
28
+ }
29
+
30
+ // 使用 ConfigProvider 包裹路由,并设置专属的 CSS 前缀和独立的 cssVar
31
+ return (
32
+ <ConfigProvider prefixCls={MICRO_PREFIX_CLS} theme={{ cssVar: { key: 'micro-app' }, hashed: false }}>
33
+ <RouterProvider router={router} />
34
+ </ConfigProvider>
35
+ );
36
+ },
37
+ errorBoundary: () => <div>子应用加载异常,请稍后重试</div>,
38
+ });
39
+
40
+ // src/main.js
41
+ if (!window.__GARFISH__) {
42
+ createRoot(document.getElementById('root')!).render(
43
+ <ConfigProvider prefixCls={MICRO_PREFIX_CLS} theme={{ cssVar: { key: 'micro-app' }, hashed: false }}>
44
+ <RouterProvider router={router} />
45
+ </ConfigProvider>
46
+ );
47
+ }
@@ -0,0 +1,20 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import NotFound from './404';
4
+ import { BrowserRouter } from 'react-router-dom';
5
+
6
+ describe('NotFound (404) 页面组件', () => {
7
+ it('应当正确渲染 404 状态码和提示信息', () => {
8
+ // Arrange: 渲染组件 (需要包裹在 Router 中因为内部使用了 useNavigate)
9
+ render(
10
+ <BrowserRouter>
11
+ <NotFound />
12
+ </BrowserRouter>
13
+ );
14
+
15
+ // Assert: 验证页面中是否出现了 404 和相关提示文字
16
+ expect(screen.getByText('404')).toBeInTheDocument();
17
+ expect(screen.getByText('抱歉,您访问的页面不存在。')).toBeInTheDocument();
18
+ expect(screen.getByRole('button', { name: '返回首页' })).toBeInTheDocument();
19
+ });
20
+ });
@@ -0,0 +1,32 @@
1
+ import { Button, Result } from 'antd';
2
+ import { useNavigate } from 'react-router-dom';
3
+
4
+ /**
5
+ * 404 页面组件
6
+ * 当用户访问不存在的路由时展示
7
+ */
8
+ export default function NotFound() {
9
+ const navigate = useNavigate();
10
+
11
+ return (
12
+ <Result
13
+ status="404"
14
+ title="404"
15
+ subTitle="抱歉,您访问的页面不存在。"
16
+ extra={
17
+ <Button type="primary" onClick={() => navigate('/')}>
18
+ 返回首页
19
+ </Button>
20
+ }
21
+ style={{
22
+ height: '100%',
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ justifyContent: 'center',
26
+ background: '#fff',
27
+ borderRadius: 8,
28
+ margin: 24,
29
+ }}
30
+ />
31
+ );
32
+ }
@@ -0,0 +1,59 @@
1
+ .home-page {
2
+ padding: 20px 0;
3
+
4
+ .welcome-header {
5
+ text-align: center;
6
+ margin-bottom: 40px;
7
+ margin-top: 40px;
8
+
9
+ h2.ant-typography {
10
+ margin-bottom: 8px;
11
+ }
12
+ }
13
+
14
+ .search-section {
15
+ max-width: 800px;
16
+ margin: 0 auto 48px;
17
+
18
+ .search-box {
19
+ background: #fff;
20
+ border-radius: 12px;
21
+ padding: 8px 8px 8px 16px;
22
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
23
+ border: 1px solid #f0f0f0;
24
+ display: flex;
25
+ align-items: center;
26
+
27
+ .search-icon {
28
+ font-size: 18px;
29
+ color: #999;
30
+ margin-right: 12px;
31
+ }
32
+
33
+ .search-input {
34
+ flex: 1;
35
+ font-size: 14px;
36
+ }
37
+
38
+ .search-btn {
39
+ margin-left: 8px;
40
+ }
41
+ }
42
+
43
+ .search-tags {
44
+ margin-top: 16px;
45
+ display: flex;
46
+ gap: 8px;
47
+ justify-content: flex-start;
48
+ padding-left: 4px;
49
+
50
+ .tag-item {
51
+ border-radius: 16px;
52
+ padding: 4px 12px;
53
+ border: 1px solid #e5e7eb;
54
+ background: #fff;
55
+ cursor: pointer;
56
+ }
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,165 @@
1
+ import { Input, Tag, Card, Row, Col, List, Button, Typography, Space } from 'antd';
2
+ import {
3
+ ArrowUpOutlined,
4
+ AppstoreOutlined,
5
+ SettingOutlined,
6
+ SafetyCertificateOutlined,
7
+ AuditOutlined,
8
+ WalletOutlined,
9
+ DatabaseOutlined,
10
+ PaperClipOutlined,
11
+ } from '@ant-design/icons';
12
+ import { useGlobalStore } from '@/store/useGlobalStore';
13
+ import './index.less';
14
+
15
+ const { Title, Text } = Typography;
16
+
17
+ // --- Components ---
18
+
19
+ /**
20
+ * 欢迎语组件 (WelcomeHeader)
21
+ * 展示用户个性化问候语和任务概览
22
+ */
23
+ const WelcomeHeader = () => {
24
+ // 从全局 Store 中获取由主应用透传过来的用户信息
25
+ const user = useGlobalStore((state) => state.user);
26
+ const token = useGlobalStore((state) => state.token);
27
+
28
+ console.log('[micro-app user]', user);
29
+ console.log('[micro-app token]', token);
30
+
31
+ const displayName = user?.name || '游客';
32
+ const roleInfo = user?.dept ? `[${user.dept}] ` : '';
33
+
34
+ return (
35
+ <div className="welcome-header">
36
+ <Title level={2}>
37
+ 下午好,{roleInfo}{displayName},你有3件待办任务...
38
+ </Title>
39
+ </div>
40
+ );
41
+ };
42
+
43
+ /**
44
+ * 搜索区域组件 (SearchSection)
45
+ * 包含搜索框和快捷操作标签 (Tag)
46
+ * 样式位于 ./index.less
47
+ */
48
+ const SearchSection = () => (
49
+ <div className="search-section">
50
+ {/* 搜索输入框 */}
51
+ <div className="search-box">
52
+ <PaperClipOutlined className="search-icon" />
53
+ <Input
54
+ variant="borderless"
55
+ placeholder="输入您想查询的数据、指令或功能,例如:帮我分析一下NVDA的最新财报..."
56
+ className="search-input"
57
+ />
58
+ <Button type="primary" shape="circle" icon={<ArrowUpOutlined />} className="search-btn" />
59
+ </div>
60
+
61
+ {/* 快捷标签 */}
62
+ <div className="search-tags">
63
+ <Tag className="tag-item">分析财报</Tag>
64
+ <Tag className="tag-item">查询头寸</Tag>
65
+ <Tag className="tag-item">压力测试</Tag>
66
+ </div>
67
+ </div>
68
+ );
69
+
70
+ /**
71
+ * 常用功能组件 (QuickActions)
72
+ * 使用 Grid 布局展示应用的核心功能入口
73
+ * 每个卡片包含:图标、标题和背景色
74
+ */
75
+ const QuickActions = () => {
76
+ // 功能入口配置数据
77
+ const actions = [
78
+ {
79
+ title: '工作空间',
80
+ icon: <AppstoreOutlined style={{ fontSize: 24, color: '#4F46E5' }} />,
81
+ color: '#EEF2FF',
82
+ },
83
+ {
84
+ title: '规则配置',
85
+ icon: <SettingOutlined style={{ fontSize: 24, color: '#0EA5E9' }} />,
86
+ color: '#F0F9FF',
87
+ },
88
+ {
89
+ title: '事后风控',
90
+ icon: <SafetyCertificateOutlined style={{ fontSize: 24, color: '#F59E0B' }} />,
91
+ color: '#FFFBEB',
92
+ },
93
+ {
94
+ title: '交易审批',
95
+ icon: <AuditOutlined style={{ fontSize: 24, color: '#10B981' }} />,
96
+ color: '#ECFDF5',
97
+ },
98
+ {
99
+ title: '证券池管理',
100
+ icon: <WalletOutlined style={{ fontSize: 24, color: '#3B82F6' }} />,
101
+ color: '#EFF6FF',
102
+ },
103
+ {
104
+ title: '数据审批',
105
+ icon: <DatabaseOutlined style={{ fontSize: 24, color: '#06B6D4' }} />,
106
+ color: '#ECFEFF',
107
+ },
108
+ ];
109
+
110
+ return (
111
+ <div style={{ maxWidth: 1000, margin: '0 auto 48px' }}>
112
+ <div
113
+ style={{
114
+ display: 'flex',
115
+ justifyContent: 'space-between',
116
+ marginBottom: 16,
117
+ padding: '0 8px',
118
+ }}
119
+ >
120
+ <Text type="secondary">常用功能</Text>
121
+ <Button type="link" size="small" style={{ color: '#999' }}>
122
+ 更多
123
+ </Button>
124
+ </div>
125
+ <Row gutter={[16, 16]}>
126
+ {actions.map((action) => (
127
+ <Col span={4} key={action.title}>
128
+ <Card
129
+ hoverable
130
+ variant="borderless"
131
+ style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.02)' }}
132
+ >
133
+ <div
134
+ style={{
135
+ width: 48,
136
+ height: 48,
137
+ borderRadius: 12,
138
+ background: action.color,
139
+ display: 'flex',
140
+ alignItems: 'center',
141
+ justifyContent: 'center',
142
+ }}
143
+ >
144
+ {action.icon}
145
+ </div>
146
+ <Text style={{ fontSize: 13, fontWeight: 500 }}>{action.title}</Text>
147
+ </Card>
148
+ </Col>
149
+ ))}
150
+ </Row>
151
+ </div>
152
+ );
153
+ };
154
+
155
+ // --- Main Page ---
156
+
157
+ export default function Home() {
158
+ return (
159
+ <div className="home-page">
160
+ <WelcomeHeader />
161
+ <SearchSection />
162
+ <QuickActions />
163
+ </div>
164
+ );
165
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * 路由配置 (React Router Data API)
3
+ * 采用对象配置模式,便于管理和扩展
4
+ */
5
+ import { lazy, Suspense, type ComponentType, type LazyExoticComponent } from 'react';
6
+ import { createBrowserRouter } from 'react-router-dom';
7
+ import { Spin } from 'antd';
8
+ import BasicLayout from '@/layouts/BasicLayout';
9
+
10
+ // 路由懒加载配置
11
+ const Home = lazy(() => import('@/pages/home'));
12
+ const NotFound = lazy(() => import('@/pages/404'));
13
+
14
+ // 全局 Loading 组件
15
+ const Loading = () => (
16
+ <div
17
+ style={{
18
+ display: 'flex',
19
+ justifyContent: 'center',
20
+ alignItems: 'center',
21
+ height: '100%',
22
+ minHeight: 400,
23
+ }}
24
+ >
25
+ <Spin size="large" />
26
+ </div>
27
+ );
28
+
29
+ // 包装懒加载组件,统一添加 Suspense
30
+ function withSuspense(Component: LazyExoticComponent<ComponentType<any>>) {
31
+ return (
32
+ <Suspense fallback={<Loading />}>
33
+ <Component />
34
+ </Suspense>
35
+ );
36
+ }
37
+
38
+ const routes = [
39
+ {
40
+ path: '/',
41
+ // 根布局:BasicLayout
42
+ element: <BasicLayout />,
43
+ // 子路由:渲染在 BasicLayout 的 <Outlet /> 中
44
+ children: [
45
+ {
46
+ index: true, // 默认子路由 (首页)
47
+ element: withSuspense(Home),
48
+ },
49
+ // 404 页面配置
50
+ {
51
+ path: '*',
52
+ element: withSuspense(NotFound),
53
+ },
54
+ ],
55
+ },
56
+ ];
57
+
58
+ // 根据是否在 Garfish 环境中运行来决定 basename
59
+ // 主应用中注册的子应用激活路径为 /micro-react-1
60
+ const basename = window.__GARFISH__ ? '/micro-react-1' : '/';
61
+
62
+ export const router = createBrowserRouter(routes, { basename });
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,20 @@
1
+ import { create } from 'zustand';
2
+
3
+ export interface UserInfo {
4
+ name: string;
5
+ role: string;
6
+ dept: string;
7
+ }
8
+
9
+ interface GlobalState {
10
+ user: UserInfo | null;
11
+ token: string | null;
12
+ // 更新全局状态的方法
13
+ setGlobalState: (state: Partial<GlobalState>) => void;
14
+ }
15
+
16
+ export const useGlobalStore = create<GlobalState>((set) => ({
17
+ user: null,
18
+ token: null,
19
+ setGlobalState: (state) => set((prev) => ({ ...prev, ...state })),
20
+ }));
@@ -0,0 +1,16 @@
1
+ /// <reference types="vitest" />
2
+ /// <reference types="vite/client" />
3
+
4
+ interface ImportMetaEnv {
5
+ readonly VITE_ENV: string;
6
+ readonly VITE_API_BASE_URL: string;
7
+ readonly VITE_APP_TITLE: string;
8
+ }
9
+
10
+ interface ImportMeta {
11
+ readonly env: ImportMetaEnv;
12
+ }
13
+
14
+ interface Window {
15
+ __GARFISH__?: boolean;
16
+ }
@@ -5,7 +5,7 @@
5
5
  "useDefineForClassFields": true,
6
6
  "lib": ["ES2023", "DOM", "DOM.Iterable"],
7
7
  "module": "ESNext",
8
- "types": ["vite/client"],
8
+ "types": ["vite/client", "node"],
9
9
  "skipLibCheck": true,
10
10
 
11
11
  /* Bundler mode */
@@ -16,6 +16,12 @@
16
16
  "noEmit": true,
17
17
  "jsx": "react-jsx",
18
18
 
19
+ /* Path Aliases */
20
+ "baseUrl": ".",
21
+ "paths": {
22
+ "@/*": ["src/*"]
23
+ },
24
+
19
25
  /* Linting */
20
26
  "strict": true,
21
27
  "noUnusedLocals": true,