generator-mico-cli 0.1.28 → 0.2.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 (64) hide show
  1. package/generators/micro-react/templates/.cursor/rules/layout-app.mdc +1 -1
  2. package/generators/micro-react/templates/.cursor/rules/request-auth.mdc +2 -2
  3. package/generators/micro-react/templates/.cursor/rules/theme-system.mdc +2 -2
  4. package/generators/micro-react/templates/CLAUDE.md +27 -11
  5. package/generators/micro-react/templates/README.md +2 -0
  6. package/generators/micro-react/templates/apps/layout/config/config.dev.ts +11 -4
  7. package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +1 -11
  8. package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +0 -7
  9. package/generators/micro-react/templates/apps/layout/config/routes.ts +10 -0
  10. 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 +105 -0
  11. package/generators/micro-react/templates/apps/layout/docs/arch-/350/257/267/346/261/202/346/250/241/345/235/227.md +17 -15
  12. 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 +234 -0
  13. 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 +432 -0
  14. 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 +175 -0
  15. package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +15 -15
  16. package/generators/micro-react/templates/apps/layout/src/app.tsx +43 -28
  17. package/generators/micro-react/templates/apps/layout/src/common/auth/{cs-auth-manager.ts → auth-manager.ts} +6 -63
  18. package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +1 -1
  19. package/generators/micro-react/templates/apps/layout/src/common/auth/tool.ts +2 -3
  20. package/generators/micro-react/templates/apps/layout/src/common/auth/type.ts +38 -0
  21. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +109 -2
  22. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +74 -1
  23. package/generators/micro-react/templates/apps/layout/src/common/micro/index.ts +0 -8
  24. package/generators/micro-react/templates/apps/layout/src/common/micro/types.ts +0 -2
  25. package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +1 -1
  26. package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +3 -11
  27. package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +2 -2
  28. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +3 -2
  29. package/generators/micro-react/templates/apps/layout/src/common/request/token-refresh.ts +2 -2
  30. package/generators/micro-react/templates/apps/layout/src/common/request/url-resolver.ts +32 -48
  31. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +1 -1
  32. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +62 -14
  33. package/generators/micro-react/templates/apps/layout/src/global.less +5 -1
  34. package/generators/micro-react/templates/apps/layout/src/hooks/useAuth.ts +2 -3
  35. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +1 -1
  36. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +17 -13
  37. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +1 -1
  38. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +11 -3
  39. package/generators/micro-react/templates/apps/layout/src/layouts/index.less +1 -1
  40. package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +52 -8
  41. package/generators/micro-react/templates/apps/layout/src/pages/403/index.tsx +28 -0
  42. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.less +275 -0
  43. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.tsx +142 -0
  44. package/generators/micro-react/templates/apps/layout/src/services/auth.ts +1 -0
  45. package/generators/micro-react/templates/apps/layout/src/services/user.ts +25 -0
  46. package/generators/micro-react/templates/packages/shared-styles/README.md +16 -14
  47. package/generators/micro-react/templates/packages/shared-styles/arco-design-mobile-override.less +91 -0
  48. package/generators/micro-react/templates/packages/shared-styles/arco-override.less +41 -0
  49. package/generators/micro-react/templates/packages/shared-styles/index.d.ts +44 -0
  50. package/generators/micro-react/templates/packages/shared-styles/index.less +0 -1
  51. package/generators/micro-react/templates/packages/shared-styles/package.json +6 -3
  52. package/generators/micro-react/templates/packages/shared-styles/themes/dark/custom-var.less +118 -74
  53. package/generators/micro-react/templates/packages/shared-styles/themes/normal/custom-var.less +175 -101
  54. package/generators/micro-react/templates/packages/shared-styles/variables-only.less +357 -225
  55. package/generators/micro-react/templates/packages/shared-styles/variables.less +290 -201
  56. package/generators/subapp-react/templates/homepage/config/config.prod.ts +2 -2
  57. package/generators/subapp-react/templates/homepage/config/config.ts +6 -0
  58. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +43 -43
  59. package/generators/subapp-react/templates/homepage/typings.d.ts +76 -0
  60. package/package.json +1 -1
  61. package/generators/micro-react/templates/apps/layout/src/styles/arco-override.less +0 -78
  62. package/generators/micro-react/templates/apps/layout/src/styles/themes/dark/custom-var.less +0 -244
  63. package/generators/micro-react/templates/apps/layout/src/styles/themes/normal/custom-var.less +0 -195
  64. package/generators/micro-react/templates/apps/layout/src/styles/variables.less +0 -5
@@ -206,7 +206,7 @@ const { isAuthenticated, user, logout } = useAuth();
206
206
  ### 主题变量引入
207
207
  ```less
208
208
  // 在组件样式中使用
209
- @import '@/styles/variables.less';
209
+ @import '<%= packageScope %>/shared-styles/variables-only';
210
210
 
211
211
  .my-component {
212
212
  background: @color-fill-1;
@@ -24,7 +24,7 @@ globs: ["**/request/**", "**/auth/**", "**/services/**"]
24
24
  | 文件 | 说明 |
25
25
  |------|------|
26
26
  | `src/common/request/index.ts` | 统一请求封装 |
27
- | `src/common/auth/cs-auth-manager.ts` | Token 存储管理 |
27
+ | `src/common/auth/auth-manager.ts` | Token 存储管理 |
28
28
  | `src/common/auth/index.ts` | 认证入口 |
29
29
  | `src/common/auth/tool.ts` | 认证工具函数 |
30
30
  | `src/requestErrorConfig.ts` | 错误处理配置 |
@@ -151,7 +151,7 @@ import {
151
151
  getStoredRefreshToken,
152
152
  setStoredRefreshToken,
153
153
  clearStoredTokens,
154
- } from '@/common/auth/cs-auth-manager';
154
+ } from '@/common/auth/auth-manager';
155
155
 
156
156
  // 获取 token
157
157
  const token = getStoredAuthToken();
@@ -178,7 +178,7 @@ const getStoredTheme = (): Theme => {
178
178
 
179
179
  ```less
180
180
  // global.less - 仅导入 Less 变量(不打包 CSS 变量)
181
- @import '@<%= projectName %>/shared-styles/variables-only';
181
+ @import '<%= packageScope %>/shared-styles/variables-only';
182
182
  ```
183
183
 
184
184
  ```typescript
@@ -203,4 +203,4 @@ if (process.env.NODE_ENV === 'development') {
203
203
  3. **优先 Less 变量**: 使用 Less 变量有编辑器提示和类型检查
204
204
  4. **避免硬编码颜色**: 所有颜色都应使用主题变量
205
205
  5. **系统跟随**: 未手动设置主题时会跟随系统偏好变化
206
- 6. **子应用共享**: 子应用使用 `@<%= projectName %>/shared-styles` 包复用主题
206
+ 6. **子应用共享**: 子应用使用 `<%= packageScope %>/shared-styles` 包复用主题
@@ -47,23 +47,24 @@ mico create subapp-react
47
47
  ## 架构
48
48
 
49
49
  ```
50
- apps/ # Workspace 应用目录
51
- ├── layout/ # 主应用(qiankun master)
50
+ apps/ # Workspace 应用目录(微前端子应用)
51
+ ├── layout/ # 主布局应用(qiankun 主应用容器)
52
52
  │ ├── src/
53
53
  │ │ ├── app.tsx # Umi 运行时配置
54
54
  │ │ ├── layouts/ # 布局组件
55
55
  │ │ ├── pages/ # 路由页面
56
56
  │ │ ├── components/ # 公共组件
57
- │ │ ├── common/ # 工具模块
57
+ │ │ ├── common/ # 工具模块(auth、request、upload、menu)
58
58
  │ │ ├── hooks/ # 自定义 Hooks
59
59
  │ │ ├── services/ # API 服务层
60
- │ │ ├── models/ # Umi model
61
- │ │ ├── locales/ # 国际化
62
- │ │ └── styles/ # 主题变量
60
+ │ │ ├── models/ # Umi model(全局状态)
61
+ │ │ ├── locales/ # 国际化文件(zh-CN、en-US)
62
+ │ │ └── styles/ # 主题变量与样式覆盖
63
63
  │ └── config/ # Umi 配置
64
64
  packages/ # 共享包
65
65
  ├── shared-styles/ # 共享样式
66
- scripts/ # 构建脚本
66
+ scripts/ # 构建与开发脚本
67
+ CICD/ # 部署资源
67
68
  ```
68
69
 
69
70
  ## TypeScript 命名规范
@@ -94,13 +95,28 @@ refactor(auth): 重构认证服务
94
95
  ## 核心模块
95
96
 
96
97
  ### 请求层
97
- API 请求配置在 `apps/layout/src/common/request/`。
98
+ API 请求配置在 `src/common/request/`(模块化拆分为 6 个文件),错误处理在 `src/requestErrorConfig.ts`。详见 [请求模块架构](./apps/layout/docs/arch-请求模块.md)。
99
+
100
+ ### 日志与常量
101
+ Logger 工具在 `src/common/logger.ts`,常量定义在 `src/common/constants.ts`。详见 [日志与常量](./apps/layout/docs/arch-日志与常量.md)。
98
102
 
99
103
  ### 认证模块
100
- 认证逻辑在 `apps/layout/src/common/auth/`。
104
+ 认证逻辑在 `src/common/auth/`,核心文件 `auth-manager.ts` 管理 Token 存储和用户信息。SSO 登录在 `getInitialState()` 中完成,确保 UI 渲染前认证已就绪。
101
105
 
102
106
  ### 菜单系统
103
- 菜单解析与类型定义在 `apps/layout/src/common/menu/`。
107
+ 菜单解析与类型定义在 `src/common/menu/`。
104
108
 
105
109
  ### 微前端
106
- layout 应用作为 qiankun 主应用,子应用通过 qiankun 配置注册。
110
+ layout 应用作为 qiankun 主应用,子应用通过 Umi 配置中的 qiankun 配置注册。详见 [微前端模式](./apps/layout/docs/feature-微前端模式.md)。
111
+
112
+ ## 相关文档
113
+
114
+ | 文档 | 说明 |
115
+ |------|------|
116
+ | [README.md](./README.md) | 项目入口、技术栈、常用命令 |
117
+ | [提交规范](./docs/commit-message.md) | Git Commit 详细规范 |
118
+ | [微前端模式](./apps/layout/docs/feature-微前端模式.md) | qiankun 架构、MicroAppLoader、子应用配置 |
119
+ | [主题色切换](./apps/layout/docs/feature-主题色切换.md) | useTheme Hook、CSS 变量系统 |
120
+ | [请求模块架构](./apps/layout/docs/arch-请求模块.md) | HTTP 请求层模块化设计 |
121
+ | [日志与常量](./apps/layout/docs/arch-日志与常量.md) | Logger 工具与常量管理 |
122
+ | [部署说明](./deployDesc.md) | CI/CD 构建与部署流程 |
@@ -34,6 +34,8 @@ pnpm install
34
34
  | `pnpm lint` | 运行 ESLint + Turborepo lint 校验 |
35
35
  | `pnpm lint:fix` | 自动修复 lint 问题 |
36
36
 
37
+ > **提示**:也可以使用 `pnpm -C apps/<app-name> dev` 直接启动指定应用,例如 `pnpm -C apps/layout dev`。
38
+
37
39
  ## 新建子应用
38
40
 
39
41
  使用 Mico CLI 快速创建新的 React 子应用:
@@ -21,7 +21,7 @@ const config: ReturnType<typeof defineConfig> = {
21
21
  content: `
22
22
  window.__MICO_MENUS__ = ${JSON.stringify(mockMenus)};
23
23
  window.__MICO_CONFIG__ = {
24
- appName: 'Audit Center',
24
+ appName: 'Mico Center',
25
25
  apiBaseUrl: '',
26
26
  };
27
27
  `,
@@ -29,9 +29,16 @@ const config: ReturnType<typeof defineConfig> = {
29
29
  ],
30
30
 
31
31
  proxy: {
32
- '/api/': {
32
+ '/api': {
33
33
  // 要代理的地址
34
- target: 'https://preview.pro.ant.design',
34
+ target: 'https://dashboard-api-test.micoplatform.comn',
35
+ // 配置了这个可以从 http 代理到 https
36
+ // 依赖 origin 的功能可能需要这个,比如 cookie
37
+ changeOrigin: true,
38
+ },
39
+ '/proxy/audit_svr': {
40
+ // 要代理的地址
41
+ target: 'https://dashboard-api-test.micoplatform.comn',
35
42
  // 配置了这个可以从 http 代理到 https
36
43
  // 依赖 origin 的功能可能需要这个,比如 cookie
37
44
  changeOrigin: true,
@@ -40,7 +47,7 @@ const config: ReturnType<typeof defineConfig> = {
40
47
  define: {
41
48
  'process.env.NODE_ENV': 'development',
42
49
  'process.env.APP_ID': 'mibot_dev',
43
- 'process.env.API_BASE_URL': 'https://dashboard-api-test.micoplatform.com',
50
+ 'process.env.API_BASE_URL': '',
44
51
  'process.env.PROXY_SUFFIX': '/',
45
52
  'process.env.LOGIN_ENDPOINT':
46
53
  '',
@@ -21,22 +21,12 @@ const config: ReturnType<typeof defineConfig> = {
21
21
  content: `
22
22
  window.__MICO_MENUS__ = ${JSON.stringify(mockMenus)};
23
23
  window.__MICO_CONFIG__ = {
24
- appName: 'Audit Center',
24
+ appName: 'Mico Center',
25
25
  apiBaseUrl: '',
26
26
  };
27
27
  `,
28
28
  },
29
29
  ],
30
-
31
- proxy: {
32
- '/api/': {
33
- // 要代理的地址
34
- target: 'https://preview.pro.ant.design',
35
- // 配置了这个可以从 http 代理到 https
36
- // 依赖 origin 的功能可能需要这个,比如 cookie
37
- changeOrigin: true,
38
- },
39
- },
40
30
  define: {
41
31
  'process.env.NODE_ENV': 'development',
42
32
  'process.env.APP_ID': 'mibot_dev',
@@ -3,13 +3,6 @@
3
3
  import { defineConfig } from '@umijs/max';
4
4
 
5
5
  const config: ReturnType<typeof defineConfig> = {
6
- proxy: {
7
- '/api/': {
8
- target: 'https://proapi.azurewebsites.net',
9
- changeOrigin: true,
10
- pathRewrite: { '^': '' },
11
- },
12
- },
13
6
  define: {
14
7
  'process.env.NODE_ENV': 'testing',
15
8
  'process.env.APP_ID': 'mibot',
@@ -5,9 +5,19 @@
5
5
  * @note Umi Max 会自动使用 src/layouts/index.tsx 作为全局布局,无需显式配置
6
6
  */
7
7
  export default [
8
+ {
9
+ path: '/user/login',
10
+ component: './User/Login',
11
+ name: '登录',
12
+ },
8
13
  {
9
14
  path: '/',
10
15
  component: './Home',
11
16
  name: '首页',
12
17
  },
18
+ {
19
+ path: '/403',
20
+ component: './403',
21
+ name: '无权限',
22
+ },
13
23
  ];
@@ -0,0 +1,105 @@
1
+ # 日志与常量
2
+
3
+ > 创建时间:2025-12-27
4
+
5
+ ## Logger 工具
6
+
7
+ 生产环境静默的日志工具,使用 `bind` 保持正确的调用栈位置。
8
+
9
+ ### 使用
10
+
11
+ ```typescript
12
+ import { layoutLogger, microAppLogger, authLogger } from '@/common/logger';
13
+
14
+ layoutLogger.log('message'); // [Layout] message
15
+ layoutLogger.error('error'); // 保持原始调用栈位置
16
+ ```
17
+
18
+ ### 实现原理
19
+
20
+ ```typescript
21
+ // 使用 bind 而非 wrapper,保持控制台显示正确的调用位置
22
+ const createLogger = (prefix: string) => ({
23
+ log: console.log.bind(console, `[${prefix}]`),
24
+ error: console.error.bind(console, `[${prefix}]`),
25
+ // ...
26
+ });
27
+ ```
28
+
29
+ ### 预定义 Logger
30
+
31
+ | Logger | 用途 |
32
+ | ---------------- | ------------ |
33
+ | `layoutLogger` | 主布局相关 |
34
+ | `microAppLogger` | 微应用加载器 |
35
+ | `authLogger` | 认证模块 |
36
+ | `requestLogger` | 请求模块 |
37
+
38
+ ## 常量定义
39
+
40
+ 集中管理魔法字符串,位于 `src/common/constants.ts`。
41
+
42
+ ### ROUTES
43
+
44
+ ```typescript
45
+ export const ROUTES = {
46
+ LOGIN: '/user/login',
47
+ REGISTER: '/user/register',
48
+ REGISTER_RESULT: '/user/register-result',
49
+ NO_AUTH_ROUTES: ['/user/login', '/user/register', '/user/register-result'],
50
+ } as const;
51
+ ```
52
+
53
+ ### THEME
54
+
55
+ ```typescript
56
+ export const THEME = {
57
+ STORAGE_KEY: '<%= ProjectName %>-theme',
58
+ DEFAULT: 'light' as const,
59
+ VALUES: ['light', 'dark'] as const,
60
+ } as const;
61
+ ```
62
+
63
+ ### TIMEZONE
64
+
65
+ ```typescript
66
+ export const TIMEZONE = {
67
+ /** localStorage 存储键(IANA 时区,如 Asia/Shanghai) */
68
+ STORAGE_KEY: '<%= ProjectName %>-timezone',
69
+ /** localStorage 存储键(用于展示的地区/名称,可选) */
70
+ REGION_STORAGE_KEY: '<%= ProjectName %>-timezone-region',
71
+ } as const;
72
+ ```
73
+
74
+ ### PRESENCE
75
+
76
+ ```typescript
77
+ export const PRESENCE = {
78
+ /** localStorage 存储键 */
79
+ STORAGE_KEY: '<%= ProjectName %>-presence-status',
80
+ } as const;
81
+ ```
82
+
83
+ ### STORAGE_KEYS
84
+
85
+ ```typescript
86
+ export const STORAGE_KEYS = {
87
+ APP_INFO: 'appInfo',
88
+ IS_SUPERUSER: 'is_superuser',
89
+ GROUPS: 'groups',
90
+ } as const;
91
+ ```
92
+
93
+ ## 文件清单
94
+
95
+ | 文件 | 说明 |
96
+ | ------------------------------------ | ------------- |
97
+ | `src/common/logger.ts` | Logger 工具 |
98
+ | `src/common/constants.ts` | 常量定义 |
99
+ | `apps/homepage/src/common/logger.ts` | 子应用 Logger |
100
+
101
+ ## 注意事项
102
+
103
+ - Logger 仅在开发环境输出,生产环境静默
104
+ - 使用 `bind` 实现,DevTools 显示实际调用位置而非 logger.ts
105
+ - 新增路由常量应添加到 `ROUTES` 对象
@@ -1,8 +1,10 @@
1
1
  # 请求模块架构
2
2
 
3
+ > 创建时间:2025-12-27
4
+
3
5
  ## 功能概述
4
6
 
5
- HTTP 请求层模块化架构,将请求逻辑拆分为 6 个职责单一的模块,遵循 SRP 原则。
7
+ HTTP 请求层模块化架构,将原 599 行单文件拆分为 7 个文件(1 个入口 + 6 个功能模块),遵循 SRP 原则。
6
8
 
7
9
  ## 模块结构
8
10
 
@@ -43,11 +45,11 @@ const data = await request<UserInfo>('/api/user');
43
45
 
44
46
  ### 配置选项
45
47
 
46
- | 选项 | 类型 | 默认值 | 说明 |
47
- |------|------|--------|------|
48
- | `skipProxy` | `boolean` | `false` | 跳过 proxySuffix 拼接 |
49
- | `baseURL` | `string` | 全局配置 | 自定义 baseURL,覆盖全局配置 |
50
- | `rawUrl` | `boolean` | `false` | 使用原始 URL,跳过所有 URL 处理 |
48
+ | 选项 | 类型 | 默认值 | 说明 |
49
+ | ----------- | --------- | -------- | ------------------------------- |
50
+ | `skipProxy` | `boolean` | `false` | 跳过 proxySuffix 拼接 |
51
+ | `baseURL` | `string` | 全局配置 | 自定义 baseURL,覆盖全局配置 |
52
+ | `rawUrl` | `boolean` | `false` | 使用原始 URL,跳过所有 URL 处理 |
51
53
 
52
54
  ### 配置优先级
53
55
 
@@ -81,7 +83,7 @@ request('/api/data', { baseURL: 'https://other-service.com' });
81
83
  // 4. 自定义 baseURL + 跳过 proxy(请求第三方 API)
82
84
  request('/api/data', {
83
85
  baseURL: 'https://third-party.com',
84
- skipProxy: true
86
+ skipProxy: true,
85
87
  });
86
88
  // 生产环境 => https://third-party.com/api/data
87
89
 
@@ -96,13 +98,13 @@ request('/api/users', { proxySuffix: '/other-proxy' });
96
98
 
97
99
  ### 典型场景
98
100
 
99
- | 场景 | 配置 |
100
- |------|------|
101
- | 请求主后端 API | 默认,无需额外配置 |
102
- | 绕过网关直连后端 | `{ skipProxy: true }` |
103
- | 请求其他微服务 | `{ baseURL: 'https://xxx' }` |
104
- | 请求第三方 API | `{ baseURL: 'https://xxx', skipProxy: true }` |
105
- | 微应用已处理 URL | `{ rawUrl: true }` |
101
+ | 场景 | 配置 |
102
+ | ---------------- | --------------------------------------------- |
103
+ | 请求主后端 API | 默认,无需额外配置 |
104
+ | 绕过网关直连后端 | `{ skipProxy: true }` |
105
+ | 请求其他微服务 | `{ baseURL: 'https://xxx' }` |
106
+ | 请求第三方 API | `{ baseURL: 'https://xxx', skipProxy: true }` |
107
+ | 微应用已处理 URL | `{ rawUrl: true }` |
106
108
 
107
109
  ## 错误处理
108
110
 
@@ -124,7 +126,7 @@ const isAxiosLikeError = (error: unknown): error is AxiosLikeError => {
124
126
  | 文件 | 说明 |
125
127
  | ------------------------------------ | -------------- |
126
128
  | `src/requestErrorConfig.ts` | 错误处理配置 |
127
- | `src/common/auth/cs-auth-manager.ts` | Token 存储管理 |
129
+ | `src/common/auth/auth-manager.ts` | Token 存储管理 |
128
130
 
129
131
  ## 注意事项
130
132
 
@@ -0,0 +1,234 @@
1
+ # 主题色切换
2
+
3
+ > 创建时间:2025-12-26
4
+
5
+ ## 功能概述
6
+
7
+ Layout 应用支持亮色/暗黑主题切换,通过 CSS 变量实现运行时动态切换,所有组件自动适配主题变化。
8
+
9
+ ## 技术方案
10
+
11
+ ### 技术栈
12
+
13
+ - 框架:React 18 + UmiJS 4
14
+ - UI 组件:Arco Design
15
+ - 样式:Less + CSS Variables
16
+ - 状态管理:React Hooks + localStorage
17
+
18
+ ### 核心实现
19
+
20
+ 采用双属性主题系统:
21
+
22
+ 1. `arco-theme` 属性控制 Arco Design 组件主题
23
+ 2. `data-theme` 属性控制自定义 CSS 变量
24
+
25
+ 两个属性都设置在 `body` 元素上,确保选择器正确匹配。Less 变量引用 CSS 变量,实现编译时类型安全和运行时动态切换。
26
+
27
+ ## 文件清单
28
+
29
+ ### 主题系统核心文件
30
+
31
+ 主题变量统一定义在 `packages/shared-styles/` 共享包中:
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 变量(子应用用) |
41
+
42
+ ### Layout 应用文件
43
+
44
+ | 文件路径 | 说明 |
45
+ | ---------------------------- | ----------------------------------------- |
46
+ | `src/global.less` | 导入 `<%= packageScope %>/shared-styles` 共享包 |
47
+ | `src/common/theme.ts` | 主题切换逻辑(`applyTheme`、`initTheme`) |
48
+ | `src/hooks/useTheme.ts` | 主题管理 Hook |
49
+
50
+ ## API / 组件接口
51
+
52
+ ### useTheme Hook
53
+
54
+ ```typescript
55
+ type Theme = 'light' | 'dark';
56
+
57
+ interface UseThemeReturn {
58
+ theme: Theme; // 当前主题
59
+ isDark: boolean; // 是否暗黑模式
60
+ toggleTheme: () => void; // 切换主题
61
+ setTheme: (theme: Theme) => void; // 设置指定主题
62
+ }
63
+
64
+ const { theme, isDark, toggleTheme, setTheme } = useTheme();
65
+ ```
66
+
67
+ ### CSS 变量使用
68
+
69
+ ```less
70
+ // 在 Less 中使用 Less 变量(推荐,有类型提示)
71
+ .my-component {
72
+ background-color: @color-fill-1;
73
+ color: @color-text-2;
74
+ border-color: @color-border-2;
75
+ }
76
+
77
+ // 或直接使用 CSS 变量
78
+ .my-component {
79
+ background-color: var(--color-fill-1);
80
+ }
81
+ ```
82
+
83
+ ### 主要颜色变量
84
+
85
+ > 完整变量列表请参考 [shared-styles 包文档](../../../packages/shared-styles/README.md#主要变量)
86
+
87
+ | 分类 | 变量 |
88
+ | ------ | --------------------------------------- |
89
+ | 品牌色 | `@Brand1-1` ~ `@Brand1-7` |
90
+ | 文字色 | `@color-text-1` ~ `@color-text-5` |
91
+ | 填充色 | `@color-fill-1` ~ `@color-fill-5` |
92
+ | 边框色 | `@color-border-1` ~ `@color-border-4` |
93
+ | 状态色 | `@Success-*`, `@Warning-*`, `@Danger-*` |
94
+
95
+ ## 使用示例
96
+
97
+ ```tsx
98
+ import { useTheme } from '@/hooks/useTheme';
99
+
100
+ const ThemeToggle: React.FC = () => {
101
+ const { isDark, toggleTheme } = useTheme();
102
+
103
+ return (
104
+ <Button onClick={toggleTheme}>{isDark ? <IconSun /> : <IconMoon />}</Button>
105
+ );
106
+ };
107
+ ```
108
+
109
+ ```less
110
+ // 组件样式自动适配主题
111
+ .my-card {
112
+ background-color: @color-text-5; // 亮色: 白色, 暗色: 深色
113
+ color: @color-text-1; // 亮色: 深色, 暗色: 白色
114
+ border: 1px solid @color-border-2;
115
+ }
116
+ ```
117
+
118
+ ## 注意事项
119
+
120
+ - `data-theme` 和 `arco-theme` 必须都设置在 `body` 元素上
121
+ - 主题 CSS 变量选择器格式:
122
+ - 暗色主题:`body[data-theme='dark']`
123
+ - 亮色主题:`body[data-theme='normal']`(注意:使用 `'normal'` 而非 `'light'`)
124
+ - Less 变量已封装 CSS 变量引用,优先使用 Less 变量(有编辑器提示)
125
+ - 主题状态持久化在 localStorage,key 通过 `THEME.STORAGE_KEY` 常量统一管理
126
+ - 未手动设置主题时,默认跟随系统偏好
127
+ - `useTheme` 使用 `useSyncExternalStore` 实现跨组件状态同步,确保所有调用 `useTheme` 的组件共享同一个主题状态
128
+
129
+ ### 常量定义
130
+
131
+ ```typescript
132
+ // src/common/constants.ts
133
+ export const THEME = {
134
+ STORAGE_KEY: '<%= ProjectName %>-theme',
135
+ DEFAULT: 'light' as const,
136
+ VALUES: ['light', 'dark'] as const,
137
+ } as const;
138
+ ```
139
+
140
+ ## 微前端子应用主题适配
141
+
142
+ ### 设计原则
143
+
144
+ - **主应用(layout)** 负责定义和注入主题 CSS 变量到 `body`
145
+ - **子应用** 只使用 Less 变量引用 CSS 变量,不重复定义
146
+ - 子应用的 Less 变量通过 `var(--xxx)` 自动适配主题切换
147
+
148
+ ### 子应用配置
149
+
150
+ #### 1. global.less - 仅导入 Less 变量
151
+
152
+ ```less
153
+ // apps/[子应用]/src/global.less
154
+ @import '<%= packageScope %>/shared-styles/variables-only';
155
+ // 不要使用 @import '<%= packageScope %>/shared-styles'(会包含 CSS 变量定义)
156
+ ```
157
+
158
+ #### 2. app.tsx - 开发环境条件注入
159
+
160
+ ```typescript
161
+ // apps/[子应用]/src/app.tsx
162
+
163
+ // 仅开发环境 + 独立运行时加载主题
164
+ if (process.env.NODE_ENV === 'development') {
165
+ if (typeof window !== 'undefined' && !window.__POWERED_BY_QIANKUN__) {
166
+ import('./styles/theme.less');
167
+ }
168
+ }
169
+ ```
170
+
171
+ > **关键点**:使用 `process.env.NODE_ENV === 'development'` 而不是运行时判断,确保生产构建时主题代码被 tree-shake 移除。
172
+
173
+ ### 打包体积对比
174
+
175
+ | 配置方式 | 生产 CSS 体积 | 是否推荐 |
176
+ | -------------------- | --------------------- | -------- |
177
+ | 直接导入主题 | ~9KB(含主题) | ❌ |
178
+ | 运行时条件导入 | ~9KB(含主题) | ❌ |
179
+ | **开发环境条件导入** | **~200B(不含主题)** | ✅ |
180
+
181
+ ### 验证方法
182
+
183
+ 构建后检查 CSS 是否包含主题变量:
184
+
185
+ ```bash
186
+ # 构建子应用
187
+ pnpm -C apps/[子应用] build
188
+
189
+ # 检查 CSS 内容(不应包含 --Brand1-6 等变量定义)
190
+ grep "Brand1-6" apps/[子应用]/dist/umi.css
191
+ # 期望:无输出
192
+
193
+ # 检查 CSS 体积
194
+ wc -c apps/[子应用]/dist/umi.css
195
+ # 期望:< 500 字节
196
+ ```
197
+
198
+ ### Arco Design 组件主题适配
199
+
200
+ 子应用使用 Arco Design 组件时,组件样式会自动跟随主应用的主题切换。
201
+
202
+ #### 原理
203
+
204
+ 1. 主应用加载 Arco Design 并暴露到 `window.arco`
205
+ 2. 主应用的 `arco.css` 包含 `arco-theme` 属性选择器
206
+ 3. 主应用切换主题时设置 `body[arco-theme="dark"]`
207
+ 4. 子应用的 Arco 组件(来自 window.arco)自动应用暗色样式
208
+
209
+ #### 子应用使用 Arco Design
210
+
211
+ > 详细配置请参考 [微前端模式 - 依赖共享机制](./feature-微前端模式.md#依赖共享机制)
212
+
213
+ ```tsx
214
+ // 子应用可以直接使用 Arco Design 组件
215
+ import { Button, Card, Message, Tag } from '@arco-design/web-react';
216
+
217
+ export default function Page() {
218
+ return (
219
+ <Card title="示例卡片">
220
+ <Button type="primary">主要按钮</Button>
221
+ <Tag color="arcoblue">标签</Tag>
222
+ </Card>
223
+ );
224
+ }
225
+ ```
226
+
227
+ **注意**:子应用需要配置 `externals` 将 Arco Design 排除打包,详见 [微前端模式文档](./feature-微前端模式.md#依赖共享机制)。
228
+
229
+ ## 相关文档
230
+
231
+ - [微前端模式](./feature-微前端模式.md) - qiankun 微前端架构与依赖共享
232
+ - [日志与常量](./arch-日志与常量.md) - Logger 工具与常量管理(含 THEME 常量)
233
+ - [shared-styles 包](../../../packages/shared-styles/README.md) - 共享样式包使用指南
234
+ - [提交规范](../../../docs/commit-message.md) - Git Commit 规范