generator-mico-cli 0.2.1 → 0.2.2-8.beta.1

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 (159) hide show
  1. package/README.md +199 -15
  2. package/bin/mico.js +232 -27
  3. package/generators/micro-react/index.js +200 -18
  4. package/generators/micro-react/meta.json +13 -0
  5. package/generators/micro-react/templates/.commitlintrc.js +1 -0
  6. package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +14 -4
  7. package/generators/micro-react/templates/.cursor/rules/cicd-deploy.mdc +10 -8
  8. package/generators/micro-react/templates/.cursor/rules/coding-conventions.mdc +1 -1
  9. package/generators/micro-react/templates/.cursor/rules/development-guide.mdc +3 -4
  10. package/generators/micro-react/templates/.cursor/rules/layout-app.mdc +38 -31
  11. package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +7 -4
  12. package/generators/micro-react/templates/.cursor/rules/theme-system.mdc +10 -12
  13. package/generators/micro-react/templates/.eslintrc.js +25 -1
  14. package/generators/micro-react/templates/AGENTS.md +5 -2
  15. package/generators/micro-react/templates/CICD/before_build.sh +76 -0
  16. package/generators/micro-react/templates/CICD/start_dev.sh +27 -3
  17. package/generators/micro-react/templates/CICD/start_prod.sh +26 -3
  18. package/generators/micro-react/templates/CICD/start_test.sh +28 -3
  19. package/generators/micro-react/templates/CICD/wangsu_fresh_dev.sh +4 -4
  20. package/generators/micro-react/templates/CICD/wangsu_fresh_prod.sh +4 -4
  21. package/generators/micro-react/templates/CICD/wangsu_fresh_test.sh +4 -4
  22. package/generators/micro-react/templates/CLAUDE.md +16 -9
  23. package/generators/micro-react/templates/README.md +42 -4
  24. package/generators/micro-react/templates/_gitignore +4 -0
  25. package/generators/micro-react/templates/_npmrc +4 -0
  26. package/generators/micro-react/templates/apps/layout/config/config.dev.ts +32 -16
  27. package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +24 -29
  28. package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +25 -6
  29. package/generators/micro-react/templates/apps/layout/config/config.prod.ts +16 -7
  30. package/generators/micro-react/templates/apps/layout/config/config.ts +27 -4
  31. package/generators/micro-react/templates/apps/layout/config/routes.ts +5 -5
  32. package/generators/micro-react/templates/apps/layout/docs/arch-/346/227/245/345/277/227/344/270/216/345/270/270/351/207/217.md +2 -2
  33. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +372 -0
  34. package/generators/micro-react/templates/apps/layout/docs/feat-/346/236/204/345/273/272define/344/270/216/345/205/215/350/256/244/350/257/201/345/210/235/345/247/213/346/200/201.md +44 -0
  35. package/generators/micro-react/templates/apps/layout/docs/feature-404/351/241/265/351/235/242.md +103 -0
  36. package/generators/micro-react/templates/apps/layout/docs/feature-/344/270/273/351/242/230/350/211/262/345/210/207/346/215/242.md +22 -26
  37. 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 +185 -28
  38. 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 +308 -63
  39. 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 +179 -0
  40. package/generators/micro-react/templates/apps/layout/docs/fix-SSO/346/227/240/351/231/220/351/207/215/345/256/232/345/220/221.md +88 -0
  41. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +324 -0
  42. package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +81 -61
  43. package/generators/micro-react/templates/apps/layout/mock/menus.ts +114 -4
  44. package/generators/micro-react/templates/apps/layout/mock/pages.ts +86 -0
  45. package/generators/micro-react/templates/apps/layout/package.json +7 -4
  46. package/generators/micro-react/templates/apps/layout/src/app.tsx +111 -76
  47. package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
  48. package/generators/micro-react/templates/apps/layout/src/common/helpers.ts +177 -0
  49. package/generators/micro-react/templates/apps/layout/src/common/locale.ts +22 -17
  50. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +192 -42
  51. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +69 -5
  52. package/generators/micro-react/templates/apps/layout/src/common/micro/index.ts +34 -0
  53. package/generators/micro-react/templates/apps/layout/src/common/micro-prefetch.ts +109 -0
  54. package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +45 -0
  55. package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +72 -10
  56. package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +2 -2
  57. package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +31 -3
  58. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +29 -11
  59. package/generators/micro-react/templates/apps/layout/src/common/request/url-resolver.ts +1 -1
  60. package/generators/micro-react/templates/apps/layout/src/common/route-guard.ts +345 -0
  61. package/generators/micro-react/templates/apps/layout/src/common/theme.ts +2 -4
  62. package/generators/micro-react/templates/apps/layout/src/common/upload/oss.ts +3 -4
  63. package/generators/micro-react/templates/apps/layout/src/common/upload/types.ts +1 -1
  64. package/generators/micro-react/templates/apps/layout/src/common/uploadFiles.ts +1 -1
  65. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +8 -3
  66. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +25 -8
  67. package/generators/micro-react/templates/apps/layout/src/components/HeaderDropdown/index.tsx +20 -0
  68. package/generators/micro-react/templates/apps/layout/src/components/IconFont/index.tsx +5 -6
  69. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.less +21 -6
  70. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +83 -149
  71. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/micro-app-manager.ts +569 -0
  72. package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +383 -0
  73. package/generators/micro-react/templates/apps/layout/src/components/RightContent/avatar-dropdown.less +35 -0
  74. package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +2 -0
  75. package/generators/micro-react/templates/apps/layout/src/constants/index.ts +170 -6
  76. package/generators/micro-react/templates/apps/layout/src/global.less +18 -9
  77. package/generators/micro-react/templates/apps/layout/src/hooks/useMenu.ts +3 -2
  78. package/generators/micro-react/templates/apps/layout/src/hooks/useRoutePermissionRefresh.ts +72 -0
  79. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +3 -1
  80. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +10 -55
  81. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +34 -4
  82. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +24 -8
  83. package/generators/micro-react/templates/apps/layout/src/layouts/index.less +84 -13
  84. package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +156 -69
  85. package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +12 -0
  86. package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +12 -0
  87. package/generators/micro-react/templates/apps/layout/src/pages/403/index.tsx +8 -2
  88. package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +78 -0
  89. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +3 -0
  90. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +7 -1
  91. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.less +1 -1
  92. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.tsx +3 -3
  93. package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +1 -1
  94. package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +63 -0
  95. package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +30 -0
  96. package/generators/micro-react/templates/apps/layout/src/services/user.ts +29 -2
  97. package/generators/micro-react/templates/apps/layout/tailwind.config.js +3 -0
  98. package/generators/micro-react/templates/deployDesc.md +3 -3
  99. package/generators/micro-react/templates/dev.preset.json +14 -0
  100. package/generators/micro-react/templates/docs/dev-preset.md +130 -0
  101. package/generators/micro-react/templates/package.json +21 -6
  102. package/generators/micro-react/templates/packages/common-intl/README.md +427 -0
  103. package/generators/micro-react/templates/packages/common-intl/package.json +34 -0
  104. package/generators/micro-react/templates/packages/common-intl/src/index.ts +7 -0
  105. package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +51 -0
  106. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +50 -0
  107. package/generators/micro-react/templates/packages/common-intl/src/utils.ts +482 -0
  108. package/generators/micro-react/templates/packages/common-intl/tsconfig.json +22 -0
  109. package/generators/micro-react/templates/packages/common-intl/vite.config.ts +25 -0
  110. package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +45 -0
  111. package/generators/micro-react/templates/scripts/collect-dist.js +10 -0
  112. package/generators/micro-react/templates/scripts/dev-preset.js +265 -0
  113. package/generators/micro-react/templates/scripts/dev-preset.schema.json +39 -0
  114. package/generators/micro-react/templates/turbo.json +4 -1
  115. package/generators/subapp-react/index.js +326 -40
  116. package/generators/subapp-react/meta.json +10 -0
  117. package/generators/subapp-react/templates/homepage/.env +2 -1
  118. package/generators/subapp-react/templates/homepage/README.md +3 -3
  119. package/generators/subapp-react/templates/homepage/config/config.dev.ts +14 -7
  120. package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +16 -5
  121. package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +16 -5
  122. package/generators/subapp-react/templates/homepage/config/config.prod.ts +14 -5
  123. package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
  124. package/generators/subapp-react/templates/homepage/config/routes.ts +2 -2
  125. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  126. package/generators/subapp-react/templates/homepage/package.json +7 -4
  127. package/generators/subapp-react/templates/homepage/src/app.tsx +18 -27
  128. package/generators/subapp-react/templates/homepage/src/common/request.ts +29 -2
  129. package/generators/subapp-react/templates/homepage/src/global.less +6 -5
  130. package/generators/subapp-react/templates/homepage/src/pages/index.less +3 -3
  131. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +99 -60
  132. package/generators/subapp-react/templates/homepage/src/styles/theme.less +1 -1
  133. package/generators/subapp-umd/ignore-list.json +5 -0
  134. package/generators/subapp-umd/index.js +309 -0
  135. package/generators/subapp-umd/meta.json +11 -0
  136. package/generators/subapp-umd/templates/README.md +94 -0
  137. package/generators/subapp-umd/templates/package.json +35 -0
  138. package/generators/subapp-umd/templates/public/index.html +34 -0
  139. package/generators/subapp-umd/templates/src/App.less +15 -0
  140. package/generators/subapp-umd/templates/src/App.tsx +13 -0
  141. package/generators/subapp-umd/templates/src/index.ts +2 -0
  142. package/generators/subapp-umd/templates/tsconfig.json +27 -0
  143. package/generators/subapp-umd/templates/webpack.config.js +70 -0
  144. package/lib/utils.js +332 -2
  145. package/package.json +15 -2
  146. package/generators/micro-react/templates/apps/layout/mock/menus.json +0 -100
  147. package/generators/micro-react/templates/apps/layout/src/common/constants.ts +0 -38
  148. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/container-manager.ts +0 -202
  149. package/generators/micro-react/templates/packages/shared-styles/README.md +0 -124
  150. package/generators/micro-react/templates/packages/shared-styles/arco-design-mobile-override.less +0 -91
  151. package/generators/micro-react/templates/packages/shared-styles/arco-override.less +0 -119
  152. package/generators/micro-react/templates/packages/shared-styles/index.d.ts +0 -44
  153. package/generators/micro-react/templates/packages/shared-styles/index.less +0 -13
  154. package/generators/micro-react/templates/packages/shared-styles/package.json +0 -30
  155. package/generators/micro-react/templates/packages/shared-styles/theme-inject.less +0 -10
  156. package/generators/micro-react/templates/packages/shared-styles/themes/dark/custom-var.less +0 -290
  157. package/generators/micro-react/templates/packages/shared-styles/themes/normal/custom-var.less +0 -269
  158. package/generators/micro-react/templates/packages/shared-styles/variables-only.less +0 -433
  159. package/generators/micro-react/templates/packages/shared-styles/variables.less +0 -452
@@ -0,0 +1,44 @@
1
+ # 构建 define 精简与免认证页初始态
2
+
3
+ > 创建时间:2026-03-24
4
+
5
+ ## 功能概述
6
+
7
+ 1. **Umi `define`**:不再通过构建期注入 `process.env.EXTERNAL_LOGIN_PATH`(本模板从未注入 `APP_ID`);SSO 外跳等依赖运行时 `window.__MICO_CONFIG__`。
8
+ 2. **`getInitialState`**:免认证路由下即使本地仍有 token,也不请求用户信息接口,减少无效调用。
9
+
10
+ ## 技术方案
11
+
12
+ ### 开发环境
13
+
14
+ `config/config.dev.ts` 的 `headScripts` 中 `window.__MICO_CONFIG__` 增加 **`externalLoginPath`**(模板默认为占位 URL,生成项目后请按实际 IdP 修改)。
15
+
16
+ `define` 仅保留 `NODE_ENV`、`API_BASE_URL`、`LOGIN_ENDPOINT`、`REFRESH_ENDPOINT`。
17
+
18
+ ### 生产 / 测试构建
19
+
20
+ `config.prod.ts`、`config.prod.development.ts`、`config.prod.testing.ts` 的 `define` 中同样**不包含** `EXTERNAL_LOGIN_PATH`,由部署时注入的 `__MICO_CONFIG__.externalLoginPath`(或 `__MICO_WORKSPACE__.casServerLoginUrl`)提供。
21
+
22
+ ### 初始态
23
+
24
+ `src/app.tsx` 中仅在 `getStoredAuthToken() && !skipAuth` 时调用 `fetchUserInfoFn()`;`skipAuth = isNoAuthRoute || isPageAuthFree`。
25
+
26
+ ## 文件清单
27
+
28
+ | 文件路径 | 说明 |
29
+ | --- | --- |
30
+ | `config/config.dev.ts` | `__MICO_CONFIG__.externalLoginPath`;移除 `EXTERNAL_LOGIN_PATH` define |
31
+ | `config/config.prod.ts` | 移除 `EXTERNAL_LOGIN_PATH` define |
32
+ | `config/config.prod.development.ts` | 同上 |
33
+ | `config/config.prod.testing.ts` | 同上 |
34
+ | `src/app.tsx` | `fetchUserInfo` 条件增加 `!skipAuth` |
35
+
36
+ ## 部署注意
37
+
38
+ - 生产 HTML 或网关需保证 `window.__MICO_CONFIG__` 含 **`appId`**、**`externalLoginPath`**(或与现有网关字段对齐),否则代理前缀、SSO 外跳可能异常。
39
+ - 详见 `src/common/request/config.ts` 中 `buildDefaultClientOptions` 的解析顺序。
40
+
41
+ ## 相关文档
42
+
43
+ - [fix-SSO无限重定向](./fix-SSO无限重定向.md)
44
+ - [arch-请求模块](./arch-请求模块.md)
@@ -0,0 +1,103 @@
1
+ # 404 页面
2
+
3
+ > 创建时间:2025-01-27
4
+
5
+ ## 功能概述
6
+
7
+ 当用户访问不存在的路由时,展示 404 页面并提供导航选项,支持返回上页或跳转至第一个有权限访问的路由。
8
+
9
+ ## 技术方案
10
+
11
+ ### 技术栈
12
+
13
+ - 框架:React 18 + @umijs/max
14
+ - UI 组件:@mico-platform/ui `Result`、`Button`、`Space`
15
+ - 路由:React Router 6 通配符路由
16
+
17
+ ### 核心实现
18
+
19
+ 1. 使用 Umi 路由通配符 `/*` 捕获所有未匹配的路径
20
+ 2. 复用 403 页面的布局风格,保持 UI 一致性
21
+ 3. 动态计算第一个可访问路由:从菜单数据中提取路由,根据用户权限过滤后返回首个有效路径
22
+
23
+ ## 文件清单
24
+
25
+ ### 新增文件
26
+
27
+ | 文件路径 | 说明 |
28
+ | --- | --- |
29
+ | `src/pages/404/index.tsx` | 404 页面组件 |
30
+
31
+ ### 修改文件
32
+
33
+ | 文件路径 | 修改内容 |
34
+ | --- | --- |
35
+ | `config/routes.ts` | 添加通配符路由 `/*` |
36
+
37
+ ## API / 组件接口
38
+
39
+ ### NotFoundPage
40
+
41
+ 无外部 Props,使用 Umi 全局状态获取用户信息。
42
+
43
+ ### getFirstAvailablePath
44
+
45
+ ```typescript
46
+ /**
47
+ * 获取第一个可访问的路由路径
48
+ */
49
+ const getFirstAvailablePath = (filterOptions: MenuFilterOptions): string;
50
+ ```
51
+
52
+ **逻辑说明**:
53
+
54
+ 1. 从 `window.__MICO_MENUS__` 获取菜单数据
55
+ 2. 根据 `disableAuth` 配置决定是否过滤权限
56
+ 3. 调用 `filterMenuItems` 过滤无权限菜单
57
+ 4. 调用 `extractRoutes` 提取路由列表
58
+ 5. 返回第一个路由的 `path`,若无则返回 `/`
59
+
60
+ ## 路由配置
61
+
62
+ ```typescript
63
+ // config/routes.ts
64
+ {
65
+ path: '/*',
66
+ component: './404',
67
+ name: '页面不存在',
68
+ }
69
+ ```
70
+
71
+ 通配符路由放在路由配置末尾,匹配所有未被其他路由匹配的路径。
72
+
73
+ ## 使用示例
74
+
75
+ 用户访问 `/non-existent-page` 时:
76
+
77
+ 1. 路由系统无法匹配到具体路由
78
+ 2. 通配符路由 `/*` 生效
79
+ 3. 渲染 404 页面,显示两个按钮:
80
+ - **返回上页**:调用 `history.back()`
81
+ - **前往首页**:跳转至第一个有权限的路由
82
+
83
+ ## 设计决策
84
+
85
+ | 决策点 | 选择 | 理由 |
86
+ | --- | --- | --- |
87
+ | UI 组件 | @mico-platform/ui Result | 与 403 页面保持一致,复用现有组件库 |
88
+ | 首页跳转逻辑 | 动态获取第一个可访问路由 | 适应动态菜单配置,不硬编码路径 |
89
+ | 权限过滤 | 复用 filterMenuItems | 与菜单权限逻辑保持一致 |
90
+
91
+ ## 相关文件
92
+
93
+ | 文件 | 说明 |
94
+ | --- | --- |
95
+ | `src/pages/403/index.tsx` | 403 页面,UI 风格参考 |
96
+ | `src/common/menu/parser.ts` | 菜单解析工具函数 |
97
+ | `src/constants/index.ts` | `isAuthDisabled` 权限控制函数 |
98
+
99
+ ## 注意事项
100
+
101
+ - 通配符路由必须放在路由配置最后,否则会提前匹配
102
+ - 动态路由(从 `window.__MICO_MENUS__` 注入)的 404 场景由 `layouts/index.tsx` 处理
103
+ - 此 404 页面主要处理静态路由未匹配的情况
@@ -11,7 +11,7 @@ Layout 应用支持亮色/暗黑主题切换,通过 CSS 变量实现运行时
11
11
  ### 技术栈
12
12
 
13
13
  - 框架:React 18 + UmiJS 4
14
- - UI 组件:Arco Design
14
+ - UI 组件:@mico-platform/ui
15
15
  - 样式:Less + CSS Variables
16
16
  - 状态管理:React Hooks + localStorage
17
17
 
@@ -19,7 +19,7 @@ Layout 应用支持亮色/暗黑主题切换,通过 CSS 变量实现运行时
19
19
 
20
20
  采用双属性主题系统:
21
21
 
22
- 1. `arco-theme` 属性控制 Arco Design 组件主题
22
+ 1. `arco-theme` 属性控制 @mico-platform/ui 组件主题(基于 Arco)
23
23
  2. `data-theme` 属性控制自定义 CSS 变量
24
24
 
25
25
  两个属性都设置在 `body` 元素上,确保选择器正确匹配。Less 变量引用 CSS 变量,实现编译时类型安全和运行时动态切换。
@@ -28,22 +28,19 @@ Layout 应用支持亮色/暗黑主题切换,通过 CSS 变量实现运行时
28
28
 
29
29
  ### 主题系统核心文件
30
30
 
31
- 主题变量统一定义在 `packages/shared-styles/` 共享包中:
31
+ 主题变量由 `@mico-platform/theme` 包提供,主应用与子应用通过该包获取 CSS 变量与 Less 变量:
32
32
 
33
- | 文件路径 | 说明 |
34
- | ----------------------------------------------------- | ------------------------------ |
35
- | `packages/shared-styles/themes/normal/custom-var.less` | 亮色主题 CSS 变量定义 |
36
- | `packages/shared-styles/themes/dark/custom-var.less` | 暗黑主题 CSS 变量定义 |
37
- | `packages/shared-styles/arco-override.less` | Arco Design 变量覆盖映射 |
38
- | `packages/shared-styles/variables.less` | Less 变量定义(引用 CSS 变量) |
39
- | `packages/shared-styles/index.less` | 入口文件,导入全部(主应用用) |
40
- | `packages/shared-styles/variables-only.less` | 仅 Less 变量(子应用用) |
33
+ | 入口/子路径 | 说明 |
34
+ | ------------------------------ | ------------------------------ |
35
+ | `@mico-platform/theme` | 主入口,CSS 变量 + Less 变量 |
36
+ | `@mico-platform/theme/variables` | Less 变量(子应用用) |
37
+ | `@mico-platform/theme/theme-inject` | 子应用独立运行时注入主题 |
41
38
 
42
39
  ### Layout 应用文件
43
40
 
44
41
  | 文件路径 | 说明 |
45
42
  | ---------------------------- | ----------------------------------------- |
46
- | `src/global.less` | 导入 `<%= packageScope %>/shared-styles` 共享包 |
43
+ | `src/global.less` | 导入 `@mico-platform/theme` |
47
44
  | `src/common/theme.ts` | 主题切换逻辑(`applyTheme`、`initTheme`) |
48
45
  | `src/hooks/useTheme.ts` | 主题管理 Hook |
49
46
 
@@ -82,7 +79,7 @@ const { theme, isDark, toggleTheme, setTheme } = useTheme();
82
79
 
83
80
  ### 主要颜色变量
84
81
 
85
- > 完整变量列表请参考 [shared-styles 包文档](../../../packages/shared-styles/README.md#主要变量)
82
+ > 完整变量列表请参考 @mico-platform/theme 包文档
86
83
 
87
84
  | 分类 | 变量 |
88
85
  | ------ | --------------------------------------- |
@@ -129,7 +126,7 @@ const ThemeToggle: React.FC = () => {
129
126
  ### 常量定义
130
127
 
131
128
  ```typescript
132
- // src/common/constants.ts
129
+ // src/constants/index.ts
133
130
  export const THEME = {
134
131
  STORAGE_KEY: '<%= ProjectName %>-theme',
135
132
  DEFAULT: 'light' as const,
@@ -151,8 +148,8 @@ export const THEME = {
151
148
 
152
149
  ```less
153
150
  // apps/[子应用]/src/global.less
154
- @import '<%= packageScope %>/shared-styles/variables-only';
155
- // 不要使用 @import '<%= packageScope %>/shared-styles'(会包含 CSS 变量定义)
151
+ @import '@mico-platform/theme/variables';
152
+ // 主应用已注入 CSS 变量时,子应用仅需 Less 变量
156
153
  ```
157
154
 
158
155
  #### 2. app.tsx - 开发环境条件注入
@@ -195,24 +192,24 @@ wc -c apps/[子应用]/dist/umi.css
195
192
  # 期望:< 500 字节
196
193
  ```
197
194
 
198
- ### Arco Design 组件主题适配
195
+ ### @mico-platform/ui 组件主题适配
199
196
 
200
- 子应用使用 Arco Design 组件时,组件样式会自动跟随主应用的主题切换。
197
+ 子应用使用 @mico-platform/ui 组件时,组件样式会自动跟随主应用的主题切换。
201
198
 
202
199
  #### 原理
203
200
 
204
- 1. 主应用加载 Arco Design 并暴露到 `window.arco`
205
- 2. 主应用的 `arco.css` 包含 `arco-theme` 属性选择器
201
+ 1. 主应用加载 @mico-platform/ui 并暴露到 `window.micoUI`
202
+ 2. 主应用的样式包含 `arco-theme` 属性选择器(基于 Arco)
206
203
  3. 主应用切换主题时设置 `body[arco-theme="dark"]`
207
- 4. 子应用的 Arco 组件(来自 window.arco)自动应用暗色样式
204
+ 4. 子应用的 UI 组件(来自 window.micoUI)自动应用暗色样式
208
205
 
209
- #### 子应用使用 Arco Design
206
+ #### 子应用使用 @mico-platform/ui
210
207
 
211
208
  > 详细配置请参考 [微前端模式 - 依赖共享机制](./feature-微前端模式.md#依赖共享机制)
212
209
 
213
210
  ```tsx
214
- // 子应用可以直接使用 Arco Design 组件
215
- import { Button, Card, Message, Tag } from '@arco-design/web-react';
211
+ // 子应用可以直接使用 @mico-platform/ui 组件
212
+ import { Button, Card, Message, Tag } from '@mico-platform/ui';
216
213
 
217
214
  export default function Page() {
218
215
  return (
@@ -224,11 +221,10 @@ export default function Page() {
224
221
  }
225
222
  ```
226
223
 
227
- **注意**:子应用需要配置 `externals` 将 Arco Design 排除打包,详见 [微前端模式文档](./feature-微前端模式.md#依赖共享机制)。
224
+ **注意**:子应用需要配置 `externals` 将 @mico-platform/ui 排除打包,详见 [微前端模式文档](./feature-微前端模式.md#依赖共享机制)。
228
225
 
229
226
  ## 相关文档
230
227
 
231
228
  - [微前端模式](./feature-微前端模式.md) - qiankun 微前端架构与依赖共享
232
229
  - [日志与常量](./arch-日志与常量.md) - Logger 工具与常量管理(含 THEME 常量)
233
- - [shared-styles 包](../../../packages/shared-styles/README.md) - 共享样式包使用指南
234
230
  - [提交规范](../../../docs/commit-message.md) - Git Commit 规范
@@ -1,6 +1,7 @@
1
1
  # 微前端模式
2
2
 
3
3
  > 创建时间:2025-12-26
4
+ > 更新时间:2025-03-20(MicroAppLoader 增加 base 与 normalizeMicroAppBase)
4
5
 
5
6
  ## 功能概述
6
7
 
@@ -12,13 +13,13 @@
12
13
 
13
14
  - 框架:React 18 + @umijs/max
14
15
  - 微前端:qiankun (通过 @umijs/max 内置插件)
15
- - UI 组件:Arco Design
16
+ - UI 组件:@mico-platform/ui
16
17
  - 路由:React Router 6
17
18
 
18
19
  ### 核心实现
19
20
 
20
- 1. 主应用通过 `window.__MICO_MENUS__` 获取菜单配置
21
- 2. 解析菜单时根据 `htmlUrl` 或 `jsUrls` 判断是否为微应用
21
+ 1. 主应用优先通过 `window.__MICO_PAGES__` 获取页面配置,无数据时降级到 `window.__MICO_MENUS__`(详见 [路由与菜单解耦](./feature-路由与菜单解耦.md))
22
+ 2. 解析页面时根据 `htmlUrl` 或 `jsUrls` 判断是否为微应用
22
23
  3. 路由匹配时,微应用类型使用 `MicroAppLoader` 组件加载
23
24
  4. `MicroAppLoader` 使用 qiankun 的 `loadMicroApp` API 动态挂载子应用
24
25
  5. 组件卸载时自动调用 `unmount()` 清理子应用
@@ -27,14 +28,16 @@
27
28
 
28
29
  ### 核心文件
29
30
 
30
- | 文件路径 | 说明 |
31
- | ------------------------------------------ | -------------------------- |
32
- | `src/components/MicroAppLoader/index.tsx` | qiankun 微应用加载器组件 |
33
- | `src/components/MicroAppLoader/index.less` | 加载器样式 |
34
- | `src/common/menu/parser.ts` | 菜单解析,包含加载类型判断 |
35
- | `src/common/menu/types.ts` | 类型定义 |
36
- | `src/layouts/index.tsx` | 主布局,集成微应用渲染 |
37
- | `config/config.ts` | qiankun master 配置 |
31
+ | 文件路径 | 说明 |
32
+ | --- | --- |
33
+ | `src/components/MicroAppLoader/index.tsx` | qiankun 微应用加载器组件 |
34
+ | `src/components/MicroAppLoader/micro-app-manager.ts` | 微应用管理器(单例),稳定容器 + 实例缓存 + 操作序列号 |
35
+ | `src/components/MicroAppLoader/index.less` | 加载器样式 |
36
+ | `src/common/menu/parser.ts` | 菜单解析,包含加载类型判断 |
37
+ | `src/common/menu/types.ts` | 类型定义 |
38
+ | `src/layouts/index.tsx` | 主布局,集成微应用渲染 |
39
+ | `src/app.tsx` | qiankun 全局错误处理 |
40
+ | `config/config.ts` | qiankun master 配置 |
38
41
 
39
42
  ## API / 组件接口
40
43
 
@@ -42,6 +45,8 @@
42
45
 
43
46
  ```typescript
44
47
  interface MicroAppLoaderProps {
48
+ /** 微应用在主应用中的挂载路径前缀(来自 ParsedRoute.base / 页面配置 base),经 normalizeMicroAppBase 后传给子应用 */
49
+ base: string;
45
50
  /** 微应用入口 URL */
46
51
  entry: string;
47
52
  /** 微应用名称 */
@@ -57,17 +62,53 @@ interface MicroAppLoaderProps {
57
62
 
58
63
  | 参数 | 类型 | 必填 | 说明 |
59
64
  |------|------|------|------|
65
+ | base | string | 是 | 挂载路径前缀;经 `normalizeMicroAppBase` 后作为子应用 `props.base` |
60
66
  | entry | string | 是 | qiankun 入口 URL (htmlUrl 或 jsUrls[0]) |
61
67
  | name | string | 是 | 微应用唯一标识 |
62
68
  | displayName | string | 否 | 显示名称,用于加载提示 |
63
69
  | routePath | string | 否 | 当前路由路径,用于子应用内部路由切换 |
64
70
 
71
+ ### MicroAppLoader 路由与 base
72
+
73
+ 主应用为微应用补充 **挂载前缀 `base`**,便于子应用对齐 basename、publicPath、内部路由等与路径相关的逻辑;**是否与免鉴权配置做前缀匹配**以当前实现为准(见下「加载门控」)。
74
+
75
+ #### `base` 与 `routePath` 的区别
76
+
77
+ | 字段 | 含义 |
78
+ | --- | --- |
79
+ | **base** | 该微应用在主应用中的**挂载前缀**,来自中台 **`page.base`**,解析为 **`ParsedRoute.base`**(缺省时解析为 **`'/'`**);可与动态路由 **`path`** 不同(如 `path` 为 `/subapp/*` 时 `base` 可为 `/subapp`)。 |
80
+ | **routePath** | 当前激活的**完整路由路径**,随浏览器 URL 变化,用于通知子应用做**内部路由同步**。 |
81
+
82
+ `routePath` 在布局内为 **`currentRoute.path`**。`base` 在 **`patchClientRoutes`** 与布局内均为 **`route.base` / `currentRoute.base`**。**`name`** 在布局侧常为基于 **`entry`** 的 **`getAppNameFromEntry`**,与 **`base`** 来源不同,需注意。
83
+
84
+ #### `normalizeMicroAppBase`
85
+
86
+ 组件内导出工具函数(见 `MicroAppLoader/index.tsx`):
87
+
88
+ ```typescript
89
+ export const normalizeMicroAppBase = (path: string): string =>
90
+ path.replace(/\/+$/, '').replace(/\*+$/, '');
91
+ ```
92
+
93
+ 含义:先去掉末尾 `/`,再去掉末尾 `*`(兼容路由表中的 `/foo/*` 等写法)。**传给子应用的 `props.base` 为规范化后的字符串**。
94
+
95
+ #### 调用处传参
96
+
97
+ | 位置 | 说明 |
98
+ | --- | --- |
99
+ | `src/app.tsx` `patchClientRoutes` | 动态注册微应用路由时:`React.createElement(MicroAppLoader, { entry, name: route.path, base: route.base, ... })` |
100
+ | `src/layouts/index.tsx` | 布局内渲染:`<MicroAppLoader base={currentRoute.base} routePath={currentRoute.path} ... />` |
101
+
102
+ #### 加载门控(认证)
103
+
104
+ 微应用开始执行 `switchTo` / 挂载前,需 **`isAuthReady`**(`isAuthDisabled`、`isPageAuthFree`、`isNoAuthRoute(location.pathname)`、`isNoPermissionRoute(location.pathname)` 或已存在 `currentUser` 等,见组件内实现)。**当前以浏览器 `location.pathname` 与全局常量为准**,未单独使用 `base` 与 `window.__MICO_CONFIG__.noAuthRouteList` 做前缀匹配。
105
+
65
106
  ### MicroAppProps (传递给子应用)
66
107
 
67
108
  ```typescript
68
109
  interface MicroAppProps {
69
110
  /** 主应用标识 */
70
- mainApp: 'portal-web';
111
+ mainApp: '<%= projectName %>';
71
112
  /** 运行环境 */
72
113
  env: 'development' | 'testing' | 'production';
73
114
  /** 认证 token */
@@ -84,6 +125,8 @@ interface MicroAppProps {
84
125
  timezone: string;
85
126
  /** 在线状态 */
86
127
  presenceStatus: string;
128
+ /** 挂载路径前缀(为 `normalizeMicroAppBase(MicroAppLoader.base)`) */
129
+ base: string;
87
130
  /** 当前路由路径 */
88
131
  routePath?: string;
89
132
  /** 共享的 request 实例,子应用可直接使用 */
@@ -122,6 +165,8 @@ export async function update(props: MicroAppProps) {
122
165
  ```typescript
123
166
  interface ParsedRoute {
124
167
  path: string;
168
+ /** 微应用挂载前缀(来自 page.base,解析缺省为 '/') */
169
+ base: string;
125
170
  name: string;
126
171
  icon: string;
127
172
  /** 加载类型: internal(内部路由) | microapp(qiankun微应用) */
@@ -139,6 +184,8 @@ interface PageConfig {
139
184
  id: number;
140
185
  name: string;
141
186
  route: string;
187
+ /** 微应用挂载前缀(可与 route 不同) */
188
+ base: string;
142
189
  enabled: boolean;
143
190
  /** 微应用 HTML 入口 URL (优先使用) */
144
191
  htmlUrl: string | null;
@@ -208,7 +255,12 @@ const menus: MenuItem[] = [
208
255
  const renderContent = () => {
209
256
  if (currentRoute?.loadType === 'microapp' && currentRoute.entry) {
210
257
  return (
211
- <MicroAppLoader entry={currentRoute.entry} name={currentRoute.name} />
258
+ <MicroAppLoader
259
+ entry={currentRoute.entry}
260
+ name={currentRoute.name}
261
+ base={currentRoute.base}
262
+ routePath={currentRoute.path}
263
+ />
212
264
  );
213
265
  }
214
266
  return <Outlet />;
@@ -253,9 +305,9 @@ export const getRequest = () => mainAppProps?.request;
253
305
 
254
306
  ### 问题背景
255
307
 
256
- 如果子应用直接安装 React、Arco Design 等大型库,会导致:
308
+ 如果子应用直接安装 React、@mico-platform/ui 等大型库,会导致:
257
309
 
258
- 1. **包体积重复**:React (~140KB) + Arco Design (~800KB) 被打包多次
310
+ 1. **包体积重复**:React (~140KB) + UI (~800KB) 被打包多次
259
311
  2. **样式冲突**:多份 CSS 可能互相覆盖
260
312
  3. **React 实例问题**:可能出现 "Invalid hook call" 错误
261
313
 
@@ -267,8 +319,8 @@ export const getRequest = () => mainAppProps?.request;
267
319
  ┌─────────────────────────────────────────────────────────────┐
268
320
  │ 主应用 (layout) │
269
321
  │ ┌─────────────────────────────────────────────────────────┐│
270
- │ │ 1. 打包并加载 React、ReactDOM、Arco Design ││
271
- │ │ 2. 暴露到 window.React / window.ReactDOM / window.arco ││
322
+ │ │ 1. 打包并加载 React、ReactDOM、@mico-platform/ui ││
323
+ │ │ 2. 暴露到 window.React / window.ReactDOM / window.micoUI ││
272
324
  │ └─────────────────────────────────────────────────────────┘│
273
325
  │ ↓ 共享 │
274
326
  │ ┌─────────────────────────────────────────────────────────┐│
@@ -286,7 +338,7 @@ export const getRequest = () => mainAppProps?.request;
286
338
 
287
339
  ```typescript
288
340
  // apps/layout/src/app.tsx
289
- import * as arco from '@arco-design/web-react';
341
+ import * as micoUI from '@mico-platform/ui';
290
342
  import React from 'react';
291
343
  import ReactDOM from 'react-dom';
292
344
 
@@ -294,7 +346,7 @@ import ReactDOM from 'react-dom';
294
346
  if (typeof window !== 'undefined') {
295
347
  (window as any).React = React;
296
348
  (window as any).ReactDOM = ReactDOM;
297
- (window as any).arco = arco;
349
+ (window as any).micoUI = micoUI;
298
350
  }
299
351
  ```
300
352
 
@@ -331,7 +383,7 @@ const config: ReturnType<typeof defineConfig> = {
331
383
  externals: {
332
384
  react: 'window.React',
333
385
  'react-dom': 'window.ReactDOM',
334
- '@arco-design/web-react': 'window.arco',
386
+ '@mico-platform/ui': 'window.micoUI',
335
387
  },
336
388
  };
337
389
 
@@ -359,23 +411,23 @@ export default defineConfig(config);
359
411
 
360
412
  #### 3. package.json - 开发依赖
361
413
 
362
- Arco Design 放在 `devDependencies`(用于类型提示和开发),生产环境从主应用获取:
414
+ @mico-platform/ui 放在 `devDependencies`(用于类型提示和开发),生产环境从主应用获取。版本由生成器在创建子应用时从 npm 解析为当时最新版本(不使用 `latest` 标签):
363
415
 
364
416
  ```json
365
417
  {
366
418
  "devDependencies": {
367
- "@arco-design/web-react": "^2.66.6"
419
+ "@mico-platform/ui": "^x.x.x"
368
420
  }
369
421
  }
370
422
  ```
371
423
 
372
- ### 子应用使用 Arco Design
424
+ ### 子应用使用 @mico-platform/ui
373
425
 
374
- 配置完成后,子应用可以正常导入和使用 Arco Design 组件:
426
+ 配置完成后,子应用可以正常导入和使用 UI 组件:
375
427
 
376
428
  ```tsx
377
429
  // apps/[子应用]/src/pages/index.tsx
378
- import { Button, Card, Message, Tag } from '@arco-design/web-react';
430
+ import { Button, Card, Message, Tag } from '@mico-platform/ui';
379
431
 
380
432
  export default function HomePage() {
381
433
  return (
@@ -393,7 +445,7 @@ export default function HomePage() {
393
445
 
394
446
  | 配置方式 | 子应用 JS 体积 | 说明 |
395
447
  | ------------------ | -------------- | ------------------------ |
396
- | 直接安装依赖 | ~1.2MB | 包含 React + Arco Design |
448
+ | 直接安装依赖 | ~1.2MB | 包含 React + @mico-platform/ui |
397
449
  | **externals 共享** | **~50KB** | 仅业务代码 |
398
450
 
399
451
  ### 运行环境说明
@@ -414,14 +466,15 @@ export default function HomePage() {
414
466
  - 组件会在 `entry` 或 `name` 变化时重新加载微应用
415
467
  - 加载失败会显示错误信息,便于调试
416
468
  - **子应用应使用主应用传递的 `request` 实例**,确保认证 token 和拦截器一致
417
- - **子应用使用 externals 共享依赖**,避免重复打包 React 和 Arco Design
469
+ - **子应用使用 externals 共享依赖**,避免重复打包 React 和 @mico-platform/ui
418
470
 
419
471
  ## 相关文档
420
472
 
473
+ - [路由与菜单解耦](./feature-路由与菜单解耦.md) - 路由注册与菜单导航数据源分离
474
+ - [菜单权限控制](./feature-菜单权限控制.md) - sideMenus 白名单权限逻辑
421
475
  - [主题色切换](./feature-主题色切换.md) - 主题系统实现与子应用适配
422
476
  - [请求模块架构](./arch-请求模块.md) - HTTP 请求层模块化设计
423
477
  - [日志与常量](./arch-日志与常量.md) - Logger 工具与常量管理
424
- - [shared-styles 包](../../../packages/shared-styles/README.md) - 共享样式包使用指南
425
478
  - [提交规范](../../../docs/commit-message.md) - Git Commit 规范
426
479
 
427
480
  ## 加载类型判断逻辑
@@ -430,3 +483,107 @@ export default function HomePage() {
430
483
  有 htmlUrl 或 jsUrls → microapp (使用 qiankun 加载)
431
484
  无 htmlUrl 且无 jsUrls → internal (使用 Outlet 渲染)
432
485
  ```
486
+
487
+ ## 加载健壮性机制
488
+
489
+ > 更新于 2025-01-25
490
+
491
+ ### 解决的问题
492
+
493
+ | 原问题 | 风险 | 修复方案 |
494
+ |--------|------|----------|
495
+ | 无全局错误处理,子应用异常可能导致页面崩溃 | 高 | 添加 `addGlobalUncaughtErrorHandler` |
496
+ | unmount 使用 rAF 时序不可靠 | 高 | 使用 `queueMicrotask` |
497
+ | 同名应用并发加载可能冲突 | 高 | 会话 ID 锁 + `waitForUnmount` |
498
+ | unmount 可能永久卡死 | 中 | 10 秒超时机制 |
499
+ | 加载期间 Props 变化被跳过 | 中 | 加载完成后重新同步 Props |
500
+
501
+ ### 全局错误处理
502
+
503
+ 在 `src/app.tsx` 中注册 qiankun 全局错误处理器,捕获子应用运行时未捕获的异常:
504
+
505
+ ```typescript
506
+ import { addGlobalUncaughtErrorHandler } from 'qiankun';
507
+
508
+ addGlobalUncaughtErrorHandler((event: Event | string) => {
509
+ // 捕获子应用 JS 运行时错误
510
+ // 捕获子应用生命周期钩子异常
511
+ // 捕获资源加载失败
512
+ console.error('[qiankun] Global uncaught error:', event);
513
+ });
514
+ ```
515
+
516
+ ### MicroAppManager API (micro-app-manager.ts)
517
+
518
+ `MicroAppManager` 是单例类,管理微应用的加载、缓存、切换和卸载:
519
+
520
+ ```typescript
521
+ interface MicroAppConfig {
522
+ name: string;
523
+ entry: string;
524
+ target: HTMLElement; // 目标挂载位置
525
+ props: Record<string, unknown>;
526
+ }
527
+
528
+ interface MicroAppState {
529
+ loading: boolean;
530
+ error: string | null;
531
+ mounted: boolean;
532
+ }
533
+
534
+ const manager = microAppManager; // 单例,导出即用
535
+
536
+ /** 切换到指定微应用(已挂载则仅更新 props) */
537
+ manager.switchTo(config: MicroAppConfig): void;
538
+
539
+ /** 更新当前已挂载微应用的 props */
540
+ manager.updateProps(props: Record<string, unknown>): void;
541
+
542
+ /** 取消待处理的请求 */
543
+ manager.cancel(): void;
544
+
545
+ /** 清除所有缓存实例 */
546
+ manager.clearCache(): Promise<void>;
547
+
548
+ /** 获取调试信息 */
549
+ manager.getDebugInfo(): object;
550
+
551
+ /** 设置状态变化回调 */
552
+ manager.setStateCallback(callback: StateChangeCallback | null): void;
553
+ ```
554
+
555
+ ### 核心设计
556
+
557
+ 1. **稳定容器**:容器在 `document.body` 中创建,激活时移到目标元素内,停用时移回 body 隐藏,不受 React 生命周期影响
558
+ 2. **实例缓存**:每个 entry 只 `loadMicroApp` 一次,后续切换复用已有实例(mount/unmount)
559
+ 3. **操作序列号**:通过递增的 `operationSeq` 检测过期操作,替代旧的会话 ID 机制
560
+ 4. **自动路由守卫**:由独立的 `route-guard.ts` 自动检测用户意图,业务代码无需感知
561
+
562
+ ### 快速切换时序
563
+
564
+ ```
565
+ 场景:A → B → A 快速切换
566
+
567
+ switchTo(A):operationSeq=1,开始 loadMicroApp
568
+
569
+ switchTo(B):operationSeq=2,A 的 pendingRequest 被替换
570
+
571
+ A 的 processRequest 在异步步骤中检测 shouldAbort(mySeq=1) → true
572
+
573
+ A 等待 mountPromise 完成后执行 safeUnmount,容器移回 body
574
+
575
+ B 开始 processRequest,检查缓存 → 无缓存 → loadMicroApp
576
+
577
+ B 加载完成后同步最新 Props(locale/timezone/routePath 等)
578
+ ```
579
+
580
+ ### 设计决策
581
+
582
+ | 决策点 | 选择 | 理由 |
583
+ | --- | --- | --- |
584
+ | 容器策略 | 稳定容器(body 中创建,移动挂载) | 不受 React 生命周期影响,避免容器被意外销毁 |
585
+ | 并发控制 | 操作序列号 + pendingRequest 队列 | 简单高效,新请求自动覆盖旧请求 |
586
+ | 实例缓存 | loadPromise 完成后立即缓存 | 即使被 abort 也可复用,避免重复加载 |
587
+ | unmount 安全 | 等待 mountPromise 完成后再 unmount | 避免 single-spa error #32 |
588
+ | 超时保护 | load 30s / mount 30s / unmount 10s | 平衡等待时间与异常检测速度 |
589
+ | Props 同步 | mount 完成后立即 safeUpdate | 确保加载期间的变化不丢失 |