generator-mico-cli 0.2.19 → 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 +86 -17
- package/generators/micro-react/templates/.eslintrc.js +24 -1
- package/generators/micro-react/templates/CICD/start_dev.sh +1 -1
- 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 +23 -21
- 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 +1 -1
- 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 +61 -36
- 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/locale.ts +3 -3
- 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/components/MicroAppLoader/index.tsx +1 -1
- package/generators/micro-react/templates/apps/layout/src/global.less +2 -3
- package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +2 -4
- package/generators/micro-react/templates/package.json +5 -2
- package/generators/micro-react/templates/packages/common-intl/README.md +8 -8
- package/generators/micro-react/templates/packages/common-intl/src/intl.ts +13 -5678
- package/generators/micro-react/templates/packages/common-intl/src/utils.ts +22 -21
- 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
- package/generators/micro-react/templates/packages/common-intl/.turbo/turbo-build.log +0 -13
- package/generators/micro-react/templates/packages/common-intl/dist/index.d.ts +0 -3
- package/generators/micro-react/templates/packages/common-intl/dist/index.js +0 -4388
- package/generators/micro-react/templates/packages/common-intl/dist/indexedDBUtils.d.ts +0 -13
- package/generators/micro-react/templates/packages/common-intl/dist/intl.d.ts +0 -1022
- package/generators/micro-react/templates/packages/common-intl/dist/utils.d.ts +0 -122
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 概述
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`<%= packageScope %>/common-intl` 是 Portal 项目的通用国际化(i18n)库,用于管理多语言文案,支持从多语言中台拉取翻译数据。
|
|
6
6
|
|
|
7
7
|
## 适用场景
|
|
8
8
|
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
- 需要从多语言中台动态获取翻译文案
|
|
11
11
|
- 希望统一管理国际化逻辑,减少重复代码
|
|
12
12
|
|
|
13
|
+
> **注意**:本文档描述的是 `@payment-portal/common-intl` 包的完整使用方式,涵盖了所有使用该包的应用(包括本仓库外的应用如 conversation-v2、session、workorder 等)。当前仓库仅包含 `layout` 和 `basis` 两个应用。
|
|
14
|
+
|
|
13
15
|
## 核心特性
|
|
14
16
|
|
|
15
17
|
| 特性 | 说明 |
|
|
@@ -22,7 +24,7 @@
|
|
|
22
24
|
|
|
23
25
|
## 两种使用模式
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
根据应用架构的不同,`<%= packageScope %>/common-intl` 支持两种使用模式:
|
|
26
28
|
|
|
27
29
|
| 模式 | 适用场景 | 示例应用 |
|
|
28
30
|
| ------------ | ------------------------------------------------ | ------------------------------------------------------------ |
|
|
@@ -64,7 +66,7 @@ import {
|
|
|
64
66
|
getCurrentLocale,
|
|
65
67
|
initIntl,
|
|
66
68
|
type ILang,
|
|
67
|
-
} from "
|
|
69
|
+
} from "<%= packageScope %>/common-intl";
|
|
68
70
|
import { Message } from "@mico-platform/ui";
|
|
69
71
|
import { request } from "@umijs/max";
|
|
70
72
|
|
|
@@ -100,7 +102,7 @@ export function render(oldRender: () => void): void {
|
|
|
100
102
|
|
|
101
103
|
```typescript
|
|
102
104
|
// apps/conversation-v2、apps/session、apps/workorder 等子应用
|
|
103
|
-
import { intl } from "
|
|
105
|
+
import { intl } from "<%= packageScope %>/common-intl";
|
|
104
106
|
|
|
105
107
|
// 直接使用,文案来自主应用
|
|
106
108
|
<h1>{intl.cs_web_workbench_conversation_record()}</h1>;
|
|
@@ -113,7 +115,7 @@ import { intl } from "@portal-web/common-intl";
|
|
|
113
115
|
**独立应用配置(apps/mico-cs-mobile/src/app.ts)**:
|
|
114
116
|
|
|
115
117
|
```typescript
|
|
116
|
-
import { initIntl } from "
|
|
118
|
+
import { initIntl } from "<%= packageScope %>/common-intl";
|
|
117
119
|
import { Toast } from "@arco-design/mobile-react";
|
|
118
120
|
import { request } from "@umijs/max";
|
|
119
121
|
import { convertLocaleToLangParam } from "./locales/utils";
|
|
@@ -149,7 +151,7 @@ export function render(oldRender: () => void): void {
|
|
|
149
151
|
**独立应用的文案文件(apps/mico-cs-mobile/src/locales/index.ts)**:
|
|
150
152
|
|
|
151
153
|
```typescript
|
|
152
|
-
import { i18n } from "
|
|
154
|
+
import { i18n } from "<%= packageScope %>/common-intl";
|
|
153
155
|
|
|
154
156
|
const intl = {
|
|
155
157
|
sdk_h5_ticket_record: () =>
|
|
@@ -173,7 +175,7 @@ import intl from "@/locales";
|
|
|
173
175
|
|
|
174
176
|
## 导出 API
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
`<%= packageScope %>/common-intl` 提供以下导出:
|
|
177
179
|
|
|
178
180
|
| 导出 | 类型 | 说明 |
|
|
179
181
|
| -------------------- | ---- | --------------------------------------------------------- |
|
|
@@ -192,18 +194,18 @@ import intl from "@/locales";
|
|
|
192
194
|
|
|
193
195
|
```typescript
|
|
194
196
|
// 微前端子应用 - 直接使用共享的 intl 对象
|
|
195
|
-
import { intl } from "
|
|
197
|
+
import { intl } from "<%= packageScope %>/common-intl";
|
|
196
198
|
intl.cs_web_common_request_failed();
|
|
197
199
|
|
|
198
200
|
// 独立应用 - 使用 i18n 函数构建自己的文案对象
|
|
199
|
-
import { i18n, initIntl, LANG } from "
|
|
201
|
+
import { i18n, initIntl, LANG } from "<%= packageScope %>/common-intl";
|
|
200
202
|
|
|
201
203
|
// 获取当前语言环境
|
|
202
|
-
import { getCurrentLocale } from "
|
|
204
|
+
import { getCurrentLocale } from "<%= packageScope %>/common-intl";
|
|
203
205
|
const currentLang = getCurrentLocale(); // 'zh_CN' | 'en' | 'ar' | 'tr'
|
|
204
206
|
|
|
205
207
|
// 获取支持的语言列表
|
|
206
|
-
import { SUPPORTED_LOCALES } from "
|
|
208
|
+
import { SUPPORTED_LOCALES } from "<%= packageScope %>/common-intl";
|
|
207
209
|
console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
|
|
208
210
|
```
|
|
209
211
|
|
|
@@ -212,7 +214,7 @@ console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
|
|
|
212
214
|
### PC 端主子应用
|
|
213
215
|
|
|
214
216
|
- **文案位置**:[packages/common-intl/src/intl.ts](../packages/common-intl/src/intl.ts)
|
|
215
|
-
- **使用方式**:`import { intl } from '
|
|
217
|
+
- **使用方式**:`import { intl } from '<%= packageScope %>/common-intl'`
|
|
216
218
|
- **适用应用**:
|
|
217
219
|
- apps/layout(主应用)
|
|
218
220
|
- apps/conversation-v2(工作台子应用)
|
|
@@ -242,7 +244,7 @@ console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
|
|
|
242
244
|
// apps/your-app/package.json
|
|
243
245
|
{
|
|
244
246
|
"dependencies": {
|
|
245
|
-
"
|
|
247
|
+
"<%= packageScope %>/common-intl": "workspace:*"
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
```
|
|
@@ -252,7 +254,7 @@ console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
|
|
|
252
254
|
**如果是 layout 的子应用**:
|
|
253
255
|
|
|
254
256
|
- 无需调用 `initIntl()`
|
|
255
|
-
- 直接使用 `import { intl } from '
|
|
257
|
+
- 直接使用 `import { intl } from '<%= packageScope %>/common-intl'`
|
|
256
258
|
|
|
257
259
|
**如果是独立应用**:
|
|
258
260
|
|
|
@@ -311,17 +313,17 @@ console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
|
|
|
311
313
|
|
|
312
314
|
目前支持以下语言:
|
|
313
315
|
|
|
314
|
-
| 语言常量
|
|
315
|
-
|
|
|
316
|
-
| `LANG.ZH_CN`
|
|
317
|
-
| `LANG.
|
|
318
|
-
| `LANG.
|
|
319
|
-
| `LANG.
|
|
316
|
+
| 语言常量 | 值 | 说明 |
|
|
317
|
+
| ------------- | ------- | -------- |
|
|
318
|
+
| `LANG.ZH_CN` | `zh_CN` | 简体中文 |
|
|
319
|
+
| `LANG.EN_US` | `en` | 英语 |
|
|
320
|
+
| `LANG.AR_SA` | `ar` | 阿拉伯语 |
|
|
321
|
+
| `LANG.TR_TR` | `tr` | 土耳其语 |
|
|
320
322
|
|
|
321
323
|
### Q: 如何在代码中获取当前语言?
|
|
322
324
|
|
|
323
325
|
```typescript
|
|
324
|
-
import { getCurrentLocale } from "
|
|
326
|
+
import { getCurrentLocale } from "<%= packageScope %>/common-intl";
|
|
325
327
|
|
|
326
328
|
const currentLang = getCurrentLocale();
|
|
327
329
|
if (currentLang === "ar") {
|
|
@@ -201,7 +201,7 @@ wc -c apps/[子应用]/dist/umi.css
|
|
|
201
201
|
1. 主应用加载 @mico-platform/ui 并暴露到 `window.micoUI`
|
|
202
202
|
2. 主应用的样式包含 `arco-theme` 属性选择器(基于 Arco)
|
|
203
203
|
3. 主应用切换主题时设置 `body[arco-theme="dark"]`
|
|
204
|
-
4. 子应用的 UI 组件(来自 window.
|
|
204
|
+
4. 子应用的 UI 组件(来自 window.micoUI)自动应用暗色样式
|
|
205
205
|
|
|
206
206
|
#### 子应用使用 @mico-platform/ui
|
|
207
207
|
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
|
|
29
29
|
### 核心文件
|
|
30
30
|
|
|
31
|
-
| 文件路径
|
|
32
|
-
|
|
|
33
|
-
| `src/components/MicroAppLoader/index.tsx`
|
|
34
|
-
| `src/components/MicroAppLoader/
|
|
35
|
-
| `src/components/MicroAppLoader/index.less`
|
|
36
|
-
| `src/common/menu/parser.ts`
|
|
37
|
-
| `src/common/menu/types.ts`
|
|
38
|
-
| `src/layouts/index.tsx`
|
|
39
|
-
| `src/app.tsx`
|
|
40
|
-
| `config/config.ts`
|
|
31
|
+
| 文件路径 | 说明 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `src/components/MicroAppLoader/index.tsx` | qiankun 微应用加载器组件 |
|
|
34
|
+
| `src/components/MicroAppLoader/micro-app-manager.ts` | 微应用管理器(单例),稳定容器 + 实例缓存 + 操作序列号 |
|
|
35
|
+
| `src/components/MicroAppLoader/index.less` | 加载器样式 |
|
|
36
|
+
| `src/common/menu/parser.ts` | 菜单解析,包含加载类型判断 |
|
|
37
|
+
| `src/common/menu/types.ts` | 类型定义 |
|
|
38
|
+
| `src/layouts/index.tsx` | 主布局,集成微应用渲染 |
|
|
39
|
+
| `src/app.tsx` | qiankun 全局错误处理 |
|
|
40
|
+
| `config/config.ts` | qiankun master 配置 |
|
|
41
41
|
|
|
42
42
|
## API / 组件接口
|
|
43
43
|
|
|
@@ -70,7 +70,7 @@ interface MicroAppLoaderProps {
|
|
|
70
70
|
```typescript
|
|
71
71
|
interface MicroAppProps {
|
|
72
72
|
/** 主应用标识 */
|
|
73
|
-
mainApp: '
|
|
73
|
+
mainApp: '<%= projectName %>';
|
|
74
74
|
/** 运行环境 */
|
|
75
75
|
env: 'development' | 'testing' | 'production';
|
|
76
76
|
/** 认证 token */
|
|
@@ -462,52 +462,77 @@ addGlobalUncaughtErrorHandler((event: Event | string) => {
|
|
|
462
462
|
});
|
|
463
463
|
```
|
|
464
464
|
|
|
465
|
-
###
|
|
465
|
+
### MicroAppManager API (micro-app-manager.ts)
|
|
466
466
|
|
|
467
|
-
|
|
467
|
+
`MicroAppManager` 是单例类,管理微应用的加载、缓存、切换和卸载:
|
|
468
468
|
|
|
469
469
|
```typescript
|
|
470
|
-
|
|
471
|
-
|
|
470
|
+
interface MicroAppConfig {
|
|
471
|
+
name: string;
|
|
472
|
+
entry: string;
|
|
473
|
+
target: HTMLElement; // 目标挂载位置
|
|
474
|
+
props: Record<string, unknown>;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
interface MicroAppState {
|
|
478
|
+
loading: boolean;
|
|
479
|
+
error: string | null;
|
|
480
|
+
mounted: boolean;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const manager = microAppManager; // 单例,导出即用
|
|
472
484
|
|
|
473
|
-
/**
|
|
474
|
-
|
|
485
|
+
/** 切换到指定微应用(已挂载则仅更新 props) */
|
|
486
|
+
manager.switchTo(config: MicroAppConfig): void;
|
|
475
487
|
|
|
476
|
-
/**
|
|
477
|
-
|
|
488
|
+
/** 更新当前已挂载微应用的 props */
|
|
489
|
+
manager.updateProps(props: Record<string, unknown>): void;
|
|
478
490
|
|
|
479
|
-
/**
|
|
480
|
-
|
|
491
|
+
/** 取消待处理的请求 */
|
|
492
|
+
manager.cancel(): void;
|
|
481
493
|
|
|
482
|
-
/**
|
|
483
|
-
|
|
494
|
+
/** 清除所有缓存实例 */
|
|
495
|
+
manager.clearCache(): Promise<void>;
|
|
496
|
+
|
|
497
|
+
/** 获取调试信息 */
|
|
498
|
+
manager.getDebugInfo(): object;
|
|
499
|
+
|
|
500
|
+
/** 设置状态变化回调 */
|
|
501
|
+
manager.setStateCallback(callback: StateChangeCallback | null): void;
|
|
484
502
|
```
|
|
485
503
|
|
|
504
|
+
### 核心设计
|
|
505
|
+
|
|
506
|
+
1. **稳定容器**:容器在 `document.body` 中创建,激活时移到目标元素内,停用时移回 body 隐藏,不受 React 生命周期影响
|
|
507
|
+
2. **实例缓存**:每个 entry 只 `loadMicroApp` 一次,后续切换复用已有实例(mount/unmount)
|
|
508
|
+
3. **操作序列号**:通过递增的 `operationSeq` 检测过期操作,替代旧的会话 ID 机制
|
|
509
|
+
4. **自动路由守卫**:由独立的 `route-guard.ts` 自动检测用户意图,业务代码无需感知
|
|
510
|
+
|
|
486
511
|
### 快速切换时序
|
|
487
512
|
|
|
488
513
|
```
|
|
489
514
|
场景:A → B → A 快速切换
|
|
490
515
|
|
|
491
|
-
|
|
492
|
-
↓
|
|
493
|
-
切换到 B,A1 cleanup 在 queueMicrotask 中执行
|
|
516
|
+
switchTo(A):operationSeq=1,开始 loadMicroApp
|
|
494
517
|
↓
|
|
495
|
-
|
|
518
|
+
switchTo(B):operationSeq=2,A 的 pendingRequest 被替换
|
|
496
519
|
↓
|
|
497
|
-
|
|
520
|
+
A 的 processRequest 在异步步骤中检测 shouldAbort(mySeq=1) → true
|
|
498
521
|
↓
|
|
499
|
-
|
|
522
|
+
A 等待 mountPromise 完成后执行 safeUnmount,容器移回 body
|
|
500
523
|
↓
|
|
501
|
-
|
|
524
|
+
B 开始 processRequest,检查缓存 → 无缓存 → loadMicroApp
|
|
502
525
|
↓
|
|
503
|
-
|
|
526
|
+
B 加载完成后同步最新 Props(locale/timezone/routePath 等)
|
|
504
527
|
```
|
|
505
528
|
|
|
506
529
|
### 设计决策
|
|
507
530
|
|
|
508
531
|
| 决策点 | 选择 | 理由 |
|
|
509
|
-
|
|
510
|
-
|
|
|
511
|
-
| 并发控制 |
|
|
512
|
-
|
|
|
513
|
-
|
|
|
532
|
+
| --- | --- | --- |
|
|
533
|
+
| 容器策略 | 稳定容器(body 中创建,移动挂载) | 不受 React 生命周期影响,避免容器被意外销毁 |
|
|
534
|
+
| 并发控制 | 操作序列号 + pendingRequest 队列 | 简单高效,新请求自动覆盖旧请求 |
|
|
535
|
+
| 实例缓存 | loadPromise 完成后立即缓存 | 即使被 abort 也可复用,避免重复加载 |
|
|
536
|
+
| unmount 安全 | 等待 mountPromise 完成后再 unmount | 避免 single-spa error #32 |
|
|
537
|
+
| 超时保护 | load 30s / mount 30s / unmount 10s | 平衡等待时间与异常检测速度 |
|
|
538
|
+
| Props 同步 | mount 完成后立即 safeUpdate | 确保加载期间的变化不丢失 |
|
|
@@ -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",
|
|
@@ -122,7 +122,7 @@ export function setLocaleToStorage(locale: SupportedLocale): void {
|
|
|
122
122
|
/**
|
|
123
123
|
* 根据语言获取图标库路径
|
|
124
124
|
*/
|
|
125
|
-
export function getIconFontPath(locale: SupportedLocale): string {
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
export function getIconFontPath(/* locale: SupportedLocale */): string {
|
|
126
|
+
// 如果后续需要支持 RTL 语言(如阿拉伯语),可在此扩展
|
|
127
|
+
return withPublicPath("/font/default.js");
|
|
128
128
|
}
|
|
@@ -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
|
|
package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx
CHANGED
|
@@ -70,7 +70,7 @@ const MicroAppLoader: React.FC<MicroAppLoaderProps> = ({
|
|
|
70
70
|
const buildProps = useCallback(() => {
|
|
71
71
|
const authInfo = getAuthInfo();
|
|
72
72
|
return {
|
|
73
|
-
mainApp: '
|
|
73
|
+
mainApp: '<%= projectName %>',
|
|
74
74
|
env,
|
|
75
75
|
authToken: authInfo.token,
|
|
76
76
|
uid: authInfo.uid,
|
|
@@ -24,13 +24,16 @@
|
|
|
24
24
|
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix && turbo run lint:fix",
|
|
25
25
|
"check-types": "turbo run check-types",
|
|
26
26
|
"lint-staged": "pnpm exec lint-staged --quiet",
|
|
27
|
-
"prepare": "husky
|
|
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",
|
|
33
34
|
"@commitlint/config-conventional": "^19.5.0",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
36
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
34
37
|
"dotenv-cli": "^7.4.1",
|
|
35
38
|
"eslint": "^8.57.0",
|
|
36
39
|
"husky": "^9.1.7",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# <%= packageScope %>/common-intl
|
|
2
2
|
|
|
3
3
|
通用国际化(i18n)库,用于 Portal 多应用间的多语言文案管理。
|
|
4
4
|
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
```json
|
|
19
19
|
{
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"
|
|
21
|
+
"<%= packageScope %>/common-intl": "workspace:*"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## 两种使用模式
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
根据应用架构的不同,`<%= packageScope %>/common-intl` 支持两种使用模式:
|
|
29
29
|
|
|
30
30
|
| 模式 | 适用场景 | 示例应用 |
|
|
31
31
|
| ------------ | ------------------------------------------------ | ------------------------------------------------------------ |
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
getCurrentLocale,
|
|
50
50
|
initIntl,
|
|
51
51
|
type ILang,
|
|
52
|
-
} from "
|
|
52
|
+
} from "<%= packageScope %>/common-intl";
|
|
53
53
|
import { Message } from "@mico-platform/ui";
|
|
54
54
|
import { request } from "@umijs/max";
|
|
55
55
|
|
|
@@ -85,7 +85,7 @@ export function render(oldRender: () => void): void {
|
|
|
85
85
|
|
|
86
86
|
```typescript
|
|
87
87
|
// apps/conversation-v2、apps/session、apps/workorder 等子应用
|
|
88
|
-
import { intl } from "
|
|
88
|
+
import { intl } from "<%= packageScope %>/common-intl";
|
|
89
89
|
|
|
90
90
|
// 直接使用,文案来自主应用
|
|
91
91
|
<h1>{intl.cs_web_workbench_conversation_record()}</h1>;
|
|
@@ -98,7 +98,7 @@ import { intl } from "@portal-web/common-intl";
|
|
|
98
98
|
**独立应用配置**(参考 `apps/mico-cs-mobile/src/app.ts`):
|
|
99
99
|
|
|
100
100
|
```typescript
|
|
101
|
-
import { initIntl } from "
|
|
101
|
+
import { initIntl } from "<%= packageScope %>/common-intl";
|
|
102
102
|
import { request } from "@umijs/max";
|
|
103
103
|
import { convertLocaleToLangParam } from "./locales/utils";
|
|
104
104
|
import { getSearchParams } from "@/common/jsbridge/jsbridge";
|
|
@@ -140,7 +140,7 @@ export function render(oldRender: () => void): void {
|
|
|
140
140
|
**独立应用的文案文件**(`apps/mico-cs-mobile/src/locales/index.ts`):集中管理所有国际化文案
|
|
141
141
|
|
|
142
142
|
```typescript
|
|
143
|
-
import { i18n } from "
|
|
143
|
+
import { i18n } from "<%= packageScope %>/common-intl";
|
|
144
144
|
|
|
145
145
|
const intl = {
|
|
146
146
|
// 无插值示例
|
|
@@ -395,7 +395,7 @@ const intl = {
|
|
|
395
395
|
2. 在业务代码中使用:
|
|
396
396
|
|
|
397
397
|
```typescript
|
|
398
|
-
import { intl } from "
|
|
398
|
+
import { intl } from "<%= packageScope %>/common-intl";
|
|
399
399
|
|
|
400
400
|
// 使用新 key
|
|
401
401
|
intl.cs_web_your_new_key();
|