generator-mico-cli 0.2.28 → 0.2.30
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/README.md +7 -20
- package/bin/mico.js +27 -62
- package/generators/micro-react/index.js +25 -1
- package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +3 -0
- package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +1 -0
- package/generators/micro-react/templates/CICD/start_dev.sh +11 -0
- package/generators/micro-react/templates/CICD/start_local.sh +9 -0
- package/generators/micro-react/templates/CICD/start_prod.sh +13 -0
- package/generators/micro-react/templates/CICD/start_test.sh +11 -0
- package/generators/micro-react/templates/CLAUDE.md +1 -0
- package/generators/micro-react/templates/README.md +1 -1
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +13 -5
- package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +12 -0
- package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +12 -0
- package/generators/micro-react/templates/apps/layout/config/config.prod.ts +14 -0
- package/generators/micro-react/templates/apps/layout/docs/feature-PermissionFilter/346/214/211/351/222/256/346/235/203/351/231/220.md +116 -0
- package/generators/micro-react/templates/apps/layout/docs/feature-/345/233/275/351/231/205/345/214/226.md +121 -0
- package/generators/micro-react/templates/apps/layout/docs/feature-/345/276/256/345/211/215/347/253/257/346/250/241/345/274/217.md +8 -0
- package/generators/micro-react/templates/apps/layout/docs/feature-/350/217/234/345/215/225/346/235/203/351/231/220/346/216/247/345/210/266.md +83 -77
- package/generators/micro-react/templates/apps/layout/docs/feature-/350/267/257/347/224/261/344/270/216/350/217/234/345/215/225/350/247/243/350/200/246.md +50 -35
- package/generators/micro-react/templates/apps/layout/docs/feature-/350/267/257/347/224/261/346/235/203/351/231/220/346/227/245/345/277/227.md +162 -0
- package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +23 -31
- package/generators/micro-react/templates/apps/layout/mock/menus.ts +14 -0
- package/generators/micro-react/templates/apps/layout/mock/pages.ts +27 -8
- package/generators/micro-react/templates/apps/layout/package.json +2 -0
- package/generators/micro-react/templates/apps/layout/src/app.tsx +85 -4
- package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
- package/generators/micro-react/templates/apps/layout/src/common/auth/tenant.ts +25 -0
- package/generators/micro-react/templates/apps/layout/src/common/auth/type.ts +41 -27
- package/generators/micro-react/templates/apps/layout/src/common/intl/formatLayoutMessage.ts +30 -0
- package/generators/micro-react/templates/apps/layout/src/common/intl/index.ts +6 -0
- package/generators/micro-react/templates/apps/layout/src/common/intl/intlRuntime.ts +14 -0
- package/generators/micro-react/templates/apps/layout/src/common/intl/localeMapping.ts +30 -0
- package/generators/micro-react/templates/apps/layout/src/common/intl/types.ts +14 -0
- package/generators/micro-react/templates/apps/layout/src/common/intl/useLayoutIntl.ts +40 -0
- package/generators/micro-react/templates/apps/layout/src/common/logger.ts +3 -4
- package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +148 -85
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +29 -6
- package/generators/micro-react/templates/apps/layout/src/common/micro/types.ts +23 -0
- package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +46 -2
- package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +74 -15
- package/generators/micro-react/templates/apps/layout/src/common/request/token-refresh.ts +2 -0
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +32 -6
- package/generators/micro-react/templates/apps/layout/src/components/PermissionFilter/index.tsx +51 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +10 -1
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/TenantDropdown.tsx +76 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +1 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/tenant-dropdown.less +48 -0
- package/generators/micro-react/templates/apps/layout/src/constants/index.ts +1 -0
- package/generators/micro-react/templates/apps/layout/src/hooks/index.ts +1 -0
- package/generators/micro-react/templates/apps/layout/src/hooks/useMenuState.ts +18 -0
- package/generators/micro-react/templates/apps/layout/src/hooks/useTenant.ts +41 -0
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +4 -1
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +21 -9
- package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +105 -60
- package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +28 -0
- package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +26 -0
- package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +7 -3
- package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +32 -0
- package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +148 -4
- package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +2 -1
- package/generators/micro-react/templates/apps/layout/src/services/user.ts +79 -21
- package/generators/micro-react/templates/apps/layout/typings.d.ts +16 -0
- package/generators/micro-react/templates/docs/package-shared.md +189 -0
- package/generators/micro-react/templates/package.json +1 -1
- package/generators/micro-react/templates/packages/common-intl/README.md +78 -368
- package/generators/micro-react/templates/packages/common-intl/package.json +3 -13
- package/generators/micro-react/templates/packages/common-intl/src/index.ts +5 -6
- package/generators/micro-react/templates/packages/common-intl/src/intl.ts +115 -28
- package/generators/micro-react/templates/packages/common-intl/src/umiLocaleBridge.ts +101 -0
- package/generators/micro-react/templates/packages/common-intl/tsconfig.json +2 -4
- package/generators/micro-react/templates/packages/shared/README.md +120 -0
- package/generators/micro-react/templates/packages/shared/package.json +26 -0
- package/generators/micro-react/templates/packages/shared/services/common/index.ts +43 -0
- package/generators/micro-react/templates/packages/shared/services/index.ts +21 -0
- package/generators/micro-react/templates/packages/shared/services/request.ts +43 -0
- package/generators/micro-react/templates/packages/shared/timezone/index.ts +228 -0
- package/generators/micro-react/templates/packages/shared/tsconfig.json +20 -0
- package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +6 -1
- package/generators/micro-react/templates/turbo.json +9 -1
- package/generators/subapp-react/index.js +28 -22
- package/generators/subapp-react/templates/homepage/README.md +1 -0
- package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +1 -0
- package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +1 -0
- package/generators/subapp-react/templates/homepage/config/config.prod.ts +1 -0
- package/generators/subapp-react/templates/homepage/config/config.ts +10 -0
- package/generators/subapp-react/templates/homepage/docs/feature-PermissionFilter/346/214/211/351/222/256/346/235/203/351/231/220.md +35 -0
- package/generators/subapp-react/templates/homepage/docs/feature-/345/233/275/351/231/205/345/214/226.md +124 -0
- package/generators/subapp-react/templates/homepage/package.json +3 -1
- package/generators/subapp-react/templates/homepage/src/app.tsx +104 -2
- package/generators/subapp-react/templates/homepage/src/common/intl/index.ts +15 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/intlRuntime.ts +14 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/localeMapping.ts +24 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/subappIntlConfig.ts +28 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/subappLocale.ts +18 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/subappOwnIntl.ts +63 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/types.ts +14 -0
- package/generators/subapp-react/templates/homepage/src/common/intl/useSubappIntl.ts +61 -0
- package/generators/subapp-react/templates/homepage/src/common/locale.ts +80 -0
- package/generators/subapp-react/templates/homepage/src/common/mainApp.ts +41 -2
- package/generators/subapp-react/templates/homepage/src/components/PermissionFilter/index.tsx +48 -0
- package/generators/subapp-react/templates/homepage/src/locales/en-US.ts +6 -0
- package/generators/subapp-react/templates/homepage/src/locales/zh-CN.ts +6 -0
- package/generators/subapp-react/templates/homepage/src/pages/index.less +10 -0
- package/generators/subapp-react/templates/homepage/src/pages/index.tsx +86 -1
- package/generators/subapp-react/templates/homepage/typings.d.ts +12 -0
- package/lib/utils.js +0 -1
- package/package.json +2 -2
- package/generators/micro-react/templates/apps/layout/docs/common-intl.md +0 -372
- package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +0 -51
- package/generators/micro-react/templates/packages/common-intl/src/utils.ts +0 -482
- package/generators/micro-react/templates/packages/common-intl/vite.config.ts +0 -25
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# 路由与菜单解耦
|
|
2
2
|
|
|
3
|
-
> 创建时间:2026-02-25
|
|
3
|
+
> 创建时间:2026-02-25 更新时间:2026-03-27
|
|
4
4
|
|
|
5
5
|
## 功能概述
|
|
6
6
|
|
|
7
|
-
将动态路由注册与菜单导航的数据源解耦。路由注册消费 `window.__MICO_PAGES__`(页面列表),菜单栏消费 `window.__MICO_MENUS__
|
|
7
|
+
将动态路由注册与菜单导航的数据源解耦。路由注册消费 `window.__MICO_PAGES__`(页面列表),菜单栏消费 `window.__MICO_MENUS__`(菜单树)。两者独立运作,**路由与侧栏权限**统一以用户信息中的 **`menu_perms`(菜单 code 列表)** 为准,与页面 **`routeKey`**、菜单项权限 code **一一对应**;无页面元数据时仍可按「菜单中是否可见」兜底。
|
|
8
8
|
|
|
9
9
|
## 技术方案
|
|
10
10
|
|
|
@@ -22,9 +22,20 @@ __MICO_PAGES__ (扁平列表,所有页面)
|
|
|
22
22
|
└── 隐藏页面(不在菜单中显示,但路由可访问)
|
|
23
23
|
|
|
24
24
|
__MICO_MENUS__ (菜单树,用于导航)
|
|
25
|
-
└── page
|
|
25
|
+
└── `page` 类型项通过 pageId / path 关联到 __MICO_PAGES__(见下方「菜单项关联页面」)
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
### 菜单项关联页面(`getMenuPage`)
|
|
29
|
+
|
|
30
|
+
侧栏过滤、从菜单树提取路由(`extractRoutes`)、`routeKey` / `menu_perms` 等需要「菜单项 → 页面配置」时,统一由 `src/common/portal-data.ts` 的 **`getMenuPage(item)`** 解析:
|
|
31
|
+
|
|
32
|
+
| 顺序 | 规则 | 说明 |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| 1 | **`pageId` → `getPageById`** | 菜单项带 `pageId` 且在 `__MICO_PAGES__` 中存在对应 `id` 时,**优先使用该页面** |
|
|
35
|
+
| 2 | **`path` + `findPageByPath`** | 上一步无结果时(无 `pageId`、或 id 在列表中不存在),用菜单 **`path`** 与页面 **`route`** 匹配(精确 + 最长前缀 `/*`),与路由侧解析规则一致 |
|
|
36
|
+
|
|
37
|
+
仅 `type === 'page'` 的菜单项会走上述逻辑;`findPageByPath` 仅匹配 **`enabled === true`** 的页面。
|
|
38
|
+
|
|
28
39
|
### 数据流
|
|
29
40
|
|
|
30
41
|
```
|
|
@@ -35,7 +46,7 @@ Before:
|
|
|
35
46
|
|
|
36
47
|
After:
|
|
37
48
|
patchClientRoutes ← getDynamicRoutes() → PAGES 优先,降级 MENUS
|
|
38
|
-
layouts 权限校验 ←
|
|
49
|
+
layouts 权限校验 ← PAGES 上 routeKey ∈ menu_perms;无 page 时 allowedMenuRoutes 兜底
|
|
39
50
|
菜单渲染 ← parseMenuItems(MENUS) ← 不变
|
|
40
51
|
```
|
|
41
52
|
|
|
@@ -53,26 +64,22 @@ page.accessControlEnabled === false?
|
|
|
53
64
|
├── 是 → 跳过 SSO 认证 + 跳过权限校验(公开页面)
|
|
54
65
|
│
|
|
55
66
|
▼
|
|
56
|
-
|
|
67
|
+
非动态路由(currentRoute 不在 PAGES 动态列表中)?
|
|
57
68
|
├── 是 → 交给 Umi 处理(404 等)
|
|
58
69
|
│
|
|
59
70
|
▼
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
│
|
|
63
|
-
│
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
│
|
|
70
|
-
│
|
|
71
|
-
|
|
72
|
-
│ accessControlEnabled: true │
|
|
73
|
-
│ → routeKey ∈ sideMenus ? 放行 : 403 │
|
|
74
|
-
│ 其他 → 放行 │
|
|
75
|
-
└─────────────────────────────────────────────┘
|
|
71
|
+
能解析到 PAGES 中的页面配置?
|
|
72
|
+
├── 是 → adminOnly → 403
|
|
73
|
+
│ accessControlEnabled && routeKey
|
|
74
|
+
│ → routeKey ∈ menu_perms ? 放行 : 403
|
|
75
|
+
│ 其他 → 放行
|
|
76
|
+
│
|
|
77
|
+
▼
|
|
78
|
+
路径仅在菜单路由中出现(无 page 元数据)?
|
|
79
|
+
├── 是 → 在 filterMenuItems(menu_perms) 后的 allowedMenuRoutes 中?
|
|
80
|
+
│ ├── 是 → 放行
|
|
81
|
+
│ └── 否 → 403
|
|
82
|
+
└── 否 → 放行(非本逻辑覆盖)
|
|
76
83
|
```
|
|
77
84
|
|
|
78
85
|
### 降级策略
|
|
@@ -93,9 +100,10 @@ getDynamicRoutes():
|
|
|
93
100
|
| 文件路径 | 修改内容 |
|
|
94
101
|
| --- | --- |
|
|
95
102
|
| `src/common/menu/types.ts` | `PageConfig` 新增 `accessControlEnabled`、`routeKey` 字段;新增 `PublicPageItem` 类型(`Omit<PageConfig, ...>`);Window 声明新增 `__MICO_PAGES__` |
|
|
96
|
-
| `src/common/
|
|
103
|
+
| `src/common/portal-data.ts` | `findPageByPath`、`getMenuPage`(pageId 优先,其次 path 匹配页面 route) |
|
|
104
|
+
| `src/common/menu/parser.ts` | `extractRoutesFromPages`、`getDynamicRoutes`;从 portal-data 再导出 `findPageByPath`;菜单过滤与 `extractRoutes` 消费 `getMenuPage` |
|
|
97
105
|
| `src/app.tsx` | `patchClientRoutes` 改为调用 `getDynamicRoutes()` |
|
|
98
|
-
| `src/layouts/index.tsx` |
|
|
106
|
+
| `src/layouts/index.tsx` | 路由匹配 `allPageRoutes`;权限以 `menu_perms` + `routeKey` 为主,无 page 时菜单路由兜底 |
|
|
99
107
|
|
|
100
108
|
### 未修改文件
|
|
101
109
|
|
|
@@ -119,16 +127,19 @@ type PublicPageItem = Omit<
|
|
|
119
127
|
| 字段 | 类型 | 说明 |
|
|
120
128
|
| --- | --- | --- |
|
|
121
129
|
| `accessControlEnabled` | `boolean` | 是否开启访问控制。`false` 时跳过 SSO 认证和权限校验(公开页面);`true` 时需要登录且通过 `routeKey` 校验权限 |
|
|
122
|
-
| `routeKey` | `string \| null` |
|
|
130
|
+
| `routeKey` | `string \| null` | 路由权限标识,与用户信息 `menu_perms`、菜单项权限 code 一致 |
|
|
123
131
|
|
|
124
|
-
###
|
|
132
|
+
### 页面数据函数(`portal-data.ts` / `parser.ts`)
|
|
125
133
|
|
|
126
134
|
```typescript
|
|
127
135
|
/** 获取 window.__MICO_PAGES__ */
|
|
128
|
-
function
|
|
136
|
+
function getPages(): PublicPageItem[];
|
|
129
137
|
|
|
130
138
|
/** 判断页面数据是否可用 */
|
|
131
|
-
function
|
|
139
|
+
function hasPages(): boolean;
|
|
140
|
+
|
|
141
|
+
/** 菜单项 → 关联页面:pageId 优先,无匹配再用 path 与页面 route 匹配 */
|
|
142
|
+
function getMenuPage(item: MenuItem): PublicPageItem | undefined;
|
|
132
143
|
|
|
133
144
|
/** 从页面数据提取路由配置 */
|
|
134
145
|
function extractRoutesFromPages(pages: PublicPageItem[]): ParsedRoute[];
|
|
@@ -136,8 +147,11 @@ function extractRoutesFromPages(pages: PublicPageItem[]): ParsedRoute[];
|
|
|
136
147
|
/** 获取动态路由(PAGES 优先,降级 MENUS) */
|
|
137
148
|
function getDynamicRoutes(): ParsedRoute[];
|
|
138
149
|
|
|
139
|
-
/** 根据路径查找页面配置(精确匹配 +
|
|
140
|
-
function findPageByPath(
|
|
150
|
+
/** 根据路径查找页面配置(精确匹配 + 最长前缀 `/*`) */
|
|
151
|
+
function findPageByPath(
|
|
152
|
+
pages: PublicPageItem[],
|
|
153
|
+
pathname: string,
|
|
154
|
+
): PublicPageItem | undefined;
|
|
141
155
|
```
|
|
142
156
|
|
|
143
157
|
### Window 全局变量
|
|
@@ -156,24 +170,25 @@ interface Window {
|
|
|
156
170
|
| 决策点 | 选择 | 理由 |
|
|
157
171
|
| --- | --- | --- |
|
|
158
172
|
| 路由数据源 | `__MICO_PAGES__` 独立于菜单 | 页面和菜单是不同维度:页面定义"有什么路由",菜单定义"导航怎么组织";解耦后支持隐藏页面 |
|
|
159
|
-
| 权限方案 |
|
|
173
|
+
| 权限方案 | `menu_perms` + `routeKey` | 与后端新用户信息接口一致;菜单项 code 与 `menu_perms` 一一对应 |
|
|
160
174
|
| 降级策略 | `getDynamicRoutes()` 自动降级 | `__MICO_PAGES__` 未注入时回退到旧行为,零配置向后兼容 |
|
|
161
175
|
| PublicPageItem 定义 | `Omit<PageConfig, ...>` 派生 | 保持与 PageConfig 的类型继承关系,避免字段重复定义和类型漂移 |
|
|
162
176
|
| accessControlEnabled 语义 | `false` = 公开页面(跳过认证+授权),`true` = 需要权限检查 | 一个字段统一控制 SSO 认证、权限校验、子应用加载等待,减少配置冗余 |
|
|
163
177
|
| 隐藏页面权限 | 先 adminOnly 再 accessControlEnabled | adminOnly 是硬拦截,accessControlEnabled + routeKey 提供用户级粒度控制 |
|
|
178
|
+
| 菜单 → 页面解析 | `pageId` 优先,再 `path` | 中台以 id 为准;路径匹配用于无 id 或 id 失效时的兜底,与 `findPageByPath` 一致 |
|
|
164
179
|
|
|
165
180
|
## 已知限制与待改进
|
|
166
181
|
|
|
167
|
-
-
|
|
168
|
-
-
|
|
182
|
+
- 用户信息接口为 **`GET /user/info/`**(OpenAPI 8),与旧 `/api/user/info` 非同一后端;`fetchUserInfo` 已切换
|
|
183
|
+
- 外链类型菜单项需配置 `nameKey` 作为权限 code,否则无法匹配 `menu_perms`
|
|
169
184
|
|
|
170
185
|
## 注意事项
|
|
171
186
|
|
|
172
187
|
- `__MICO_PAGES__` 只包含用户在后台配置的微应用页面,404/403 等静态页面不在其中
|
|
173
|
-
- `__MICO_MENUS__`
|
|
174
|
-
-
|
|
188
|
+
- `__MICO_MENUS__` 中 `page` 类型项通过 **`pageId`**(优先)或 **`path` 与页面 `route` 匹配** 关联到 `__MICO_PAGES__` 中的页面配置
|
|
189
|
+
- 调试时可在控制台过滤 `routePermission` 查看结构化权限日志(详见 [路由权限日志](./feature-路由权限日志.md))
|
|
175
190
|
|
|
176
191
|
## 相关文档
|
|
177
192
|
|
|
178
193
|
- [微前端模式](./feature-微前端模式.md) - 微应用加载机制
|
|
179
|
-
- [菜单权限控制](./feature-菜单权限控制.md) -
|
|
194
|
+
- [菜单权限控制](./feature-菜单权限控制.md) - `menu_perms` 与菜单过滤
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 路由权限日志
|
|
2
|
+
|
|
3
|
+
> 创建时间:2026-03-27
|
|
4
|
+
|
|
5
|
+
## 功能概述
|
|
6
|
+
|
|
7
|
+
在 layout 中输出两类结构化开发日志,便于本地排查权限问题:
|
|
8
|
+
|
|
9
|
+
1. **`routePermission`**:`BasicLayout` 中 **`isForbidden` 路由权限判定**(为何放行 / 为何 403)。
|
|
10
|
+
2. **`menuFilter`**:`filterMenuItems` 中**被隐藏的菜单项**及**隐藏原因**(侧栏不可见条目)。
|
|
11
|
+
|
|
12
|
+
日志均经 `layoutLogger` 输出,**仅开发环境生效**,生产构建无控制台输出。
|
|
13
|
+
|
|
14
|
+
## 技术方案
|
|
15
|
+
|
|
16
|
+
### 技术栈
|
|
17
|
+
|
|
18
|
+
- 框架:React 18 + @umijs/max
|
|
19
|
+
- 日志:`apps/layout/src/common/logger.ts` 的 `layoutLogger`(`NODE_ENV === 'development'` 时 `console.log`)
|
|
20
|
+
|
|
21
|
+
### 核心实现
|
|
22
|
+
|
|
23
|
+
1. 在 `BasicLayout` 的 `useMemo`(`isForbidden`)中,于各分支返回前调用 `layoutLogger.log('routePermission', payload)`。
|
|
24
|
+
2. 统一使用 **`routePermission`** 作为首参,便于控制台过滤;`payload` 为结构化对象,包含 `verdict`、`reason`、`branch`(部分分支)及路径、页面上下文。
|
|
25
|
+
3. **不记录**「无动态路由 `currentRoute`」与「无页面元数据且未命中菜单兜底」的常见放行路径,避免刷屏。
|
|
26
|
+
4. 在 `parser.ts` 的 `filterMenuItems` 中,于菜单项被剔除时输出 **`menuFilter`**;**关闭权限**或**超级用户**时不打菜单隐藏日志(此时无实质过滤)。
|
|
27
|
+
|
|
28
|
+
## 文件清单
|
|
29
|
+
|
|
30
|
+
### 修改文件
|
|
31
|
+
|
|
32
|
+
| 文件路径 | 说明 |
|
|
33
|
+
|----------|------|
|
|
34
|
+
| `apps/layout/src/layouts/index.tsx` | `isForbidden` 内各关键分支的 `routePermission` 日志 |
|
|
35
|
+
| `apps/layout/src/common/menu/parser.ts` | `getMenuItemFilterOutcome`、`filterMenuItems` 内 `menuFilter` 隐藏日志 |
|
|
36
|
+
|
|
37
|
+
## 日志字段说明
|
|
38
|
+
|
|
39
|
+
### 通用字段
|
|
40
|
+
|
|
41
|
+
| 字段 | 说明 |
|
|
42
|
+
|------|------|
|
|
43
|
+
| `verdict` | `skip`:跳过权限校验;`allow`:允许访问;`deny`:403 |
|
|
44
|
+
| `reason` | 见下表 |
|
|
45
|
+
| `pathname` | 当前 `location.pathname` |
|
|
46
|
+
| `routePath` | 匹配到的动态路由 `currentRoute.path`(有 `currentRoute` 时) |
|
|
47
|
+
| `userId` | `currentUser.id` |
|
|
48
|
+
| `isSuperuser` | 是否超管 |
|
|
49
|
+
| `menuPermsCount` | `menu_perms` 长度 |
|
|
50
|
+
|
|
51
|
+
### `reason` 取值
|
|
52
|
+
|
|
53
|
+
| reason | verdict | 含义 |
|
|
54
|
+
|--------|---------|------|
|
|
55
|
+
| `disableAuth` | skip | `__MICO_CONFIG__.disableAuth` 等效关闭权限 |
|
|
56
|
+
| `noPermissionRoute` | skip | 命中免权限路由列表 |
|
|
57
|
+
| `superuser` | skip | 超级用户不校验 |
|
|
58
|
+
| `adminOnly` | deny | 页面 `adminOnly`,非超管 |
|
|
59
|
+
| `publicPage` | allow | `accessControlEnabled === false` |
|
|
60
|
+
| `accessControlNoRouteKey` | allow | 已开启访问控制但未配置 `routeKey`,不做 `menu_perms` 校验(与侧栏 `isMenuPageRequiringPermCode` 一致) |
|
|
61
|
+
| `routeKeyNotInMenuPerms` | deny | `routeKey` 不在 `menu_perms` |
|
|
62
|
+
| `routeKeyInMenuPerms` | allow | `routeKey` 在 `menu_perms` |
|
|
63
|
+
| `notInFilteredMenuRoutes` | deny | 菜单兜底分支:过滤后路由不包含当前路径 |
|
|
64
|
+
| `inFilteredMenuRoutes` | allow | 菜单兜底分支:过滤后仍包含 |
|
|
65
|
+
|
|
66
|
+
### 分支字段 `branch`
|
|
67
|
+
|
|
68
|
+
| branch | 含义 |
|
|
69
|
+
|--------|------|
|
|
70
|
+
| `pageMeta` | 已解析到 `__MICO_PAGES__` 页面配置时的 `routeKey` / `menu_perms` 判定 |
|
|
71
|
+
| `menuRouteFallback` | 无页面元数据时,用「全量菜单路由 vs `filterMenuItems` 后菜单路由」比对 |
|
|
72
|
+
|
|
73
|
+
### 页面元数据分支额外字段
|
|
74
|
+
|
|
75
|
+
| 字段 | 说明 |
|
|
76
|
+
|------|------|
|
|
77
|
+
| `pageId` | 页面配置 id |
|
|
78
|
+
| `routeKey` | 页面 `routeKey` |
|
|
79
|
+
| `keyInMenuPerms` | `routeKey` 是否在 `menu_perms` 中(仅当需校验 `routeKey` 时输出) |
|
|
80
|
+
|
|
81
|
+
### 菜单兜底分支额外字段
|
|
82
|
+
|
|
83
|
+
| 字段 | 说明 |
|
|
84
|
+
|------|------|
|
|
85
|
+
| `inAllowed` | 当前路径是否在过滤后的允许菜单路由中 |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 菜单过滤日志 `menuFilter`
|
|
90
|
+
|
|
91
|
+
### 通用字段
|
|
92
|
+
|
|
93
|
+
| 字段 | 说明 |
|
|
94
|
+
|------|------|
|
|
95
|
+
| `verdict` | 固定 `hidden` |
|
|
96
|
+
| `reason` | 见下表 |
|
|
97
|
+
| `menuId` | 菜单项 `id` |
|
|
98
|
+
| `menuType` | `group` / `page` / `link` |
|
|
99
|
+
| `name` | 菜单展示名(配置中的 `name`) |
|
|
100
|
+
| `nameKey` | 菜单 `nameKey`(若有) |
|
|
101
|
+
| `permCode` | `getMenuItemPermCode` 解析出的权限 code(可能为 `null`) |
|
|
102
|
+
| `menuPermsCount` | 当前用户 `menu_perms` 长度 |
|
|
103
|
+
| `path` | 菜单路由或关联页路由 |
|
|
104
|
+
|
|
105
|
+
### `menuFilter.reason` 取值
|
|
106
|
+
|
|
107
|
+
| reason | 含义 |
|
|
108
|
+
|--------|------|
|
|
109
|
+
| `adminOnly` | 菜单项 `adminOnly`,非超管不可见 |
|
|
110
|
+
| `missingPermCode` | `page` 无可用 `routeKey`、`link` 无 `nameKey`,无法匹配 `menu_perms` |
|
|
111
|
+
| `menuPermsEmpty` | `menu_perms` 为空数组 |
|
|
112
|
+
| `permCodeNotInMenuPerms` | 权限 code 不在 `menu_perms` 中 |
|
|
113
|
+
| `groupNoVisibleChildren` | 分组下子菜单全部过滤后无可见项 |
|
|
114
|
+
| `allChildrenFilteredOut` | 父级单项通过(`page`/`link` 有权限),但子级全部过滤后无子项可展示 |
|
|
115
|
+
|
|
116
|
+
说明:`group` 作为容器在子项仍可见时**不会**被记为 `hidden`;仅当整组被剔除时打日志。
|
|
117
|
+
|
|
118
|
+
## 使用示例
|
|
119
|
+
|
|
120
|
+
在浏览器控制台过滤:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
routePermission
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
或:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
menuFilter
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
或:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
[Layout]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
(具体前缀以 `layoutLogger` 实现为准。)
|
|
139
|
+
|
|
140
|
+
## 设计决策
|
|
141
|
+
|
|
142
|
+
| 决策点 | 选择 | 理由 |
|
|
143
|
+
|--------|------|------|
|
|
144
|
+
| 日志前缀 | 固定 `'routePermission'` + 对象载荷 | 可过滤、可结构化,便于 AI/人工检索 |
|
|
145
|
+
| 生产环境 | 静默 | `layoutLogger` 在 `production` 下不输出 |
|
|
146
|
+
| 无 `currentRoute` 不打日志 | 跳过 | 静态路由访问频繁,避免噪音 |
|
|
147
|
+
| `menuFilter` 与超管/关权限 | 不打 | 无过滤效果时无隐藏项可记 |
|
|
148
|
+
|
|
149
|
+
## 已知限制与待改进
|
|
150
|
+
|
|
151
|
+
- 日志仅在**开发环境**可见;线上问题需依赖 Sentry 或其它监控,不在本功能内。
|
|
152
|
+
- `renderContent` 另有 `renderContent:` 日志,与 `routePermission` 独立,排查时可同时参考。
|
|
153
|
+
|
|
154
|
+
## 注意事项
|
|
155
|
+
|
|
156
|
+
- 权限判定逻辑以 `layouts/index.tsx` 与 [菜单权限控制](./feature-菜单权限控制.md)、[路由与菜单解耦](./feature-路由与菜单解耦.md) 为准;本文档**仅描述日志字段**,不替代权限语义说明。
|
|
157
|
+
|
|
158
|
+
## 相关文档
|
|
159
|
+
|
|
160
|
+
- [菜单权限控制](./feature-菜单权限控制.md)
|
|
161
|
+
- [路由与菜单解耦](./feature-路由与菜单解耦.md)
|
|
162
|
+
- [日志与常量](./arch-日志与常量.md)(`layoutLogger` 行为)
|
|
@@ -5,38 +5,30 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export default {
|
|
8
|
-
//
|
|
9
|
-
'GET /
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"side_menus": [
|
|
30
|
-
'首页',
|
|
31
|
-
'示例模块.示例页面',
|
|
32
|
-
'微应用示例.子应用页面',
|
|
33
|
-
'外部链接',
|
|
34
|
-
'权限管理',
|
|
35
|
-
],
|
|
36
|
-
"region_permissions": []
|
|
8
|
+
// 获取用户信息(OpenAPI 8 GET /user/info/,与 fetchUserInfo 一致)
|
|
9
|
+
'GET /user/info/': {
|
|
10
|
+
code: 200,
|
|
11
|
+
data: {
|
|
12
|
+
id: 381,
|
|
13
|
+
avatar:
|
|
14
|
+
'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
|
|
15
|
+
email: '本地测试mock用户@micous.com',
|
|
16
|
+
name: 'Easton',
|
|
17
|
+
app_perms: [],
|
|
18
|
+
region_perms: [],
|
|
19
|
+
menu_perms: [
|
|
20
|
+
'cs_web_menu_home',
|
|
21
|
+
'cs_web_menu_example_page',
|
|
22
|
+
'cs_web_menu_subapp_page',
|
|
23
|
+
'cs_web_menu_external_link',
|
|
24
|
+
'cs_web_menu_permission_management',
|
|
25
|
+
'cs_web_menu_group_management',
|
|
26
|
+
],
|
|
27
|
+
button_perms: ['cs_web_btn_subapp_demo', 'cs_web_btn_home_demo'],
|
|
28
|
+
is_superuser: false,
|
|
37
29
|
},
|
|
38
|
-
|
|
39
|
-
},
|
|
30
|
+
msg: 'ok',
|
|
31
|
+
},
|
|
40
32
|
|
|
41
33
|
// 获取统计数据
|
|
42
34
|
// 'GET /api/dashboard/stats': {
|
|
@@ -116,6 +116,20 @@ const mockMenus: MockMenuItem[] = [
|
|
|
116
116
|
adminOnly: true,
|
|
117
117
|
children: [],
|
|
118
118
|
},
|
|
119
|
+
{
|
|
120
|
+
id: 9,
|
|
121
|
+
name: '小组管理',
|
|
122
|
+
nameEn: 'Group Management',
|
|
123
|
+
nameKey: 'cs_web_menu_group_management',
|
|
124
|
+
type: 'page',
|
|
125
|
+
path: '/group-management',
|
|
126
|
+
icon: 'Group',
|
|
127
|
+
enabled: true,
|
|
128
|
+
sortOrder: 4,
|
|
129
|
+
pageId: 125,
|
|
130
|
+
adminOnly: true,
|
|
131
|
+
children: [],
|
|
132
|
+
}
|
|
119
133
|
];
|
|
120
134
|
|
|
121
135
|
export default mockMenus;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - id: 页面唯一标识
|
|
7
7
|
* - name: 页面名称
|
|
8
8
|
* - route: 路由路径
|
|
9
|
+
* - base: 微应用挂载前缀(可与 route 不同)
|
|
9
10
|
* - htmlUrl: 微应用 HTML 入口 URL
|
|
10
11
|
* - jsUrls: 额外 JS 资源
|
|
11
12
|
* - cssUrls: 额外 CSS 资源
|
|
@@ -25,12 +26,12 @@ const mockPages: PublicPageItem[] = [
|
|
|
25
26
|
{
|
|
26
27
|
id: 125,
|
|
27
28
|
name: '登录页',
|
|
28
|
-
nameEn: 'Login',
|
|
29
|
-
nameKey: 'page.user.login',
|
|
30
29
|
route: '/user/login',
|
|
31
30
|
base: '/user/login',
|
|
31
|
+
// htmlUrl:
|
|
32
|
+
// 'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.2/login/index.html',
|
|
32
33
|
htmlUrl:
|
|
33
|
-
'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.
|
|
34
|
+
'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.9/login/index.html',
|
|
34
35
|
jsUrls: [],
|
|
35
36
|
cssUrls: [],
|
|
36
37
|
prefixPath: '/user',
|
|
@@ -45,12 +46,32 @@ const mockPages: PublicPageItem[] = [
|
|
|
45
46
|
{
|
|
46
47
|
id: 124,
|
|
47
48
|
name: '权限管理',
|
|
48
|
-
nameEn: 'Permission Management',
|
|
49
|
-
nameKey: 'page.permission',
|
|
50
49
|
route: '/permission',
|
|
51
50
|
base: '/',
|
|
51
|
+
// htmlUrl:
|
|
52
|
+
// 'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.3/permission/index.html',
|
|
52
53
|
htmlUrl:
|
|
53
|
-
'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.
|
|
54
|
+
'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.9/permission/index.html',
|
|
55
|
+
jsUrls: [],
|
|
56
|
+
cssUrls: [],
|
|
57
|
+
prefixPath: '',
|
|
58
|
+
routeMode: 'prefix',
|
|
59
|
+
enabled: true,
|
|
60
|
+
accessControlEnabled: true,
|
|
61
|
+
adminOnly: true,
|
|
62
|
+
routeKey: null,
|
|
63
|
+
mainDocumentId: 59,
|
|
64
|
+
version: 'v2026.02.26-04.13-419',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 125,
|
|
68
|
+
name: '小组管理',
|
|
69
|
+
route: '/group-management',
|
|
70
|
+
base: '/',
|
|
71
|
+
// htmlUrl:
|
|
72
|
+
// 'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.3/permission/index.html',
|
|
73
|
+
htmlUrl:
|
|
74
|
+
'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.9/group-management/index.html',
|
|
54
75
|
jsUrls: [],
|
|
55
76
|
cssUrls: [],
|
|
56
77
|
prefixPath: '',
|
|
@@ -65,8 +86,6 @@ const mockPages: PublicPageItem[] = [
|
|
|
65
86
|
{
|
|
66
87
|
id: 115,
|
|
67
88
|
name: '兜底',
|
|
68
|
-
nameEn: 'Fallback',
|
|
69
|
-
nameKey: 'page.fallback',
|
|
70
89
|
route: '/*',
|
|
71
90
|
base: '/',
|
|
72
91
|
htmlUrl: '',
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
"test": "cross-env UMI_ENV=test max dev"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"<%= packageScope %>/common-intl": "workspace:*",
|
|
26
|
+
"<%= packageScope %>/shared": "workspace:*",
|
|
25
27
|
"@mico-platform/ui": "<%= micoUiVersion %>",
|
|
26
28
|
"@mico-platform/theme": "<%= themeVersion %>",
|
|
27
29
|
"@umijs/max": "^4.6.15",
|
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import { history, type RequestConfig } from '@umijs/max';
|
|
2
2
|
import { addGlobalUncaughtErrorHandler } from 'qiankun';
|
|
3
|
+
import * as CommonWebSentry from '@common-web/sentry';
|
|
3
4
|
import { SentryErrorBoundary } from '@common-web/sentry';
|
|
4
5
|
import { errorConfig } from './requestErrorConfig';
|
|
5
6
|
// 将 @mico-platform/ui 暴露到 window,供子应用 externals 使用
|
|
6
7
|
import * as micoUI from '@mico-platform/ui';
|
|
8
|
+
import dayjs from 'dayjs';
|
|
7
9
|
import React from 'react';
|
|
8
10
|
import ReactDOM from 'react-dom';
|
|
9
11
|
|
|
12
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
13
|
+
import dayjsTimezone from 'dayjs/plugin/timezone';
|
|
14
|
+
import dayjsUtc from 'dayjs/plugin/utc';
|
|
15
|
+
import { request as commonRequest } from './common/request';
|
|
16
|
+
import { configureRequest } from '<%= packageScope %>/shared/services';
|
|
17
|
+
import { configureTimezone } from '<%= packageScope %>/shared/timezone';
|
|
18
|
+
import { getTimezone } from '@/common/helpers';
|
|
19
|
+
import {
|
|
20
|
+
configureLocale,
|
|
21
|
+
fetchMultilingualData,
|
|
22
|
+
type ILang,
|
|
23
|
+
} from '<%= packageScope %>/common-intl';
|
|
24
|
+
import * as CommonIntl from '<%= packageScope %>/common-intl';
|
|
10
25
|
import { getStoredAuthToken } from './common/auth/auth-manager';
|
|
11
26
|
import type { IUserInfo } from './common/auth/type';
|
|
12
27
|
import { fetchUserInfo } from './services/user';
|
|
@@ -23,10 +38,32 @@ import {
|
|
|
23
38
|
} from './common/request/sso';
|
|
24
39
|
import { initTheme } from './common/theme';
|
|
25
40
|
import MicroAppLoader from './components/MicroAppLoader';
|
|
41
|
+
import { isCommonIntlEnabled } from '@/common/intl';
|
|
26
42
|
import { isNoAuthRoute } from '@/constants';
|
|
27
|
-
import { getCurrentLocale } from '@/common/locale';
|
|
28
43
|
import '@mico-platform/theme/dist/css/theme.css';
|
|
29
44
|
import './global.less';
|
|
45
|
+
import { getCurrentLocale, setLocaleToStorage } from './common/locale';
|
|
46
|
+
import { ilangToUmiLocale, umiLocaleToILang } from '@/common/intl/localeMapping';
|
|
47
|
+
|
|
48
|
+
// 主应用:将统一 request 注入 shared 包,供共享服务层(getRequest)使用
|
|
49
|
+
// 注意:模块顶层注入,确保任何业务调用 getRequest() 之前已就绪
|
|
50
|
+
configureRequest(commonRequest as <T = unknown>(url: string, options?: Record<string, unknown>) => Promise<T>);
|
|
51
|
+
|
|
52
|
+
// 主应用:扩展 dayjs 插件并注入「当前 IANA 时区」获取器,供 shared/timezone 使用
|
|
53
|
+
// 说明:apps/layout/src/common/helpers.ts 已扩展 utc/timezone,此处再补 customParseFormat(shared/timezone 的 parseDateInTimezone 需要它)
|
|
54
|
+
// dayjs.extend 内部去重,重复调用安全
|
|
55
|
+
dayjs.extend(dayjsUtc);
|
|
56
|
+
dayjs.extend(dayjsTimezone);
|
|
57
|
+
dayjs.extend(customParseFormat);
|
|
58
|
+
configureTimezone({ getTimezone });
|
|
59
|
+
|
|
60
|
+
// 主应用:common-intl initIntl 的 getLocale/setLocale 与 Umi `umi_locale` 单一数据源对齐(见 packages/common-intl configureLocale)
|
|
61
|
+
configureLocale({
|
|
62
|
+
getLocale: () => umiLocaleToILang(getCurrentLocale()),
|
|
63
|
+
setLocale: (lang: ILang) => {
|
|
64
|
+
setLocaleToStorage(ilangToUmiLocale(lang));
|
|
65
|
+
},
|
|
66
|
+
});
|
|
30
67
|
|
|
31
68
|
// ==================== qiankun 全局错误处理 ====================
|
|
32
69
|
// 捕获子应用运行时未捕获的异常,防止页面崩溃
|
|
@@ -80,16 +117,33 @@ if (typeof window !== 'undefined') {
|
|
|
80
117
|
// 注意:这里不阻止错误冒泡,让控制台仍能显示原始错误
|
|
81
118
|
// 如果需要阻止,可以 return true
|
|
82
119
|
});
|
|
120
|
+
|
|
121
|
+
// 注入构建信息
|
|
122
|
+
if (typeof window !== 'undefined') {
|
|
123
|
+
window.__MICO_BUILD__ = {
|
|
124
|
+
branchOrTag: process.env.BRANCH_OR_TAG,
|
|
125
|
+
gitCommit: process.env.GIT_COMMIT,
|
|
126
|
+
version: process.env.VERSION,
|
|
127
|
+
buildTime: dayjs(process.env.BUILD_TIME).format('YYYY-MM-DD HH:mm:ss'),
|
|
128
|
+
buildNumber: process.env.BUILD_NUMBER,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
83
131
|
}
|
|
84
132
|
|
|
85
133
|
// ==================== 微前端共享依赖 ====================
|
|
86
134
|
// 将公共库暴露到 window,供子应用复用,避免重复打包
|
|
87
135
|
// 子应用通过 externals 配置引用这些全局变量
|
|
88
|
-
if (typeof window !== 'undefined') {
|
|
136
|
+
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
|
|
89
137
|
const win = window as unknown as Record<string, unknown>;
|
|
90
138
|
win.React = React;
|
|
91
139
|
win.ReactDOM = ReactDOM;
|
|
140
|
+
win.CommonWebSentry = CommonWebSentry;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (typeof window !== 'undefined') {
|
|
144
|
+
const win = window as unknown as Record<string, unknown>;
|
|
92
145
|
win.micoUI = micoUI;
|
|
146
|
+
win.CommonIntl = CommonIntl;
|
|
93
147
|
}
|
|
94
148
|
|
|
95
149
|
// 初始化主题(在页面加载时立即执行,避免闪烁)
|
|
@@ -107,6 +161,33 @@ export const locale = {
|
|
|
107
161
|
},
|
|
108
162
|
};
|
|
109
163
|
|
|
164
|
+
// ==================== 国际化数据预加载 ====================
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 配置了有效 `__MICO_CONFIG__.commonIntl` 时首屏拉取中台文案;失败仍继续渲染。
|
|
168
|
+
* @see generators/micro-react/templates/packages/common-intl/README.md
|
|
169
|
+
*/
|
|
170
|
+
export function render(oldRender: () => void): void {
|
|
171
|
+
if (!isCommonIntlEnabled()) {
|
|
172
|
+
oldRender();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
fetchMultilingualData({
|
|
176
|
+
requestInstance: commonRequest,
|
|
177
|
+
messageInstance: {
|
|
178
|
+
error: micoUI.Message.error,
|
|
179
|
+
warning: micoUI.Message.warning,
|
|
180
|
+
},
|
|
181
|
+
lang: umiLocaleToILang(getCurrentLocale()) as ILang,
|
|
182
|
+
localeRequestUrl: process.env.LOCALE_REQUEST_URL,
|
|
183
|
+
})
|
|
184
|
+
.then(oldRender)
|
|
185
|
+
.catch((error: Error) => {
|
|
186
|
+
console.error('获取多语言文案失败', error);
|
|
187
|
+
oldRender();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
110
191
|
/**
|
|
111
192
|
* @see https://umijs.org/docs/api/runtime-config#getinitialstate
|
|
112
193
|
*/
|
|
@@ -137,8 +218,8 @@ export async function getInitialState(): Promise<{
|
|
|
137
218
|
await ensureSsoSession();
|
|
138
219
|
}
|
|
139
220
|
|
|
140
|
-
// 有 token
|
|
141
|
-
//
|
|
221
|
+
// 有 token 就获取用户信息(登录后 refresh、免认证页同样需要 currentUser:
|
|
222
|
+
// 如 PermissionFilter / MicroAppLoader 注入子应用的 button_perms)
|
|
142
223
|
if (getStoredAuthToken() && !skipAuth) {
|
|
143
224
|
const userInfo = await fetchUserInfoFn();
|
|
144
225
|
if (userInfo) {
|
|
@@ -2,12 +2,15 @@ import { authLogger } from '@/common/logger';
|
|
|
2
2
|
import { checkStaffAuth } from '@/services/auth';
|
|
3
3
|
import { handleAuthFailureRedirect } from '../request';
|
|
4
4
|
import { clearStoredTokens, getAuthInfo } from './auth-manager';
|
|
5
|
+
import { clearStoredTenantCode } from './tenant';
|
|
5
6
|
|
|
6
7
|
// 导出 STORAGE_KEYS 常量
|
|
7
8
|
export { STORAGE_KEYS } from '../../constants';
|
|
8
9
|
|
|
9
10
|
export function logout(): void {
|
|
10
11
|
clearStoredTokens();
|
|
12
|
+
// 清理当前租户,避免切换账号后残留
|
|
13
|
+
clearStoredTenantCode();
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
/**
|