generator-mico-cli 0.2.7 → 0.2.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/generators/micro-react/index.js +8 -3
- package/generators/micro-react/templates/.eslintrc.js +1 -0
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +5 -5
- package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +6 -30
- package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +6 -6
- package/generators/micro-react/templates/apps/layout/config/config.prod.ts +6 -6
- package/generators/micro-react/templates/apps/layout/src/app.tsx +18 -6
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +4 -0
- package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +2 -2
- package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +2 -2
- package/generators/micro-react/templates/apps/layout/src/constants/index.ts +72 -6
- package/generators/micro-react/templates/apps/layout/src/hooks/useRoutePermissionRefresh.ts +2 -2
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +0 -1
- package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +2 -2
- package/generators/micro-react/templates/apps/layout/src/services/user.ts +1 -0
- package/generators/micro-react/templates/apps/layout/tailwind.config.js +3 -0
- package/generators/subapp-react/index.js +10 -1
- package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +0 -1
- package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +0 -1
- package/generators/subapp-react/templates/homepage/src/common/request.ts +27 -0
- package/package.json +1 -1
|
@@ -139,15 +139,20 @@ module.exports = class extends Generator {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
install() {
|
|
143
|
+
this.log('');
|
|
144
|
+
this.log('📦 正在安装依赖...');
|
|
145
|
+
this.spawnCommandSync('pnpm', ['install'], {
|
|
146
|
+
cwd: this.destDir
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
142
150
|
end() {
|
|
143
151
|
this.log('');
|
|
144
152
|
this.log('✅ 项目创建成功!');
|
|
145
153
|
this.log('');
|
|
146
154
|
this.log(' 后续步骤:');
|
|
147
155
|
this.log('');
|
|
148
|
-
this.log(' # 安装依赖');
|
|
149
|
-
this.log(' pnpm install');
|
|
150
|
-
this.log('');
|
|
151
156
|
this.log(' # 启动开发服务器');
|
|
152
157
|
this.log(' pnpm dev');
|
|
153
158
|
this.log('');
|
|
@@ -43,15 +43,15 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
43
43
|
},
|
|
44
44
|
define: {
|
|
45
45
|
'process.env.NODE_ENV': 'development',
|
|
46
|
-
'process.env.APP_ID': '
|
|
46
|
+
'process.env.APP_ID': '<%= projectName %>',
|
|
47
47
|
'process.env.API_BASE_URL': '',
|
|
48
|
-
'process.env.PROXY_SUFFIX': '/',
|
|
48
|
+
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
49
49
|
'process.env.LOGIN_ENDPOINT':
|
|
50
|
-
'',
|
|
50
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
51
51
|
'process.env.REFRESH_ENDPOINT':
|
|
52
|
-
'',
|
|
52
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/refresh/',
|
|
53
53
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
54
|
-
'',
|
|
54
|
+
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
|
|
@@ -1,43 +1,19 @@
|
|
|
1
1
|
// https://umijs.org/config/
|
|
2
2
|
|
|
3
3
|
import { defineConfig } from '@umijs/max';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
|
|
7
|
-
// 使用 fs 读取 JSON 避免成为配置依赖,修改 menus.json 不会触发服务器重启
|
|
8
|
-
const mockMenus = JSON.parse(
|
|
9
|
-
fs.readFileSync(path.join(__dirname, '../mock/menus.json'), 'utf-8'),
|
|
10
|
-
);
|
|
11
4
|
|
|
12
5
|
const config: ReturnType<typeof defineConfig> = {
|
|
13
|
-
publicPath: '/',
|
|
14
|
-
/**
|
|
15
|
-
* @name 注入到 HTML head 的脚本
|
|
16
|
-
* @description 开发环境注入 mock 菜单数据
|
|
17
|
-
* @doc https://umijs.org/docs/api/config#headscripts
|
|
18
|
-
*/
|
|
19
|
-
headScripts: [
|
|
20
|
-
{
|
|
21
|
-
content: `
|
|
22
|
-
window.__MICO_MENUS__ = ${JSON.stringify(mockMenus)};
|
|
23
|
-
window.__MICO_CONFIG__ = {
|
|
24
|
-
appName: 'Mico Center',
|
|
25
|
-
apiBaseUrl: '',
|
|
26
|
-
};
|
|
27
|
-
`,
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
6
|
define: {
|
|
31
7
|
'process.env.NODE_ENV': 'development',
|
|
32
|
-
'process.env.APP_ID': '
|
|
33
|
-
'process.env.API_BASE_URL': '
|
|
34
|
-
'process.env.PROXY_SUFFIX': '/',
|
|
8
|
+
'process.env.APP_ID': '<%= projectName %>',
|
|
9
|
+
'process.env.API_BASE_URL': '',
|
|
10
|
+
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
35
11
|
'process.env.LOGIN_ENDPOINT':
|
|
36
|
-
'',
|
|
12
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
37
13
|
'process.env.REFRESH_ENDPOINT':
|
|
38
|
-
'',
|
|
14
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/refresh/',
|
|
39
15
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
40
|
-
'',
|
|
16
|
+
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
41
17
|
},
|
|
42
18
|
};
|
|
43
19
|
|
|
@@ -5,15 +5,15 @@ import { defineConfig } from '@umijs/max';
|
|
|
5
5
|
const config: ReturnType<typeof defineConfig> = {
|
|
6
6
|
define: {
|
|
7
7
|
'process.env.NODE_ENV': 'testing',
|
|
8
|
-
'process.env.APP_ID': '
|
|
9
|
-
'process.env.API_BASE_URL': '
|
|
10
|
-
'process.env.PROXY_SUFFIX': '/',
|
|
8
|
+
'process.env.APP_ID': '<%= projectName %>',
|
|
9
|
+
'process.env.API_BASE_URL': '',
|
|
10
|
+
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
11
11
|
'process.env.LOGIN_ENDPOINT':
|
|
12
|
-
'',
|
|
12
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
13
13
|
'process.env.REFRESH_ENDPOINT':
|
|
14
|
-
'',
|
|
14
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/refresh/',
|
|
15
15
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
16
|
-
'',
|
|
16
|
+
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
17
17
|
},
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -10,15 +10,15 @@ const PUBLIC_PATH: string = CDN_PUBLIC_PATH
|
|
|
10
10
|
const config: ReturnType<typeof defineConfig> = {
|
|
11
11
|
define: {
|
|
12
12
|
'process.env.NODE_ENV': 'production',
|
|
13
|
-
'process.env.APP_ID': '
|
|
14
|
-
'process.env.API_BASE_URL': '
|
|
15
|
-
'process.env.PROXY_SUFFIX': '/',
|
|
13
|
+
'process.env.APP_ID': '<%= projectName %>',
|
|
14
|
+
'process.env.API_BASE_URL': '',
|
|
15
|
+
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
16
16
|
'process.env.LOGIN_ENDPOINT':
|
|
17
|
-
'',
|
|
17
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
18
18
|
'process.env.REFRESH_ENDPOINT':
|
|
19
|
-
'',
|
|
19
|
+
'https://dashboard-api-test.micoplatform.com/api/yufu_login/refresh/',
|
|
20
20
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
21
|
-
'',
|
|
21
|
+
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
22
22
|
},
|
|
23
23
|
// 生产环境:将所有代码打包到一个文件
|
|
24
24
|
extraBabelPlugins: ['babel-plugin-dynamic-import-node'],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { history,
|
|
2
|
-
import { addGlobalUncaughtErrorHandler
|
|
1
|
+
import { history, type RequestConfig } from '@umijs/max';
|
|
2
|
+
import { addGlobalUncaughtErrorHandler } from 'qiankun';
|
|
3
3
|
import { errorConfig } from './requestErrorConfig';
|
|
4
4
|
// 解决「React19 中无法使用 Message/Notification」的问题。 @see https://github.com/arco-design/arco-design/issues/2900#issuecomment-2796571653
|
|
5
5
|
import * as arco from '@arco-design/web-react';
|
|
@@ -10,15 +10,18 @@ import { getStoredAuthToken } from './common/auth/auth-manager';
|
|
|
10
10
|
import type { IUserInfo } from './common/auth/type';
|
|
11
11
|
import { fetchUserInfo } from './services/user';
|
|
12
12
|
import { extractRoutes, getWindowMenus } from './common/menu';
|
|
13
|
-
import { ensureSsoSession } from './common/request/sso';
|
|
14
13
|
import {
|
|
15
14
|
clearMicroAppProps,
|
|
16
15
|
type IMicroAppProps,
|
|
17
16
|
setMicroAppProps,
|
|
18
17
|
} from './common/micro';
|
|
18
|
+
import {
|
|
19
|
+
ensureSsoSession,
|
|
20
|
+
handleAuthFailureRedirect,
|
|
21
|
+
} from './common/request/sso';
|
|
19
22
|
import { initTheme } from './common/theme';
|
|
20
23
|
import MicroAppLoader from './components/MicroAppLoader';
|
|
21
|
-
import {
|
|
24
|
+
import { isNoAuthRoute } from '@/constants';
|
|
22
25
|
import './global.less';
|
|
23
26
|
|
|
24
27
|
// ==================== qiankun 全局错误处理 ====================
|
|
@@ -110,10 +113,10 @@ export async function getInitialState(): Promise<{
|
|
|
110
113
|
};
|
|
111
114
|
|
|
112
115
|
const { location } = history;
|
|
113
|
-
const
|
|
116
|
+
const noAuthRoute = isNoAuthRoute(location.pathname);
|
|
114
117
|
|
|
115
118
|
// 非免认证路由:走 SSO 流程
|
|
116
|
-
if (!
|
|
119
|
+
if (!noAuthRoute) {
|
|
117
120
|
await ensureSsoSession();
|
|
118
121
|
}
|
|
119
122
|
|
|
@@ -128,6 +131,15 @@ export async function getInitialState(): Promise<{
|
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
// 非免认证路由且没有 token,跳转到 SSO 登录
|
|
135
|
+
if (!noAuthRoute) {
|
|
136
|
+
handleAuthFailureRedirect();
|
|
137
|
+
// 返回空状态,页面会被重定向
|
|
138
|
+
return {
|
|
139
|
+
fetchUserInfo: fetchUserInfoFn,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
131
143
|
return {
|
|
132
144
|
fetchUserInfo: fetchUserInfoFn,
|
|
133
145
|
};
|
|
@@ -157,6 +157,10 @@ declare global {
|
|
|
157
157
|
apiBaseUrl?: string;
|
|
158
158
|
/** 默认重定向路径,访问 "/" 时自动跳转到此路径 */
|
|
159
159
|
defaultPath?: string;
|
|
160
|
+
/** 动态配置的免鉴权路由列表,支持精确匹配和前缀匹配(以 /* 结尾) */
|
|
161
|
+
noAuthRouteList?: string[];
|
|
162
|
+
/** 动态配置的不显示布局路由列表,支持精确匹配和前缀匹配(以 /* 结尾) */
|
|
163
|
+
noLayoutRouteList?: string[];
|
|
160
164
|
[key: string]: unknown;
|
|
161
165
|
};
|
|
162
166
|
__MICO_WORKSPACE__?: WorkspaceConfig | null;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { request as rawRequest } from '@umijs/max';
|
|
18
18
|
import { setStoredAuthToken } from '../auth/auth-manager';
|
|
19
|
-
import {
|
|
19
|
+
import { isNoAuthRoute } from '@/constants';
|
|
20
20
|
|
|
21
21
|
// 配置相关
|
|
22
22
|
import {
|
|
@@ -64,7 +64,7 @@ initDefaultInterceptors(isFetchingToken, addToPendingQueue);
|
|
|
64
64
|
* 判断当前路由是否跳过认证
|
|
65
65
|
*/
|
|
66
66
|
const shouldSkipAuth = (): boolean => {
|
|
67
|
-
return
|
|
67
|
+
return isNoAuthRoute(location.pathname);
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { findRouteByPath } from '@/common/menu';
|
|
2
|
-
import {
|
|
2
|
+
import { isNoLayoutRoute } from '@/constants';
|
|
3
3
|
import useMenu from '@/hooks/useMenu';
|
|
4
4
|
import { Tabs } from '@arco-design/web-react';
|
|
5
5
|
import { history, useLocation } from '@umijs/max';
|
|
@@ -47,7 +47,7 @@ function AppTabs() {
|
|
|
47
47
|
const [tabs, setTabs] = useState<TabItem[]>([]);
|
|
48
48
|
|
|
49
49
|
const showTabs = useMemo(() => {
|
|
50
|
-
return !
|
|
50
|
+
return !isNoLayoutRoute(location.pathname);
|
|
51
51
|
}, [location.pathname]);
|
|
52
52
|
|
|
53
53
|
const microAppPrefixes = useMemo(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 应用常量定义
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
export const DEFAULT_NAME = 'Mico';
|
|
5
5
|
/**
|
|
6
6
|
* 路由路径常量
|
|
7
7
|
*/
|
|
@@ -19,7 +19,7 @@ export const ROUTES = {
|
|
|
19
19
|
} as const;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* 无需认证的路由列表(静态配置)
|
|
23
23
|
*/
|
|
24
24
|
export const NO_AUTH_ROUTE_LIST: string[] = [
|
|
25
25
|
ROUTES.LOGIN,
|
|
@@ -29,12 +29,78 @@ export const NO_AUTH_ROUTE_LIST: string[] = [
|
|
|
29
29
|
ROUTES.NOT_FOUND,
|
|
30
30
|
];
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* 获取合并后的免鉴权路由列表
|
|
34
|
+
* 合并静态常量 + window.__MICO_CONFIG__.noAuthRouteList
|
|
35
|
+
*/
|
|
36
|
+
export const getNoAuthRouteList = (): string[] => {
|
|
37
|
+
const dynamicRoutes = window.__MICO_CONFIG__?.noAuthRouteList ?? [];
|
|
38
|
+
return [...new Set([...NO_AUTH_ROUTE_LIST, ...dynamicRoutes])];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 判断路径是否匹配路由列表(支持精确匹配和前缀匹配)
|
|
43
|
+
* @param pathname - 当前路由路径
|
|
44
|
+
* @param routes - 路由列表
|
|
45
|
+
* @returns 是否匹配
|
|
46
|
+
*/
|
|
47
|
+
const matchRouteList = (pathname: string, routes: string[]): boolean => {
|
|
48
|
+
return routes.some((route) => {
|
|
49
|
+
// 前缀匹配:/public/* 匹配 /public/xxx
|
|
50
|
+
if (route.endsWith('/*')) {
|
|
51
|
+
const prefix = route.slice(0, -1); // 去掉末尾的 *,保留 /
|
|
52
|
+
return pathname.startsWith(prefix) || pathname === prefix.slice(0, -1);
|
|
53
|
+
}
|
|
54
|
+
// 精确匹配
|
|
55
|
+
return pathname === route;
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 判断指定路径是否为免鉴权路由
|
|
61
|
+
* 支持精确匹配和前缀匹配(以 /* 结尾的模式)
|
|
62
|
+
* @param pathname - 当前路由路径
|
|
63
|
+
* @returns 是否免鉴权
|
|
64
|
+
*/
|
|
65
|
+
export const isNoAuthRoute = (pathname: string): boolean => {
|
|
66
|
+
return matchRouteList(pathname, getNoAuthRouteList());
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 不显示布局的路由列表(静态配置)
|
|
71
|
+
* 注意:403/404 保留布局,方便用户通过导航返回
|
|
72
|
+
*/
|
|
73
|
+
export const NO_LAYOUT_ROUTE_LIST: string[] = [
|
|
74
|
+
ROUTES.LOGIN,
|
|
75
|
+
ROUTES.REGISTER,
|
|
76
|
+
ROUTES.REGISTER_RESULT,
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 获取合并后的不显示布局路由列表
|
|
81
|
+
* 合并静态常量 + window.__MICO_CONFIG__.noLayoutRouteList
|
|
82
|
+
*/
|
|
83
|
+
export const getNoLayoutRouteList = (): string[] => {
|
|
84
|
+
const dynamicRoutes = window.__MICO_CONFIG__?.noLayoutRouteList ?? [];
|
|
85
|
+
return [...new Set([...NO_LAYOUT_ROUTE_LIST, ...dynamicRoutes])];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 判断指定路径是否不显示布局
|
|
90
|
+
* 支持精确匹配和前缀匹配(以 /* 结尾的模式)
|
|
91
|
+
* @param pathname - 当前路由路径
|
|
92
|
+
* @returns 是否不显示布局
|
|
93
|
+
*/
|
|
94
|
+
export const isNoLayoutRoute = (pathname: string): boolean => {
|
|
95
|
+
return matchRouteList(pathname, getNoLayoutRouteList());
|
|
96
|
+
};
|
|
97
|
+
|
|
32
98
|
/**
|
|
33
99
|
* 主题相关常量
|
|
34
100
|
*/
|
|
35
101
|
export const THEME = {
|
|
36
102
|
/** localStorage 存储键 */
|
|
37
|
-
STORAGE_KEY: '
|
|
103
|
+
STORAGE_KEY: '<%= ProjectName %>-theme',
|
|
38
104
|
/** 默认主题 */
|
|
39
105
|
DEFAULT: 'light' as const,
|
|
40
106
|
/** 可选主题值 */
|
|
@@ -46,9 +112,9 @@ export const THEME = {
|
|
|
46
112
|
*/
|
|
47
113
|
export const TIMEZONE = {
|
|
48
114
|
/** localStorage 存储键(IANA 时区,如 Asia/Shanghai) */
|
|
49
|
-
STORAGE_KEY: '
|
|
115
|
+
STORAGE_KEY: '<%= ProjectName %>-timezone',
|
|
50
116
|
/** localStorage 存储键(用于展示的地区/名称,可选) */
|
|
51
|
-
REGION_STORAGE_KEY: '
|
|
117
|
+
REGION_STORAGE_KEY: '<%= ProjectName %>-timezone-region',
|
|
52
118
|
} as const;
|
|
53
119
|
|
|
54
120
|
/**
|
|
@@ -56,7 +122,7 @@ export const TIMEZONE = {
|
|
|
56
122
|
*/
|
|
57
123
|
export const PRESENCE = {
|
|
58
124
|
/** localStorage 存储键 */
|
|
59
|
-
STORAGE_KEY: '
|
|
125
|
+
STORAGE_KEY: '<%= ProjectName %>-presence-status',
|
|
60
126
|
} as const;
|
|
61
127
|
|
|
62
128
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLocation, useModel } from '@umijs/max';
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { layoutLogger } from '@/common/logger';
|
|
4
|
-
import {
|
|
4
|
+
import { isNoAuthRoute } from '@/constants';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 路由切换时自动刷新用户权限
|
|
@@ -39,7 +39,7 @@ export function useRoutePermissionRefresh() {
|
|
|
39
39
|
prevPathRef.current = location.pathname;
|
|
40
40
|
|
|
41
41
|
// 免认证路由不需要刷新
|
|
42
|
-
if (
|
|
42
|
+
if (isNoAuthRoute(location.pathname)) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { getAppNameFromEntry } from '@/common/micro';
|
|
9
9
|
import AppTabs from '@/components/AppTabs';
|
|
10
10
|
import MicroAppLoader from '@/components/MicroAppLoader';
|
|
11
|
-
import {
|
|
11
|
+
import { isNoLayoutRoute } from '@/constants';
|
|
12
12
|
import { useRoutePermissionRefresh } from '@/hooks/useRoutePermissionRefresh';
|
|
13
13
|
import ForbiddenPage from '@/pages/403';
|
|
14
14
|
import { Layout, Spin } from '@arco-design/web-react';
|
|
@@ -83,7 +83,7 @@ const BasicLayout: React.FC = () => {
|
|
|
83
83
|
}, [currentRoute, allRoutes, allowedRoutes, location.pathname, filterOptions]);
|
|
84
84
|
|
|
85
85
|
// 判断是否需要显示布局
|
|
86
|
-
const showLayout = !
|
|
86
|
+
const showLayout = !isNoLayoutRoute(location.pathname);
|
|
87
87
|
|
|
88
88
|
// 渲染页面内容
|
|
89
89
|
const renderContent = () => {
|
|
@@ -17,6 +17,7 @@ export interface IUserInfoResponse {
|
|
|
17
17
|
export async function fetchUserInfo(): Promise<IUserInfo> {
|
|
18
18
|
const response = await request<IUserInfoResponse>(USER_INFO_API, {
|
|
19
19
|
method: 'GET',
|
|
20
|
+
skipProxy: true,
|
|
20
21
|
});
|
|
21
22
|
if (response.code === 200 && response.data) {
|
|
22
23
|
return response.data;
|
|
@@ -177,12 +177,21 @@ module.exports = class extends Generator {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
install() {
|
|
181
|
+
this.log('');
|
|
182
|
+
this.log('📦 正在安装依赖...');
|
|
183
|
+
this.spawnCommandSync('pnpm', ['install'], {
|
|
184
|
+
cwd: this.monorepoRoot
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
180
188
|
end() {
|
|
181
189
|
this.log('');
|
|
182
190
|
this.log('✅ 子应用创建成功!');
|
|
183
191
|
this.log('');
|
|
192
|
+
this.log(' 后续步骤:');
|
|
193
|
+
this.log('');
|
|
184
194
|
this.log(` cd apps/${this.appName}`);
|
|
185
|
-
this.log(' pnpm install');
|
|
186
195
|
this.log(' pnpm dev');
|
|
187
196
|
this.log('');
|
|
188
197
|
}
|
|
@@ -46,4 +46,31 @@ export function getRequestSource(): 'main-app' | 'umi' {
|
|
|
46
46
|
return getMainAppRequest() ? 'main-app' : 'umi';
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* 从错误对象中提取错误消息
|
|
51
|
+
* 优先使用后端返回的 msg,否则使用默认消息
|
|
52
|
+
*/
|
|
53
|
+
export function getErrorMessage(error: unknown, defaultMsg: string): string {
|
|
54
|
+
if (error && typeof error === 'object') {
|
|
55
|
+
// 尝试从 error.data.msg 获取(umi-request 格式)
|
|
56
|
+
const err = error as Record<string, any>;
|
|
57
|
+
if (err.data?.msg) {
|
|
58
|
+
return err.data.msg;
|
|
59
|
+
}
|
|
60
|
+
// 尝试从 error.response.data.msg 获取(axios 格式)
|
|
61
|
+
if (err.response?.data?.msg) {
|
|
62
|
+
return err.response.data.msg;
|
|
63
|
+
}
|
|
64
|
+
// 尝试从 error.msg 获取
|
|
65
|
+
if (err.msg) {
|
|
66
|
+
return err.msg;
|
|
67
|
+
}
|
|
68
|
+
// 尝试从 error.message 获取
|
|
69
|
+
if (err.message) {
|
|
70
|
+
return err.message;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return defaultMsg;
|
|
74
|
+
}
|
|
75
|
+
|
|
49
76
|
|