generator-mico-cli 0.2.28 → 0.2.30

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 (112) hide show
  1. package/README.md +7 -20
  2. package/bin/mico.js +27 -62
  3. package/generators/micro-react/index.js +25 -1
  4. package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +3 -0
  5. package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +1 -0
  6. package/generators/micro-react/templates/CICD/start_dev.sh +11 -0
  7. package/generators/micro-react/templates/CICD/start_local.sh +9 -0
  8. package/generators/micro-react/templates/CICD/start_prod.sh +13 -0
  9. package/generators/micro-react/templates/CICD/start_test.sh +11 -0
  10. package/generators/micro-react/templates/CLAUDE.md +1 -0
  11. package/generators/micro-react/templates/README.md +1 -1
  12. package/generators/micro-react/templates/apps/layout/config/config.dev.ts +13 -5
  13. package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +12 -0
  14. package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +12 -0
  15. package/generators/micro-react/templates/apps/layout/config/config.prod.ts +14 -0
  16. package/generators/micro-react/templates/apps/layout/docs/feature-PermissionFilter/346/214/211/351/222/256/346/235/203/351/231/220.md +116 -0
  17. package/generators/micro-react/templates/apps/layout/docs/feature-/345/233/275/351/231/205/345/214/226.md +121 -0
  18. 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 +8 -0
  19. 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 +83 -77
  20. 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 +50 -35
  21. package/generators/micro-react/templates/apps/layout/docs/feature-/350/267/257/347/224/261/346/235/203/351/231/220/346/227/245/345/277/227.md +162 -0
  22. package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +23 -31
  23. package/generators/micro-react/templates/apps/layout/mock/menus.ts +14 -0
  24. package/generators/micro-react/templates/apps/layout/mock/pages.ts +27 -8
  25. package/generators/micro-react/templates/apps/layout/package.json +2 -0
  26. package/generators/micro-react/templates/apps/layout/src/app.tsx +85 -4
  27. package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
  28. package/generators/micro-react/templates/apps/layout/src/common/auth/tenant.ts +25 -0
  29. package/generators/micro-react/templates/apps/layout/src/common/auth/type.ts +41 -27
  30. package/generators/micro-react/templates/apps/layout/src/common/intl/formatLayoutMessage.ts +30 -0
  31. package/generators/micro-react/templates/apps/layout/src/common/intl/index.ts +6 -0
  32. package/generators/micro-react/templates/apps/layout/src/common/intl/intlRuntime.ts +14 -0
  33. package/generators/micro-react/templates/apps/layout/src/common/intl/localeMapping.ts +30 -0
  34. package/generators/micro-react/templates/apps/layout/src/common/intl/types.ts +14 -0
  35. package/generators/micro-react/templates/apps/layout/src/common/intl/useLayoutIntl.ts +40 -0
  36. package/generators/micro-react/templates/apps/layout/src/common/logger.ts +3 -4
  37. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +148 -85
  38. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +29 -6
  39. package/generators/micro-react/templates/apps/layout/src/common/micro/types.ts +23 -0
  40. package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +46 -2
  41. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +74 -15
  42. package/generators/micro-react/templates/apps/layout/src/common/request/token-refresh.ts +2 -0
  43. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +32 -6
  44. package/generators/micro-react/templates/apps/layout/src/components/PermissionFilter/index.tsx +51 -0
  45. package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +10 -1
  46. package/generators/micro-react/templates/apps/layout/src/components/RightContent/TenantDropdown.tsx +76 -0
  47. package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +1 -0
  48. package/generators/micro-react/templates/apps/layout/src/components/RightContent/tenant-dropdown.less +48 -0
  49. package/generators/micro-react/templates/apps/layout/src/constants/index.ts +1 -0
  50. package/generators/micro-react/templates/apps/layout/src/hooks/index.ts +1 -0
  51. package/generators/micro-react/templates/apps/layout/src/hooks/useMenuState.ts +18 -0
  52. package/generators/micro-react/templates/apps/layout/src/hooks/useTenant.ts +41 -0
  53. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +4 -1
  54. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +21 -9
  55. package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +105 -60
  56. package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +28 -0
  57. package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +26 -0
  58. package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +7 -3
  59. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +32 -0
  60. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +148 -4
  61. package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +2 -1
  62. package/generators/micro-react/templates/apps/layout/src/services/user.ts +79 -21
  63. package/generators/micro-react/templates/apps/layout/typings.d.ts +16 -0
  64. package/generators/micro-react/templates/docs/package-shared.md +189 -0
  65. package/generators/micro-react/templates/package.json +1 -1
  66. package/generators/micro-react/templates/packages/common-intl/README.md +78 -368
  67. package/generators/micro-react/templates/packages/common-intl/package.json +3 -13
  68. package/generators/micro-react/templates/packages/common-intl/src/index.ts +5 -6
  69. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +115 -28
  70. package/generators/micro-react/templates/packages/common-intl/src/umiLocaleBridge.ts +101 -0
  71. package/generators/micro-react/templates/packages/common-intl/tsconfig.json +2 -4
  72. package/generators/micro-react/templates/packages/shared/README.md +120 -0
  73. package/generators/micro-react/templates/packages/shared/package.json +26 -0
  74. package/generators/micro-react/templates/packages/shared/services/common/index.ts +43 -0
  75. package/generators/micro-react/templates/packages/shared/services/index.ts +21 -0
  76. package/generators/micro-react/templates/packages/shared/services/request.ts +43 -0
  77. package/generators/micro-react/templates/packages/shared/timezone/index.ts +228 -0
  78. package/generators/micro-react/templates/packages/shared/tsconfig.json +20 -0
  79. package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +6 -1
  80. package/generators/micro-react/templates/turbo.json +9 -1
  81. package/generators/subapp-react/index.js +28 -22
  82. package/generators/subapp-react/templates/homepage/README.md +1 -0
  83. package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +1 -0
  84. package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +1 -0
  85. package/generators/subapp-react/templates/homepage/config/config.prod.ts +1 -0
  86. package/generators/subapp-react/templates/homepage/config/config.ts +10 -0
  87. package/generators/subapp-react/templates/homepage/docs/feature-PermissionFilter/346/214/211/351/222/256/346/235/203/351/231/220.md +35 -0
  88. package/generators/subapp-react/templates/homepage/docs/feature-/345/233/275/351/231/205/345/214/226.md +124 -0
  89. package/generators/subapp-react/templates/homepage/package.json +3 -1
  90. package/generators/subapp-react/templates/homepage/src/app.tsx +104 -2
  91. package/generators/subapp-react/templates/homepage/src/common/intl/index.ts +15 -0
  92. package/generators/subapp-react/templates/homepage/src/common/intl/intlRuntime.ts +14 -0
  93. package/generators/subapp-react/templates/homepage/src/common/intl/localeMapping.ts +24 -0
  94. package/generators/subapp-react/templates/homepage/src/common/intl/subappIntlConfig.ts +28 -0
  95. package/generators/subapp-react/templates/homepage/src/common/intl/subappLocale.ts +18 -0
  96. package/generators/subapp-react/templates/homepage/src/common/intl/subappOwnIntl.ts +63 -0
  97. package/generators/subapp-react/templates/homepage/src/common/intl/types.ts +14 -0
  98. package/generators/subapp-react/templates/homepage/src/common/intl/useSubappIntl.ts +61 -0
  99. package/generators/subapp-react/templates/homepage/src/common/locale.ts +80 -0
  100. package/generators/subapp-react/templates/homepage/src/common/mainApp.ts +41 -2
  101. package/generators/subapp-react/templates/homepage/src/components/PermissionFilter/index.tsx +48 -0
  102. package/generators/subapp-react/templates/homepage/src/locales/en-US.ts +6 -0
  103. package/generators/subapp-react/templates/homepage/src/locales/zh-CN.ts +6 -0
  104. package/generators/subapp-react/templates/homepage/src/pages/index.less +10 -0
  105. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +86 -1
  106. package/generators/subapp-react/templates/homepage/typings.d.ts +12 -0
  107. package/lib/utils.js +0 -1
  108. package/package.json +2 -2
  109. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +0 -372
  110. package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +0 -51
  111. package/generators/micro-react/templates/packages/common-intl/src/utils.ts +0 -482
  112. package/generators/micro-react/templates/packages/common-intl/vite.config.ts +0 -25
@@ -1,3 +1,5 @@
1
+ import PermissionFilter from '@/components/PermissionFilter';
2
+ import { useSubappIntl } from '@/common/intl';
1
3
  import { getRequestSource, request } from '@/common/request';
2
4
  import {
3
5
  Alert,
@@ -54,6 +56,14 @@ interface IListItem {
54
56
  * 4. Less 变量自动适配主应用的主题切换
55
57
  */
56
58
  export default function HomePage() {
59
+ const {
60
+ formatMessage,
61
+ commonIntlEnabled,
62
+ locale,
63
+ subappOwnIntl,
64
+ subappOwnIntlTag,
65
+ } = useSubappIntl();
66
+
57
67
  const [loading, setLoading] = useState(false);
58
68
  const [userInfo, setUserInfo] = useState<IUserInfo | null>(null);
59
69
  const [stats, setStats] = useState<IStatsData | null>(null);
@@ -143,6 +153,48 @@ export default function HomePage() {
143
153
 
144
154
  <Divider />
145
155
 
156
+ <Card
157
+ title={formatMessage({
158
+ id: 'page.subapp.home.demoSectionTitle',
159
+ defaultMessage: '国际化示例',
160
+ })}
161
+ style={{ marginBottom: 16 }}
162
+ >
163
+ <Title heading={4}>
164
+ {formatMessage({
165
+ id: 'page.subapp.home.title',
166
+ defaultMessage: '子应用首页',
167
+ })}
168
+ </Title>
169
+ <Paragraph className="subapp-intl-hint">
170
+ common-intl 优先样例(使用主应用的tag):
171
+ {formatMessage({
172
+ id: 'cs_web_workbench_userlist_chat',
173
+ defaultMessage: '看到该文案代表未启用 主应用commonIntl 或中台无该 key',
174
+ })}
175
+ </Paragraph>
176
+ <Paragraph className="subapp-intl-hint">
177
+ common-intl 优先样例(使用子应用的tag):
178
+ {formatMessage({
179
+ id: 'sdk_h5_ticket_you_can_leave_us_a_message_we_will_reply_within_24_hours',
180
+ defaultMessage: '看到该文案代表未启用 子应用commonIntl 或中台无该 key',
181
+ })}
182
+ </Paragraph>
183
+ <Paragraph className="<%= appName %>-intl-hint">
184
+ 仅子应用 locales 的 key(intl 通常无该 key):
185
+ {formatMessage({
186
+ id: 'page.subapp.home.umiOnly',
187
+ defaultMessage: '若仍见此默认文案,请检查 locales 是否注册该 id',
188
+ })}
189
+ </Paragraph>
190
+ <Paragraph type="secondary" className="<%= appName %>-intl-meta">
191
+ commonIntlEnabled: {String(commonIntlEnabled)} · locale: {locale}
192
+ {subappOwnIntl
193
+ ? ` · subappOwnIntl: true · tag: ${subappOwnIntlTag ?? '-'}`
194
+ : ' · subappOwnIntl: false'}
195
+ </Paragraph>
196
+ </Card>
197
+
146
198
  {/* 请求示例 */}
147
199
  <Spin loading={loading} style={{ display: 'block' }}>
148
200
  <Card
@@ -265,6 +317,39 @@ export default function HomePage() {
265
317
  </Card>
266
318
  </Spin>
267
319
 
320
+ {/* PermissionFilter:按主应用传入的 button_perms 控制展示 */}
321
+ <Card title="🔐 PermissionFilter 按钮权限示例" style={{ marginBottom: 16 }}>
322
+ <Paragraph>
323
+ 子应用通过 qiankun 接收主应用注入的{' '}
324
+ <Text code>button_perms</Text> / <Text code>is_superuser</Text>。
325
+ 仅当权限匹配(或超级用户)时渲染 <Text code>children</Text>,否则渲染{' '}
326
+ <Text code>fallback</Text>。
327
+ </Paragraph>
328
+ <Paragraph type="secondary" style={{ marginBottom: 12 }}>
329
+ 示例 permissionKey 为 <Text code>cs_web_btn_subapp_demo</Text>
330
+ 。嵌入主应用时,需在主应用用户信息接口的{' '}
331
+ <Text code>button_perms</Text> 中包含该标识;独立运行子应用时无主应用
332
+ props,将始终走 fallback。
333
+ </Paragraph>
334
+ <PermissionFilter
335
+ permissionKey="cs_web_btn_subapp_demo"
336
+ fallback={
337
+ <Alert
338
+ type="warning"
339
+ title="无权限"
340
+ content="未在 button_perms 中包含 cs_web_btn_subapp_demo,或为独立运行子应用。"
341
+ />
342
+ }
343
+ >
344
+ <Space>
345
+ <Button type="primary" status="success">
346
+ 有权限时可见的操作
347
+ </Button>
348
+ <Text type="success">(当前用户具备该按钮权限)</Text>
349
+ </Space>
350
+ </PermissionFilter>
351
+ </Card>
352
+
268
353
  {/* @mico-platform/ui 组件示例 */}
269
354
  <Card title="📦 @mico-platform/ui 组件" style={{ marginBottom: 16 }}>
270
355
  <Paragraph>
@@ -363,7 +448,7 @@ export default function HomePage() {
363
448
  <Alert
364
449
  type="info"
365
450
  title="依赖共享"
366
- content="通过 externals 配置,子应用复用主应用的 React 和 @mico-platform/ui,打包体积减少 ~1MB"
451
+ content="通过 externals 配置,子应用复用主应用的 React、@mico-platform/ui 和 common-intl 包(含多语言文案数据),打包体积减少 ~1MB"
367
452
  />
368
453
  <Alert
369
454
  type="success"
@@ -87,6 +87,18 @@ declare global {
87
87
  __MICO_CONFIG__?: {
88
88
  appName?: string;
89
89
  apiBaseUrl?: string;
90
+ /** 多语言中台(与 commonIntl 二选一字段名,见 common-intl intlRuntime) */
91
+ intl?: {
92
+ tag: string;
93
+ app_name: string;
94
+ indexedDBParams?: { dbName?: string };
95
+ };
96
+ /** 多语言中台保底配置(可选);与 packages/common-intl README、子应用可选 intl 模块配合 */
97
+ commonIntl?: {
98
+ tag: string;
99
+ app_name: string;
100
+ indexedDBParams?: { dbName?: string };
101
+ };
90
102
  [key: string]: unknown;
91
103
  };
92
104
  }
package/lib/utils.js CHANGED
@@ -376,7 +376,6 @@ async function runDoctorChecks() {
376
376
  const results = {
377
377
  node: checkNodeVersion('18'),
378
378
  pnpm: checkCommand('pnpm'),
379
- yo: checkCommand('yo'),
380
379
  git: checkCommand('git'),
381
380
  npm: null
382
381
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.2.28",
3
+ "version": "0.2.30",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": [
6
6
  "yeoman-generator",
@@ -30,7 +30,6 @@
30
30
  "@biomejs/biome": "^1.9.4",
31
31
  "husky": "^9.1.7",
32
32
  "vitest": "^4.0.18",
33
- "yeoman-environment": "^3.19.3",
34
33
  "yeoman-test": "^6.3.0"
35
34
  },
36
35
  "engines": {
@@ -39,6 +38,7 @@
39
38
  "dependencies": {
40
39
  "semver": "^7.6.3",
41
40
  "update-notifier": "^7.3.1",
41
+ "yeoman-environment": "^3.19.3",
42
42
  "yeoman-generator": "^5.9.0"
43
43
  }
44
44
  }
@@ -1,372 +0,0 @@
1
- # 通用国际化库使用指南
2
-
3
- ## 概述
4
-
5
- `<%= packageScope %>/common-intl` 是 Portal 项目的通用国际化(i18n)库,用于管理多语言文案,支持从多语言中台拉取翻译数据。
6
-
7
- ## 适用场景
8
-
9
- - 应用需要支持多语言切换(中文、英文、阿拉伯语、土耳其语等)
10
- - 需要从多语言中台动态获取翻译文案
11
- - 希望统一管理国际化逻辑,减少重复代码
12
-
13
- > **注意**:本文档描述的是 `@payment-portal/common-intl` 包的完整使用方式,涵盖了所有使用该包的应用(包括本仓库外的应用如 conversation-v2、session、workorder 等)。当前仓库仅包含 `layout` 和 `basis` 两个应用。
14
-
15
- ## 核心特性
16
-
17
- | 特性 | 说明 |
18
- | ---------- | ------------------------------------------------ |
19
- | 跨端兼容 | 通过外部注入 `messageInstance`,适配不同 UI 框架 |
20
- | 离线缓存 | 支持 IndexedDB + 内存双重缓存 |
21
- | 插值替换 | 支持 `%AA%`、`%BB%` 等动态占位符 |
22
- | 降级兜底 | 翻译缺失时自动返回默认文案 |
23
- | 微前端共享 | 主应用获取文案后,子应用可直接使用 |
24
-
25
- ## 两种使用模式
26
-
27
- 根据应用架构的不同,`<%= packageScope %>/common-intl` 支持两种使用模式:
28
-
29
- | 模式 | 适用场景 | 示例应用 |
30
- | ------------ | ------------------------------------------------ | ------------------------------------------------------------ |
31
- | 微前端模式 | qiankun 主子应用架构,主应用获取文案后子应用共享 | layout、conversation-v2、session、workorder、faq、permission |
32
- | 独立应用模式 | 独立运行的应用,自己获取和管理文案 | mico-cs-mobile |
33
-
34
- ### 微前端模式
35
-
36
- 在 qiankun 微前端架构中,**主应用负责获取文案**,子应用直接使用共享的文案对象,无需重复初始化。
37
-
38
- **工作原理**:
39
-
40
- - 主应用调用 `initIntl()` 获取远程文案
41
- - 文案数据存储到 `window.__MICO_COMMON_INTL_TRANSLATIONS__`
42
- - 子应用直接使用 `intl` 对象,自动从 window 读取共享数据
43
-
44
- ```
45
- ┌─────────────────────────────────────────────────────────────┐
46
- │ apps/layout(主应用) │
47
- │ ┌─────────────────────────────────────────────────────────┐│
48
- │ │ initIntl() → 请求远程文案 → 存储到 window 对象 ││
49
- │ └─────────────────────────────────────────────────────────┘│
50
- └─────────────────────────────────────────────────────────────┘
51
-
52
- ┌─────────────────────┼─────────────────────┐
53
- ↓ ↓ ↓
54
- ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
55
- │ conversation │ │ session │ │ workorder │
56
- │ 子应用 │ │ 子应用 │ │ 子应用 │
57
- │ import {intl} │ │ import {intl} │ │ import {intl} │
58
- │ 直接使用 │ │ 直接使用 │ │ 直接使用 │
59
- └───────────────┘ └───────────────┘ └───────────────┘
60
- ```
61
-
62
- **主应用配置(apps/layout/src/app.tsx)**:
63
-
64
- ```typescript
65
- import {
66
- getCurrentLocale,
67
- initIntl,
68
- type ILang,
69
- } from "<%= packageScope %>/common-intl";
70
- import { Message } from "@mico-platform/ui";
71
- import { request } from "@umijs/max";
72
-
73
- // 初始化国际化模块
74
- const fetchMultilingualData = initIntl({
75
- requestInstance: request,
76
- messageInstance: {
77
- error: (msg: string) => Message.error(msg),
78
- warning: (msg: string) => Message.warning(msg),
79
- },
80
- fetchMultilingualDataParams: {
81
- tag: "cs_fe_pc",
82
- lang: getCurrentLocale() as ILang,
83
- app_name: "middle",
84
- },
85
- indexedDBParams: {
86
- dbName: "mico_cs_web_i18n_db",
87
- },
88
- });
89
-
90
- // 在应用渲染前加载多语言数据
91
- export function render(oldRender: () => void): void {
92
- fetchMultilingualData()
93
- .then(oldRender)
94
- .catch((error: Error) => {
95
- console.error("获取多语言文案失败", error);
96
- oldRender(); // 失败时继续渲染,使用兜底文案
97
- });
98
- }
99
- ```
100
-
101
- **子应用使用(无需初始化)**:
102
-
103
- ```typescript
104
- // apps/conversation-v2、apps/session、apps/workorder 等子应用
105
- import { intl } from "<%= packageScope %>/common-intl";
106
-
107
- // 直接使用,文案来自主应用
108
- <h1>{intl.cs_web_workbench_conversation_record()}</h1>;
109
- ```
110
-
111
- ### 独立应用模式
112
-
113
- 对于非 qiankun 架构的独立应用(如 H5 应用),需要自己调用 `initIntl()` 获取文案,并维护独立的文案文件。
114
-
115
- **独立应用配置(apps/mico-cs-mobile/src/app.ts)**:
116
-
117
- ```typescript
118
- import { initIntl } from "<%= packageScope %>/common-intl";
119
- import { Toast } from "@arco-design/mobile-react";
120
- import { request } from "@umijs/max";
121
- import { convertLocaleToLangParam } from "./locales/utils";
122
- import { getSearchParams } from "@/common/jsbridge/jsbridge";
123
-
124
- // 初始化国际化模块
125
- const fetchMultilingualData = initIntl({
126
- requestInstance: request,
127
- messageInstance: {
128
- error: (msg: string) => Toast.error(msg),
129
- warning: (msg: string) => Toast.warn(msg),
130
- },
131
- fetchMultilingualDataParams: {
132
- tag: "cs_fe_mobile", // 独立应用使用不同的 tag
133
- lang: convertLocaleToLangParam(getSearchParams().language as string),
134
- app_name: "middle",
135
- },
136
- indexedDBParams: {
137
- dbName: "mico_cs_mobile_i18n_db",
138
- },
139
- });
140
-
141
- export function render(oldRender: () => void): void {
142
- fetchMultilingualData()
143
- .then(oldRender)
144
- .catch((error: Error) => {
145
- console.error("获取多语言文案失败", error);
146
- oldRender();
147
- });
148
- }
149
- ```
150
-
151
- **独立应用的文案文件(apps/mico-cs-mobile/src/locales/index.ts)**:
152
-
153
- ```typescript
154
- import { i18n } from "<%= packageScope %>/common-intl";
155
-
156
- const intl = {
157
- sdk_h5_ticket_record: () =>
158
- i18n({
159
- key: "sdk_h5_ticket_record",
160
- defaultMessage: "工单记录",
161
- }),
162
- // ... 其他文案
163
- };
164
-
165
- export default intl;
166
- ```
167
-
168
- **在组件中使用**:
169
-
170
- ```typescript
171
- import intl from "@/locales";
172
-
173
- <h1>{intl.sdk_h5_ticket_record()}</h1>;
174
- ```
175
-
176
- ## 导出 API
177
-
178
- `<%= packageScope %>/common-intl` 提供以下导出:
179
-
180
- | 导出 | 类型 | 说明 |
181
- | -------------------- | ---- | --------------------------------------------------------- |
182
- | `initIntl` | 函数 | 初始化国际化模块,返回 `fetchMultilingualData` 函数 |
183
- | `i18n` | 函数 | 翻译函数,用于获取单条翻译文案 |
184
- | `intl` | 对象 | PC 端主子应用共享的文案对象(仅供 layout 及其子应用使用) |
185
- | `LANG` | 常量 | 支持的语言常量:`ZH_CN`、`EN`、`AR`、`TR` |
186
- | `LOCALE` | 常量 | `LANG` 的别名,用于兼容 |
187
- | `SUPPORTED_LOCALES` | 常量 | 支持的语言列表数组 |
188
- | `getCurrentLocale` | 函数 | 获取当前语言环境(按优先级:URL > localStorage > 浏览器) |
189
- | `setLocaleToStorage` | 函数 | 设置语言到 localStorage |
190
- | `ILang` | 类型 | 语言类型定义 |
191
- | `TLocale` | 类型 | `ILang` 的别名,用于兼容 |
192
-
193
- ### 导入示例
194
-
195
- ```typescript
196
- // 微前端子应用 - 直接使用共享的 intl 对象
197
- import { intl } from "<%= packageScope %>/common-intl";
198
- intl.cs_web_common_request_failed();
199
-
200
- // 独立应用 - 使用 i18n 函数构建自己的文案对象
201
- import { i18n, initIntl, LANG } from "<%= packageScope %>/common-intl";
202
-
203
- // 获取当前语言环境
204
- import { getCurrentLocale } from "<%= packageScope %>/common-intl";
205
- const currentLang = getCurrentLocale(); // 'zh_CN' | 'en' | 'ar' | 'tr'
206
-
207
- // 获取支持的语言列表
208
- import { SUPPORTED_LOCALES } from "<%= packageScope %>/common-intl";
209
- console.log(SUPPORTED_LOCALES); // ['zh_CN', 'en', 'ar', 'tr']
210
- ```
211
-
212
- ## 文案管理规则
213
-
214
- ### PC 端主子应用
215
-
216
- - **文案位置**:[packages/common-intl/src/intl.ts](../packages/common-intl/src/intl.ts)
217
- - **使用方式**:`import { intl } from '<%= packageScope %>/common-intl'`
218
- - **适用应用**:
219
- - apps/layout(主应用)
220
- - apps/conversation-v2(工作台子应用)
221
- - apps/session(服务记录子应用)
222
- - apps/workorder(工单子应用)
223
- - apps/faq(FAQ 子应用)
224
- - apps/permission(权限管理子应用)
225
- - packages/shared(公共包)
226
-
227
- ### 独立应用(如 mico-cs-mobile)
228
-
229
- - **文案位置**:各应用自己的 `src/locales/index.ts`
230
- - **使用方式**:`import intl from '@/locales'`
231
- - **原因**:独立应用有自己的多语言标签(tag),文案独立管理
232
-
233
- ### layout-crm 应用
234
-
235
- - **角色**:另一个主应用(类似 layout)
236
- - **使用方式**:使用 `getCurrentLocale`、`LOCALE` 等工具函数
237
- - **说明**:layout-crm 是独立的布局应用,可按需配置国际化初始化
238
-
239
- ## 快速接入
240
-
241
- ### 1. 添加依赖
242
-
243
- ```json
244
- // apps/your-app/package.json
245
- {
246
- "dependencies": {
247
- "<%= packageScope %>/common-intl": "workspace:*"
248
- }
249
- }
250
- ```
251
-
252
- ### 2. 根据模式选择接入方式
253
-
254
- **如果是 layout 的子应用**:
255
-
256
- - 无需调用 `initIntl()`
257
- - 直接使用 `import { intl } from '<%= packageScope %>/common-intl'`
258
-
259
- **如果是独立应用**:
260
-
261
- - 在 `app.ts` 中调用 `initIntl()` 并配置
262
- - 创建自己的国际化文案集中管理文件,如 `src/locales/index.ts`
263
- - 使用 `import intl from '@/locales'`
264
-
265
- ## 语言优先级
266
-
267
- `getCurrentLocale()` 函数按以下优先级确定当前语言:
268
-
269
- 1. **URL 参数**:`?lang=zh_CN`
270
- 2. **localStorage**:`umi_locale` 键
271
- 3. **浏览器默认语言**:`navigator.language`
272
-
273
- ## 详细文档
274
-
275
- 完整的 API 参考、类型定义和占位符规则,请参阅:
276
-
277
- - **[packages/common-intl/README.md](../packages/common-intl/README.md)**
278
-
279
- ## 常见问题
280
-
281
- ### Q: 微前端子应用需要调用 initIntl 吗?
282
-
283
- 不需要。主应用(layout)负责初始化和获取文案,子应用直接使用共享的 `intl` 对象即可。
284
-
285
- ### Q: 如何获取多语言中台的 `tag` 和 `app_name`?
286
-
287
- 请联系多语言中台管理员,根据你的应用申请对应的配置参数。
288
-
289
- ### Q: 翻译数据什么时候加载?
290
-
291
- 推荐在 UmiJS 的 `render` 钩子中调用 `fetchMultilingualData()`,确保在应用渲染前完成加载。
292
-
293
- ### Q: 如何添加新的翻译文案?
294
-
295
- 1. 在多语言中台添加新的翻译 key 和对应的各语言翻译
296
- 2. PC 端:在 `packages/common-intl/src/intl.ts` 中添加对应的函数
297
- 3. 独立应用:在应用自己的 `src/locales/index.ts` 中添加
298
- 4. 在代码中通过 `intl.xxx()` 调用
299
-
300
- ### Q: IndexedDB 不可用怎么办?
301
-
302
- 库会自动降级到内存缓存模式,不影响正常使用,但页面刷新后需要重新拉取数据。
303
-
304
- ### Q: 主应用获取文案失败,子应用会怎样?
305
-
306
- 会显示兜底文案(`defaultMessage`)。建议在定义文案时始终提供有意义的兜底文案。
307
-
308
- ### Q: 如何切换语言?
309
-
310
- 语言切换由主应用(layout)的 AvatarDropdown 组件处理,切换后会刷新页面重新加载对应语言的文案。
311
-
312
- ### Q: 支持哪些语言?
313
-
314
- 目前支持以下语言:
315
-
316
- | 语言常量 | 值 | 说明 |
317
- | ------------- | ------- | -------- |
318
- | `LANG.ZH_CN` | `zh_CN` | 简体中文 |
319
- | `LANG.EN_US` | `en` | 英语 |
320
- | `LANG.AR_SA` | `ar` | 阿拉伯语 |
321
- | `LANG.TR_TR` | `tr` | 土耳其语 |
322
-
323
- ### Q: 如何在代码中获取当前语言?
324
-
325
- ```typescript
326
- import { getCurrentLocale } from "<%= packageScope %>/common-intl";
327
-
328
- const currentLang = getCurrentLocale();
329
- if (currentLang === "ar") {
330
- // 处理阿拉伯语的 RTL 布局
331
- }
332
- ```
333
-
334
- ### Q: 模块级常量中使用 intl 时,为什么文案显示不正确?
335
-
336
- 当在模块顶层定义常量时,`intl.xxx()` 会在模块加载时立即执行,此时多语言文案可能还未加载完成,导致显示兜底文案或空值。
337
-
338
- **错误示例**:
339
-
340
- ```typescript
341
- // ❌ 模块加载时立即执行,此时文案可能未加载
342
- export const STATUS_TEXT = {
343
- pending: intl.cs_web_status_pending(),
344
- completed: intl.cs_web_status_completed(),
345
- };
346
- ```
347
-
348
- **正确做法**:用函数包裹,延迟到运行时获取文案。
349
-
350
- ```typescript
351
- // ✅ 函数形式,运行时调用才获取文案
352
- export const getStatusText = (status: TStatus): string => {
353
- const map: Record<TStatus, string> = {
354
- pending: intl.cs_web_status_pending(),
355
- completed: intl.cs_web_status_completed(),
356
- };
357
- return map[status];
358
- };
359
- ```
360
-
361
- **在组件中使用时**,如果需要构建选项列表,可用 `useMemo`:
362
-
363
- ```tsx
364
- const options = useMemo(
365
- () =>
366
- Object.values(Status).map((status) => ({
367
- value: status,
368
- label: getStatusText(status),
369
- })),
370
- [],
371
- );
372
- ```
@@ -1,51 +0,0 @@
1
- /**
2
- * 检查当前环境是否支持 IndexedDB
3
- */
4
- export function isIndexedDBSupported(): boolean {
5
- try {
6
- return (
7
- typeof window !== 'undefined' &&
8
- 'indexedDB' in window &&
9
- window.indexedDB !== null
10
- );
11
- } catch {
12
- return false;
13
- }
14
- }
15
-
16
- /**
17
- * 打开 IndexedDB 数据库
18
- * @param dbName 数据库名称
19
- * @param dbVersion 数据库版本号
20
- * @param storeName 对象存储名称
21
- * @param keyPathKey keyPath 字段名,用于对象存储的主键索引
22
- * @param onUpgradeNeeded 数据库升级回调
23
- */
24
- export function openDatabase(
25
- dbName: string,
26
- dbVersion: number,
27
- storeName: string,
28
- keyPathKey?: string,
29
- onUpgradeNeeded?: (database: IDBDatabase) => void,
30
- ): Promise<IDBDatabase> {
31
- return new Promise((resolve, reject) => {
32
- const request = indexedDB.open(dbName, dbVersion);
33
-
34
- request.onerror = () => {
35
- reject(request.error);
36
- };
37
-
38
- request.onsuccess = () => {
39
- resolve(request.result);
40
- };
41
-
42
- request.onupgradeneeded = (event) => {
43
- const database = (event.target as IDBOpenDBRequest).result;
44
- if (!database.objectStoreNames.contains(storeName)) {
45
- const options = keyPathKey ? { keyPath: keyPathKey } : undefined;
46
- database.createObjectStore(storeName, options);
47
- }
48
- onUpgradeNeeded?.(database);
49
- };
50
- });
51
- }