@4399ywkf/cli 1.0.7 → 1.0.9

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 (254) hide show
  1. package/dist/templates/AntdStaticMethods/index.tsx +20 -0
  2. package/dist/templates/AppTheme.tsx +136 -0
  3. package/dist/templates/DIRECTORY_STRUCTURE.md +141 -0
  4. package/dist/templates/GlobalProvider/AppTheme.tsx +136 -0
  5. package/dist/templates/GlobalProvider/Locale.tsx +84 -0
  6. package/dist/templates/GlobalProvider/Query.tsx +12 -0
  7. package/dist/templates/GlobalProvider/StyleRegistry.tsx +9 -0
  8. package/dist/templates/GlobalProvider/index.tsx +23 -0
  9. package/dist/templates/HarmonyOS_Sans_Bold.woff2 +0 -0
  10. package/dist/templates/HarmonyOS_Sans_Medium.woff2 +0 -0
  11. package/dist/templates/HarmonyOS_Sans_Regular.woff2 +0 -0
  12. package/dist/templates/Locale.tsx +49 -54
  13. package/dist/templates/MainContentWrap.tsx +11 -15
  14. package/dist/templates/Query.tsx +12 -0
  15. package/dist/templates/StyleRegistry.tsx +9 -0
  16. package/dist/templates/ThemeContext.tsx +27 -24
  17. package/dist/templates/analyzeUnusedKeys.ts +506 -0
  18. package/dist/templates/app/.i18nrc.js +57 -0
  19. package/dist/templates/app/config/env/.env.public.tpl +2 -19
  20. package/dist/templates/app/config/jwt/index.ts +4 -4
  21. package/dist/templates/app/config/request/error-handler.ts +67 -0
  22. package/dist/templates/app/config/request/index.ts +127 -129
  23. package/dist/templates/app/config/request/interceptors.ts +118 -0
  24. package/dist/templates/app/config/request/token-manager.ts +23 -0
  25. package/dist/templates/app/config/request/types.ts +63 -0
  26. package/dist/templates/app/config/rspack/rspack.config.mjs +62 -61
  27. package/dist/templates/app/config/rspack/rspack.prod.mjs +41 -62
  28. package/dist/templates/app/docs/DIRECTORY_STRUCTURE.md +141 -0
  29. package/dist/templates/app/docs/glossary.md +11 -0
  30. package/dist/templates/app/locales/zh-CN/common.json +3 -0
  31. package/dist/templates/app/package.json.tpl +8 -25
  32. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  33. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  34. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  35. package/dist/templates/app/react-app-env.d.ts +13 -8
  36. package/dist/templates/app/scripts/i18nWorkflow/analyzeUnusedKeys.ts +506 -0
  37. package/dist/templates/app/scripts/i18nWorkflow/cleanUnusedKeys.ts +344 -0
  38. package/dist/templates/app/scripts/i18nWorkflow/const.ts +18 -0
  39. package/dist/templates/app/scripts/i18nWorkflow/flattenLocaleKeys.ts +139 -0
  40. package/dist/templates/app/scripts/i18nWorkflow/genDefaultLocale.ts +19 -0
  41. package/dist/templates/app/scripts/i18nWorkflow/genDiff.ts +49 -0
  42. package/dist/templates/app/scripts/i18nWorkflow/i18nConfig.ts +7 -0
  43. package/dist/templates/app/scripts/i18nWorkflow/index.ts +11 -0
  44. package/dist/templates/app/scripts/i18nWorkflow/protectedPatterns.ts +91 -0
  45. package/dist/templates/app/scripts/i18nWorkflow/utils.ts +76 -0
  46. package/dist/templates/app/src/bootstrap/index.ts +34 -0
  47. package/dist/templates/app/src/components/AntdStaticMethods/index.tsx +20 -0
  48. package/dist/templates/app/src/config/env.ts +84 -0
  49. package/dist/templates/app/src/index.tsx +13 -51
  50. package/dist/templates/app/src/layout/GlobalProvider/AppTheme.tsx +136 -0
  51. package/dist/templates/app/src/layout/GlobalProvider/Locale.tsx +84 -0
  52. package/dist/templates/app/src/layout/GlobalProvider/Query.tsx +12 -0
  53. package/dist/templates/app/src/layout/GlobalProvider/StyleRegistry.tsx +9 -0
  54. package/dist/templates/app/src/layout/GlobalProvider/index.tsx +23 -0
  55. package/dist/templates/app/src/layout/Locale.tsx +14 -18
  56. package/dist/templates/app/src/layout/MainContentWrap.tsx +11 -15
  57. package/dist/templates/app/src/layout/ThemeContext.tsx +27 -24
  58. package/dist/templates/app/src/locales/default/common.ts +3 -1
  59. package/dist/templates/app/src/locales/utils.ts +23 -0
  60. package/dist/templates/app/src/micro/garfish.ts +53 -0
  61. package/dist/templates/app/src/pages/base/index.tsx +280 -25
  62. package/dist/templates/app/src/routes.tsx +21 -12
  63. package/dist/templates/app/src/types/global.d.ts +19 -0
  64. package/dist/templates/app/src/utils/index.ts +3 -1
  65. package/dist/templates/app/store/middleware/createDevtools.ts +7 -7
  66. package/dist/templates/app/tsconfig.json +19 -3
  67. package/dist/templates/base/index.tsx +280 -25
  68. package/dist/templates/bootstrap/index.ts +34 -0
  69. package/dist/templates/cleanUnusedKeys.ts +344 -0
  70. package/dist/templates/common.json +3 -0
  71. package/dist/templates/common.ts +3 -1
  72. package/dist/templates/components/AntdStaticMethods/index.tsx +20 -0
  73. package/dist/templates/config/env/.env.public.tpl +2 -19
  74. package/dist/templates/config/env.ts +84 -0
  75. package/dist/templates/config/jwt/index.ts +4 -4
  76. package/dist/templates/config/request/error-handler.ts +67 -0
  77. package/dist/templates/config/request/index.ts +127 -129
  78. package/dist/templates/config/request/interceptors.ts +118 -0
  79. package/dist/templates/config/request/token-manager.ts +23 -0
  80. package/dist/templates/config/request/types.ts +63 -0
  81. package/dist/templates/config/rspack/rspack.config.mjs +62 -61
  82. package/dist/templates/config/rspack/rspack.prod.mjs +41 -62
  83. package/dist/templates/const.ts +18 -0
  84. package/dist/templates/createDevtools.ts +7 -7
  85. package/dist/templates/default/common.ts +3 -1
  86. package/dist/templates/docs/DIRECTORY_STRUCTURE.md +141 -0
  87. package/dist/templates/docs/glossary.md +11 -0
  88. package/dist/templates/env/.env.public.tpl +2 -19
  89. package/dist/templates/env.ts +83 -2
  90. package/dist/templates/error-handler.ts +67 -0
  91. package/dist/templates/flattenLocaleKeys.ts +139 -0
  92. package/dist/templates/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  93. package/dist/templates/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  94. package/dist/templates/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  95. package/dist/templates/garfish.ts +53 -0
  96. package/dist/templates/genDefaultLocale.ts +19 -0
  97. package/dist/templates/genDiff.ts +49 -0
  98. package/dist/templates/global.d.ts +19 -0
  99. package/dist/templates/glossary.md +11 -0
  100. package/dist/templates/i18nConfig.ts +7 -0
  101. package/dist/templates/i18nWorkflow/analyzeUnusedKeys.ts +506 -0
  102. package/dist/templates/i18nWorkflow/cleanUnusedKeys.ts +344 -0
  103. package/dist/templates/i18nWorkflow/const.ts +18 -0
  104. package/dist/templates/i18nWorkflow/flattenLocaleKeys.ts +139 -0
  105. package/dist/templates/i18nWorkflow/genDefaultLocale.ts +19 -0
  106. package/dist/templates/i18nWorkflow/genDiff.ts +49 -0
  107. package/dist/templates/i18nWorkflow/i18nConfig.ts +7 -0
  108. package/dist/templates/i18nWorkflow/index.ts +11 -0
  109. package/dist/templates/i18nWorkflow/protectedPatterns.ts +91 -0
  110. package/dist/templates/i18nWorkflow/utils.ts +76 -0
  111. package/dist/templates/index.tsx +280 -25
  112. package/dist/templates/interceptors.ts +118 -0
  113. package/dist/templates/jwt/index.ts +4 -4
  114. package/dist/templates/layout/GlobalProvider/AppTheme.tsx +136 -0
  115. package/dist/templates/layout/GlobalProvider/Locale.tsx +84 -0
  116. package/dist/templates/layout/GlobalProvider/Query.tsx +12 -0
  117. package/dist/templates/layout/GlobalProvider/StyleRegistry.tsx +9 -0
  118. package/dist/templates/layout/GlobalProvider/index.tsx +23 -0
  119. package/dist/templates/layout/Locale.tsx +14 -18
  120. package/dist/templates/layout/MainContentWrap.tsx +11 -15
  121. package/dist/templates/layout/ThemeContext.tsx +27 -24
  122. package/dist/templates/locales/default/common.ts +3 -1
  123. package/dist/templates/locales/utils.ts +23 -0
  124. package/dist/templates/locales/zh-CN/common.json +3 -0
  125. package/dist/templates/micro/garfish.ts +53 -0
  126. package/dist/templates/middleware/createDevtools.ts +7 -7
  127. package/dist/templates/package.json.tpl +8 -25
  128. package/dist/templates/page.tsx +21 -19
  129. package/dist/templates/pages/base/index.tsx +280 -25
  130. package/dist/templates/protectedPatterns.ts +91 -0
  131. package/dist/templates/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  132. package/dist/templates/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  133. package/dist/templates/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  134. package/dist/templates/react-app-env.d.ts +13 -8
  135. package/dist/templates/request/error-handler.ts +67 -0
  136. package/dist/templates/request/index.ts +127 -129
  137. package/dist/templates/request/interceptors.ts +118 -0
  138. package/dist/templates/request/token-manager.ts +23 -0
  139. package/dist/templates/request/types.ts +63 -0
  140. package/dist/templates/routes.tsx +21 -12
  141. package/dist/templates/rspack/rspack.config.mjs +62 -61
  142. package/dist/templates/rspack/rspack.prod.mjs +41 -62
  143. package/dist/templates/rspack.config.mjs +62 -61
  144. package/dist/templates/rspack.prod.mjs +41 -62
  145. package/dist/templates/scripts/i18nWorkflow/analyzeUnusedKeys.ts +506 -0
  146. package/dist/templates/scripts/i18nWorkflow/cleanUnusedKeys.ts +344 -0
  147. package/dist/templates/scripts/i18nWorkflow/const.ts +18 -0
  148. package/dist/templates/scripts/i18nWorkflow/flattenLocaleKeys.ts +139 -0
  149. package/dist/templates/scripts/i18nWorkflow/genDefaultLocale.ts +19 -0
  150. package/dist/templates/scripts/i18nWorkflow/genDiff.ts +49 -0
  151. package/dist/templates/scripts/i18nWorkflow/i18nConfig.ts +7 -0
  152. package/dist/templates/scripts/i18nWorkflow/index.ts +11 -0
  153. package/dist/templates/scripts/i18nWorkflow/protectedPatterns.ts +91 -0
  154. package/dist/templates/scripts/i18nWorkflow/utils.ts +76 -0
  155. package/dist/templates/src/bootstrap/index.ts +34 -0
  156. package/dist/templates/src/components/AntdStaticMethods/index.tsx +20 -0
  157. package/dist/templates/src/config/env.ts +84 -0
  158. package/dist/templates/src/index.tsx +13 -51
  159. package/dist/templates/src/layout/GlobalProvider/AppTheme.tsx +136 -0
  160. package/dist/templates/src/layout/GlobalProvider/Locale.tsx +84 -0
  161. package/dist/templates/src/layout/GlobalProvider/Query.tsx +12 -0
  162. package/dist/templates/src/layout/GlobalProvider/StyleRegistry.tsx +9 -0
  163. package/dist/templates/src/layout/GlobalProvider/index.tsx +23 -0
  164. package/dist/templates/src/layout/Locale.tsx +14 -18
  165. package/dist/templates/src/layout/MainContentWrap.tsx +11 -15
  166. package/dist/templates/src/layout/ThemeContext.tsx +27 -24
  167. package/dist/templates/src/locales/default/common.ts +3 -1
  168. package/dist/templates/src/locales/utils.ts +23 -0
  169. package/dist/templates/src/micro/garfish.ts +53 -0
  170. package/dist/templates/src/pages/base/index.tsx +280 -25
  171. package/dist/templates/src/routes.tsx +21 -12
  172. package/dist/templates/src/types/global.d.ts +19 -0
  173. package/dist/templates/src/utils/index.ts +3 -1
  174. package/dist/templates/store/middleware/createDevtools.ts +7 -7
  175. package/dist/templates/token-manager.ts +23 -0
  176. package/dist/templates/tsconfig.json +19 -3
  177. package/dist/templates/type.ts +23 -24
  178. package/dist/templates/types/global.d.ts +19 -0
  179. package/dist/templates/utils/index.ts +3 -1
  180. package/dist/templates/utils.ts +23 -0
  181. package/dist/templates/zh-CN/common.json +3 -0
  182. package/package.json +19 -21
  183. package/dist/templates/app/config/sentry/sentry.config.ts +0 -188
  184. package/dist/templates/app/src/hooks/useRouteTitle.tsx +0 -36
  185. package/dist/templates/app/src/hooks/useSentry.ts +0 -92
  186. package/dist/templates/app/src/pages/base/layout.tsx +0 -6
  187. package/dist/templates/app/src/pages/base/page.tsx +0 -25
  188. package/dist/templates/app/src/utils/env.ts +0 -3
  189. package/dist/templates/app/src/utils/format.ts +0 -21
  190. package/dist/templates/app/src/utils/getMicroApp.ts +0 -39
  191. package/dist/templates/app/src/utils/sentry.ts +0 -187
  192. package/dist/templates/app/src/utils/sentryDecorators.ts +0 -34
  193. package/dist/templates/app/src/utils/updateVersion.ts +0 -186
  194. package/dist/templates/base/layout.tsx +0 -6
  195. package/dist/templates/base/page.tsx +0 -25
  196. package/dist/templates/config/public/404.png +0 -0
  197. package/dist/templates/config/public/favicon.ico +0 -0
  198. package/dist/templates/config/public/images/banner_market_modal.webp +0 -0
  199. package/dist/templates/config/public/images/chatmode_chat_dark.webp +0 -0
  200. package/dist/templates/config/public/images/chatmode_chat_light.webp +0 -0
  201. package/dist/templates/config/public/images/chatmode_docs_dark.webp +0 -0
  202. package/dist/templates/config/public/images/chatmode_docs_light.webp +0 -0
  203. package/dist/templates/config/public/images/empty_topic_dark.webp +0 -0
  204. package/dist/templates/config/public/images/empty_topic_light.webp +0 -0
  205. package/dist/templates/config/public/images/screenshot_background.webp +0 -0
  206. package/dist/templates/config/public/images/theme_auto.webp +0 -0
  207. package/dist/templates/config/public/images/theme_dark.webp +0 -0
  208. package/dist/templates/config/public/images/theme_light.webp +0 -0
  209. package/dist/templates/config/public/index.html +0 -29
  210. package/dist/templates/config/sentry/sentry.config.ts +0 -188
  211. package/dist/templates/format.ts +0 -21
  212. package/dist/templates/getMicroApp.ts +0 -39
  213. package/dist/templates/hooks/useRouteTitle.tsx +0 -36
  214. package/dist/templates/hooks/useSentry.ts +0 -92
  215. package/dist/templates/layout.tsx +0 -6
  216. package/dist/templates/pages/base/layout.tsx +0 -6
  217. package/dist/templates/pages/base/page.tsx +0 -25
  218. package/dist/templates/sentry/sentry.config.ts +0 -188
  219. package/dist/templates/sentry.config.ts +0 -188
  220. package/dist/templates/sentry.ts +0 -187
  221. package/dist/templates/sentryDecorators.ts +0 -34
  222. package/dist/templates/src/hooks/useRouteTitle.tsx +0 -36
  223. package/dist/templates/src/hooks/useSentry.ts +0 -92
  224. package/dist/templates/src/pages/base/layout.tsx +0 -6
  225. package/dist/templates/src/pages/base/page.tsx +0 -25
  226. package/dist/templates/src/utils/env.ts +0 -3
  227. package/dist/templates/src/utils/format.ts +0 -21
  228. package/dist/templates/src/utils/getMicroApp.ts +0 -39
  229. package/dist/templates/src/utils/sentry.ts +0 -187
  230. package/dist/templates/src/utils/sentryDecorators.ts +0 -34
  231. package/dist/templates/src/utils/updateVersion.ts +0 -186
  232. package/dist/templates/updateVersion.ts +0 -186
  233. package/dist/templates/useRouteTitle.tsx +0 -36
  234. package/dist/templates/useSentry.ts +0 -92
  235. package/dist/templates/utils/env.ts +0 -3
  236. package/dist/templates/utils/format.ts +0 -21
  237. package/dist/templates/utils/getMicroApp.ts +0 -39
  238. package/dist/templates/utils/sentry.ts +0 -187
  239. package/dist/templates/utils/sentryDecorators.ts +0 -34
  240. package/dist/templates/utils/updateVersion.ts +0 -186
  241. /package/dist/templates/app/{config/public → public}/404.png +0 -0
  242. /package/dist/templates/app/{config/public → public}/favicon.ico +0 -0
  243. /package/dist/templates/app/{config/public → public}/images/banner_market_modal.webp +0 -0
  244. /package/dist/templates/app/{config/public → public}/images/chatmode_chat_dark.webp +0 -0
  245. /package/dist/templates/app/{config/public → public}/images/chatmode_chat_light.webp +0 -0
  246. /package/dist/templates/app/{config/public → public}/images/chatmode_docs_dark.webp +0 -0
  247. /package/dist/templates/app/{config/public → public}/images/chatmode_docs_light.webp +0 -0
  248. /package/dist/templates/app/{config/public → public}/images/empty_topic_dark.webp +0 -0
  249. /package/dist/templates/app/{config/public → public}/images/empty_topic_light.webp +0 -0
  250. /package/dist/templates/app/{config/public → public}/images/screenshot_background.webp +0 -0
  251. /package/dist/templates/app/{config/public → public}/images/theme_auto.webp +0 -0
  252. /package/dist/templates/app/{config/public → public}/images/theme_dark.webp +0 -0
  253. /package/dist/templates/app/{config/public → public}/images/theme_light.webp +0 -0
  254. /package/dist/templates/app/{config/public → public}/index.html +0 -0
@@ -0,0 +1,141 @@
1
+ # 企业脚手架目录规划说明
2
+
3
+ ## 1. 现状概览
4
+
5
+ ```
6
+ app/
7
+ ├── config/ # 构建 + 运行时配置混放
8
+ │ ├── env/ # 环境变量文件
9
+ │ ├── jwt/ # 运行时
10
+ │ ├── request/ # 运行时
11
+ │ ├── router/ # 渲染入口(renderClient)
12
+ │ └── rspack/ # 构建
13
+ ├── locales/ # 文案 JSON(与 src/locales 双源)
14
+ ├── public/
15
+ ├── scripts/
16
+ ├── src/
17
+ │ ├── bootstrap/
18
+ │ ├── color/ # 设计 token 色板
19
+ │ ├── components/
20
+ │ ├── config/ # 仅 env.ts(与根 config 易混淆)
21
+ │ ├── const/
22
+ │ ├── layout/
23
+ │ ├── locales/ # i18n 逻辑 + TS 文案
24
+ │ ├── micro/
25
+ │ ├── pages/
26
+ │ ├── routes.tsx
27
+ │ ├── styles/ # 全局样式 + theme 算法
28
+ │ ├── types/
29
+ │ └── utils/
30
+ └── store/ # 与 src 平级
31
+ ├── middleware/
32
+ └── user/
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 2. 结论:整体可用,有几处需约定或收敛
38
+
39
+ - **做得好的**:`store` 独立、按 agent/slice 拆分;`pages` + `layout` + `components` 分层清晰;构建配置集中在 `config/rspack`、环境变量在 `config/env`,便于维护。
40
+ - **需要约定的**:根目录 `config` 与 `src/config` 的职责边界、`locales` 双源、`color`/`styles`/`theme` 的归属。
41
+ - **可优化项**:收敛「配置与文案」的入口、统一命名(如 `const` vs `constants`)、可选能力(如 `micro`)在文档中说明。
42
+
43
+ ---
44
+
45
+ ## 3. 问题与建议
46
+
47
+ ### 3.1 config 双位置(根 config vs src/config)
48
+
49
+ | 位置 | 内容 | 问题 |
50
+ |------------|----------------|------------------------------|
51
+ | 根 `config/` | env 文件、rspack、request、jwt、router | 构建与运行时混在同一层 |
52
+ | `src/config/` | 仅 `env.ts`(zod 解析) | 新人易困惑「改 env 改哪边」 |
53
+
54
+ **建议(二选一或折中):**
55
+
56
+ - **方案 A(推荐)**:约定「根 `config/` = 仅构建与环境文件」:只放 `env/`、`rspack/`;把 `request/`、`jwt/`、`router/` 迁到 `src/config/`(或 `src/core/`),alias 保持 `@config` 指向 `src/config`,构建配置单独用 `config/rspack` 路径。这样「构建配置在根 config,运行时配置在 src」边界清晰。
57
+ - **方案 B**:维持现状,在 README 中明确写清:「环境变量与构建用根 `config/`,运行时解析用 `src/config/env.ts`;请求/路由等由根 `config/` 的模块提供」,减少误改。
58
+
59
+ ### 3.2 locales 双源(根 locales vs src/locales)
60
+
61
+ - 根 `locales/zh-CN/common.json` 与 `src/locales/default/common.ts` 内容重复,且有脚本把 TS 转 JSON。
62
+ - **建议**:选单一数据源。若以 i18n 代码为主,保留 `src/locales`,删除根 `locales/` 和转换脚本,构建或运行时从 `src/locales` 生成/加载;若以 JSON 为主,则只保留根 `locales/`,在 README 中说明「文案只放根 locales」。
63
+
64
+ ### 3.3 store 与 src 平级
65
+
66
+ - `store/` 在项目根与 `src/` 平级,符合「状态与 UI 分离」的常见企业习惯;alias `@store` 指向根下 `store` 也合理。
67
+ - **建议**:保持现状;在 README 或本说明中写一句:「业务 UI 在 `src/`,领域状态在 `store/`,按 agent/slice 拆分」,避免被误挪进 `src`。
68
+
69
+ ### 3.4 src 内部:color / styles / theme
70
+
71
+ - `color/`:色板与 token 数据;`styles/`:全局样式、antd 覆盖、**theme 算法与 customToken**;`types/` 中还有 `customStylish`、`customToken`。
72
+ - 问题:主题相关分散在 `color`、`styles/theme`、`styles`、`types`,新人找「改主题」入口不直观。
73
+ - **建议**:
74
+ - 要么保留 `color/` 但在 README 标明「设计 token 与色板,被 `styles/theme` 消费」;
75
+ - 要么将 `color/` 收进 `styles/theme/`(如 `styles/theme/color/`),入口统一为 `styles/theme`,减少顶层目录。
76
+ - 不强求一步到位,但需在文档中画一条线:**主题与 token 的入口是 `src/styles/theme`(及可选 `src/color`)**。
77
+
78
+ ### 3.5 横切目录:const / types / utils
79
+
80
+ - `const/`、`types/`、`utils/` 是常见横切层,结构合理。
81
+ - 小问题:`const/constants.ts` 当前为空;`types` 里既有全局类型又有与 theme 强相关的类型。
82
+ - **建议**:`const` 保留,删除或补全 `constants.ts`,避免空文件;在 README 或本说明中约定「全局业务常量放 `const/`,组件/页面私有常量随模块」。`types` 可注明「与 theme/样式强相关的类型与 `styles/theme` 同目录或在本目录集中维护」,二选一即可。
83
+
84
+ ### 3.6 可选能力:micro、bootstrap
85
+
86
+ - `micro/` 仅 Garfish,已作为可选项;`bootstrap/` 仅应用启动逻辑。
87
+ - **建议**:保持 `micro/` 在 `src` 下,README 中说明「微前端为可选项,入口与配置见 xxx」。`bootstrap/` 可保留;若希望根入口更短,可把 `bootstrapWithEnv()` 的实现迁到 `src/index.tsx` 或 `src/config/bootstrap.ts`,只保留单文件也可。
88
+
89
+ ### 3.7 pages 与路由
90
+
91
+ - `pages/` 下有 404、base、index 等;路由定义在 `src/routes.tsx`,渲染入口在 `config/router/index.tsx`。
92
+ - **建议**:约定「路由表仅由 `src/routes.tsx` 维护;`config/router` 只负责 `renderClient` 与挂载」,在 README 或本说明写清,避免在 `config/router` 里再配路由造成双源。
93
+
94
+ ### 3.8 根目录与脚本
95
+
96
+ - 根目录的 `tsconfig`、`tailwind`、`postcss`、`scripts/` 等符合常规,无需调整。
97
+ - `scripts/` 若仅剩「locales 转 JSON」且已决定废弃根 `locales/`,可删除该脚本;否则保留并注明用途。
98
+
99
+ ---
100
+
101
+ ## 4. 推荐约定(最小改动版)
102
+
103
+ 在不做大范围迁移的前提下,建议先做「约定文档化 + 少量收敛」:
104
+
105
+ 1. **配置**:在 README 中写清「根 `config/` = 构建与环境文件;运行时配置与请求/路由实现来自 `@config`(当前指向根 config,或你们改为 src/config)」。
106
+ 2. **文案**:选定 locales 单一数据源(推荐 `src/locales`),删除或弃用另一侧及转换脚本。
107
+ 3. **主题**:在 README 中标明「主题与 token 入口:`src/styles/theme`,色板数据见 `src/color`(可选)」。
108
+ 4. **store**:说明「全局状态在根 `store/`,按 agent/slice 划分,与 `src` 并列」。
109
+ 5. **路由**:说明「路由表只在 `src/routes.tsx` 维护;`config/router` 仅负责渲染与挂载」。
110
+ 6. **空文件**:删除或补全 `src/const/constants.ts`。
111
+
112
+ 若后续要做更大调整,再考虑:把 request/jwt/router 迁入 `src/config` 或 `src/core`、将 `color` 并入 `styles/theme` 等。
113
+
114
+ ---
115
+
116
+ ## 5. 可选:目标结构示意(供长期演进参考)
117
+
118
+ ```
119
+ app/
120
+ ├── config/ # 仅构建与环境
121
+ │ ├── env/
122
+ │ └── rspack/
123
+ ├── public/
124
+ ├── scripts/
125
+ ├── src/
126
+ │ ├── config/ # 运行时:env 解析、request、router 挂载等
127
+ │ ├── core/ # 可选:bootstrap、微前端入口等
128
+ │ ├── layout/
129
+ │ ├── pages/
130
+ │ ├── components/
131
+ │ ├── styles/ # 全局样式 + theme(含 token/color 或引用)
132
+ │ ├── locales/ # 单一 i18n 数据源
133
+ │ ├── const/
134
+ │ ├── types/
135
+ │ ├── utils/
136
+ │ ├── routes.tsx
137
+ │ └── index.tsx
138
+ └── store/
139
+ ```
140
+
141
+ 当前模板不必立刻改成上述结构,可先落实「约定 + 文档 + 删除冗余」,再按团队习惯逐步演进。
@@ -0,0 +1,11 @@
1
+ # Glossary
2
+
3
+ 以下是一些词汇的固定翻译:
4
+
5
+ | develop key | zh-CN (中文) | en-US(English) |
6
+ | ----------- | ------------ | -------------- |
7
+ | agent | 助理 | Agent |
8
+ | agentGroup | 群组 | Group |
9
+ | page | 文稿 | Page |
10
+ | topic | 话题 | Topic |
11
+ | thread | 子话题 | Thread |
@@ -1,5 +1,5 @@
1
1
  API_PREFIX="/api"
2
- API_TIMEOUT=60 * 1000
2
+ API_TIMEOUT=60000
3
3
 
4
4
  COOKIE_NAME='ywkf_jwt'
5
5
 
@@ -9,23 +9,6 @@ OUTPUT_PATH='dist'
9
9
  BASENAME='/'
10
10
 
11
11
  PUBLIC_PATH='/s{{{ name }}}/'
12
- VERSION_NOTIFY_TIME=30000
13
-
14
-
15
- # Sentry 配置 - (官网)
16
- # REACT_APP_SENTRY_DSN="https://95add4dc797c22aa2224494e4abd4d71@o4509466151878656.ingest.us.sentry.io/4509466153058304"
17
- # SENTRY_PROJECT="javascript-react"
18
- # SENTRY_ORG="test-x6m"
19
- # SENTRY_AUTH_TOKEN="d477b94cfe375f5b4e4e88ac4fc15a8be8557652cea424710b6f7f19be4f0b3d"
20
- # SENTRY_URL="https://test-x6m.sentry.io/"
21
12
 
22
13
  # 帮助中心
23
- HELP_CENTER_URL="https://im-support.gz4399.com/"
24
-
25
- # 是否开启Sentry
26
- SENTRY_ENABLED='{{SENTRY_ENABLED}}'
27
- REACT_APP_SENTRY_DSN='{{SENTRY_DSN}}'
28
- SENTRY_PROJECT='{{{ name }}}'
29
- SENTRY_ORG="sentry"
30
- SENTRY_AUTH_TOKEN="f13c66cd7a3629c8324cceb62fdb65aae1f337abbec4ebbadbe0a22447708994"
31
- SENTRY_URL="https://sentry.gz4399.com/"
14
+ HELP_CENTER_URL="https://im-support.gz4399.com/"
@@ -1,3 +1,84 @@
1
- export const isDev = process.env.NODE_ENV === 'development';
1
+ import { z } from "zod";
2
2
 
3
- export const isOnServerSide = typeof window === 'undefined';
3
+ /**
4
+ * 环境变量 Schema 定义
5
+ */
6
+ const envSchema = z.object({
7
+ // Node 环境
8
+ NODE_ENV: z
9
+ .enum(["development", "test", "testDevelopment", "production"])
10
+ .default("development"),
11
+
12
+ // 应用配置
13
+ APP_NAME: z.string().min(1, "应用名称不能为空").default("app"),
14
+ APP_CNAME: z.string().default("应用"),
15
+ BASENAME: z.string().optional(),
16
+
17
+ // API 配置
18
+ API_PREFIX: z.string().default("/api"),
19
+ API_TIMEOUT: z
20
+ .string()
21
+ .transform(Number)
22
+ .pipe(z.number().positive())
23
+ .default(30000),
24
+
25
+ // Cookie 配置
26
+ COOKIE_NAME: z.string().default("access_token"),
27
+
28
+ // 其他配置
29
+ HELP_CENTER_URL: z.string().url().optional(),
30
+ OUTPUT_PATH: z.string().default("dist"),
31
+ PUBLIC_PATH: z.string().default("/"),
32
+ });
33
+
34
+ /**
35
+ * 安全解析环境变量(开发模式下使用默认值)
36
+ */
37
+ function safeParseEnv() {
38
+ const result = envSchema.safeParse(process.env);
39
+
40
+ if (!result.success) {
41
+ if (process.env.NODE_ENV === "production") {
42
+ // 生产环境严格校验
43
+ console.error("❌ 环境变量验证失败:");
44
+ result.error.issues.forEach((err) => {
45
+ console.error(` - ${err.path.join(".")}: ${err.message}`);
46
+ });
47
+ throw new Error("环境变量配置错误");
48
+ } else {
49
+ // 开发环境警告但不中断
50
+ console.warn("⚠️ 环境变量验证警告:");
51
+ result.error.issues.forEach((err) => {
52
+ console.warn(` - ${err.path.join(".")}: ${err.message}`);
53
+ });
54
+ }
55
+ }
56
+
57
+ return result.success ? result.data : envSchema.parse({});
58
+ }
59
+
60
+ /**
61
+ * 导出类型安全的环境变量
62
+ */
63
+ export const env = safeParseEnv();
64
+
65
+ /**
66
+ * 环境变量类型
67
+ */
68
+ export type Env = z.infer<typeof envSchema>;
69
+
70
+ /**
71
+ * 工具函数:判断是否为开发环境
72
+ */
73
+ export const isDev = env.NODE_ENV === "development";
74
+
75
+ /**
76
+ * 工具函数:判断是否为生产环境
77
+ */
78
+ export const isProd = env.NODE_ENV === "production";
79
+
80
+ /**
81
+ * 工具函数:判断是否为测试环境
82
+ */
83
+ export const isTest =
84
+ env.NODE_ENV === "test" || env.NODE_ENV === "testDevelopment";
@@ -0,0 +1,67 @@
1
+ import { message as antdMessage } from "antd";
2
+ import type { AxiosError } from "axios";
3
+ import type { RequestConfig, ApiResponse } from "./types";
4
+
5
+ /**
6
+ * 错误处理器
7
+ */
8
+ export class ErrorHandler {
9
+ /**
10
+ * 处理请求错误
11
+ */
12
+ handle(error: any, config?: RequestConfig): void {
13
+ const messageConfig = config?.message;
14
+
15
+ // 如果明确禁用错误提示
16
+ if (messageConfig?.showError === false) {
17
+ return;
18
+ }
19
+
20
+ const axiosError = error as AxiosError<ApiResponse>;
21
+ let errorMessage = messageConfig?.errorMessage;
22
+
23
+ // 如果没有自定义错误消息,使用默认逻辑
24
+ if (!errorMessage) {
25
+ if (axiosError.response) {
26
+ const { status, data } = axiosError.response;
27
+
28
+ // 优先使用后端返回的消息
29
+ errorMessage = data?.message;
30
+
31
+ // 如果后端没有返回消息,使用默认消息
32
+ if (!errorMessage) {
33
+ errorMessage = this.getDefaultErrorMessage(status);
34
+ }
35
+ } else if (axiosError.request) {
36
+ errorMessage = "网络错误,请检查您的网络连接";
37
+ } else {
38
+ errorMessage = axiosError.message || "请求失败";
39
+ }
40
+ }
41
+
42
+ // 显示错误提示
43
+ antdMessage.error(errorMessage);
44
+ }
45
+
46
+ /**
47
+ * 获取默认错误消息
48
+ */
49
+ private getDefaultErrorMessage(status: number): string {
50
+ const errorMessages: Record<number, string> = {
51
+ 400: "请求参数错误",
52
+ 401: "未授权,请重新登录",
53
+ 403: "拒绝访问",
54
+ 404: "请求的资源不存在",
55
+ 405: "请求方法不允许",
56
+ 408: "请求超时",
57
+ 500: "服务器内部错误",
58
+ 502: "网关错误",
59
+ 503: "服务暂时不可用",
60
+ 504: "网关超时",
61
+ };
62
+
63
+ return errorMessages[status] || `请求失败 (${status})`;
64
+ }
65
+ }
66
+
67
+ export const errorHandler = new ErrorHandler();
@@ -0,0 +1,139 @@
1
+ /* eslint-disable unicorn/prefer-top-level-await */
2
+ import prettier from '@prettier/sync';
3
+ import { consola } from 'consola';
4
+ import { colors } from 'consola/utils';
5
+ import { readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
6
+ import { resolve } from 'node:path';
7
+ import { pathToFileURL } from 'node:url';
8
+
9
+ import { toLodashPath } from '../../src/locales/utils';
10
+ import { localeDir, localeDirJsonList, localesDir, srcDefaultLocales } from './const';
11
+
12
+ const prettierOptions = prettier.resolveConfig(resolve(__dirname, '../../.prettierrc.js')) ?? {};
13
+
14
+ const DEFAULT_SKIP_FILES = new Set(['index.ts', 'models.ts', 'providers.ts']);
15
+
16
+ const isPlainObject = (value: unknown): value is Record<string, unknown> => {
17
+ if (!value || typeof value !== 'object') return false;
18
+ return Object.prototype.toString.call(value) === '[object Object]';
19
+ };
20
+
21
+ const shouldPreserveObject = (value: Record<string, unknown>) => {
22
+ const keys = Object.keys(value);
23
+ if (keys.length === 0) return true;
24
+ return keys.every((key) => /^\d+$/.test(key));
25
+ };
26
+
27
+ const flattenObject = (input: Record<string, unknown>) => {
28
+ const output: Record<string, unknown> = {};
29
+
30
+ const addEntry = (pathSegments: Array<number | string>, value: unknown) => {
31
+ const key = toLodashPath(pathSegments);
32
+ if (Object.prototype.hasOwnProperty.call(output, key)) {
33
+ throw new Error(`Duplicate i18n key detected: ${key}`);
34
+ }
35
+ output[key] = value;
36
+ };
37
+
38
+ const visit = (value: unknown, pathSegments: Array<number | string>) => {
39
+ if (Array.isArray(value)) {
40
+ addEntry(pathSegments, value);
41
+ return;
42
+ }
43
+
44
+ if (isPlainObject(value)) {
45
+ if (shouldPreserveObject(value)) {
46
+ addEntry(pathSegments, value);
47
+ return;
48
+ }
49
+
50
+ const entries = Object.entries(value);
51
+ if (entries.length === 0) {
52
+ addEntry(pathSegments, value);
53
+ return;
54
+ }
55
+
56
+ for (const [childKey, childValue] of entries) {
57
+ visit(childValue, [...pathSegments, childKey]);
58
+ }
59
+ return;
60
+ }
61
+
62
+ addEntry(pathSegments, value);
63
+ };
64
+
65
+ for (const [key, value] of Object.entries(input)) {
66
+ visit(value, [key]);
67
+ }
68
+
69
+ return output;
70
+ };
71
+
72
+ const writeTs = (filePath: string, data: Record<string, unknown>) => {
73
+ const content = `export default ${JSON.stringify(data, null, 2)};\n`;
74
+ const formatted = prettier.format(content, {
75
+ ...prettierOptions,
76
+ parser: 'typescript',
77
+ });
78
+ writeFileSync(filePath, formatted, 'utf8');
79
+ };
80
+
81
+ const writeJson = (filePath: string, data: Record<string, unknown>) => {
82
+ const json = JSON.stringify(data, null, 2);
83
+ const formatted = prettier.format(json, {
84
+ ...prettierOptions,
85
+ parser: 'json',
86
+ });
87
+ writeFileSync(filePath, formatted, 'utf8');
88
+ };
89
+
90
+ const flattenDefaultLocales = async () => {
91
+ const files = readdirSync(srcDefaultLocales).filter((file) => file.endsWith('.ts'));
92
+
93
+ for (const file of files) {
94
+ if (DEFAULT_SKIP_FILES.has(file)) continue;
95
+
96
+ const filePath = resolve(srcDefaultLocales, file);
97
+ const fileUrl = pathToFileURL(filePath).href;
98
+ const loaded = await import(fileUrl);
99
+ const data = loaded.default ?? loaded;
100
+
101
+ const flat = flattenObject(data as Record<string, unknown>);
102
+ writeTs(filePath, flat);
103
+ consola.success(colors.cyan(file), colors.gray('flattened'));
104
+ }
105
+ };
106
+
107
+ const flattenLocaleJsons = () => {
108
+ const localeFolders = readdirSync(localesDir).filter((dir) =>
109
+ statSync(localeDir(dir)).isDirectory(),
110
+ );
111
+
112
+ for (const locale of localeFolders) {
113
+ const jsonFiles = localeDirJsonList(locale);
114
+ for (const jsonFile of jsonFiles) {
115
+ const filePath = resolve(localeDir(locale), jsonFile);
116
+ const raw = readFileSync(filePath, 'utf8');
117
+ const data = JSON.parse(raw);
118
+ const flat = flattenObject(data);
119
+ writeJson(filePath, flat);
120
+ consola.success(colors.cyan(`${locale}/${jsonFile}`), colors.gray('flattened'));
121
+ }
122
+ }
123
+ };
124
+
125
+ const run = async () => {
126
+ consola.start('Flattening src/locales/default...');
127
+ await flattenDefaultLocales();
128
+
129
+ consola.start('Flattening locales JSON files...');
130
+ flattenLocaleJsons();
131
+
132
+ consola.success('Flattening completed.');
133
+ };
134
+
135
+ run().catch((error) => {
136
+ consola.error(error);
137
+ // eslint-disable-next-line unicorn/no-process-exit
138
+ process.exit(1);
139
+ });
@@ -0,0 +1,53 @@
1
+ import type { Root } from "react-dom";
2
+ import { renderClient } from "@config/router";
3
+ import { createRouter } from "@/routes";
4
+
5
+ interface GarfishProvider {
6
+ render: (props: { basename: string }) => void;
7
+ destroy: () => void;
8
+ }
9
+
10
+ interface RenderContext {
11
+ basename?: string;
12
+ rootElement: HTMLElement | null;
13
+ }
14
+
15
+ /**
16
+ * Garfish 微前端生命周期适配器
17
+ */
18
+ export function createGarfishProvider(appName: string): GarfishProvider {
19
+ let root: Root | null = null;
20
+
21
+ return {
22
+ render({ basename }: { basename: string }) {
23
+ const context: RenderContext = {
24
+ basename,
25
+ rootElement: document.getElementById(appName) ?? document.body,
26
+ };
27
+
28
+ root = renderClient(context);
29
+
30
+ // 向主应用通知路由信息
31
+ if (window.Garfish?.channel) {
32
+ window.Garfish.channel.emit("router", {
33
+ name: appName,
34
+ routes: createRouter(basename),
35
+ });
36
+ }
37
+ },
38
+
39
+ destroy() {
40
+ if (root) {
41
+ root.unmount();
42
+ root = null;
43
+ }
44
+ },
45
+ };
46
+ }
47
+
48
+ /**
49
+ * 判断是否在微前端环境中运行
50
+ */
51
+ export function isMicroApp(): boolean {
52
+ return typeof window !== "undefined" && Boolean(window.__GARFISH__);
53
+ }
@@ -0,0 +1,19 @@
1
+ import { consola } from 'consola';
2
+ import { colors } from 'consola/utils';
3
+
4
+ import { entryLocaleJsonFilepath, i18nConfig, srcDefaultLocales } from './const';
5
+ import { tagWhite, writeJSONWithPrettier } from './utils';
6
+
7
+ export const genDefaultLocale = () => {
8
+ consola.info(`Default locale is ${i18nConfig.entryLocale}...`);
9
+
10
+ const resources = require(srcDefaultLocales);
11
+ const data = Object.entries(resources.default);
12
+ consola.start(`Generate default locale json, found ${data.length} namespaces...`);
13
+
14
+ for (const [ns, value] of data) {
15
+ const filepath = entryLocaleJsonFilepath(`${ns}.json`);
16
+ writeJSONWithPrettier(filepath, value);
17
+ consola.success(tagWhite(ns), colors.gray(filepath));
18
+ }
19
+ };
@@ -0,0 +1,49 @@
1
+ import { consola } from 'consola';
2
+ import { colors } from 'consola/utils';
3
+ import { unset } from 'es-toolkit/compat';
4
+ import { diff } from 'just-diff';
5
+ import { existsSync } from 'node:fs';
6
+
7
+ import {
8
+ entryLocaleJsonFilepath,
9
+ i18nConfig,
10
+ outputLocaleJsonFilepath,
11
+ srcDefaultLocales,
12
+ } from './const';
13
+ import { readJSON, tagWhite, writeJSONWithPrettier } from './utils';
14
+
15
+ export const genDiff = () => {
16
+ consola.start(`Remove diff analysis...`);
17
+
18
+ const resources = require(srcDefaultLocales);
19
+ const data = Object.entries(resources.default);
20
+
21
+ for (const [ns, devJSON] of data) {
22
+ const filepath = entryLocaleJsonFilepath(`${ns}.json`);
23
+ if (!existsSync(filepath)) continue;
24
+ const previousProdJSON = readJSON(filepath);
25
+
26
+ const diffResult = diff(previousProdJSON, devJSON as any);
27
+ if (diffResult.length === 0) {
28
+ consola.success(tagWhite(ns), colors.gray(filepath));
29
+ continue;
30
+ }
31
+
32
+ const clearLocals = [];
33
+
34
+ for (const locale of i18nConfig.outputLocales) {
35
+ const localeFilepath = outputLocaleJsonFilepath(locale, `${ns}.json`);
36
+ if (!existsSync(localeFilepath)) continue;
37
+ const localeJSON = readJSON(localeFilepath);
38
+
39
+ for (const item of diffResult) {
40
+ unset(localeJSON, item.path);
41
+ }
42
+
43
+ writeJSONWithPrettier(localeFilepath, localeJSON);
44
+ clearLocals.push(locale);
45
+ }
46
+ consola.info('clear', clearLocals);
47
+ consola.success(tagWhite(ns), colors.gray(filepath));
48
+ }
49
+ };
@@ -0,0 +1,19 @@
1
+ import type { Env } from "@/config/env";
2
+
3
+ declare global {
4
+ interface Window {
5
+ __GARFISH__?: boolean;
6
+ Garfish?: {
7
+ channel: {
8
+ emit: (event: string, data: any) => void;
9
+ on: (event: string, handler: (data: any) => void) => void;
10
+ };
11
+ };
12
+ }
13
+
14
+ namespace NodeJS {
15
+ interface ProcessEnv extends Env {}
16
+ }
17
+ }
18
+
19
+ export {};
@@ -0,0 +1,11 @@
1
+ # Glossary
2
+
3
+ 以下是一些词汇的固定翻译:
4
+
5
+ | develop key | zh-CN (中文) | en-US(English) |
6
+ | ----------- | ------------ | -------------- |
7
+ | agent | 助理 | Agent |
8
+ | agentGroup | 群组 | Group |
9
+ | page | 文稿 | Page |
10
+ | topic | 话题 | Topic |
11
+ | thread | 子话题 | Thread |
@@ -0,0 +1,7 @@
1
+ import { createRequire } from 'node:module';
2
+
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const config = require('../../.i18nrc');
6
+
7
+ export default config;