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.
- package/README.md +29 -0
- package/bin/mico.js +124 -5
- package/generators/micro-react/index.js +76 -17
- package/generators/micro-react/templates/CLAUDE.md +11 -5
- package/generators/micro-react/templates/_gitignore +2 -0
- package/generators/micro-react/templates/apps/layout/config/config.ts +21 -0
- package/generators/micro-react/templates/apps/layout/docs/common-intl.md +8 -6
- 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
- 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
- package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +4 -2
- package/generators/micro-react/templates/apps/layout/mock/menus.ts +7 -2
- package/generators/micro-react/templates/apps/layout/package.json +3 -2
- package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +3 -15
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +4 -0
- package/generators/micro-react/templates/apps/layout/src/global.less +1 -2
- package/generators/micro-react/templates/package.json +2 -1
- package/generators/subapp-react/index.js +81 -13
- package/generators/subapp-react/templates/homepage/config/config.dev.ts +8 -1
- package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
- package/generators/subapp-react/templates/homepage/config/routes.ts +1 -1
- package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
- package/generators/subapp-react/templates/homepage/package.json +3 -2
- package/generators/subapp-react/templates/homepage/src/app.tsx +1 -1
- package/generators/subapp-react/templates/homepage/src/common/request.ts +2 -2
- package/generators/subapp-react/templates/homepage/src/global.less +2 -1
- package/generators/subapp-react/templates/homepage/src/pages/index.less +1 -1
- package/generators/subapp-react/templates/homepage/src/pages/index.tsx +27 -27
- package/lib/utils.js +200 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 菜单权限控制
|
|
2
2
|
|
|
3
|
-
> 创建时间:2026-01-24 更新时间:2026-
|
|
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/
|
|
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,
|
|
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
|
-
"
|
|
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 (
|
|
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
|
|
|
@@ -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
|
-
|
|
12
|
+
getPackageVersionsParallel,
|
|
13
13
|
setupErrorHandlers,
|
|
14
14
|
createLogger,
|
|
15
|
-
|
|
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 =
|
|
148
|
-
const themeVer =
|
|
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
|
-
|
|
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 Mock API
|
|
3
|
-
* @description
|
|
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
|
|
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
|
}
|
|
@@ -26,12 +26,12 @@ export async function request<T = any>(
|
|
|
26
26
|
|
|
27
27
|
if (mainAppRequest) {
|
|
28
28
|
// 微前端模式:使用主应用的 request
|
|
29
|
-
console.log('[
|
|
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('[
|
|
34
|
+
console.log('[<%= appName %>] Using umi request:', url);
|
|
35
35
|
// umi request 默认返回 data,skipErrorHandler 可选
|
|
36
36
|
return umiRequest<T>(url, {
|
|
37
37
|
skipErrorHandler: true,
|
|
@@ -135,7 +135,7 @@ export default function HomePage() {
|
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
return (
|
|
138
|
-
<div className="
|
|
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="
|
|
320
|
-
<div className="
|
|
321
|
-
<div className="
|
|
322
|
-
<span className="
|
|
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="
|
|
325
|
-
<div className="
|
|
326
|
-
<span className="
|
|
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="
|
|
329
|
-
<div className="
|
|
330
|
-
<span className="
|
|
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="
|
|
333
|
-
<div className="
|
|
334
|
-
<span className="
|
|
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="
|
|
337
|
-
<div className="
|
|
338
|
-
<span className="
|
|
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="
|
|
346
|
-
<div className="
|
|
347
|
-
<div className="
|
|
348
|
-
<span className="
|
|
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="
|
|
351
|
-
<div className="
|
|
352
|
-
<span className="
|
|
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="
|
|
355
|
-
<div className="
|
|
356
|
-
<span className="
|
|
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>
|