generator-mico-cli 0.2.20 → 0.2.21

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 (29) hide show
  1. package/README.md +29 -0
  2. package/bin/mico.js +124 -5
  3. package/generators/micro-react/index.js +76 -17
  4. package/generators/micro-react/templates/CLAUDE.md +11 -5
  5. package/generators/micro-react/templates/_gitignore +2 -0
  6. package/generators/micro-react/templates/apps/layout/config/config.ts +21 -0
  7. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +8 -6
  8. 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 +60 -35
  9. 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 +7 -2
  10. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +4 -2
  11. package/generators/micro-react/templates/apps/layout/mock/menus.ts +7 -2
  12. package/generators/micro-react/templates/apps/layout/package.json +3 -2
  13. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +3 -15
  14. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +4 -0
  15. package/generators/micro-react/templates/apps/layout/src/global.less +1 -2
  16. package/generators/micro-react/templates/package.json +2 -1
  17. package/generators/subapp-react/index.js +81 -13
  18. package/generators/subapp-react/templates/homepage/config/config.dev.ts +8 -1
  19. package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
  20. package/generators/subapp-react/templates/homepage/config/routes.ts +1 -1
  21. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  22. package/generators/subapp-react/templates/homepage/package.json +3 -2
  23. package/generators/subapp-react/templates/homepage/src/app.tsx +1 -1
  24. package/generators/subapp-react/templates/homepage/src/common/request.ts +2 -2
  25. package/generators/subapp-react/templates/homepage/src/global.less +2 -1
  26. package/generators/subapp-react/templates/homepage/src/pages/index.less +1 -1
  27. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +27 -27
  28. package/lib/utils.js +200 -2
  29. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # 菜单权限控制
2
2
 
3
- > 创建时间:2026-01-24 更新时间:2026-01-27
3
+ > 创建时间:2026-01-24 更新时间:2026-02-08
4
4
 
5
5
  ## 功能概述
6
6
 
@@ -92,6 +92,10 @@
92
92
  ├── 是 → 允许访问所有菜单
93
93
 
94
94
 
95
+ 菜单项 adminOnly === true?
96
+ ├── 是 → 禁止访问(仅超级管理员可见)
97
+
98
+
95
99
  检查 side_menus 白名单
96
100
  ├── 精确匹配:menuPath === side_menus[i]
97
101
  ├── 前缀匹配:side_menus[i].startsWith(menuPath + '.')
@@ -241,7 +245,7 @@ export const NO_PERMISSION_ROUTE_LIST: string[] = ['/403', '/404'];
241
245
  │ └── 配置队列 ✅ 精确匹配 "列队管理.配置队列"
242
246
  ├── 质量管理 ❌ 不在白名单
243
247
  │ └── 抽样检查 ❌ 不在白名单
244
- └── 权限管理 ❌ 硬编码禁止(非超级用户)
248
+ └── 权限管理 ❌ adminOnly=true,非超级用户不可见
245
249
  ```
246
250
 
247
251
  ### Layout 中的权限判断
@@ -288,6 +292,7 @@ if (!isAuthReady) {
288
292
  | 免权限路由的菜单 | 显示全部 | 用户访问公开页面时应能看到所有导航选项 |
289
293
  | 免权限路由的子应用 | 直接加载 | 不等待 currentUser,避免加载卡住 |
290
294
  | 静态路由不受权限控制 | 默认允许访问 | 见下方"静态路由与动态路由"说明 |
295
+ | adminOnly 判断 | 读取菜单数据字段 | 替代硬编码菜单名称匹配,由后端数据驱动,支持多语言且无需前端维护 |
291
296
 
292
297
  ## 静态路由与动态路由
293
298
 
@@ -307,12 +307,13 @@ getCurrentTimezone() / getTimezone()
307
307
  }
308
308
  ```
309
309
 
310
+
310
311
  ## 文件清单
311
312
 
312
313
  | 文件路径 | 说明 |
313
- |----------|------|
314
+ | --- | --- |
314
315
  | `apps/layout/src/common/helpers.ts` | 时区工具函数实现 |
315
- | `apps/layout/src/common/auth/type.ts` | 存储键常量定义(`STORAGE_KEYS.TIMEZONE` 等) |
316
+ | `apps/layout/src/constants/index.ts` | 存储键常量定义(`TIMEZONE`、`STORAGE_KEYS` 等) |
316
317
  | `apps/layout/src/services/config/index.ts` | 时区列表 API 服务 |
317
318
  | `apps/layout/src/services/config/type.ts` | 时区类型定义 |
318
319
  | `apps/layout/src/components/RightContent/AvatarDropdown.tsx` | 时区切换 UI 组件 |
@@ -320,3 +321,4 @@ getCurrentTimezone() / getTimezone()
320
321
  ## 相关文档
321
322
 
322
323
  - [AvatarDropdown 组件](../apps/layout/docs/feature-avatar-dropdown.md)
324
+
@@ -21,7 +21,10 @@
21
21
  import type { MenuItem, PageConfig } from '@/common/menu/types';
22
22
 
23
23
  /** Mock 页面配置 - 只需要核心字段 */
24
- type MockPageConfig = Pick<PageConfig, 'id' | 'name' | 'route' | 'enabled' | 'htmlUrl' | 'jsUrls' | 'cssUrls'>;
24
+ type MockPageConfig = Pick<PageConfig,
25
+ | 'id' | 'name' | 'route' | 'enabled' | 'htmlUrl' | 'jsUrls' | 'cssUrls'
26
+ | 'adminOnly'
27
+ >;
25
28
 
26
29
  /** Mock 菜单项 - page 字段使用简化类型,包含多语言字段 */
27
30
  type MockMenuItem = Omit<MenuItem, 'page' | 'children'> & {
@@ -155,12 +158,14 @@ const mockMenus: MockMenuItem[] = [
155
158
  "enabled": true,
156
159
  "sortOrder": 3,
157
160
  "pageId": null,
161
+ "adminOnly": true,
158
162
  "page": {
159
163
  "id": 8,
160
164
  "name": "permission",
161
165
  "route": "/permission",
162
166
  "enabled": true,
163
- "htmlUrl": "//localhost:8010",
167
+ "adminOnly": true,
168
+ "htmlUrl": "https://cdn-portal.micoplatform.com/portal-center/common-web/0.0.1/permission/index.html",
164
169
  "jsUrls": [],
165
170
  "cssUrls": []
166
171
  },
@@ -25,8 +25,6 @@
25
25
  "@mico-platform/ui": "<%= micoUiVersion %>",
26
26
  "@mico-platform/theme": "<%= themeVersion %>",
27
27
  "@umijs/max": "^4.6.15",
28
- "babel-plugin-dynamic-import-node": "^2.3.3",
29
- "cross-env": "^10.1.0",
30
28
  "dayjs": "^1.11.19",
31
29
  "qiankun": "^2.10.16",
32
30
  "react": "^18.2.0",
@@ -37,6 +35,9 @@
37
35
  "@types/react": "^18.0.33",
38
36
  "@types/react-dom": "^18.0.11",
39
37
  "@types/spark-md5": "^3.0.5",
38
+ "babel-plugin-dynamic-import-node": "^2.3.3",
39
+ "babel-plugin-import": "^1.13.8",
40
+ "cross-env": "^10.1.0",
40
41
  "lint-staged": "^13.2.0",
41
42
  "prettier": "^2.8.7",
42
43
  "prettier-plugin-organize-imports": "^3.2.2",
@@ -55,14 +55,11 @@ export const getMenuIdentifier = (
55
55
  return item.nameEn || item.nameKey || '';
56
56
  };
57
57
 
58
- // 权限管理菜单的多格式标识符(用于硬编码权限判断)
59
- const PERMISSION_MENU_IDENTIFIERS = ['权限管理', 'Permission', 'permission'];
60
-
61
58
  /**
62
59
  * 检查菜单路径是否允许访问(白名单逻辑)
63
60
  * - 免权限校验路由,始终允许访问
64
61
  * - 超级用户可以访问所有菜单
65
- * - 非超级用户不能访问"权限管理"
62
+ * - 非超级用户不能访问 adminOnly 菜单
66
63
  * - 菜单路径在 sideMenus 中,或是 sideMenus 中某项的前缀(父级菜单)
67
64
  */
68
65
  const isMenuAllowed = (
@@ -82,11 +79,8 @@ const isMenuAllowed = (
82
79
  // 超级用户可以访问所有菜单
83
80
  if (isSuperuserUser(options.isSuperuser)) return true;
84
81
 
85
- // 非超级用户不能访问"权限管理"(支持多格式匹配)
86
- if (PERMISSION_MENU_IDENTIFIERS.includes(menuPath)) return false;
87
-
88
- // 非超级用户不能访问"权限管理"
89
- if (menuPath === '权限管理') return false;
82
+ // 非超级用户不能访问 adminOnly 菜单
83
+ if (item.adminOnly) return false;
90
84
 
91
85
  const sideMenus = options.sideMenus || [];
92
86
 
@@ -103,12 +97,6 @@ const isMenuAllowed = (
103
97
  });
104
98
  };
105
99
 
106
- export const isRouteAllowed = (
107
- menuPath: string,
108
- options: MenuFilterOptions = {},
109
- ): boolean => {
110
- return isMenuAllowed(menuPath, options);
111
- };
112
100
  /**
113
101
  * 根据权限过滤菜单项(白名单逻辑)
114
102
  */
@@ -28,6 +28,8 @@ export interface PageConfig {
28
28
  prefixPath: string;
29
29
  /** 路由匹配模式 */
30
30
  routeMode: PageRouteMode;
31
+ /** 是否仅超级管理员可见 */
32
+ adminOnly?: boolean;
31
33
  /** 关联的主文档 ID */
32
34
  mainDocumentId: number;
33
35
  /** 所属工作空间子域名 */
@@ -67,6 +69,8 @@ export interface MenuItem {
67
69
  pageId: number | null;
68
70
  /** 页面配置(type=page 时存在) */
69
71
  page: PageConfig | null;
72
+ /** 是否仅超级管理员可见 */
73
+ adminOnly?: boolean;
70
74
  children: MenuItem[];
71
75
  }
72
76
 
@@ -8,7 +8,6 @@
8
8
  }
9
9
 
10
10
  #root {
11
- height: 100vh;
12
- min-height: 800px;
11
+ min-height: 100vh;
13
12
  display: flex;
14
13
  }
@@ -26,7 +26,8 @@
26
26
  "lint-staged": "pnpm exec lint-staged --quiet",
27
27
  "prepare": "husky",
28
28
  "test": "dotenv -e .env -e .env.local -- turbo run test",
29
- "create:umi-app": "./scripts/create-umi-app.sh"
29
+ "create:umi-app": "./scripts/create-umi-app.sh",
30
+ "upgrade:mico": "npx @mico-platform/mico-up"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@commitlint/cli": "^19.5.0",
@@ -9,10 +9,10 @@ const {
9
9
  collectFiles,
10
10
  transformDestPath,
11
11
  isTemplateFile,
12
- getLatestNpmVersion,
12
+ getPackageVersionsParallel,
13
13
  setupErrorHandlers,
14
14
  createLogger,
15
- // isVerbose,
15
+ loadMicorc,
16
16
  } = require('../../lib/utils');
17
17
 
18
18
  const IGNORE_LIST = require('./ignore-list.json');
@@ -24,6 +24,18 @@ module.exports = class extends Generator {
24
24
  initializing() {
25
25
  this.monorepoRoot = process.cwd();
26
26
  this.logger = createLogger(this);
27
+
28
+ // 检查 dry-run 模式
29
+ this.isDryRun = this.options.dryRun || process.env.MICO_DRY_RUN === '1';
30
+
31
+ // 加载 .micorc 配置
32
+ const { config: rcConfig, configPath } = loadMicorc(this.monorepoRoot);
33
+ this.rcConfig = rcConfig;
34
+ if (configPath) {
35
+ this.logger.verbose('Loaded config from:', configPath);
36
+ this.logger.verbose('Config:', JSON.stringify(rcConfig, null, 2));
37
+ }
38
+
27
39
  const appsDir = path.join(this.monorepoRoot, 'apps');
28
40
  const workspaceFile = path.join(this.monorepoRoot, 'pnpm-workspace.yaml');
29
41
 
@@ -77,13 +89,14 @@ module.exports = class extends Generator {
77
89
  }
78
90
 
79
91
  const detectedScope = this._detectPackageScope();
92
+ const rc = this.rcConfig || {};
80
93
 
81
94
  this.answers = await this.prompt([
82
95
  {
83
96
  type: 'input',
84
97
  name: 'appName',
85
98
  message: 'Sub app name',
86
- default: 'subapp',
99
+ default: rc.defaultSubappName || 'subapp',
87
100
  filter: (input) => toKebab(input),
88
101
  validate: (input) => {
89
102
  const value = toKebab(input);
@@ -99,7 +112,7 @@ module.exports = class extends Generator {
99
112
  type: 'input',
100
113
  name: 'packageScope',
101
114
  message: 'Package scope',
102
- default: detectedScope || '@my-project',
115
+ default: rc.packageScope || detectedScope || '@my-project',
103
116
  validate: (input) => {
104
117
  if (!input) return 'Package scope is required';
105
118
  if (!input.startsWith('@')) return 'Package scope must start with @';
@@ -122,7 +135,7 @@ module.exports = class extends Generator {
122
135
  }
123
136
  }
124
137
 
125
- writing() {
138
+ async writing() {
126
139
  try {
127
140
  if (!fs.existsSync(this.templateDir)) {
128
141
  console.error('');
@@ -132,20 +145,25 @@ module.exports = class extends Generator {
132
145
  process.exit(1);
133
146
  }
134
147
 
135
- this.log('');
136
- this.log(`📦 Creating sub-app: ${this.appName}`);
137
- this.log(` Destination: apps/${this.appName}`);
138
- this.log('');
139
-
140
148
  this.logger.verbose('Template directory:', this.templateDir);
141
149
  this.logger.verbose('Destination directory:', this.destDir);
142
150
 
143
151
  // 在 mico_cli 根目录执行 npm view,以使用该目录 .npmrc 中的 Nexus 认证
144
152
  const cliRoot = path.resolve(__dirname, '../..');
145
- this.logger.verbose('Fetching latest package versions...');
153
+ this.logger.verbose('Fetching latest package versions (parallel)...');
154
+
155
+ // 并行获取版本
156
+ const versions = await getPackageVersionsParallel(
157
+ [
158
+ { name: '@mico-platform/ui', fallback: '1.0.0' },
159
+ { name: '@mico-platform/theme', fallback: '1.0.0' },
160
+ ],
161
+ 8000,
162
+ cliRoot,
163
+ );
146
164
 
147
- const micoUiVer = getLatestNpmVersion('@mico-platform/ui', '1.0.0', 8000, cliRoot);
148
- const themeVer = getLatestNpmVersion('@mico-platform/theme', '1.0.0', 8000, cliRoot);
165
+ const micoUiVer = versions['@mico-platform/ui'];
166
+ const themeVer = versions['@mico-platform/theme'];
149
167
 
150
168
  this.logger.verbose('@mico-platform/ui version:', micoUiVer);
151
169
  this.logger.verbose('@mico-platform/theme version:', themeVer);
@@ -171,6 +189,50 @@ module.exports = class extends Generator {
171
189
  process.exit(1);
172
190
  }
173
191
 
192
+ // Dry-run 模式:只列出文件,不实际创建
193
+ if (this.isDryRun) {
194
+ this.log('');
195
+ this.log('\x1b[33m📋 Dry run mode - no files will be created\x1b[0m');
196
+ this.log('');
197
+ this.log(` Sub-app: ${this.appName}`);
198
+ this.log(` Scope: ${this.packageScope}`);
199
+ this.log(` Destination: apps/${this.appName}`);
200
+ this.log('');
201
+ this.log(' Would create the following files:');
202
+ this.log('');
203
+
204
+ let templateCount = 0;
205
+ let copyCount = 0;
206
+
207
+ for (const relPath of files) {
208
+ const destRelPath = transformDestPath(relPath);
209
+ const isTemplate = isTemplateFile(relPath);
210
+ const tag = isTemplate ? '\x1b[32m[tpl]\x1b[0m' : '\x1b[36m[cpy]\x1b[0m';
211
+ this.log(` ${tag} apps/${this.appName}/${destRelPath}`);
212
+
213
+ if (isTemplate) {
214
+ templateCount++;
215
+ } else {
216
+ copyCount++;
217
+ }
218
+ }
219
+
220
+ this.log('');
221
+ this.log(` Total: ${files.length} files (${templateCount} templates, ${copyCount} static)`);
222
+ this.log('');
223
+ this.log(' Run without --dry-run to actually create these files.');
224
+ this.log('');
225
+
226
+ // 设置标记以跳过后续阶段
227
+ this._skipInstall = true;
228
+ return;
229
+ }
230
+
231
+ this.log('');
232
+ this.log(`📦 Creating sub-app: ${this.appName}`);
233
+ this.log(` Destination: apps/${this.appName}`);
234
+ this.log('');
235
+
174
236
  this.logger.verbose(`Processing ${files.length} files...`);
175
237
 
176
238
  let templateCount = 0;
@@ -203,6 +265,9 @@ module.exports = class extends Generator {
203
265
  }
204
266
 
205
267
  install() {
268
+ // 跳过 dry-run 模式
269
+ if (this._skipInstall) return;
270
+
206
271
  this.log('');
207
272
  this.log('📦 正在安装依赖...');
208
273
  this.spawnCommandSync('pnpm', ['install'], {
@@ -211,6 +276,9 @@ module.exports = class extends Generator {
211
276
  }
212
277
 
213
278
  end() {
279
+ // 跳过 dry-run 模式
280
+ if (this._skipInstall) return;
281
+
214
282
  this.log('');
215
283
  this.log('✅ 子应用创建成功!');
216
284
  this.log('');
@@ -2,6 +2,13 @@
2
2
 
3
3
  import { defineConfig } from '@umijs/max';
4
4
 
5
+ /**
6
+ * ⚠️⚠️ 不要修改这个变量名,版本升级工具会读取这个变量名,进行版本升级
7
+ * @name mico-ui 版本
8
+ * @description 开发环境使用 mico-ui 的最新版本
9
+ */
10
+ const MICO_UI_VERSION = '<%= micoUiVersionExact %>';
11
+
5
12
  /**
6
13
  * 开发环境配置
7
14
  * - 不配置 externals,直接打包依赖,方便独立运行调试
@@ -52,7 +59,7 @@ const config: ReturnType<typeof defineConfig> = {
52
59
  */
53
60
  styles: [
54
61
  // @mico-platform/ui 基础样式(使用运行时解析的最新版本号,避免 latest 标签)
55
- 'https://cdn-portal-test.micoplatform.com/portal-center/mico-ui/<%= micoUiVersionExact %>/ui/dist/css/mico-ui.min.css'
62
+ `https://cdn-portal.micoplatform.com/portal-center/mico-ui/${MICO_UI_VERSION}/ui/dist/css/mico-ui.min.css`,
56
63
  ],
57
64
  };
58
65
 
@@ -102,6 +102,27 @@ const config: ReturnType<typeof defineConfig> = {
102
102
  codeSplitting: {
103
103
  jsStrategy: 'granularChunks',
104
104
  },
105
+
106
+ /**
107
+ * @name 额外 Babel Presets
108
+ * @description 使用 @mico-platform/ui 的 babel preset,实现组件与图标的按需加载
109
+ */
110
+ extraBabelPresets: ['@mico-platform/ui/babel-preset'],
111
+
112
+ /**
113
+ * @name MFSU 配置
114
+ * @description
115
+ * - exclude: theme 子路径解析;ui 尽量与主应用一起编译
116
+ * - shared: React 单例,确保 MFSU 预打包里的组件(如 UI 库)与应用共用同一份 React,否则 useContext 报 null
117
+ * @doc https://umijs.org/docs/guides/mfsu
118
+ */
119
+ mfsu: {
120
+ exclude: ['@mico-platform/theme', '@mico-platform/ui'],
121
+ shared: {
122
+ react: { singleton: true },
123
+ 'react-dom': { singleton: true },
124
+ },
125
+ },
105
126
  };
106
127
 
107
128
  export default defineConfig(config);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @name 路由配置
3
- * @description homepage 子应用的路由配置
3
+ * @description <%= appName %> 子应用的路由配置
4
4
  */
5
5
  export default [
6
6
  { path: '/<%= appName %>', component: '@/pages/index' },
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @name Mock API
3
- * @description homepage 子应用的 Mock 数据
3
+ * @description <%= appName %> 子应用的 Mock 数据
4
4
  * @doc https://umijs.org/docs/guides/mock
5
5
  */
6
6
 
@@ -12,7 +12,7 @@ export default {
12
12
  // id: 1001,
13
13
  // name: '张三',
14
14
  // email: 'zhangsan@example.com',
15
- // avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=homepage',
15
+ // avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=<%= appName %>',
16
16
  // role: 'admin',
17
17
  // department: '技术部',
18
18
  // },
@@ -17,8 +17,6 @@
17
17
  "dependencies": {
18
18
  "@mico-platform/theme": "<%= themeVersion %>",
19
19
  "@umijs/max": "^4.4.8",
20
- "babel-plugin-dynamic-import-node": "^2.3.3",
21
- "cross-env": "^10.1.0",
22
20
  "react": "^18.2.0",
23
21
  "react-dom": "^18.2.0"
24
22
  },
@@ -26,6 +24,9 @@
26
24
  "@mico-platform/ui": "<%= micoUiVersion %>",
27
25
  "@types/react": "^18.0.33",
28
26
  "@types/react-dom": "^18.0.11",
27
+ "babel-plugin-dynamic-import-node": "^2.3.3",
28
+ "babel-plugin-import": "^1.13.8",
29
+ "cross-env": "^10.1.0",
29
30
  "typescript": "^5.0.3"
30
31
  }
31
32
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @name 应用入口配置
3
- * @description homepage 子应用的运行时配置
3
+ * @description <%= appName %> 子应用的运行时配置
4
4
  * @doc https://umijs.org/docs/max/micro-frontend#子应用配置
5
5
  *
6
6
  * 注意:app.tsx 只能导出 Umi 规定的 API(qiankun、getInitialState 等)
@@ -26,12 +26,12 @@ export async function request<T = any>(
26
26
 
27
27
  if (mainAppRequest) {
28
28
  // 微前端模式:使用主应用的 request
29
- console.log('[homepage] Using main app request:', url);
29
+ console.log('[<%= appName %>] Using main app request:', url);
30
30
  return mainAppRequest<T>(url, options);
31
31
  }
32
32
 
33
33
  // 独立运行模式:使用 umi request
34
- console.log('[homepage] Using umi request:', url);
34
+ console.log('[<%= appName %>] Using umi request:', url);
35
35
  // umi request 默认返回 data,skipErrorHandler 可选
36
36
  return umiRequest<T>(url, {
37
37
  skipErrorHandler: true,
@@ -20,7 +20,8 @@ body {
20
20
  'Noto Sans', sans-serif;
21
21
  }
22
22
 
23
- #homepage-root {
23
+ #<%= appName %>-root {
24
24
  width: 100%;
25
25
  height: 100%;
26
+ background-color: var(--color-fill-1);
26
27
  }
@@ -6,7 +6,7 @@
6
6
  // 导入主题变量(仅 Less 变量,子应用用)
7
7
  @import '@mico-platform/theme/variables';
8
8
 
9
- .homepage {
9
+ .<%= appName %> {
10
10
  padding: @spacing-lg;
11
11
  min-height: 100vh;
12
12
  // 使用主题色变量 - 背景色会随主题切换自动变化
@@ -135,7 +135,7 @@ export default function HomePage() {
135
135
  };
136
136
 
137
137
  return (
138
- <div className="homepage">
138
+ <div className="<%= appName %>">
139
139
  <Title heading={2}>🎨 子应用主题 & 组件示例</Title>
140
140
  <Paragraph type="secondary">
141
141
  子应用复用主应用的 React 和 @mico-platform/ui,无重复打包,主题自动同步
@@ -316,44 +316,44 @@ export default function HomePage() {
316
316
  </Paragraph>
317
317
 
318
318
  <Title heading={6}>品牌色 & 功能色</Title>
319
- <div className="homepage-colors">
320
- <div className="homepage-color-item">
321
- <div className="homepage-color-box brand-1" />
322
- <span className="homepage-color-label">@Brand1-6</span>
319
+ <div className="<%= appName %>-colors">
320
+ <div className="<%= appName %>-color-item">
321
+ <div className="<%= appName %>-color-box brand-1" />
322
+ <span className="<%= appName %>-color-label">@Brand1-6</span>
323
323
  </div>
324
- <div className="homepage-color-item">
325
- <div className="homepage-color-box brand-2" />
326
- <span className="homepage-color-label">@Brand2-6</span>
324
+ <div className="<%= appName %>-color-item">
325
+ <div className="<%= appName %>-color-box brand-2" />
326
+ <span className="<%= appName %>-color-label">@Brand2-6</span>
327
327
  </div>
328
- <div className="homepage-color-item">
329
- <div className="homepage-color-box success" />
330
- <span className="homepage-color-label">@Success-6</span>
328
+ <div className="<%= appName %>-color-item">
329
+ <div className="<%= appName %>-color-box success" />
330
+ <span className="<%= appName %>-color-label">@Success-6</span>
331
331
  </div>
332
- <div className="homepage-color-item">
333
- <div className="homepage-color-box warning" />
334
- <span className="homepage-color-label">@Warning-6</span>
332
+ <div className="<%= appName %>-color-item">
333
+ <div className="<%= appName %>-color-box warning" />
334
+ <span className="<%= appName %>-color-label">@Warning-6</span>
335
335
  </div>
336
- <div className="homepage-color-item">
337
- <div className="homepage-color-box danger" />
338
- <span className="homepage-color-label">@Danger-6</span>
336
+ <div className="<%= appName %>-color-item">
337
+ <div className="<%= appName %>-color-box danger" />
338
+ <span className="<%= appName %>-color-label">@Danger-6</span>
339
339
  </div>
340
340
  </div>
341
341
 
342
342
  <Title heading={6} style={{ marginTop: 16 }}>
343
343
  中性色(随主题自动切换)
344
344
  </Title>
345
- <div className="homepage-colors">
346
- <div className="homepage-color-item">
347
- <div className="homepage-color-box fill-1" />
348
- <span className="homepage-color-label">@color-fill-1</span>
345
+ <div className="<%= appName %>-colors">
346
+ <div className="<%= appName %>-color-item">
347
+ <div className="<%= appName %>-color-box fill-1" />
348
+ <span className="<%= appName %>-color-label">@color-fill-1</span>
349
349
  </div>
350
- <div className="homepage-color-item">
351
- <div className="homepage-color-box fill-2" />
352
- <span className="homepage-color-label">@color-fill-2</span>
350
+ <div className="<%= appName %>-color-item">
351
+ <div className="<%= appName %>-color-box fill-2" />
352
+ <span className="<%= appName %>-color-label">@color-fill-2</span>
353
353
  </div>
354
- <div className="homepage-color-item">
355
- <div className="homepage-color-box fill-3" />
356
- <span className="homepage-color-label">@color-fill-3</span>
354
+ <div className="<%= appName %>-color-item">
355
+ <div className="<%= appName %>-color-box fill-3" />
356
+ <span className="<%= appName %>-color-label">@color-fill-3</span>
357
357
  </div>
358
358
  </div>
359
359
  </Card>