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
@@ -0,0 +1,324 @@
1
+ # 时区工具函数
2
+
3
+ > 创建时间:2025-01-27
4
+
5
+ ## 概述
6
+
7
+ 本模块提供时区管理工具函数,支持 UTC-12 到 UTC+14 的全时区范围。基于 `dayjs` 及其 `utc`、`timezone` 插件实现,时区偏移量存储在 `localStorage` 中,支持用户切换时区。
8
+
9
+ **文件位置**:`apps/layout/src/common/helpers.ts`
10
+
11
+ ## 核心概念
12
+
13
+ ### 时区表示法
14
+
15
+ 本模块使用两种时区表示法:
16
+
17
+ | 表示法 | 格式 | 示例 | 说明 |
18
+ |--------|------|------|------|
19
+ | **UTC Offset** | `UTC+N` / `UTC-N` | `UTC+8`、`UTC-5` | 用于用户界面显示 |
20
+ | **IANA 时区** | `地区/城市` | `Asia/Shanghai`、`America/New_York` | 用于 dayjs 时区计算 |
21
+
22
+ ### 存储机制
23
+
24
+ 时区信息通过 `localStorage` 持久化:
25
+
26
+ | 存储键 | 常量 | 说明 |
27
+ |--------|------|------|
28
+ | `mico-cs-timezone` | `STORAGE_KEYS.TIMEZONE` | 存储数字(如 `8`)或字符串(如 `UTC+8`) |
29
+ | `mico-cs-timezone-region` | `STORAGE_KEYS.TIMEZONE_REGION` | 存储 IANA 时区标识(如 `Asia/Shanghai`) |
30
+
31
+ ## 常量定义
32
+
33
+ ### TIMEZONE
34
+
35
+ UTC 偏移量键的枚举映射,覆盖 UTC-12 到 UTC+14:
36
+
37
+ ```typescript
38
+ export const TIMEZONE = {
39
+ 'UTC-12': 'UTC-12',
40
+ 'UTC-11': 'UTC-11',
41
+ // ... 省略中间值
42
+ 'UTC+12': 'UTC+12',
43
+ 'UTC+13': 'UTC+13',
44
+ 'UTC+14': 'UTC+14',
45
+ } as const;
46
+
47
+ export type TTimezone = keyof typeof TIMEZONE;
48
+ ```
49
+
50
+ ### TIMEZONE_HASH
51
+
52
+ UTC 偏移量到 IANA 时区标识的映射表:
53
+
54
+ ```typescript
55
+ export const TIMEZONE_HASH: Record<TTimezone, string> = {
56
+ [TIMEZONE['UTC-12']]: 'Etc/GMT+12', // 无居住区
57
+ [TIMEZONE['UTC-11']]: 'Pacific/Pago_Pago', // 帕果帕果,美属萨摩亚
58
+ [TIMEZONE['UTC-10']]: 'Pacific/Honolulu', // 檀香山,夏威夷
59
+ [TIMEZONE['UTC-9']]: 'America/Anchorage', // 安克雷奇,阿拉斯加
60
+ [TIMEZONE['UTC-8']]: 'America/Los_Angeles', // 洛杉矶
61
+ [TIMEZONE['UTC-7']]: 'America/Denver', // 丹佛
62
+ [TIMEZONE['UTC-6']]: 'America/Chicago', // 芝加哥
63
+ [TIMEZONE['UTC-5']]: 'America/New_York', // 纽约
64
+ [TIMEZONE['UTC-4']]: 'America/Puerto_Rico', // 波多黎各
65
+ [TIMEZONE['UTC-3']]: 'America/Sao_Paulo', // 圣保罗
66
+ [TIMEZONE['UTC-2']]: 'America/Noronha', // 费尔南多岛
67
+ [TIMEZONE['UTC-1']]: 'Atlantic/Azores', // 亚速尔群岛
68
+ [TIMEZONE['UTC+0']]: 'Europe/London', // 伦敦
69
+ [TIMEZONE['UTC+1']]: 'Europe/Paris', // 巴黎
70
+ [TIMEZONE['UTC+2']]: 'Europe/Kyiv', // 基辅
71
+ [TIMEZONE['UTC+3']]: 'Europe/Moscow', // 莫斯科
72
+ [TIMEZONE['UTC+4']]: 'Asia/Dubai', // 迪拜
73
+ [TIMEZONE['UTC+5']]: 'Asia/Tashkent', // 塔什干
74
+ [TIMEZONE['UTC+6']]: 'Asia/Dhaka', // 达卡
75
+ [TIMEZONE['UTC+7']]: 'Asia/Bangkok', // 曼谷
76
+ [TIMEZONE['UTC+8']]: 'Asia/Shanghai', // 上海(默认)
77
+ [TIMEZONE['UTC+9']]: 'Asia/Tokyo', // 东京
78
+ [TIMEZONE['UTC+10']]: 'Australia/Sydney', // 悉尼
79
+ [TIMEZONE['UTC+11']]: 'Pacific/Noumea', // 努美阿
80
+ [TIMEZONE['UTC+12']]: 'Pacific/Auckland', // 奥克兰
81
+ [TIMEZONE['UTC+13']]: 'Pacific/Tongatapu', // 汤加
82
+ [TIMEZONE['UTC+14']]: 'Pacific/Kiritimati', // 基里巴斯圣诞岛
83
+ };
84
+ ```
85
+
86
+ > **说明**:地理上有 24 个时区,但实际应用中存在 UTC+13 和 UTC+14(太平洋岛国),因此本模块覆盖 27 个时区。
87
+
88
+ ## API 参考
89
+
90
+ ### 时区转换函数
91
+
92
+ #### utcOffsetToTimezone
93
+
94
+ 将 UTC 偏移量数字转换为 `UTC+N` 格式字符串。
95
+
96
+ ```typescript
97
+ function utcOffsetToTimezone(utcOffset: number): string;
98
+ ```
99
+
100
+ | 参数 | 类型 | 说明 |
101
+ |------|------|------|
102
+ | `utcOffset` | `number` | UTC 偏移量,如 `8` 表示 UTC+8 |
103
+
104
+ **示例**:
105
+
106
+ ```typescript
107
+ utcOffsetToTimezone(8); // => 'UTC+8'
108
+ utcOffsetToTimezone(-5); // => 'UTC-5'
109
+ utcOffsetToTimezone(0); // => 'UTC+0'
110
+ ```
111
+
112
+ #### utcOffsetToTimeZoneStr
113
+
114
+ 将 UTC 偏移量转换为 IANA 时区标识。
115
+
116
+ ```typescript
117
+ function utcOffsetToTimeZoneStr(utcOffset: number): string;
118
+ ```
119
+
120
+ **回退逻辑**:
121
+
122
+ 1. 查找 `TIMEZONE_HASH` 映射
123
+ 2. 若无匹配,使用 `dayjs.tz.guess()` 推断浏览器时区
124
+ 3. 最终回退到 `Asia/Shanghai`
125
+
126
+ **示例**:
127
+
128
+ ```typescript
129
+ utcOffsetToTimeZoneStr(8); // => 'Asia/Shanghai'
130
+ utcOffsetToTimeZoneStr(-5); // => 'America/New_York'
131
+ ```
132
+
133
+ ### 时区读写函数
134
+
135
+ #### getTimezoneOffset
136
+
137
+ 从 `localStorage` 获取时区偏移量数字。
138
+
139
+ ```typescript
140
+ function getTimezoneOffset(): number;
141
+ ```
142
+
143
+ **返回值**:偏移量数字,默认 `8`(UTC+8)
144
+
145
+ #### getTimezone
146
+
147
+ 获取当前时区的 IANA 标识。
148
+
149
+ ```typescript
150
+ function getTimezone(): string;
151
+ ```
152
+
153
+ **返回值**:IANA 时区标识(如 `Asia/Shanghai`)
154
+
155
+ **回退逻辑**:
156
+
157
+ 1. 从 `localStorage` 读取存储值
158
+ 2. 若为数字字符串,转换为 `UTC+N` 格式后查找 IANA 映射
159
+ 3. 若已是 `UTC+N` 格式,直接查找 IANA 映射
160
+ 4. 若无匹配,使用 `dayjs.tz.guess()` 推断
161
+ 5. 最终回退到 `Asia/Shanghai`
162
+
163
+ #### getCurrentTimezone
164
+
165
+ 获取当前时区的 `UTC+N` 格式字符串。
166
+
167
+ ```typescript
168
+ function getCurrentTimezone(): string;
169
+ ```
170
+
171
+ **返回值**:UTC 偏移量字符串(如 `UTC+8`),默认 `UTC+8`
172
+
173
+ #### setTimezone
174
+
175
+ 设置时区到 `localStorage`。
176
+
177
+ ```typescript
178
+ function setTimezone(timezone: string): void;
179
+ ```
180
+
181
+ | 参数 | 类型 | 说明 |
182
+ |------|------|------|
183
+ | `timezone` | `string` | 时区字符串,如 `UTC+8` 或偏移量数字字符串如 `8` |
184
+
185
+ #### getTimezoneRegion
186
+
187
+ 获取时区地区(IANA 标识)。
188
+
189
+ ```typescript
190
+ function getTimezoneRegion(): string;
191
+ ```
192
+
193
+ **返回值**:时区地区字符串(如 `Asia/Shanghai`),未设置则返回空字符串
194
+
195
+ #### setTimezoneRegion
196
+
197
+ 设置时区地区到 `localStorage`。
198
+
199
+ ```typescript
200
+ function setTimezoneRegion(region: string): void;
201
+ ```
202
+
203
+ | 参数 | 类型 | 说明 |
204
+ |------|------|------|
205
+ | `region` | `string` | IANA 时区标识,如 `Asia/Shanghai` |
206
+
207
+ ## 使用示例
208
+
209
+ ### 初始化时区
210
+
211
+ ```typescript
212
+ import { setTimezone, setTimezoneRegion } from '@/common/helpers';
213
+
214
+ // 用户选择 UTC+9 (东京)
215
+ setTimezone('9');
216
+ setTimezoneRegion('Asia/Tokyo');
217
+ ```
218
+
219
+ ### 获取当前时区
220
+
221
+ ```typescript
222
+ import { getCurrentTimezone, getTimezoneRegion } from '@/common/helpers';
223
+
224
+ const timezone = getCurrentTimezone(); // => 'UTC+8'
225
+ const region = getTimezoneRegion(); // => 'Asia/Shanghai'
226
+ ```
227
+
228
+ ### 用户时区切换(AvatarDropdown)
229
+
230
+ **文件**:`apps/layout/src/components/RightContent/AvatarDropdown.tsx`
231
+
232
+ 用户头像下拉菜单中的时区选择器,允许用户切换时区并刷新页面:
233
+
234
+ ```typescript
235
+ import {
236
+ getCurrentTimezone,
237
+ getTimezoneRegion,
238
+ setTimezoneRegion as setTimezoneRegionToStorage,
239
+ setTimezone as setTimezoneToStorage,
240
+ utcOffsetToTimezone,
241
+ } from '@/common/helpers';
242
+
243
+ // 获取当前时区用于显示
244
+ const [currentTimezone, setCurrentTimezone] = useState(getCurrentTimezone());
245
+
246
+ // 用户切换时区时
247
+ const handleTimezoneChange = (key: string) => {
248
+ const lastSlashIndex = key.lastIndexOf('/');
249
+ const region = key.substring(0, lastSlashIndex); // 如 "Asia/Shanghai"
250
+ const utcOffsetStr = key.substring(lastSlashIndex + 1); // 如 "8"
251
+
252
+ // 保存到 localStorage
253
+ setTimezoneToStorage(utcOffsetStr);
254
+ setTimezoneRegionToStorage(region);
255
+
256
+ // 刷新页面使时区生效
257
+ window.location.reload();
258
+ };
259
+ ```
260
+
261
+ ## 数据流
262
+
263
+ ```
264
+ 用户选择时区
265
+
266
+ setTimezone('9') / setTimezoneRegion('Asia/Tokyo')
267
+
268
+ localStorage 存储
269
+
270
+ getCurrentTimezone() / getTimezone()
271
+
272
+ 返回 'UTC+9' / 'Asia/Tokyo'
273
+ ```
274
+
275
+ ## 注意事项
276
+
277
+ 1. **默认时区为 UTC+8**:如果 `localStorage` 中没有存储时区信息,所有函数默认使用 `Asia/Shanghai`(UTC+8)。
278
+
279
+ 2. **存储兼容性**:时区存储支持两种格式:
280
+ - 数字字符串(如 `"8"`):推荐格式
281
+ - UTC 格式(如 `"UTC+8"`):兼容格式
282
+
283
+ 读取时会自动兼容两种格式。
284
+
285
+ 3. **时区列表来源**:时区列表支持两种模式:
286
+
287
+ **模式一:静态列表(默认)**
288
+
289
+ 未配置 `timezoneListUrl` 时,使用内置的静态时区列表(覆盖 UTC-12 到 UTC+14 共 27 个时区)。
290
+
291
+ **模式二:API 获取**
292
+
293
+ 通过 `window.__MICO_CONFIG__.timezoneListUrl` 配置 API 地址:
294
+
295
+ ```javascript
296
+ // 在 index.html 或应用初始化时配置
297
+ window.__MICO_CONFIG__ = {
298
+ timezoneListUrl: '/custom/api/getTimezoneList',
299
+ };
300
+ ```
301
+
302
+ API 返回格式:
303
+ ```typescript
304
+ interface ITimezone {
305
+ utc_offset: number; // UTC 偏移量
306
+ region: string; // IANA 时区标识
307
+ }
308
+ ```
309
+
310
+
311
+ ## 文件清单
312
+
313
+ | 文件路径 | 说明 |
314
+ | --- | --- |
315
+ | `apps/layout/src/common/helpers.ts` | 时区工具函数实现 |
316
+ | `apps/layout/src/constants/index.ts` | 存储键常量定义(`TIMEZONE`、`STORAGE_KEYS` 等) |
317
+ | `apps/layout/src/services/config/index.ts` | 时区列表 API 服务 |
318
+ | `apps/layout/src/services/config/type.ts` | 时区类型定义 |
319
+ | `apps/layout/src/components/RightContent/AvatarDropdown.tsx` | 时区切换 UI 组件 |
320
+
321
+ ## 相关文档
322
+
323
+ - [AvatarDropdown 组件](../apps/layout/docs/feature-avatar-dropdown.md)
324
+
@@ -6,73 +6,93 @@
6
6
 
7
7
  export default {
8
8
  // 获取用户信息
9
- // 'GET /api/user/info': {
9
+ 'GET /api/user/info': {
10
+ "code": 200,
11
+ "data": {
12
+ "id": 381,
13
+ "last_login": "2026-03-06T02:37:10.050735Z",
14
+ "is_superuser": true,
15
+ "username": "本地测试mock用户",
16
+ "first_name": "",
17
+ "last_name": "",
18
+ "email": "本地测试mock用户@micous.com",
19
+ "is_staff": true,
20
+ "is_active": true,
21
+ "type": 1,
22
+ "phone": "",
23
+ "agency_id": 0,
24
+ "avatar": "https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png",
25
+ "user_name": "Easton",
26
+ "permission_tree": [
27
+ ],
28
+ "miss_permissions": [],
29
+ "side_menus": [
30
+ '首页',
31
+ '示例模块.示例页面',
32
+ '微应用示例.子应用页面',
33
+ '外部链接',
34
+ '权限管理',
35
+ ],
36
+ "region_permissions": []
37
+ },
38
+ "msg": "ok"
39
+ },
40
+
41
+ // 获取统计数据
42
+ // 'GET /api/dashboard/stats': {
10
43
  // success: true,
11
44
  // data: {
12
- // id: 1001,
13
- // name: '张三',
14
- // email: 'zhangsan@example.com',
15
- // avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=homepage',
16
- // role: 'admin',
17
- // department: '技术部',
45
+ // totalUsers: 12580,
46
+ // activeUsers: 3420,
47
+ // pendingTasks: 156,
48
+ // completedTasks: 8934,
49
+ // lastUpdated: new Date().toISOString(),
18
50
  // },
19
51
  // },
20
52
 
21
- // 获取统计数据
22
- 'GET /api/dashboard/stats': {
23
- success: true,
24
- data: {
25
- totalUsers: 12580,
26
- activeUsers: 3420,
27
- pendingTasks: 156,
28
- completedTasks: 8934,
29
- lastUpdated: new Date().toISOString(),
30
- },
31
- },
32
-
33
53
  // 获取列表数据
34
- 'GET /api/items': {
35
- success: true,
36
- data: {
37
- list: [
38
- {
39
- id: 1,
40
- title: '待审核内容 A',
41
- status: 'pending',
42
- createdAt: '2025-12-27 10:00:00',
43
- },
44
- {
45
- id: 2,
46
- title: '待审核内容 B',
47
- status: 'pending',
48
- createdAt: '2025-12-27 09:30:00',
49
- },
50
- {
51
- id: 3,
52
- title: '已通过内容 C',
53
- status: 'approved',
54
- createdAt: '2025-12-26 15:00:00',
55
- },
56
- {
57
- id: 4,
58
- title: '已拒绝内容 D',
59
- status: 'rejected',
60
- createdAt: '2025-12-26 14:00:00',
61
- },
62
- ],
63
- total: 4,
64
- page: 1,
65
- pageSize: 10,
66
- },
67
- },
54
+ // 'GET /api/items': {
55
+ // success: true,
56
+ // data: {
57
+ // list: [
58
+ // {
59
+ // id: 1,
60
+ // title: '待审核内容 A',
61
+ // status: 'pending',
62
+ // createdAt: '2025-12-27 10:00:00',
63
+ // },
64
+ // {
65
+ // id: 2,
66
+ // title: '待审核内容 B',
67
+ // status: 'pending',
68
+ // createdAt: '2025-12-27 09:30:00',
69
+ // },
70
+ // {
71
+ // id: 3,
72
+ // title: '已通过内容 C',
73
+ // status: 'approved',
74
+ // createdAt: '2025-12-26 15:00:00',
75
+ // },
76
+ // {
77
+ // id: 4,
78
+ // title: '已拒绝内容 D',
79
+ // status: 'rejected',
80
+ // createdAt: '2025-12-26 14:00:00',
81
+ // },
82
+ // ],
83
+ // total: 4,
84
+ // page: 1,
85
+ // pageSize: 10,
86
+ // },
87
+ // },
68
88
 
69
89
  // POST 请求示例
70
- 'POST /api/items/approve': (req: any, res: any) => {
71
- const { id } = req.body || {};
72
- res.json({
73
- success: true,
74
- message: `Item ${id} approved successfully`,
75
- data: { id, status: 'approved' },
76
- });
77
- },
90
+ // 'POST /api/items/approve': (req: any, res: any) => {
91
+ // const { id } = req.body || {};
92
+ // res.json({
93
+ // success: true,
94
+ // message: `Item ${id} approved successfully`,
95
+ // data: { id, status: 'approved' },
96
+ // });
97
+ // },
78
98
  };
@@ -2,10 +2,120 @@
2
2
  * Mock 菜单数据
3
3
  * 用于开发环境测试
4
4
  *
5
- * 注意:实际数据存放在 menus.json 中
6
- * 修改菜单数据请编辑 menus.json 文件,不会触发服务器重启
5
+ * 菜单结构说明:
6
+ * - id: 菜单唯一标识
7
+ * - name: 菜单名称
8
+ * - type: 'page' | 'group' (page: 页面, group: 分组)
9
+ * - path: 路由路径 (type=page 时与 PAGES 中的 route 一致, group 类型为 null)
10
+ * - icon: 图标名称
11
+ * - enabled: 是否启用
12
+ * - sortOrder: 排序权重
13
+ * - pageId: 关联的页面 ID (通过 pageId 与 __MICO_PAGES__ 关联)
14
+ * - children: 子菜单数组
7
15
  */
8
- import mockMenusData from './menus.json';
9
16
 
10
- export const mockMenus = mockMenusData;
17
+ import type { MenuItem } from '@/common/menu/types';
18
+
19
+ /** Mock 菜单项 */
20
+ type MockMenuItem = Omit<MenuItem, 'children'> & {
21
+ children: MockMenuItem[];
22
+ };
23
+
24
+ const mockMenus: MockMenuItem[] = [
25
+ {
26
+ id: 1,
27
+ name: '首页',
28
+ nameEn: 'Home',
29
+ nameKey: 'cs_web_menu_home',
30
+ type: 'page',
31
+ path: '/',
32
+ icon: 'Home',
33
+ enabled: true,
34
+ sortOrder: 0,
35
+ pageId: 1,
36
+ children: [],
37
+ },
38
+ {
39
+ id: 2,
40
+ name: '示例模块',
41
+ nameEn: 'Example Module',
42
+ nameKey: 'cs_web_menu_example_module',
43
+ type: 'group',
44
+ path: null,
45
+ icon: 'List',
46
+ enabled: true,
47
+ sortOrder: 1,
48
+ pageId: null,
49
+ children: [
50
+ {
51
+ id: 3,
52
+ name: '示例页面',
53
+ nameEn: 'Example Page',
54
+ nameKey: 'cs_web_menu_example_page',
55
+ type: 'page',
56
+ path: '/example/page',
57
+ icon: 'File',
58
+ enabled: true,
59
+ sortOrder: 1,
60
+ pageId: 45,
61
+ children: [],
62
+ },
63
+ ],
64
+ },
65
+ {
66
+ id: 5,
67
+ name: '微应用示例',
68
+ nameEn: 'Microapp Example',
69
+ nameKey: 'cs_web_menu_microapp_example',
70
+ type: 'group',
71
+ path: null,
72
+ icon: 'Apps',
73
+ enabled: true,
74
+ sortOrder: 2,
75
+ pageId: null,
76
+ children: [
77
+ {
78
+ id: 6,
79
+ name: '子应用页面',
80
+ nameEn: 'Subapp Page',
81
+ nameKey: 'cs_web_menu_subapp_page',
82
+ type: 'page',
83
+ path: '/subapp',
84
+ icon: 'Desktop',
85
+ enabled: true,
86
+ sortOrder: 1,
87
+ pageId: 55,
88
+ children: [],
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ id: 7,
94
+ name: '外部链接',
95
+ nameEn: 'External Link',
96
+ nameKey: 'cs_web_menu_external_link',
97
+ type: 'link',
98
+ path: 'https://github.com',
99
+ icon: 'Link',
100
+ enabled: true,
101
+ sortOrder: 3,
102
+ pageId: null,
103
+ children: [],
104
+ },
105
+ {
106
+ id: 8,
107
+ name: '权限管理',
108
+ nameEn: 'Permission Management',
109
+ nameKey: 'cs_web_menu_permission_management',
110
+ type: 'page',
111
+ path: '/permission',
112
+ icon: 'Permission',
113
+ enabled: true,
114
+ sortOrder: 3,
115
+ pageId: null,
116
+ adminOnly: true,
117
+ children: [],
118
+ },
119
+ ];
120
+
11
121
  export default mockMenus;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Mock 页面数据
3
+ * 用于开发环境测试,模拟 window.__MICO_PAGES__ 数据
4
+ *
5
+ * 页面结构说明:
6
+ * - id: 页面唯一标识
7
+ * - name: 页面名称
8
+ * - route: 路由路径
9
+ * - htmlUrl: 微应用 HTML 入口 URL
10
+ * - jsUrls: 额外 JS 资源
11
+ * - cssUrls: 额外 CSS 资源
12
+ * - prefixPath: 路由前缀路径
13
+ * - routeMode: 路由匹配模式 (prefix | exact)
14
+ * - enabled: 是否启用
15
+ * - accessControlEnabled: 是否开启权限控制
16
+ * - adminOnly: 是否仅超级管理员可见
17
+ * - routeKey: 路由权限标识
18
+ * - mainDocumentId: 关联的主文档 ID
19
+ * - version: 当前版本号
20
+ */
21
+
22
+ import type { PublicPageItem } from '@/common/menu/types';
23
+
24
+ const mockPages: PublicPageItem[] = [
25
+ {
26
+ id: 125,
27
+ name: '登录页',
28
+ nameEn: 'Login',
29
+ nameKey: 'page.user.login',
30
+ route: '/user/login',
31
+ base: '/user/login',
32
+ htmlUrl:
33
+ 'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.4/login/index.html',
34
+ jsUrls: [],
35
+ cssUrls: [],
36
+ prefixPath: '/user',
37
+ routeMode: 'exact',
38
+ enabled: true,
39
+ accessControlEnabled: false,
40
+ adminOnly: false,
41
+ routeKey: null,
42
+ mainDocumentId: 59,
43
+ version: 'v2026.02.26-04.21-000',
44
+ },
45
+ {
46
+ id: 124,
47
+ name: '权限管理',
48
+ nameEn: 'Permission Management',
49
+ nameKey: 'page.permission',
50
+ route: '/permission',
51
+ base: '/',
52
+ htmlUrl:
53
+ 'https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.4/permission/index.html',
54
+ jsUrls: [],
55
+ cssUrls: [],
56
+ prefixPath: '',
57
+ routeMode: 'prefix',
58
+ enabled: true,
59
+ accessControlEnabled: true,
60
+ adminOnly: true,
61
+ routeKey: null,
62
+ mainDocumentId: 59,
63
+ version: 'v2026.02.26-04.13-419',
64
+ },
65
+ {
66
+ id: 115,
67
+ name: '兜底',
68
+ nameEn: 'Fallback',
69
+ nameKey: 'page.fallback',
70
+ route: '/*',
71
+ base: '/',
72
+ htmlUrl: '',
73
+ jsUrls: [],
74
+ cssUrls: [],
75
+ prefixPath: '',
76
+ routeMode: 'prefix',
77
+ enabled: true,
78
+ accessControlEnabled: true,
79
+ adminOnly: false,
80
+ routeKey: null,
81
+ mainDocumentId: 59,
82
+ version: 'v2026.01.26-14.25-095',
83
+ },
84
+ ];
85
+
86
+ export default mockPages;