generator-mico-cli 0.1.29 → 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 (160) 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 +33 -17
  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 +10 -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/arch-/350/257/267/346/261/202/346/250/241/345/235/227.md +1 -1
  34. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +372 -0
  35. 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
  36. package/generators/micro-react/templates/apps/layout/docs/feature-404/351/241/265/351/235/242.md +103 -0
  37. 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
  38. 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
  39. 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 +420 -0
  40. 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
  41. 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
  42. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +324 -0
  43. package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +81 -61
  44. package/generators/micro-react/templates/apps/layout/mock/menus.ts +114 -4
  45. package/generators/micro-react/templates/apps/layout/mock/pages.ts +86 -0
  46. package/generators/micro-react/templates/apps/layout/package.json +7 -4
  47. package/generators/micro-react/templates/apps/layout/src/app.tsx +122 -83
  48. package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
  49. package/generators/micro-react/templates/apps/layout/src/common/helpers.ts +177 -0
  50. package/generators/micro-react/templates/apps/layout/src/common/locale.ts +22 -17
  51. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +283 -28
  52. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +69 -5
  53. package/generators/micro-react/templates/apps/layout/src/common/micro/index.ts +34 -0
  54. package/generators/micro-react/templates/apps/layout/src/common/micro-prefetch.ts +109 -0
  55. package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +45 -0
  56. package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +72 -10
  57. package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +2 -2
  58. package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +31 -3
  59. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +29 -11
  60. package/generators/micro-react/templates/apps/layout/src/common/request/url-resolver.ts +23 -8
  61. package/generators/micro-react/templates/apps/layout/src/common/route-guard.ts +345 -0
  62. package/generators/micro-react/templates/apps/layout/src/common/theme.ts +2 -4
  63. package/generators/micro-react/templates/apps/layout/src/common/upload/oss.ts +3 -4
  64. package/generators/micro-react/templates/apps/layout/src/common/upload/types.ts +1 -1
  65. package/generators/micro-react/templates/apps/layout/src/common/uploadFiles.ts +1 -1
  66. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +8 -3
  67. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +25 -8
  68. package/generators/micro-react/templates/apps/layout/src/components/HeaderDropdown/index.tsx +20 -0
  69. package/generators/micro-react/templates/apps/layout/src/components/IconFont/index.tsx +5 -6
  70. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.less +21 -6
  71. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +83 -107
  72. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/micro-app-manager.ts +569 -0
  73. package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +383 -0
  74. package/generators/micro-react/templates/apps/layout/src/components/RightContent/avatar-dropdown.less +35 -0
  75. package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +2 -0
  76. package/generators/micro-react/templates/apps/layout/src/constants/index.ts +170 -6
  77. package/generators/micro-react/templates/apps/layout/src/global.less +19 -6
  78. package/generators/micro-react/templates/apps/layout/src/hooks/useMenu.ts +3 -2
  79. package/generators/micro-react/templates/apps/layout/src/hooks/useRoutePermissionRefresh.ts +72 -0
  80. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +3 -1
  81. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +10 -55
  82. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +34 -4
  83. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +33 -9
  84. package/generators/micro-react/templates/apps/layout/src/layouts/index.less +84 -13
  85. package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +178 -47
  86. package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +12 -0
  87. package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +12 -0
  88. package/generators/micro-react/templates/apps/layout/src/pages/403/index.tsx +34 -0
  89. package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +78 -0
  90. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +3 -0
  91. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +7 -1
  92. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.less +1 -1
  93. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.tsx +9 -5
  94. package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +1 -1
  95. package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +63 -0
  96. package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +30 -0
  97. package/generators/micro-react/templates/apps/layout/src/services/user.ts +29 -2
  98. package/generators/micro-react/templates/apps/layout/tailwind.config.js +3 -0
  99. package/generators/micro-react/templates/deployDesc.md +3 -3
  100. package/generators/micro-react/templates/dev.preset.json +14 -0
  101. package/generators/micro-react/templates/docs/dev-preset.md +130 -0
  102. package/generators/micro-react/templates/package.json +21 -6
  103. package/generators/micro-react/templates/packages/common-intl/README.md +427 -0
  104. package/generators/micro-react/templates/packages/common-intl/package.json +34 -0
  105. package/generators/micro-react/templates/packages/common-intl/src/index.ts +7 -0
  106. package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +51 -0
  107. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +50 -0
  108. package/generators/micro-react/templates/packages/common-intl/src/utils.ts +482 -0
  109. package/generators/micro-react/templates/packages/common-intl/tsconfig.json +22 -0
  110. package/generators/micro-react/templates/packages/common-intl/vite.config.ts +25 -0
  111. package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +45 -0
  112. package/generators/micro-react/templates/scripts/collect-dist.js +10 -0
  113. package/generators/micro-react/templates/scripts/dev-preset.js +265 -0
  114. package/generators/micro-react/templates/scripts/dev-preset.schema.json +39 -0
  115. package/generators/micro-react/templates/turbo.json +4 -1
  116. package/generators/subapp-react/index.js +326 -40
  117. package/generators/subapp-react/meta.json +10 -0
  118. package/generators/subapp-react/templates/homepage/.env +2 -1
  119. package/generators/subapp-react/templates/homepage/README.md +3 -3
  120. package/generators/subapp-react/templates/homepage/config/config.dev.ts +14 -7
  121. package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +16 -5
  122. package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +16 -5
  123. package/generators/subapp-react/templates/homepage/config/config.prod.ts +14 -5
  124. package/generators/subapp-react/templates/homepage/config/config.ts +27 -0
  125. package/generators/subapp-react/templates/homepage/config/routes.ts +2 -2
  126. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  127. package/generators/subapp-react/templates/homepage/package.json +7 -4
  128. package/generators/subapp-react/templates/homepage/src/app.tsx +18 -27
  129. package/generators/subapp-react/templates/homepage/src/common/request.ts +29 -2
  130. package/generators/subapp-react/templates/homepage/src/global.less +6 -5
  131. package/generators/subapp-react/templates/homepage/src/pages/index.less +3 -3
  132. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +99 -60
  133. package/generators/subapp-react/templates/homepage/src/styles/theme.less +1 -1
  134. package/generators/subapp-umd/ignore-list.json +5 -0
  135. package/generators/subapp-umd/index.js +309 -0
  136. package/generators/subapp-umd/meta.json +11 -0
  137. package/generators/subapp-umd/templates/README.md +94 -0
  138. package/generators/subapp-umd/templates/package.json +35 -0
  139. package/generators/subapp-umd/templates/public/index.html +34 -0
  140. package/generators/subapp-umd/templates/src/App.less +15 -0
  141. package/generators/subapp-umd/templates/src/App.tsx +13 -0
  142. package/generators/subapp-umd/templates/src/index.ts +2 -0
  143. package/generators/subapp-umd/templates/tsconfig.json +27 -0
  144. package/generators/subapp-umd/templates/webpack.config.js +70 -0
  145. package/lib/utils.js +332 -2
  146. package/package.json +15 -2
  147. package/generators/micro-react/templates/apps/layout/mock/menus.json +0 -100
  148. package/generators/micro-react/templates/apps/layout/src/common/constants.ts +0 -38
  149. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/container-manager.ts +0 -202
  150. package/generators/micro-react/templates/packages/shared-styles/README.md +0 -124
  151. package/generators/micro-react/templates/packages/shared-styles/arco-design-mobile-override.less +0 -91
  152. package/generators/micro-react/templates/packages/shared-styles/arco-override.less +0 -119
  153. package/generators/micro-react/templates/packages/shared-styles/index.d.ts +0 -44
  154. package/generators/micro-react/templates/packages/shared-styles/index.less +0 -13
  155. package/generators/micro-react/templates/packages/shared-styles/package.json +0 -30
  156. package/generators/micro-react/templates/packages/shared-styles/theme-inject.less +0 -10
  157. package/generators/micro-react/templates/packages/shared-styles/themes/dark/custom-var.less +0 -290
  158. package/generators/micro-react/templates/packages/shared-styles/themes/normal/custom-var.less +0 -269
  159. package/generators/micro-react/templates/packages/shared-styles/variables-only.less +0 -433
  160. package/generators/micro-react/templates/packages/shared-styles/variables.less +0 -452
@@ -3,7 +3,7 @@
3
3
  * 支持在 localStorage 中存储主题状态,并在页面加载时动态加载对应的主题
4
4
  */
5
5
 
6
- import { THEME } from './constants';
6
+ import { THEME } from '@/constants';
7
7
 
8
8
  export type ThemeMode = 'light' | 'dark';
9
9
 
@@ -44,16 +44,14 @@ export function setTheme(theme: ThemeMode): void {
44
44
 
45
45
  /**
46
46
  * 应用主题到 DOM
47
- * 通过切换 body 的 data-theme 和 arco-theme 属性来应用不同的主题
47
+ * 通过切换 body 的 data-theme 和 arco-theme 属性来应用不同的主题(@mico-platform/ui 基于 Arco,兼容 arco-theme)
48
48
  */
49
49
  export function applyTheme(theme: ThemeMode): void {
50
50
  if (typeof document === 'undefined') return;
51
51
 
52
52
  if (theme === 'dark') {
53
- document.body.setAttribute('arco-theme', 'dark');
54
53
  document.body.setAttribute('data-theme', 'dark');
55
54
  } else {
56
- document.body.removeAttribute('arco-theme');
57
55
  document.body.setAttribute('data-theme', 'normal');
58
56
  }
59
57
  }
@@ -1,9 +1,8 @@
1
1
  import { fetchUploadSignedUrl } from '@/services/oss';
2
- import type { UploadProps } from '@arco-design/web-react';
3
- import { Message } from '@arco-design/web-react';
4
- import type { UploadItem } from '@arco-design/web-react/es/Upload';
2
+ import type { UploadProps, UploadItem } from '@mico-platform/ui';
3
+ import { Message } from '@mico-platform/ui';
5
4
  import SparkMD5 from 'spark-md5';
6
- import type { TDirCategory } from '../constants';
5
+ import type { TDirCategory } from '@/constants';
7
6
  import type {
8
7
  OssUploadError,
9
8
  UploadLifecycleEvent,
@@ -1,4 +1,4 @@
1
- import type { TDirCategory } from '../constants';
1
+ import type { TDirCategory } from '@/constants';
2
2
 
3
3
  export interface UploadLifecycleEvent {
4
4
  stage: 'hashing' | 'signing' | 'uploading';
@@ -1,7 +1,7 @@
1
1
  // ! 这个函数不能放到 ./helpers.ts 中,因为 ./request/index.ts 从 ./helpers.ts 导入了 getFromStorage, safeParseJSON,如果放到 ./helpers.ts 中,会导致循环引入
2
2
  // ! 开发态下,发生循环引入时, mako 不会有编译时报错,但运行时会报错
3
3
 
4
- import type { TDirCategory } from './constants';
4
+ import type { TDirCategory } from '@/constants';
5
5
  import { uploadToOss } from './upload/oss';
6
6
 
7
7
  /** 上传文件到 OSS 并获取 URL */
@@ -1,10 +1,15 @@
1
- @import '<%= packageScope %>/shared-styles/variables-only';
1
+ @import '@mico-platform/theme/variables';
2
2
 
3
3
  .app-tabs.arco-tabs {
4
+ // margin-bottom: 8px;
4
5
  min-height: 46px;
5
6
  position: fixed;
7
+ // width: calc(100vw - @sidebar-width - 63px + 48px);
8
+ // transform: translateX(-24px);
9
+ // padding-left: 24px;
10
+ // width: calc(100vw - var(--sider-width) - 46px);
6
11
  right: 0;
7
- left: var(--sider-width, 200px);
12
+ left: var(--sider-width);
8
13
  padding-left: 16px;
9
14
  transition: left 0.2s ease;
10
15
  z-index: 999;
@@ -15,11 +20,11 @@
15
20
 
16
21
  .arco-tabs-header-title {
17
22
  border: none;
18
- background-color: transparent;
19
23
  border-radius: @border-radius-lg;
20
24
 
21
25
  &-active {
22
26
  border: none;
27
+ // background-color: @color-fill-3;
23
28
  }
24
29
 
25
30
  &-active:hover {
@@ -1,7 +1,7 @@
1
- import { findRouteByPath } from '@/common/menu';
2
- import { NO_AUTH_ROUTE_LIST } from '@/constants';
1
+ import { findRouteByPath, getMenuLabel, isChineseLocale } from '@/common/menu';
2
+ import { isNoLayoutRoute } from '@/constants';
3
3
  import useMenu from '@/hooks/useMenu';
4
- import { Tabs } from '@arco-design/web-react';
4
+ import { Tabs } from '@mico-platform/ui';
5
5
  import { history, useLocation } from '@umijs/max';
6
6
  import { useEffect, useMemo, useState } from 'react';
7
7
  import './index.less';
@@ -9,7 +9,12 @@ import './index.less';
9
9
  const TabPane = Tabs.TabPane;
10
10
 
11
11
  interface TabItem {
12
+ /** 菜单显示名称(中文) */
12
13
  title: string;
14
+ /** 菜单显示名称(英文) */
15
+ titleEn?: string;
16
+ /** 国际化 key */
17
+ nameKey?: string;
13
18
  key: string;
14
19
  path: string;
15
20
  icon?: string;
@@ -47,7 +52,7 @@ function AppTabs() {
47
52
  const [tabs, setTabs] = useState<TabItem[]>([]);
48
53
 
49
54
  const showTabs = useMemo(() => {
50
- return !NO_AUTH_ROUTE_LIST.includes(location.pathname);
55
+ return !isNoLayoutRoute(location.pathname);
51
56
  }, [location.pathname]);
52
57
 
53
58
  const microAppPrefixes = useMemo(() => {
@@ -110,6 +115,8 @@ function AppTabs() {
110
115
  if (!existingTab) {
111
116
  const newTab: TabItem = {
112
117
  title: currentRoute.name,
118
+ titleEn: currentRoute.nameEn,
119
+ nameKey: currentRoute.nameKey,
113
120
  key: tabKey,
114
121
  path: tabPath,
115
122
  icon: currentRoute.icon,
@@ -120,7 +127,12 @@ function AppTabs() {
120
127
 
121
128
  return prevTabs.map((tab) => {
122
129
  if (shouldReuseTab(tab.path, actualPath)) {
123
- return { ...tab, title: currentRoute.name };
130
+ return {
131
+ ...tab,
132
+ title: currentRoute.name,
133
+ titleEn: currentRoute.nameEn,
134
+ nameKey: currentRoute.nameKey,
135
+ };
124
136
  }
125
137
  return tab;
126
138
  });
@@ -174,9 +186,14 @@ function AppTabs() {
174
186
  onDeleteTab={handleDeleteTab}
175
187
  onChange={handleTabChange}
176
188
  >
177
- {tabs.map((tab) => (
178
- <TabPane destroyOnHide key={tab.key} title={tab.title} />
179
- ))}
189
+ {tabs.map((tab) => {
190
+ const isChinese = isChineseLocale();
191
+ const label = getMenuLabel(
192
+ { name: tab.title, nameEn: tab.titleEn, nameKey: tab.nameKey },
193
+ isChinese,
194
+ );
195
+ return <TabPane destroyOnHide key={tab.key} title={label} />;
196
+ })}
180
197
  </Tabs>
181
198
  );
182
199
  }
@@ -0,0 +1,20 @@
1
+ import { Dropdown, type DropdownProps } from '@mico-platform/ui';
2
+ import React from 'react';
3
+
4
+ export type HeaderDropdownProps = {
5
+ placement?:
6
+ | 'bottomLeft'
7
+ | 'bottomRight'
8
+ | 'topLeft'
9
+ | 'topCenter'
10
+ | 'topRight'
11
+ | 'bottomCenter';
12
+ } & Omit<DropdownProps, 'overlay'>;
13
+
14
+ const HeaderDropdown: React.FC<HeaderDropdownProps> = ({
15
+ ...restProps
16
+ }) => {
17
+ return <Dropdown {...restProps} />;
18
+ };
19
+
20
+ export default HeaderDropdown;
@@ -1,5 +1,5 @@
1
- import { getCurrentLocale, getIconFontPath } from '@/common/locale';
2
- import { Icon } from '@arco-design/web-react';
1
+ import { getIconFontPath } from '@/common/locale';
2
+ import { Icon } from '@mico-platform/ui';
3
3
 
4
4
  // 该组件用于自定义的图标,用法见https://arco.design/react/components/icon#%E6%B7%BB%E5%8A%A0-iconbox-%E9%A1%B9%E7%9B%AE
5
5
  // 图标的名称可以在设计图ued里面找到 https://www.figma.com/design/skTJZPfwLCDgEV9JC6wzpP/%E5%AE%A2%E6%9C%8D%E4%B8%AD%E5%BF%83_%E4%BC%9A%E8%AF%9D%E7%AE%A1%E7%90%86_%E5%B7%A5%E4%BD%9C%E5%8F%B0?node-id=647-4835&t=8swGel7i3bPnKkul-0
@@ -7,13 +7,12 @@ import { Icon } from '@arco-design/web-react';
7
7
  // 字体库地址:https://arco.design/iconbox/mime/lib/1945/0
8
8
 
9
9
  /**
10
- * 根据当前语言加载对应的图标库
10
+ * 根据当前语言加载对应的图标库(当前只有中文)
11
11
  * 语言切换时会重新加载页面,所以这里只需要在初始化时根据当前语言加载
12
12
  */
13
13
  function createIconFont() {
14
- // 获取当前语言(按优先级:URL参数 > localStorage > 浏览器默认)
15
- const currentLocale = getCurrentLocale();
16
- const iconPath = getIconFontPath(currentLocale);
14
+ // TODO: 后续支持多语言时,需要根据当前语言加载对应的图标库
15
+ const iconPath = getIconFontPath();
17
16
 
18
17
  // 创建 IconFont 实例
19
18
  return Icon.addFromIconFontCn({ src: iconPath });
@@ -4,20 +4,17 @@
4
4
 
5
5
  .micro-app-container {
6
6
  width: 100%;
7
- height: 100%;
8
7
  position: relative;
8
+ display: flex;
9
+ flex-direction: column;
9
10
  overflow: auto;
10
11
  }
11
12
 
12
13
  .micro-app-loading {
13
- position: absolute;
14
- top: 0;
15
- left: 0;
16
- right: 0;
17
- bottom: 0;
18
14
  display: flex;
19
15
  align-items: center;
20
16
  justify-content: center;
17
+ min-height: 600px;
21
18
  background: var(--color-bg-1);
22
19
  z-index: 10;
23
20
  }
@@ -48,10 +45,28 @@
48
45
  // 激活时在文档流中,继承占位元素的尺寸
49
46
  width: 100%;
50
47
  height: 100%;
48
+ display: flex;
49
+ flex: 1;
50
+ flex-direction: column;
51
51
  overflow: auto;
52
+ min-height: calc(100vh - 134px);
53
+
52
54
 
53
55
  > div {
56
+ flex: 1;
57
+ display: flex;
58
+ flex-direction: column;
59
+ }
60
+
61
+ > div > div {
54
62
  height: 100%;
63
+ display: flex;
64
+ flex: 1 1;
65
+ }
66
+
67
+ > div > div > div {
68
+ width: 100%;
69
+ flex: 1 1;
55
70
  }
56
71
 
57
72
  // 隐藏状态(在 body 中)
@@ -1,20 +1,18 @@
1
1
  import { getAuthInfo } from '@/common/auth/auth-manager';
2
2
  import { EEnv, getEnv } from '@/common/env';
3
+ import { getCurrentLocale } from '@/common/locale';
3
4
  import { request } from '@/common/request';
4
- import { Spin } from '@arco-design/web-react';
5
- import { loadMicroApp } from 'qiankun';
6
- import React, { useEffect, useMemo, useRef, useState } from 'react';
7
- import {
8
- activateContainer,
9
- deactivateContainer,
10
- getContainer,
11
- getMicroApp,
12
- setMicroApp,
13
- unmountApp,
14
- } from './container-manager';
5
+ import { isPageAuthFree } from '@/common/menu/parser';
6
+ import { isAuthDisabled, isNoAuthRoute, isNoPermissionRoute } from '@/constants';
7
+ import { Spin } from '@mico-platform/ui';
8
+ import { useLocation, useModel } from '@umijs/max';
9
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
10
  import './index.less';
11
+ import { microAppManager, type MicroAppState } from './micro-app-manager';
16
12
 
17
13
  interface MicroAppLoaderProps {
14
+ /** 微应用在主应用中的挂载路径前缀(来自 ParsedRoute.base / 页面配置 base),经 normalizeMicroAppBase 后传给子应用 */
15
+ base: string;
18
16
  entry: string;
19
17
  name: string;
20
18
  displayName?: string;
@@ -22,6 +20,10 @@ interface MicroAppLoaderProps {
22
20
  routePath?: string;
23
21
  }
24
22
 
23
+ /** 微应用 base:先去掉末尾 /,再去掉末尾 *(与路由 path 约定一致) */
24
+ export const normalizeMicroAppBase = (path: string): string =>
25
+ path.replace(/\/+$/, '').replace(/\*+$/, '');
26
+
25
27
  const sanitizeId = (path: string): string => {
26
28
  return (
27
29
  path
@@ -32,17 +34,34 @@ const sanitizeId = (path: string): string => {
32
34
  );
33
35
  };
34
36
 
37
+ /**
38
+ * 微应用加载器
39
+ *
40
+ * 使用 MicroAppManager 统一管理微应用的加载和卸载。
41
+ * 用户意图追踪在 MicroAppManager 内部处理。
42
+ */
35
43
  const MicroAppLoader: React.FC<MicroAppLoaderProps> = ({
44
+ base,
36
45
  entry,
37
46
  name,
38
47
  displayName,
39
48
  routePath,
40
49
  }) => {
41
50
  const wrapperRef = useRef<HTMLDivElement>(null);
42
- const mountIdRef = useRef(0);
43
- const [loading, setLoading] = useState(true);
44
- const [error, setError] = useState<string | null>(null);
45
- const isMountedRef = useRef(false);
51
+ const [state, setState] = useState<MicroAppState>({
52
+ loading: true,
53
+ error: null,
54
+ mounted: false,
55
+ });
56
+
57
+ const { initialState } = useModel('@@initialState');
58
+ const location = useLocation();
59
+ const isAuthReady =
60
+ isAuthDisabled() ||
61
+ isPageAuthFree(location.pathname) ||
62
+ isNoAuthRoute(location.pathname) ||
63
+ isNoPermissionRoute(location.pathname) ||
64
+ !!initialState?.currentUser;
46
65
 
47
66
  const appName = sanitizeId(name);
48
67
 
@@ -55,131 +74,88 @@ const MicroAppLoader: React.FC<MicroAppLoaderProps> = ({
55
74
  : 'production';
56
75
  }, []);
57
76
 
58
- // 使用 ref 存储构建 props 的函数,避免 effect 依赖变化导致微应用重新加载
59
- const buildPropsRef = useRef(() => ({}));
60
- buildPropsRef.current = () => {
77
+ // 构建传递给子应用的 props
78
+ const buildProps = useCallback(() => {
61
79
  const authInfo = getAuthInfo();
62
80
  return {
63
- mainApp: 'portal-web',
81
+ mainApp: '<%= projectName %>',
64
82
  env,
65
83
  authToken: authInfo.token,
66
84
  uid: authInfo.uid,
67
85
  avatar: authInfo.avatar,
68
86
  nickname: authInfo.nickname,
87
+ base: normalizeMicroAppBase(base || '/'),
69
88
  // 传递当前路由路径,让子应用进行内部路由切换
70
89
  routePath,
71
90
  // 传递主应用的 request 实例,子应用可直接使用
72
91
  request,
92
+ // 传递当前多语言类型给子应用(zh-CN, en-US)
93
+ locale: getCurrentLocale(),
73
94
  };
74
- };
95
+ }, [base, env, routePath]);
75
96
 
76
- // 当路由等"无需重载"的状态更新时,通过 update() 通知子应用
77
- useEffect(() => {
78
- if (!isMountedRef.current) return;
97
+ // ref 持有最新的 buildProps,避免加载 effect 依赖它导致子应用被重载
98
+ const buildPropsRef = useRef(buildProps);
99
+ buildPropsRef.current = buildProps;
79
100
 
80
- const microApp = getMicroApp(appName);
81
- microApp?.update?.(buildPropsRef.current());
82
- }, [appName, routePath]);
101
+ // props 变化时,通知子应用更新(不重新加载)
102
+ useEffect(() => {
103
+ if (state.mounted) {
104
+ microAppManager.updateProps(buildProps());
105
+ }
106
+ }, [state.mounted, buildProps]);
83
107
 
108
+ // 加载微应用(只在 entry/appName/isAuthReady 变化时触发)
84
109
  useEffect(() => {
85
110
  const wrapper = wrapperRef.current;
86
- if (!wrapper) return;
87
-
88
- const currentMountId = ++mountIdRef.current;
89
- let isCancelled = false;
90
-
91
- setLoading(true);
92
- setError(null);
93
-
94
- const container = getContainer(appName);
95
- activateContainer(appName, wrapper);
96
-
97
- const loadApp = async () => {
98
- // 卸载旧实例
99
- const existingApp = getMicroApp(appName);
100
- if (existingApp) {
101
- try {
102
- await existingApp.unmount();
103
- } catch {
104
- // 忽略
105
- }
106
- }
107
-
108
- if (isCancelled) return;
109
-
110
- try {
111
- const microApp = loadMicroApp(
112
- {
113
- name: `${appName}_${currentMountId}`,
114
- entry,
115
- container,
116
- props: buildPropsRef.current(),
117
- },
118
- { sandbox: { loose: true } },
119
- );
120
-
121
- // 立即给 loadPromise 添加错误处理器,防止 unhandled rejection
122
- // 虽然提前检查了服务可达性,但 qiankun 可能因其他原因失败(CORS、HTML 解析等)
123
- microApp.loadPromise.catch((err) => {
124
- console.error(`[MicroAppLoader] ${appName} loadPromise rejected:`, err);
125
- });
126
-
127
- setMicroApp(appName, microApp);
128
-
129
- if (isCancelled) {
130
- unmountApp(appName);
131
- return;
132
- }
133
-
134
- // mountPromise 内部会等待 loadPromise,错误会传递到 catch 块
135
- await microApp.mountPromise;
136
-
137
- if (!isCancelled) {
138
- isMountedRef.current = true;
139
- setLoading(false);
140
- }
141
- } catch (err) {
142
- if (!isCancelled) {
143
- setError(err instanceof Error ? err.message : 'Unknown error');
144
- setLoading(false);
145
- }
146
- }
147
- };
148
-
149
- loadApp();
111
+ if (!wrapper) {
112
+ console.warn('[MicroAppLoader] wrapper is null, skip loading');
113
+ return;
114
+ }
115
+
116
+ // 等待认证信息准备好
117
+ if (!isAuthReady) {
118
+ console.log('[MicroAppLoader] waiting for auth ready:', { appName, entry });
119
+ return;
120
+ }
121
+
122
+ console.log('🔍[路由调试] MicroAppLoader useEffect 执行', { appName, entry });
123
+
124
+ // 设置状态回调
125
+ microAppManager.setStateCallback(setState);
126
+
127
+ // 切换到目标微应用
128
+ microAppManager.switchTo({
129
+ name: appName,
130
+ entry,
131
+ target: wrapper,
132
+ props: buildPropsRef.current(),
133
+ });
150
134
 
151
135
  return () => {
152
- isCancelled = true;
153
- isMountedRef.current = false;
154
-
155
- // 同步执行,确保在下一次 activate 前移走容器
156
- deactivateContainer(appName);
157
-
158
- // 异步卸载微应用,给 qiankun 足够时间完成清理
159
- requestAnimationFrame(() => {
160
- unmountApp(appName);
161
- });
136
+ console.log('🔍[路由调试] MicroAppLoader cleanup', { appName });
137
+ microAppManager.cancel();
138
+ microAppManager.setStateCallback(null);
162
139
  };
163
- // 注意:不依赖 sharedServices,websocket 变化时通过 update() 更新 props 而不重新加载微应用
164
- }, [entry, appName, env]);
140
+ }, [entry, appName, isAuthReady, buildProps]);
165
141
 
166
142
  return (
167
143
  <div className="micro-app-container">
168
- {error && (
144
+ {state.error && (
169
145
  <div className="micro-app-error">
170
146
  <p>微应用加载失败</p>
171
- <p className="error-detail">{error}</p>
147
+ <p className="error-detail">{state.error}</p>
172
148
  </div>
173
149
  )}
174
- {loading && !error && (
150
+ {state.loading && !state.error && (
175
151
  <div className="micro-app-loading">
176
152
  <Spin dot tip={`正在加载 ${displayName || name}...`} />
177
153
  </div>
178
154
  )}
179
- {/* qiankun 容器挂载点,error 时隐藏 */}
155
+ {/* qiankun 容器挂载点 */}
180
156
  <div
181
157
  ref={wrapperRef}
182
- style={{ display: error ? 'none' : 'block', height: '100%' }}
158
+ style={{ display: state.error ? 'none' : 'block', height: '100%' }}
183
159
  />
184
160
  </div>
185
161
  );