generator-mico-cli 0.2.8 → 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.
@@ -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('');
@@ -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 { NO_AUTH_ROUTE_LIST } from '@/constants';
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 isNoAuthRoute = NO_AUTH_ROUTE_LIST.includes(location.pathname);
116
+ const noAuthRoute = isNoAuthRoute(location.pathname);
114
117
 
115
118
  // 非免认证路由:走 SSO 流程
116
- if (!isNoAuthRoute) {
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 { NO_AUTH_ROUTE_LIST } from '@/constants';
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 NO_AUTH_ROUTE_LIST.includes(location.pathname);
67
+ return isNoAuthRoute(location.pathname);
68
68
  };
69
69
 
70
70
  /**
@@ -1,5 +1,5 @@
1
1
  import { findRouteByPath } from '@/common/menu';
2
- import { NO_AUTH_ROUTE_LIST } from '@/constants';
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 !NO_AUTH_ROUTE_LIST.includes(location.pathname);
50
+ return !isNoLayoutRoute(location.pathname);
51
51
  }, [location.pathname]);
52
52
 
53
53
  const microAppPrefixes = useMemo(() => {
@@ -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: 'audit-center-theme',
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: 'audit-center-timezone',
115
+ STORAGE_KEY: '<%= ProjectName %>-timezone',
50
116
  /** localStorage 存储键(用于展示的地区/名称,可选) */
51
- REGION_STORAGE_KEY: 'audit-center-timezone-region',
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: 'audit-center-presence-status',
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 { NO_AUTH_ROUTE_LIST } from '@/constants';
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 (NO_AUTH_ROUTE_LIST.includes(location.pathname)) {
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 { NO_AUTH_ROUTE_LIST } from '@/constants';
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 = !NO_AUTH_ROUTE_LIST.includes(location.pathname);
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
  }
@@ -1,7 +1,6 @@
1
1
  // https://umijs.org/config/
2
2
 
3
3
  import { defineConfig } from '@umijs/max';
4
- const { CDN_PUBLIC_PATH } = process.env;
5
4
 
6
5
 
7
6
  const config: ReturnType<typeof defineConfig> = {
@@ -1,7 +1,6 @@
1
1
  // https://umijs.org/config/
2
2
 
3
3
  import { defineConfig } from '@umijs/max';
4
- const { CDN_PUBLIC_PATH } = process.env;
5
4
 
6
5
 
7
6
  const config: ReturnType<typeof defineConfig> = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": [
6
6
  "yeoman-generator",