@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.
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/template/main-app/.env.development +7 -0
- package/dist/template/main-app/.env.production +7 -0
- package/dist/template/{zhiguan → main-app}/README.md +13 -10
- 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
- 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
- package/dist/template/{zhiguan → main-app}/package.json +4 -2
- package/dist/template/{zhiguan → main-app}/src/api/user.ts +1 -1
- package/dist/template/main-app/src/components/AuthRoute/index.tsx +25 -0
- package/dist/template/{zhiguan → main-app}/src/layouts/BasicLayout.tsx +15 -7
- package/dist/template/main-app/src/main.tsx +36 -0
- package/dist/template/{zhiguan → main-app}/src/pages/404.test.tsx +1 -1
- package/dist/template/{zhiguan → main-app}/src/pages/home/index.tsx +2 -68
- package/dist/template/main-app/src/pages/login/index.tsx +97 -0
- package/dist/template/main-app/src/pages/micro-app/index.tsx +12 -0
- package/dist/template/{zhiguan → main-app}/src/router/index.tsx +18 -2
- package/dist/template/main-app/src/store/useGlobalStore.ts +29 -0
- package/dist/template/main-app/src/style.less +40 -0
- package/dist/template/main-app/src/utils/request/index.ts +113 -0
- package/dist/template/{zhiguan → main-app}/src/vite-env.d.ts +1 -0
- package/dist/template/{zhiguan → main-app}/vite.config.ts +28 -0
- package/dist/template/micro-app/.editorconfig +16 -0
- package/dist/template/micro-app/.env +1 -0
- package/dist/template/micro-app/.env.test +4 -0
- package/dist/template/micro-app/.prettierignore +34 -0
- package/dist/template/micro-app/.prettierrc +14 -0
- package/dist/template/micro-app/README.md +186 -0
- package/dist/template/micro-app/eslint.config.js +27 -0
- package/dist/template/micro-app/package-lock.json +7274 -0
- package/dist/template/micro-app/package.json +63 -0
- package/dist/template/micro-app/src/api/user.ts +21 -0
- package/dist/template/micro-app/src/assets/Frame 20.png +0 -0
- package/dist/template/micro-app/src/components/Chart/index.tsx +22 -0
- package/dist/template/micro-app/src/components/ErrorBoundary/index.tsx +82 -0
- package/dist/template/micro-app/src/layouts/BasicLayout.tsx +21 -0
- package/dist/template/micro-app/src/main.tsx +47 -0
- package/dist/template/micro-app/src/pages/404.test.tsx +20 -0
- package/dist/template/micro-app/src/pages/404.tsx +32 -0
- package/dist/template/micro-app/src/pages/home/index.less +59 -0
- package/dist/template/micro-app/src/pages/home/index.tsx +165 -0
- package/dist/template/micro-app/src/router/index.tsx +62 -0
- package/dist/template/micro-app/src/setupTests.ts +1 -0
- package/dist/template/micro-app/src/store/useGlobalStore.ts +20 -0
- package/dist/template/micro-app/src/vite-env.d.ts +16 -0
- package/dist/template/{react19 → micro-app}/tsconfig.app.json +7 -1
- package/dist/template/micro-app/vite.config.ts +116 -0
- package/dist/template/operations-tem/gitignore +24 -0
- package/package.json +1 -1
- package/dist/template/react19/README.md +0 -75
- package/dist/template/react19/eslint.config.js +0 -23
- package/dist/template/react19/package.json +0 -34
- package/dist/template/react19/src/App.css +0 -184
- package/dist/template/react19/src/App.tsx +0 -121
- package/dist/template/react19/src/assets/hero.png +0 -0
- package/dist/template/react19/src/assets/vite.svg +0 -1
- package/dist/template/react19/src/index.css +0 -111
- package/dist/template/react19/src/main.tsx +0 -10
- package/dist/template/react19/vite.config.ts +0 -11
- package/dist/template/zhiguan/src/main.tsx +0 -38
- package/dist/template/zhiguan/src/store/useCounterStore.ts +0 -24
- /package/dist/template/{zhiguan → main-app}/.editorconfig +0 -0
- /package/dist/template/{zhiguan → main-app}/.env +0 -0
- /package/dist/template/{zhiguan → main-app}/.env.test +0 -0
- /package/dist/template/{zhiguan → main-app}/.prettierignore +0 -0
- /package/dist/template/{zhiguan → main-app}/.prettierrc +0 -0
- /package/dist/template/{zhiguan → main-app}/docs/Git/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
- /package/dist/template/{zhiguan → main-app}/docs/React/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
- /package/dist/template/{zhiguan → main-app}/docs/TypeScript/345/274/200/345/217/221/350/247/204/350/214/203.md" +0 -0
- /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
- /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
- /package/dist/template/{zhiguan → main-app}/eslint.config.js +0 -0
- /package/dist/template/{react19 → main-app}/index.html +0 -0
- /package/dist/template/{react19 → main-app}/public/favicon.svg +0 -0
- /package/dist/template/{react19 → main-app}/public/icons.svg +0 -0
- /package/dist/template/{zhiguan → main-app}/src/assets/Frame 20.png +0 -0
- /package/dist/template/{react19 → main-app}/src/assets/react.svg +0 -0
- /package/dist/template/{zhiguan → main-app}/src/components/Chart/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/components/ErrorBoundary/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/404.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/about/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/calendar/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/dashboard/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/home/index.less +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/settings/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/pages/workspace/index.tsx +0 -0
- /package/dist/template/{zhiguan → main-app}/src/setupTests.ts +0 -0
- /package/dist/template/{zhiguan → main-app}/tsconfig.app.json +0 -0
- /package/dist/template/{react19 → main-app}/tsconfig.json +0 -0
- /package/dist/template/{react19 → main-app}/tsconfig.node.json +0 -0
- /package/dist/template/{zhiguan → micro-app}/.env.development +0 -0
- /package/dist/template/{zhiguan → micro-app}/.env.production +0 -0
- /package/dist/template/{zhiguan → micro-app}/index.html +0 -0
- /package/dist/template/{zhiguan → micro-app}/public/favicon.svg +0 -0
- /package/dist/template/{zhiguan → micro-app}/public/icons.svg +0 -0
- /package/dist/template/{zhiguan → micro-app}/src/assets/react.svg +0 -0
- /package/dist/template/{zhiguan → micro-app}/src/style.less +0 -0
- /package/dist/template/{zhiguan → micro-app}/src/utils/request/index.ts +0 -0
- /package/dist/template/{zhiguan → micro-app}/tsconfig.json +0 -0
- /package/dist/template/{zhiguan → micro-app}/tsconfig.node.json +0 -0
|
@@ -36,7 +36,7 @@ const SearchSection = () => (
|
|
|
36
36
|
<div className="search-box">
|
|
37
37
|
<PaperClipOutlined className="search-icon" />
|
|
38
38
|
<Input
|
|
39
|
-
|
|
39
|
+
variant="borderless"
|
|
40
40
|
placeholder="输入您想查询的数据、指令或功能,例如:帮我分析一下NVDA的最新财报..."
|
|
41
41
|
className="search-input"
|
|
42
42
|
/>
|
|
@@ -112,15 +112,7 @@ const QuickActions = () => {
|
|
|
112
112
|
<Col span={4} key={action.title}>
|
|
113
113
|
<Card
|
|
114
114
|
hoverable
|
|
115
|
-
|
|
116
|
-
bodyStyle={{
|
|
117
|
-
padding: '24px 12px',
|
|
118
|
-
display: 'flex',
|
|
119
|
-
flexDirection: 'column',
|
|
120
|
-
alignItems: 'center',
|
|
121
|
-
justifyContent: 'center',
|
|
122
|
-
gap: 12,
|
|
123
|
-
}}
|
|
115
|
+
variant="borderless"
|
|
124
116
|
style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.02)' }}
|
|
125
117
|
>
|
|
126
118
|
<div
|
|
@@ -145,63 +137,6 @@ const QuickActions = () => {
|
|
|
145
137
|
);
|
|
146
138
|
};
|
|
147
139
|
|
|
148
|
-
/**
|
|
149
|
-
* 待办任务组件 (TaskList)
|
|
150
|
-
* 展示用户今日待办事项,支持紧急程度标记
|
|
151
|
-
*/
|
|
152
|
-
const TaskList = () => {
|
|
153
|
-
// 模拟任务数据
|
|
154
|
-
const tasks = [
|
|
155
|
-
{ time: '16:30', content: '确认:交易对手方授信额度调整', tag: '紧急', tagColor: '#EF4444' },
|
|
156
|
-
{ time: '17:00', content: '复核:昨日异常交易流水', tag: '', tagColor: '' },
|
|
157
|
-
{ time: '17:12', content: '复核:昨日异常交易流水', tag: '', tagColor: '' },
|
|
158
|
-
];
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<div style={{ maxWidth: 1000, margin: '0 auto' }}>
|
|
162
|
-
<Text type="secondary" style={{ marginBottom: 16, display: 'block', paddingLeft: 8 }}>
|
|
163
|
-
待办任务
|
|
164
|
-
</Text>
|
|
165
|
-
<List
|
|
166
|
-
dataSource={tasks}
|
|
167
|
-
renderItem={(item) => (
|
|
168
|
-
<List.Item
|
|
169
|
-
style={{
|
|
170
|
-
background: '#fff',
|
|
171
|
-
borderRadius: 12,
|
|
172
|
-
marginBottom: 12,
|
|
173
|
-
padding: '20px 24px',
|
|
174
|
-
border: '1px solid #f0f0f0',
|
|
175
|
-
display: 'flex',
|
|
176
|
-
alignItems: 'center',
|
|
177
|
-
}}
|
|
178
|
-
>
|
|
179
|
-
<div style={{ display: 'flex', alignItems: 'center', flex: 1 }}>
|
|
180
|
-
<Text type="secondary" style={{ width: 60, marginRight: 16 }}>
|
|
181
|
-
{item.time}
|
|
182
|
-
</Text>
|
|
183
|
-
<Text style={{ fontSize: 15, fontWeight: 500 }}>{item.content}</Text>
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
|
-
<Space size={16}>
|
|
187
|
-
{item.tag && (
|
|
188
|
-
<Tag
|
|
189
|
-
color={item.tagColor}
|
|
190
|
-
style={{ borderRadius: 4, border: 'none', marginRight: 0 }}
|
|
191
|
-
>
|
|
192
|
-
{item.tag}
|
|
193
|
-
</Tag>
|
|
194
|
-
)}
|
|
195
|
-
<Button type="link" size="small">
|
|
196
|
-
处理
|
|
197
|
-
</Button>
|
|
198
|
-
</Space>
|
|
199
|
-
</List.Item>
|
|
200
|
-
)}
|
|
201
|
-
/>
|
|
202
|
-
</div>
|
|
203
|
-
);
|
|
204
|
-
};
|
|
205
140
|
|
|
206
141
|
// --- Main Page ---
|
|
207
142
|
|
|
@@ -211,7 +146,6 @@ export default function Home() {
|
|
|
211
146
|
<WelcomeHeader />
|
|
212
147
|
<SearchSection />
|
|
213
148
|
<QuickActions />
|
|
214
|
-
<TaskList />
|
|
215
149
|
</div>
|
|
216
150
|
);
|
|
217
151
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { useNavigate, useLocation } from 'react-router-dom';
|
|
3
|
+
import { Card, Form, Input, Button, Typography, message } from 'antd';
|
|
4
|
+
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
|
5
|
+
import { useGlobalStore } from '@/store/useGlobalStore';
|
|
6
|
+
|
|
7
|
+
const { Title } = Typography;
|
|
8
|
+
|
|
9
|
+
export default function Login() {
|
|
10
|
+
const [loading, setLoading] = useState(false);
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
const location = useLocation();
|
|
13
|
+
const setLoginState = useGlobalStore((state) => state.setLoginState);
|
|
14
|
+
|
|
15
|
+
// 获取用户原本想访问的页面,默认为首页
|
|
16
|
+
const from = location.state?.from?.pathname || '/';
|
|
17
|
+
|
|
18
|
+
const onFinish = async (values: any) => {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
try {
|
|
21
|
+
// 模拟一个登录请求的延迟
|
|
22
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
23
|
+
|
|
24
|
+
// 模拟成功后从后端拿到的数据
|
|
25
|
+
const mockToken = 'Bearer mock-jwt-token-12345';
|
|
26
|
+
const mockUser = {
|
|
27
|
+
name: values.username || '国泰海通-张三',
|
|
28
|
+
role: 'admin',
|
|
29
|
+
dept: '交易部',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// 1. 将 Token 和用户信息存入全局 Store
|
|
33
|
+
setLoginState(mockUser, mockToken);
|
|
34
|
+
|
|
35
|
+
message.success('登录成功!');
|
|
36
|
+
|
|
37
|
+
// 2. 跳转回原本的页面
|
|
38
|
+
navigate(from, { replace: true });
|
|
39
|
+
} catch (error) {
|
|
40
|
+
message.error('登录失败,请重试');
|
|
41
|
+
} finally {
|
|
42
|
+
setLoading(false);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
style={{
|
|
49
|
+
display: 'flex',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
height: '100vh',
|
|
53
|
+
backgroundColor: '#f0f2f5',
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<Card
|
|
57
|
+
style={{
|
|
58
|
+
width: 400,
|
|
59
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
|
60
|
+
borderRadius: 8,
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<div style={{ textAlign: 'center', marginBottom: 32 }}>
|
|
64
|
+
<Title level={3}>PILOTCORE</Title>
|
|
65
|
+
<span style={{ color: '#8c8c8c' }}>微前端业务基座登录</span>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<Form
|
|
69
|
+
name="login"
|
|
70
|
+
initialValues={{ remember: true }}
|
|
71
|
+
onFinish={onFinish}
|
|
72
|
+
size="large"
|
|
73
|
+
>
|
|
74
|
+
<Form.Item
|
|
75
|
+
name="username"
|
|
76
|
+
rules={[{ required: true, message: '请输入用户名!' }]}
|
|
77
|
+
>
|
|
78
|
+
<Input prefix={<UserOutlined />} placeholder="用户名 (任意输入)" />
|
|
79
|
+
</Form.Item>
|
|
80
|
+
|
|
81
|
+
<Form.Item
|
|
82
|
+
name="password"
|
|
83
|
+
rules={[{ required: true, message: '请输入密码!' }]}
|
|
84
|
+
>
|
|
85
|
+
<Input.Password prefix={<LockOutlined />} placeholder="密码 (任意输入)" />
|
|
86
|
+
</Form.Item>
|
|
87
|
+
|
|
88
|
+
<Form.Item>
|
|
89
|
+
<Button type="primary" htmlType="submit" block loading={loading}>
|
|
90
|
+
登 录
|
|
91
|
+
</Button>
|
|
92
|
+
</Form.Item>
|
|
93
|
+
</Form>
|
|
94
|
+
</Card>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
@@ -6,8 +6,10 @@ import { lazy, Suspense, type ComponentType, type LazyExoticComponent } from 're
|
|
|
6
6
|
import { createBrowserRouter } from 'react-router-dom';
|
|
7
7
|
import { Spin } from 'antd';
|
|
8
8
|
import BasicLayout from '@/layouts/BasicLayout';
|
|
9
|
+
import AuthRoute from '@/components/AuthRoute';
|
|
9
10
|
|
|
10
11
|
// 路由懒加载配置
|
|
12
|
+
const Login = lazy(() => import('@/pages/login'));
|
|
11
13
|
const Home = lazy(() => import('@/pages/home'));
|
|
12
14
|
const About = lazy(() => import('@/pages/about'));
|
|
13
15
|
const Dashboard = lazy(() => import('@/pages/dashboard'));
|
|
@@ -15,6 +17,7 @@ const Workspace = lazy(() => import('@/pages/workspace'));
|
|
|
15
17
|
const Calendar = lazy(() => import('@/pages/calendar'));
|
|
16
18
|
const Settings = lazy(() => import('@/pages/settings'));
|
|
17
19
|
const NotFound = lazy(() => import('@/pages/404'));
|
|
20
|
+
const MicroApp = lazy(() => import('@/pages/micro-app'));
|
|
18
21
|
|
|
19
22
|
// 全局 Loading 组件
|
|
20
23
|
const Loading = () => (
|
|
@@ -41,10 +44,18 @@ function withSuspense(Component: LazyExoticComponent<ComponentType<any>>) {
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export const router = createBrowserRouter([
|
|
47
|
+
{
|
|
48
|
+
path: '/login',
|
|
49
|
+
element: withSuspense(Login),
|
|
50
|
+
},
|
|
44
51
|
{
|
|
45
52
|
path: '/',
|
|
46
|
-
// 根布局:BasicLayout (包含侧边栏和 Header)
|
|
47
|
-
element:
|
|
53
|
+
// 根布局:BasicLayout (包含侧边栏和 Header),用 AuthRoute 保护
|
|
54
|
+
element: (
|
|
55
|
+
<AuthRoute>
|
|
56
|
+
<BasicLayout />
|
|
57
|
+
</AuthRoute>
|
|
58
|
+
),
|
|
48
59
|
// 子路由:渲染在 BasicLayout 的 <Outlet /> 中
|
|
49
60
|
children: [
|
|
50
61
|
{
|
|
@@ -71,6 +82,11 @@ export const router = createBrowserRouter([
|
|
|
71
82
|
path: 'settings',
|
|
72
83
|
element: withSuspense(Settings),
|
|
73
84
|
},
|
|
85
|
+
// 子应用路由:匹配所有 /micro-react-1 及之后的路径
|
|
86
|
+
{
|
|
87
|
+
path: 'micro-react-1/*',
|
|
88
|
+
element: withSuspense(MicroApp),
|
|
89
|
+
},
|
|
74
90
|
// 404 页面配置
|
|
75
91
|
{
|
|
76
92
|
path: '*',
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import { persist } from 'zustand/middleware';
|
|
3
|
+
|
|
4
|
+
export interface UserInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
role: string;
|
|
7
|
+
dept: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface GlobalState {
|
|
11
|
+
user: UserInfo | null;
|
|
12
|
+
token: string | null;
|
|
13
|
+
setLoginState: (user: UserInfo, token: string) => void;
|
|
14
|
+
clearLoginState: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useGlobalStore = create<GlobalState>()(
|
|
18
|
+
persist(
|
|
19
|
+
(set) => ({
|
|
20
|
+
user: null,
|
|
21
|
+
token: null,
|
|
22
|
+
setLoginState: (user, token) => set({ user, token }),
|
|
23
|
+
clearLoginState: () => set({ user: null, token: null }),
|
|
24
|
+
}),
|
|
25
|
+
{
|
|
26
|
+
name: 'main-app-storage', // 持久化到 localStorage 的 key
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
* {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* ==========================================================================
|
|
6
|
+
全局自定义滚动条样式
|
|
7
|
+
统一 Windows 和 Mac 系统的滚动条视觉体验 (扁平化、简约风格)
|
|
8
|
+
========================================================================== */
|
|
9
|
+
|
|
10
|
+
/* 针对 WebKit 浏览器 (Chrome, Safari, Edge) */
|
|
11
|
+
::-webkit-scrollbar {
|
|
12
|
+
width: 8px; /* 垂直滚动条宽度 */
|
|
13
|
+
height: 8px; /* 水平滚动条高度 */
|
|
14
|
+
background-color: transparent; /* 滚动条背景透明 */
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* 滚动条轨道 */
|
|
18
|
+
::-webkit-scrollbar-track {
|
|
19
|
+
background: transparent;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* 滚动条滑块 */
|
|
24
|
+
::-webkit-scrollbar-thumb {
|
|
25
|
+
background-color: rgba(144, 147, 153, 0.3); /* 默认浅灰色 */
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
border: 2px solid transparent; /* 通过透明边框让滑块看起来更细 */
|
|
28
|
+
background-clip: padding-box; /* 配合 border 实现视觉变细 */
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* 鼠标悬停在滑块上时 */
|
|
32
|
+
::-webkit-scrollbar-thumb:hover {
|
|
33
|
+
background-color: rgba(144, 147, 153, 0.5); /* 悬停时加深颜色 */
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* 针对 Firefox (目前仅支持部分属性) */
|
|
37
|
+
* {
|
|
38
|
+
scrollbar-width: thin; /* 设置滚动条为细条 */
|
|
39
|
+
scrollbar-color: rgba(144, 147, 153, 0.3) transparent; /* 滑块颜色 轨道颜色 */
|
|
40
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用网络请求工具 (Axios Encapsulation)
|
|
3
|
+
* 封装了全局请求拦截、响应处理和错误统一处理
|
|
4
|
+
*/
|
|
5
|
+
import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios';
|
|
6
|
+
import { message } from 'antd';
|
|
7
|
+
import { useGlobalStore } from '@/store/useGlobalStore';
|
|
8
|
+
|
|
9
|
+
// 定义通用的后端响应结构
|
|
10
|
+
export interface BaseResponse<T = unknown> {
|
|
11
|
+
code: number; // 业务状态码 (0/200: 成功, 其他: 失败)
|
|
12
|
+
data: T; // 业务数据
|
|
13
|
+
message: string; // 提示信息
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 创建 Axios 实例的工厂函数
|
|
17
|
+
function createRequest(config: AxiosRequestConfig) {
|
|
18
|
+
const instance = axios.create(config);
|
|
19
|
+
|
|
20
|
+
// 请求拦截器
|
|
21
|
+
instance.interceptors.request.use(
|
|
22
|
+
(reqConfig) => {
|
|
23
|
+
// 在发送请求之前,从 zustand 获取 token
|
|
24
|
+
const token = useGlobalStore.getState().token;
|
|
25
|
+
if (token && reqConfig.headers) {
|
|
26
|
+
reqConfig.headers.Authorization = `Bearer ${token}`;
|
|
27
|
+
}
|
|
28
|
+
return reqConfig;
|
|
29
|
+
},
|
|
30
|
+
(error) => {
|
|
31
|
+
return Promise.reject(error);
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// 响应拦截器
|
|
36
|
+
instance.interceptors.response.use(
|
|
37
|
+
(response: AxiosResponse<BaseResponse>) => {
|
|
38
|
+
const { data } = response;
|
|
39
|
+
// 根据自定义的 code 判断请求是否成功 (假设 0 或 200 为成功)
|
|
40
|
+
if (data.code === 0 || data.code === 200) {
|
|
41
|
+
return data.data as any; // 拆包返回 data
|
|
42
|
+
} else {
|
|
43
|
+
// 处理业务错误,例如提示用户
|
|
44
|
+
const errorMsg = data.message || '请求失败';
|
|
45
|
+
message.error(errorMsg);
|
|
46
|
+
return Promise.reject(new Error(errorMsg));
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
(error) => {
|
|
50
|
+
// 处理 HTTP 错误,例如 401, 404, 500 等
|
|
51
|
+
if (error.response) {
|
|
52
|
+
const status = error.response.status;
|
|
53
|
+
switch (status) {
|
|
54
|
+
case 401:
|
|
55
|
+
message.error('登录状态已过期,请重新登录');
|
|
56
|
+
// 清除登录状态并跳转到登录页
|
|
57
|
+
useGlobalStore.getState().clearLoginState();
|
|
58
|
+
window.location.href = '/login';
|
|
59
|
+
break;
|
|
60
|
+
case 403:
|
|
61
|
+
message.error('拒绝访问');
|
|
62
|
+
break;
|
|
63
|
+
case 404:
|
|
64
|
+
message.error('请求接口不存在');
|
|
65
|
+
break;
|
|
66
|
+
case 500:
|
|
67
|
+
message.error('服务器内部错误');
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
message.error(`网络错误: ${status}`);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
message.error('网络连接异常,请检查网络设置!');
|
|
74
|
+
}
|
|
75
|
+
return Promise.reject(error);
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// 返回封装好的请求方法对象
|
|
80
|
+
return {
|
|
81
|
+
/**
|
|
82
|
+
* 发送 GET 请求
|
|
83
|
+
* @param url 请求地址
|
|
84
|
+
* @param config Axios 配置
|
|
85
|
+
*/
|
|
86
|
+
get: <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
|
87
|
+
return instance.get(url, config);
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* 发送 POST 请求
|
|
91
|
+
* @param url 请求地址
|
|
92
|
+
* @param data 请求体数据
|
|
93
|
+
* @param config Axios 配置
|
|
94
|
+
*/
|
|
95
|
+
post: <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
|
|
96
|
+
return instance.post(url, data, config);
|
|
97
|
+
},
|
|
98
|
+
put: <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
|
|
99
|
+
return instance.put(url, data, config);
|
|
100
|
+
},
|
|
101
|
+
delete: <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
|
102
|
+
return instance.delete(url, config);
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 导出默认 request 实例
|
|
108
|
+
// 可以直接 import { request } from '@/utils/request' 使用
|
|
109
|
+
export const request = createRequest({
|
|
110
|
+
// 从环境变量 VITE_API_BASE_URL 获取基础地址,默认为 /api
|
|
111
|
+
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
|
|
112
|
+
timeout: 10000, // 超时时间 10s
|
|
113
|
+
});
|
|
@@ -3,11 +3,39 @@ import react, { reactCompilerPreset } from '@vitejs/plugin-react'
|
|
|
3
3
|
import babel from '@rolldown/plugin-babel'
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import { visualizer } from 'rollup-plugin-visualizer'
|
|
6
|
+
// import cdn from 'vite-plugin-cdn-import'
|
|
6
7
|
|
|
7
8
|
// https://vite.dev/config/
|
|
8
9
|
export default defineConfig({
|
|
9
10
|
plugins: [
|
|
10
11
|
react(),
|
|
12
|
+
// 暂时注释 CDN 抽离配置,因为内网环境暂不支持
|
|
13
|
+
/*
|
|
14
|
+
cdn({
|
|
15
|
+
modules: [
|
|
16
|
+
{
|
|
17
|
+
name: 'react',
|
|
18
|
+
var: 'React',
|
|
19
|
+
path: `https://unpkg.com/react@19.2.4/umd/react.production.min.js`,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'react-dom',
|
|
23
|
+
var: 'ReactDOM',
|
|
24
|
+
path: `https://unpkg.com/react-dom@19.2.4/umd/react-dom.production.min.js`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'dayjs',
|
|
28
|
+
var: 'dayjs',
|
|
29
|
+
path: `https://unpkg.com/dayjs@1.11.10/dayjs.min.js`,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'antd',
|
|
33
|
+
var: 'antd',
|
|
34
|
+
path: `https://unpkg.com/antd@6.3.3/dist/antd.min.js`,
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}),
|
|
38
|
+
*/
|
|
11
39
|
babel({ presets: [reactCompilerPreset()] }),
|
|
12
40
|
process.env.ANALYZE === 'true' && visualizer({
|
|
13
41
|
open: true,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
+
|
|
3
|
+
# top-most EditorConfig file
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
# Unix-style newlines with a newline ending every file
|
|
7
|
+
[*]
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
charset = utf-8
|
|
11
|
+
trim_trailing_whitespace = true
|
|
12
|
+
indent_style = space
|
|
13
|
+
indent_size = 2
|
|
14
|
+
|
|
15
|
+
[*.md]
|
|
16
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_API_BASE_URL=/api
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 忽略格式化的目录和文件
|
|
2
|
+
node_modules
|
|
3
|
+
dist
|
|
4
|
+
build
|
|
5
|
+
coverage
|
|
6
|
+
|
|
7
|
+
# 忽略特定类型的文件
|
|
8
|
+
*.png
|
|
9
|
+
*.jpg
|
|
10
|
+
*.jpeg
|
|
11
|
+
*.gif
|
|
12
|
+
*.svg
|
|
13
|
+
*.ico
|
|
14
|
+
*.eot
|
|
15
|
+
*.ttf
|
|
16
|
+
*.woff
|
|
17
|
+
*.woff2
|
|
18
|
+
*.mp4
|
|
19
|
+
*.webm
|
|
20
|
+
*.ogg
|
|
21
|
+
*.mp3
|
|
22
|
+
*.wav
|
|
23
|
+
*.flac
|
|
24
|
+
*.aac
|
|
25
|
+
|
|
26
|
+
# 忽略锁定文件
|
|
27
|
+
package-lock.json
|
|
28
|
+
yarn.lock
|
|
29
|
+
pnpm-lock.yaml
|
|
30
|
+
|
|
31
|
+
# 其他忽略
|
|
32
|
+
.DS_Store
|
|
33
|
+
.idea
|
|
34
|
+
.vscode
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"printWidth": 100,
|
|
3
|
+
"tabWidth": 2,
|
|
4
|
+
"useTabs": false,
|
|
5
|
+
"semi": true,
|
|
6
|
+
"singleQuote": true,
|
|
7
|
+
"quoteProps": "as-needed",
|
|
8
|
+
"jsxSingleQuote": false,
|
|
9
|
+
"trailingComma": "all",
|
|
10
|
+
"bracketSpacing": true,
|
|
11
|
+
"bracketSameLine": false,
|
|
12
|
+
"arrowParens": "always",
|
|
13
|
+
"endOfLine": "lf"
|
|
14
|
+
}
|