@qlover/create-app 0.7.15 → 0.9.0

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 (363) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
  3. package/dist/configs/_common/.github/workflows/release.yml +2 -2
  4. package/dist/configs/_common/.gitignore.template +6 -0
  5. package/dist/configs/_common/.prettierignore +17 -5
  6. package/dist/configs/_common/.vscode/settings.json +6 -1
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/templates/next-app/.env.template +1 -1
  10. package/dist/templates/next-app/README.en.md +0 -1
  11. package/dist/templates/next-app/README.md +0 -1
  12. package/dist/templates/next-app/config/Identifier/api.ts +5 -5
  13. package/dist/templates/next-app/config/Identifier/common/admint.table.ts +69 -0
  14. package/dist/templates/next-app/config/Identifier/common/common.ts +76 -0
  15. package/dist/templates/next-app/config/Identifier/common/index.ts +3 -0
  16. package/dist/templates/next-app/config/Identifier/{validator.ts → common/validators.ts} +5 -5
  17. package/dist/templates/next-app/config/Identifier/index.ts +2 -12
  18. package/dist/templates/next-app/config/Identifier/pages/index.ts +6 -0
  19. package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +27 -0
  20. package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +266 -0
  21. package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +293 -0
  22. package/dist/templates/{react-app/config/Identifier → next-app/config/Identifier/pages}/page.home.ts +15 -22
  23. package/dist/templates/next-app/config/Identifier/{page.login.ts → pages/page.login.ts} +28 -34
  24. package/dist/templates/next-app/config/Identifier/{page.register.ts → pages/page.register.ts} +30 -29
  25. package/dist/templates/next-app/config/adminNavs.ts +19 -0
  26. package/dist/templates/next-app/config/common.ts +22 -13
  27. package/dist/templates/next-app/config/i18n/HomeI18n.ts +5 -5
  28. package/dist/templates/next-app/config/i18n/admin18n.ts +61 -19
  29. package/dist/templates/next-app/config/i18n/i18nConfig.ts +2 -0
  30. package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +36 -0
  31. package/dist/templates/next-app/config/i18n/loginI18n.ts +22 -22
  32. package/dist/templates/next-app/config/i18n/register18n.ts +23 -24
  33. package/dist/templates/next-app/docs/en/index.md +0 -1
  34. package/dist/templates/next-app/docs/en/project-structure.md +0 -1
  35. package/dist/templates/next-app/docs/zh/index.md +0 -1
  36. package/dist/templates/next-app/docs/zh/project-structure.md +0 -1
  37. package/dist/templates/next-app/make/generateLocales.ts +19 -12
  38. package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +15 -0
  39. package/dist/templates/next-app/migrations/sql/1694244000000.sql +11 -0
  40. package/dist/templates/next-app/package.json +7 -3
  41. package/dist/templates/next-app/public/locales/en.json +172 -207
  42. package/dist/templates/next-app/public/locales/zh.json +172 -207
  43. package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +153 -0
  44. package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +48 -50
  45. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -2
  46. package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +34 -0
  47. package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +40 -0
  48. package/dist/templates/next-app/src/app/api/admin/locales/route.ts +42 -0
  49. package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +32 -0
  50. package/dist/templates/next-app/src/app/api/locales/json/route.ts +44 -0
  51. package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +1 -13
  52. package/dist/templates/next-app/src/base/cases/Datetime.ts +18 -0
  53. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +12 -6
  54. package/dist/templates/next-app/src/base/cases/ResourceState.ts +17 -0
  55. package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +25 -0
  56. package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +200 -0
  57. package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +8 -0
  58. package/dist/templates/next-app/src/base/services/AdminLocalesService.ts +20 -0
  59. package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +26 -0
  60. package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +42 -0
  61. package/dist/templates/next-app/src/base/services/ResourceService.ts +122 -0
  62. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +104 -0
  63. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +38 -5
  64. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +1 -1
  65. package/dist/templates/next-app/src/i18n/request.ts +30 -1
  66. package/dist/templates/next-app/src/server/PageParams.ts +2 -10
  67. package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +5 -0
  68. package/dist/templates/next-app/src/server/port/DBTableInterface.ts +2 -0
  69. package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +43 -0
  70. package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +197 -0
  71. package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +122 -0
  72. package/dist/templates/next-app/src/server/sqlBridges/SupabaseBridge.ts +60 -11
  73. package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +6 -0
  74. package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +131 -0
  75. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +2 -5
  76. package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +32 -16
  77. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +2 -1
  78. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +28 -29
  79. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +2 -1
  80. package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +17 -3
  81. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +5 -4
  82. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +5 -4
  83. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +3 -2
  84. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +1 -1
  85. package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +118 -0
  86. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +5 -6
  87. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +1 -1
  88. package/dist/templates/next-app/src/uikit/components/With.tsx +2 -2
  89. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +62 -0
  90. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +28 -0
  91. package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +6 -0
  92. package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +8 -14
  93. package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +25 -0
  94. package/dist/templates/react-app/.prettierignore +17 -0
  95. package/dist/templates/react-app/README.en.md +71 -54
  96. package/dist/templates/react-app/README.md +35 -18
  97. package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +14 -0
  98. package/dist/templates/react-app/__tests__/__mocks__/MockAppConfit.ts +1 -1
  99. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +2 -2
  100. package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +1 -1
  101. package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +45 -0
  102. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +34 -0
  103. package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +46 -0
  104. package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +12 -0
  105. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -2
  106. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +51 -0
  107. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +69 -0
  108. package/dist/templates/react-app/__tests__/setup/index.ts +1 -51
  109. package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +51 -0
  110. package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +115 -0
  111. package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +2 -2
  112. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +1 -1
  113. package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +3 -5
  114. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +13 -2
  115. package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +1 -1
  116. package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +1 -1
  117. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +5 -5
  118. package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +1 -2
  119. package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +25 -15
  120. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +29 -15
  121. package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +19 -9
  122. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +153 -0
  123. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +9 -7
  124. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +4 -5
  125. package/dist/templates/react-app/__tests__/src/main.test.tsx +4 -4
  126. package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +68 -59
  127. package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +274 -0
  128. package/dist/templates/react-app/config/IOCIdentifier.ts +11 -8
  129. package/dist/templates/react-app/config/Identifier/{common.error.ts → common/common.error.ts} +5 -5
  130. package/dist/templates/react-app/config/Identifier/{common.ts → common/common.ts} +9 -9
  131. package/dist/templates/react-app/config/Identifier/common/index.ts +2 -0
  132. package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +56 -0
  133. package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +103 -0
  134. package/dist/templates/react-app/config/Identifier/index.ts +1 -9
  135. package/dist/templates/react-app/config/Identifier/pages/index.ts +9 -0
  136. package/dist/templates/react-app/config/Identifier/{page.about.ts → pages/page.about.ts} +34 -26
  137. package/dist/templates/react-app/config/Identifier/{page.executor.ts → pages/page.executor.ts} +47 -39
  138. package/dist/templates/{next-app/config/Identifier → react-app/config/Identifier/pages}/page.home.ts +24 -23
  139. package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +102 -0
  140. package/dist/templates/react-app/config/Identifier/{page.jsonStorage.ts → pages/page.jsonStorage.ts} +18 -11
  141. package/dist/templates/react-app/config/Identifier/{page.login.ts → pages/page.login.ts} +37 -27
  142. package/dist/templates/react-app/config/Identifier/pages/page.message.ts +20 -0
  143. package/dist/templates/react-app/config/Identifier/{page.register.ts → pages/page.register.ts} +37 -25
  144. package/dist/templates/react-app/config/Identifier/{page.request.ts → pages/page.request.ts} +34 -44
  145. package/dist/templates/react-app/config/app.router.ts +81 -61
  146. package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +51 -0
  147. package/dist/templates/react-app/config/i18n/aboutI18n.ts +42 -0
  148. package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +17 -0
  149. package/dist/templates/react-app/config/i18n/executorI18n.ts +51 -0
  150. package/dist/templates/react-app/config/i18n/homeI18n.ts +24 -0
  151. package/dist/templates/react-app/config/i18n/i18nConfig.ts +30 -0
  152. package/dist/templates/react-app/config/i18n/identifiter18n.ts +30 -0
  153. package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +27 -0
  154. package/dist/templates/react-app/config/i18n/login18n.ts +42 -0
  155. package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +22 -0
  156. package/dist/templates/react-app/config/i18n/messageI18n.ts +14 -0
  157. package/dist/templates/react-app/config/i18n/notFoundI18n.ts +34 -0
  158. package/dist/templates/react-app/config/i18n/register18n.ts +40 -0
  159. package/dist/templates/react-app/config/i18n/request18n.ts +41 -0
  160. package/dist/templates/react-app/config/theme.ts +14 -4
  161. package/dist/templates/react-app/docs/en/bootstrap.md +1670 -341
  162. package/dist/templates/react-app/docs/en/components/chat-message-component.md +314 -0
  163. package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +270 -0
  164. package/dist/templates/react-app/docs/en/components/message-base-list-component.md +172 -0
  165. package/dist/templates/react-app/docs/en/development-guide.md +1021 -345
  166. package/dist/templates/react-app/docs/en/env.md +1132 -278
  167. package/dist/templates/react-app/docs/en/i18n.md +858 -147
  168. package/dist/templates/react-app/docs/en/index.md +733 -104
  169. package/dist/templates/react-app/docs/en/ioc.md +1228 -287
  170. package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +321 -0
  171. package/dist/templates/react-app/docs/en/playwright/index.md +19 -0
  172. package/dist/templates/react-app/docs/en/playwright/installation-summary.md +332 -0
  173. package/dist/templates/react-app/docs/en/playwright/overview.md +222 -0
  174. package/dist/templates/react-app/docs/en/playwright/quickstart.md +325 -0
  175. package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +340 -0
  176. package/dist/templates/react-app/docs/en/playwright/setup-complete.md +290 -0
  177. package/dist/templates/react-app/docs/en/playwright/testing-guide.md +565 -0
  178. package/dist/templates/react-app/docs/en/store.md +1194 -184
  179. package/dist/templates/react-app/docs/en/why-no-globals.md +797 -0
  180. package/dist/templates/react-app/docs/zh/bootstrap.md +1670 -341
  181. package/dist/templates/react-app/docs/zh/components/chat-message-component.md +314 -0
  182. package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +270 -0
  183. package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +172 -0
  184. package/dist/templates/react-app/docs/zh/development-guide.md +1021 -345
  185. package/dist/templates/react-app/docs/zh/env.md +1132 -275
  186. package/dist/templates/react-app/docs/zh/i18n.md +858 -147
  187. package/dist/templates/react-app/docs/zh/index.md +717 -104
  188. package/dist/templates/react-app/docs/zh/ioc.md +1229 -287
  189. package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +321 -0
  190. package/dist/templates/react-app/docs/zh/playwright/index.md +19 -0
  191. package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +332 -0
  192. package/dist/templates/react-app/docs/zh/playwright/overview.md +222 -0
  193. package/dist/templates/react-app/docs/zh/playwright/quickstart.md +325 -0
  194. package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +340 -0
  195. package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +290 -0
  196. package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +565 -0
  197. package/dist/templates/react-app/docs/zh/store.md +1192 -184
  198. package/dist/templates/react-app/docs/zh/why-no-globals.md +797 -0
  199. package/dist/templates/react-app/e2e/App.spec.ts +319 -0
  200. package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +40 -0
  201. package/dist/templates/react-app/e2e/main.spec.ts +20 -0
  202. package/dist/templates/react-app/e2e/utils/test-helpers.ts +19 -0
  203. package/dist/templates/react-app/eslint.config.mjs +247 -0
  204. package/dist/templates/react-app/makes/eslint-utils.mjs +195 -0
  205. package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +26 -0
  206. package/dist/templates/react-app/package.json +31 -3
  207. package/dist/templates/react-app/playwright.config.ts +79 -0
  208. package/dist/templates/react-app/public/locales/en/common.json +233 -179
  209. package/dist/templates/react-app/public/locales/zh/common.json +233 -179
  210. package/dist/templates/react-app/src/App.tsx +15 -42
  211. package/dist/templates/react-app/src/base/apis/AiApi.ts +5 -5
  212. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +1 -1
  213. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  214. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +8 -8
  215. package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +1 -1
  216. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +6 -6
  217. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  218. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +12 -14
  219. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +1 -1
  220. package/dist/templates/react-app/src/base/cases/DialogHandler.ts +5 -2
  221. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -3
  222. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +3 -3
  223. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +2 -2
  224. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +4 -4
  225. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +1 -1
  226. package/dist/templates/react-app/src/base/cases/ResourceState.ts +23 -0
  227. package/dist/templates/react-app/src/base/cases/RouterLoader.ts +4 -4
  228. package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +26 -0
  229. package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +2 -3
  230. package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +1 -1
  231. package/dist/templates/react-app/src/base/port/IOCInterface.ts +36 -0
  232. package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +2 -1
  233. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +1 -1
  234. package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +2 -2
  235. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +9 -5
  236. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +1 -1
  237. package/dist/templates/react-app/src/base/services/I18nService.ts +29 -29
  238. package/dist/templates/react-app/src/base/services/IdentifierService.ts +143 -0
  239. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +3 -3
  240. package/dist/templates/react-app/src/base/services/RouteService.ts +27 -8
  241. package/dist/templates/react-app/src/base/services/UserService.ts +8 -8
  242. package/dist/templates/react-app/src/base/types/Page.ts +14 -2
  243. package/dist/templates/react-app/src/base/types/global.d.ts +1 -1
  244. package/dist/templates/react-app/src/core/IOC.ts +5 -46
  245. package/dist/templates/react-app/src/core/bootstraps/{BootstrapApp.ts → BootstrapClient.ts} +44 -17
  246. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +14 -7
  247. package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +1 -1
  248. package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +1 -1
  249. package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +40 -0
  250. package/dist/templates/react-app/src/core/{IocRegisterImpl.ts → clientIoc/ClientIOCRegister.ts} +35 -24
  251. package/dist/templates/react-app/src/core/globals.ts +9 -9
  252. package/dist/templates/react-app/src/main.tsx +4 -4
  253. package/dist/templates/react-app/src/pages/404.tsx +6 -3
  254. package/dist/templates/react-app/src/pages/500.tsx +5 -2
  255. package/dist/templates/react-app/src/pages/NoRouteFound.tsx +5 -0
  256. package/dist/templates/react-app/src/pages/auth/Layout.tsx +9 -6
  257. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +46 -56
  258. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +46 -58
  259. package/dist/templates/react-app/src/pages/base/AboutPage.tsx +35 -40
  260. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +51 -51
  261. package/dist/templates/react-app/src/pages/base/HomePage.tsx +14 -15
  262. package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +70 -11
  263. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +24 -25
  264. package/dist/templates/react-app/src/pages/base/Layout.tsx +2 -2
  265. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +40 -0
  266. package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +3 -2
  267. package/dist/templates/react-app/src/pages/base/RequestPage.tsx +41 -59
  268. package/dist/templates/react-app/src/styles/css/antd-themes/{_default.css → _common/_default.css} +85 -0
  269. package/dist/templates/react-app/src/styles/css/antd-themes/{dark.css → _common/dark.css} +99 -0
  270. package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +3 -0
  271. package/dist/templates/react-app/src/styles/css/antd-themes/{pink.css → _common/pink.css} +86 -0
  272. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +4 -3
  273. package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +108 -0
  274. package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +67 -0
  275. package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +3 -0
  276. package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +67 -0
  277. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +34 -0
  278. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +31 -0
  279. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +3 -0
  280. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +36 -0
  281. package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +44 -0
  282. package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +43 -0
  283. package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +3 -0
  284. package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +43 -0
  285. package/dist/templates/react-app/src/styles/css/page.css +4 -3
  286. package/dist/templates/react-app/src/styles/css/themes/_default.css +1 -0
  287. package/dist/templates/react-app/src/styles/css/themes/dark.css +1 -0
  288. package/dist/templates/react-app/src/styles/css/themes/pink.css +1 -0
  289. package/dist/templates/react-app/src/styles/css/zIndex.css +1 -1
  290. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +3 -3
  291. package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +2 -2
  292. package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +1 -1
  293. package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +3 -3
  294. package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +35 -0
  295. package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +15 -11
  296. package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +14 -11
  297. package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +18 -0
  298. package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +13 -0
  299. package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +62 -0
  300. package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +38 -0
  301. package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +48 -27
  302. package/dist/templates/react-app/src/uikit/components/Loading.tsx +4 -2
  303. package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +4 -5
  304. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +34 -11
  305. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +240 -0
  306. package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +9 -5
  307. package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +6 -3
  308. package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +97 -40
  309. package/dist/templates/react-app/src/uikit/components/UserAuthProvider.tsx +5 -5
  310. package/dist/templates/react-app/src/uikit/components/With.tsx +17 -0
  311. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +176 -0
  312. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +21 -0
  313. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +106 -0
  314. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +271 -0
  315. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +102 -0
  316. package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +86 -0
  317. package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +17 -11
  318. package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +13 -0
  319. package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +26 -0
  320. package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +8 -11
  321. package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +25 -0
  322. package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +35 -0
  323. package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +3 -3
  324. package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -1
  325. package/dist/templates/react-app/tsconfig.e2e.json +21 -0
  326. package/dist/templates/react-app/tsconfig.json +8 -1
  327. package/dist/templates/react-app/tsconfig.node.json +1 -1
  328. package/dist/templates/react-app/tsconfig.test.json +3 -1
  329. package/dist/templates/react-app/vite.config.ts +50 -34
  330. package/package.json +2 -1
  331. package/dist/configs/react-app/eslint.config.js +0 -94
  332. package/dist/templates/next-app/config/Identifier/common.error.ts +0 -41
  333. package/dist/templates/next-app/config/Identifier/common.ts +0 -69
  334. package/dist/templates/next-app/config/Identifier/page.about.ts +0 -181
  335. package/dist/templates/next-app/config/Identifier/page.admin.ts +0 -48
  336. package/dist/templates/next-app/config/Identifier/page.executor.ts +0 -272
  337. package/dist/templates/next-app/config/Identifier/page.identifiter.ts +0 -39
  338. package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +0 -72
  339. package/dist/templates/next-app/config/Identifier/page.request.ts +0 -182
  340. package/dist/templates/next-app/src/base/cases/ChatAction.ts +0 -21
  341. package/dist/templates/next-app/src/base/cases/FocusBarAction.ts +0 -36
  342. package/dist/templates/next-app/src/base/cases/RequestState.ts +0 -20
  343. package/dist/templates/next-app/src/base/port/AdminPageInterface.ts +0 -85
  344. package/dist/templates/next-app/src/base/port/AsyncStateInterface.ts +0 -7
  345. package/dist/templates/next-app/src/base/services/AdminUserService.ts +0 -45
  346. package/dist/templates/next-app/src/uikit/components/ChatRoot.tsx +0 -17
  347. package/dist/templates/next-app/src/uikit/components/chat/ChatActionInterface.ts +0 -30
  348. package/dist/templates/next-app/src/uikit/components/chat/ChatFocusBar.tsx +0 -65
  349. package/dist/templates/next-app/src/uikit/components/chat/ChatMessages.tsx +0 -59
  350. package/dist/templates/next-app/src/uikit/components/chat/ChatWrap.tsx +0 -28
  351. package/dist/templates/next-app/src/uikit/components/chat/FocusBarActionInterface.ts +0 -19
  352. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +0 -17
  353. package/dist/templates/next-app/src/uikit/hook/useStore.ts +0 -15
  354. package/dist/templates/react-app/__tests__/__mocks__/I18nService.ts +0 -13
  355. package/dist/templates/react-app/__tests__/src/App.test.tsx +0 -139
  356. package/dist/templates/react-app/config/Identifier/page.identifiter.ts +0 -39
  357. package/dist/templates/react-app/config/i18n.ts +0 -15
  358. package/dist/templates/react-app/docs/en/project-structure.md +0 -434
  359. package/dist/templates/react-app/docs/zh/project-structure.md +0 -434
  360. package/dist/templates/react-app/src/base/cases/RequestState.ts +0 -20
  361. package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +0 -7
  362. package/dist/templates/react-app/src/uikit/hooks/useDocumentTitle.ts +0 -15
  363. package/dist/templates/react-app/src/uikit/hooks/useStore.ts +0 -15
@@ -1,274 +1,431 @@
1
- # 开发规范指南
1
+ # 开发指南
2
2
 
3
- ## 目录
3
+ > **📖 本文档提供完整的页面开发流程和实战指南,帮助你快速上手项目开发。**
4
4
 
5
- 1. [项目结构规范](#项目结构规范)
6
- 2. [代码风格规范](#代码风格规范)
7
- 3. [组件开发规范](#组件开发规范)
8
- 4. [状态管理规范](#状态管理规范)
9
- 5. [路由开发规范](#路由开发规范)
10
- 6. [国际化开发规范](#国际化开发规范)
11
- 7. [主题样式规范](#主题样式规范)
12
- 8. [测试规范](#测试规范)
13
- 9. [文档规范](#文档规范)
5
+ ## 📋 目录
14
6
 
15
- ## 项目结构规范
7
+ - [开发一个页面需要什么](#-开发一个页面需要什么)
8
+ - [完整开发流程](#-完整开发流程)
9
+ - [实战示例:用户列表页](#-实战示例用户列表页)
10
+ - [常见场景](#-常见场景)
11
+ - [代码规范](#-代码规范)
12
+ - [开发工具](#-开发工具)
16
13
 
17
- > 💡 这里仅列出基本规范,完整的项目结构说明请参考 [项目结构文档](./project-structure.md)
14
+ ---
18
15
 
19
- ### 1. 目录结构
16
+ ## 🎯 开发一个页面需要什么
17
+
18
+ ### 核心清单
19
+
20
+ 一个完整的页面通常需要以下组成部分:
20
21
 
21
22
  ```
22
- src/
23
- ├── base/ # 基础功能实现
24
- │ ├── cases/ # 业务场景实现
25
- │ ├── services/ # 核心服务实现
26
- │ └── types/ # 类型定义
27
- ├── core/ # 核心功能
28
- │ ├── bootstraps/ # 启动相关
29
- │ ├── registers/ # 注册器
30
- │ └── IOC.ts # IOC 容器
31
- ├── pages/ # 页面组件
32
- │ ├── auth/ # 认证相关页面
33
- │ └── base/ # 基础页面
34
- ├── styles/ # 样式文件
35
- │ └── css/
36
- │ ├── themes/ # 主题相关
37
- │ └── antd-themes/ # Ant Design 主题
38
- ├── uikit/ # UI 组件库
39
- │ ├── components/ # 通用组件
40
- │ ├── contexts/ # React Context
41
- │ ├── hooks/ # 自定义 Hooks
42
- │ └── providers/ # 提供者组件
43
- └── App.tsx # 应用入口
23
+ ✅ 1. 接口定义 (Port) - base/port/XxxServiceInterface.ts
24
+ 2. 服务实现 (Service) - base/services/XxxService.ts
25
+ 3. API 适配器 (可选) - base/apis/xxxApi/XxxApi.ts
26
+ 4. 路由配置 - config/app.router.ts
27
+ 5. i18n 文本定义 - config/Identifier/pages/page.xxx.ts
28
+ 6. 页面组件 - pages/xxx/XxxPage.tsx
29
+ 7. IOC 注册 (如果是新服务) - core/clientIoc/ClientIOCRegister.ts
30
+ 8. 测试文件 - __tests__/src/pages/xxx/XxxPage.test.tsx
44
31
  ```
45
32
 
46
- ### 2. 命名规范
33
+ ### 依赖关系图
47
34
 
48
- - **文件命名**:
49
- - 组件文件:`PascalCase.tsx`(如:`UserProfile.tsx`)
50
- - 工具文件:`camelCase.ts`(如:`formatDate.ts`)
51
- - 类型文件:`PascalCase.types.ts`(如:`User.types.ts`)
52
- - 样式文件:`camelCase.css`(如:`buttonStyles.css`)
35
+ ```
36
+ ┌─────────────────────────────────────────┐
37
+ 路由配置 (app.router.ts) │
38
+ 定义页面路径和元数据 │
39
+ └──────────────┬──────────────────────────┘
40
+
41
+ ┌─────────────────────────────────────────┐
42
+ │ 页面组件 (XxxPage.tsx) │
43
+ │ - 使用 useIOC 获取服务 │
44
+ │ - 使用 useStore 订阅状态 │
45
+ │ - 使用 useAppTranslation 获取翻译 │
46
+ │ - 处理 UI 渲染和用户交互 │
47
+ └──────────────┬──────────────────────────┘
48
+
49
+ ┌─────────────────────────────────────────┐
50
+ │ 服务层 (XxxService.ts) │
51
+ │ - 实现业务逻辑 │
52
+ │ - 继承 StoreInterface │
53
+ │ - 依赖注入其他服务 │
54
+ └──────────────┬──────────────────────────┘
55
+
56
+ ┌─────────────────────────────────────────┐
57
+ │ 接口定义 (XxxServiceInterface.ts) │
58
+ │ - 定义服务契约 │
59
+ │ - 便于测试和 mock │
60
+ └─────────────────────────────────────────┘
61
+
62
+ ┌─────────────────────────────────────────┐
63
+ │ API 适配器 (XxxApi.ts) │
64
+ │ - 封装 HTTP 请求 │
65
+ │ - 转换数据格式 │
66
+ └─────────────────────────────────────────┘
67
+
68
+ ┌─────────────────────────────────────────┐
69
+ │ i18n 文本 (page.xxx.ts) │
70
+ │ - 定义页面所有文本的 Key │
71
+ │ - 自动生成翻译文件 │
72
+ └─────────────────────────────────────────┘
73
+ ```
53
74
 
54
- - **目录命名**:
55
- - 全小写,使用连字符分隔(如:`user-profile/`)
56
- - 功能模块使用单数形式(如:`auth/`,而不是 `auths/`)
75
+ ---
57
76
 
58
- ## 代码风格规范
77
+ ## 🚀 完整开发流程
59
78
 
60
- > 💡 这里仅列出基本规范,更多 TypeScript 和 React 开发规范请参考 [TypeScript 开发规范](./typescript-guide.md)
79
+ ### 流程图
61
80
 
62
- ### 1. TypeScript 规范
81
+ ```
82
+ 📝 1. 需求分析
83
+ ├── 确定页面功能
84
+ ├── 确定数据来源(API)
85
+ └── 确定交互逻辑
86
+
87
+ 🎨 2. 定义 i18n Key
88
+ ├── 页面标题、按钮文本等
89
+ └── 错误提示、成功提示等
90
+
91
+ 🔌 3. 定义接口 (Port)
92
+ ├── 服务接口
93
+ └── 数据类型
94
+
95
+ ⚙️ 4. 实现服务 (Service)
96
+ ├── 继承 StoreInterface
97
+ ├── 实现业务逻辑
98
+ └── 依赖注入
99
+
100
+ 🌐 5. 实现 API 适配器(如果需要)
101
+ ├── 封装 HTTP 请求
102
+ └── 数据转换
103
+
104
+ 🗺️ 6. 配置路由
105
+ ├── 添加路由配置
106
+ └── 设置元数据
107
+
108
+ 🎭 7. 实现页面组件
109
+ ├── 使用 useIOC 获取服务
110
+ ├── 使用 useStore 订阅状态
111
+ └── 实现 UI 渲染
112
+
113
+ 🔗 8. 注册到 IOC(如果是新服务)
114
+ └── 在 ClientIOCRegister 中注册
115
+
116
+ 🧪 9. 编写测试
117
+ ├── 服务测试(逻辑)
118
+ ├── UI 测试(渲染)
119
+ └── 集成测试(流程)
120
+
121
+ ✅ 10. 自测和提交
122
+ ├── 功能自测
123
+ ├── 代码检查
124
+ └── 提交 PR
125
+ ```
63
126
 
64
- ```typescript
65
- // 使用 interface 定义对象类型
66
- interface UserProfile {
67
- id: string;
68
- name: string;
69
- age?: number; // 可选属性使用 ?
70
- }
127
+ ---
71
128
 
72
- // 使用 type 定义联合类型或工具类型
73
- type Theme = 'light' | 'dark' | 'pink';
74
- type Nullable<T> = T | null;
129
+ ## 📚 实战示例:用户列表页
75
130
 
76
- // 使用 enum 定义常量枚举
77
- enum UserRole {
78
- ADMIN = 'ADMIN',
79
- USER = 'USER',
80
- GUEST = 'GUEST'
81
- }
131
+ 假设我们要开发一个用户列表页面,功能包括:
82
132
 
83
- // 函数类型声明
84
- function processUser(user: UserProfile): void {
85
- // 实现
86
- }
133
+ - 显示用户列表
134
+ - 搜索用户
135
+ - 分页加载
136
+ - 查看用户详情
87
137
 
88
- // 泛型使用有意义的名称
89
- interface Repository<TEntity> {
90
- find(id: string): Promise<TEntity>;
91
- }
92
- ```
138
+ ### 1. 需求分析
93
139
 
94
- ### 2. React 规范
140
+ **功能清单:**
95
141
 
96
- ```tsx
97
- // 函数组件使用 FC 类型
98
- interface Props {
99
- name: string;
100
- age: number;
101
- }
142
+ - 📄 显示用户列表(头像、姓名、邮箱、角色)
143
+ - 🔍 搜索用户(按姓名搜索)
144
+ - 📃 分页(每页 10 条)
145
+ - 👁️ 查看详情(点击跳转详情页)
146
+ - 🔄 刷新列表
102
147
 
103
- const UserCard: FC<Props> = ({ name, age }) => {
104
- return (
105
- <div>
106
- <h3>{name}</h3>
107
- <p>{age}</p>
108
- </div>
109
- );
110
- };
148
+ **数据来源:**
111
149
 
112
- // Hooks 规范
113
- const useUser = (userId: string) => {
114
- const [user, setUser] = useState<UserProfile | null>(null);
115
- const [loading, setLoading] = useState(false);
150
+ - API: `GET /api/users?page=1&pageSize=10&keyword=xxx`
116
151
 
117
- useEffect(() => {
118
- // 实现
119
- }, [userId]);
152
+ ### 2. 定义 i18n Key
153
+
154
+ ```typescript
155
+ // config/Identifier/pages/page.users.ts
156
+
157
+ /**
158
+ * @description User list page title
159
+ * @localZh 用户列表
160
+ * @localEn User List
161
+ */
162
+ export const PAGE_USERS_TITLE = 'page.users.title';
163
+
164
+ /**
165
+ * @description Search user placeholder
166
+ * @localZh 搜索用户姓名
167
+ * @localEn Search user name
168
+ */
169
+ export const PAGE_USERS_SEARCH_PLACEHOLDER = 'page.users.search.placeholder';
170
+
171
+ /**
172
+ * @description View user detail button
173
+ * @localZh 查看详情
174
+ * @localEn View Detail
175
+ */
176
+ export const PAGE_USERS_VIEW_DETAIL = 'page.users.viewDetail';
177
+
178
+ /**
179
+ * @description Refresh button
180
+ * @localZh 刷新
181
+ * @localEn Refresh
182
+ */
183
+ export const PAGE_USERS_REFRESH = 'page.users.refresh';
120
184
 
121
- return { user, loading };
122
- };
185
+ /**
186
+ * @description Loading message
187
+ * @localZh 加载中...
188
+ * @localEn Loading...
189
+ */
190
+ export const PAGE_USERS_LOADING = 'page.users.loading';
191
+
192
+ /**
193
+ * @description Empty message
194
+ * @localZh 暂无用户数据
195
+ * @localEn No users found
196
+ */
197
+ export const PAGE_USERS_EMPTY = 'page.users.empty';
123
198
  ```
124
199
 
125
- ## 组件开发规范
200
+ ### 3. 定义接口和类型
126
201
 
127
- > 💡 这里仅列出基本规范,完整的组件开发指南请参考 [组件开发指南](./component-guide.md)
202
+ ```typescript
203
+ // base/port/UserServiceInterface.ts
128
204
 
129
- ### 1. 组件分类
205
+ import { StoreInterface } from '@qlover/corekit-bridge';
130
206
 
131
- - **页面组件**:放在 `pages/` 目录下
132
- - **业务组件**:放在对应业务模块目录下
133
- - **通用组件**:放在 `uikit/components/` 目录下
134
- - **布局组件**:放在 `uikit/layouts/` 目录下
207
+ /**
208
+ * 用户信息
209
+ */
210
+ export interface UserInfo {
211
+ id: string;
212
+ name: string;
213
+ email: string;
214
+ avatar: string;
215
+ role: 'admin' | 'user';
216
+ }
135
217
 
136
- ### 2. 组件实现
218
+ /**
219
+ * 用户列表查询参数
220
+ */
221
+ export interface UserListParams {
222
+ page: number;
223
+ pageSize: number;
224
+ keyword?: string;
225
+ }
137
226
 
138
- ```tsx
139
- // 1. 导入顺序
140
- import { FC, useEffect, useState } from 'react'; // React 相关
141
- import { useTranslation } from 'react-i18next'; // 第三方库
142
- import { UserService } from '@/services/user'; // 项目内部导入
143
- import { Button } from './Button'; // 相对路径导入
227
+ /**
228
+ * 用户列表响应
229
+ */
230
+ export interface UserListResponse {
231
+ list: UserInfo[];
232
+ total: number;
233
+ page: number;
234
+ pageSize: number;
235
+ }
144
236
 
145
- // 2. 类型定义
146
- interface Props {
147
- userId: string;
148
- onUpdate?: (user: User) => void;
237
+ /**
238
+ * 用户服务状态
239
+ */
240
+ export interface UserServiceState extends StoreStateInterface {
241
+ users: UserInfo[];
242
+ total: number;
243
+ page: number;
244
+ pageSize: number;
245
+ loading: boolean;
246
+ error: Error | null;
149
247
  }
150
248
 
151
- // 3. 组件实现
152
- export const UserProfile: FC<Props> = ({ userId, onUpdate }) => {
153
- // 3.1 Hooks 声明
154
- const { t } = useTranslation();
155
- const [user, setUser] = useState<User | null>(null);
249
+ /**
250
+ * 用户服务接口
251
+ */
252
+ export abstract class UserServiceInterface extends StoreInterface<UserServiceState> {
253
+ /**
254
+ * 获取用户列表
255
+ */
256
+ abstract fetchUsers(params: UserListParams): Promise<void>;
156
257
 
157
- // 3.2 副作用
158
- useEffect(() => {
159
- // 实现
160
- }, [userId]);
258
+ /**
259
+ * 搜索用户
260
+ */
261
+ abstract searchUsers(keyword: string): Promise<void>;
161
262
 
162
- // 3.3 事件处理
163
- const handleUpdate = () => {
164
- // 实现
165
- };
263
+ /**
264
+ * 刷新列表
265
+ */
266
+ abstract refreshUsers(): Promise<void>;
166
267
 
167
- // 3.4 渲染方法
168
- const renderHeader = () => {
169
- return <h2>{user?.name}</h2>;
268
+ /**
269
+ * 选择器
270
+ */
271
+ abstract selector: {
272
+ users: (state: UserServiceState) => UserInfo[];
273
+ loading: (state: UserServiceState) => boolean;
274
+ total: (state: UserServiceState) => number;
170
275
  };
171
-
172
- // 3.5 返回 JSX
173
- return (
174
- <div>
175
- {renderHeader()}
176
- <Button onClick={handleUpdate}>{t('common.update')}</Button>
177
- </div>
178
- );
179
- };
276
+ }
180
277
  ```
181
278
 
182
- ## 状态管理规范
279
+ ### 4. 实现 API 适配器
183
280
 
184
- > 💡 这里仅列出基本规范,完整的状态管理指南请参考 [Store 开发指南](./store.md)
281
+ ```typescript
282
+ // base/apis/userApi/UserApi.ts
185
283
 
186
- ### 1. Store 实现
284
+ import { injectable, inject } from 'inversify';
285
+ import { HttpClient } from '@/base/cases/HttpClient';
286
+ import type {
287
+ UserListParams,
288
+ UserListResponse
289
+ } from '@/base/port/UserServiceInterface';
187
290
 
188
- ```typescript
189
- // 1. 状态接口定义
190
- interface UserState extends StoreStateInterface {
191
- currentUser: User | null;
192
- loading: boolean;
193
- error: string | null;
291
+ @injectable()
292
+ export class UserApi {
293
+ constructor(@inject(HttpClient) private http: HttpClient) {}
294
+
295
+ /**
296
+ * 获取用户列表
297
+ */
298
+ async getUserList(params: UserListParams): Promise<UserListResponse> {
299
+ const response = await this.http.get('/api/users', { params });
300
+
301
+ // 转换后端数据格式
302
+ return {
303
+ list: response.data.items.map((item: any) => ({
304
+ id: item.user_id,
305
+ name: item.user_name,
306
+ email: item.user_email,
307
+ avatar: item.avatar_url,
308
+ role: item.user_role
309
+ })),
310
+ total: response.data.total_count,
311
+ page: response.data.current_page,
312
+ pageSize: response.data.page_size
313
+ };
314
+ }
194
315
  }
316
+ ```
317
+
318
+ ### 5. 实现服务
319
+
320
+ ```typescript
321
+ // base/services/UserService.ts
322
+
323
+ import { injectable, inject } from 'inversify';
324
+ import {
325
+ UserServiceInterface,
326
+ UserServiceState
327
+ } from '@/base/port/UserServiceInterface';
328
+ import { UserApi } from '@/base/apis/userApi/UserApi';
329
+ import type { UserListParams } from '@/base/port/UserServiceInterface';
195
330
 
196
- // 2. Store 实现
197
331
  @injectable()
198
- export class UserStore extends StoreInterface<UserState> {
199
- constructor() {
332
+ export class UserService extends UserServiceInterface {
333
+ constructor(@inject(UserApi) private api: UserApi) {
334
+ // 初始化状态
200
335
  super(() => ({
201
- currentUser: null,
336
+ users: [],
337
+ total: 0,
338
+ page: 1,
339
+ pageSize: 10,
202
340
  loading: false,
203
341
  error: null
204
342
  }));
205
343
  }
206
344
 
207
- // 3. 选择器定义
345
+ /**
346
+ * 选择器
347
+ */
208
348
  selector = {
209
- currentUser: (state: UserState) => state.currentUser,
210
- loading: (state: UserState) => state.loading
349
+ users: (state: UserServiceState) => state.users,
350
+ loading: (state: UserServiceState) => state.loading,
351
+ total: (state: UserServiceState) => state.total,
352
+ page: (state: UserServiceState) => state.page,
353
+ pageSize: (state: UserServiceState) => state.pageSize
211
354
  };
212
355
 
213
- // 4. 操作方法
214
- async fetchUser(id: string) {
356
+ /**
357
+ * 获取用户列表
358
+ */
359
+ async fetchUsers(params: UserListParams): Promise<void> {
215
360
  try {
216
- this.emit({ ...this.state, loading: true });
217
- const user = await api.getUser(id);
218
- this.emit({ ...this.state, currentUser: user, loading: false });
361
+ // 1. 设置加载状态
362
+ this.emit({ ...this.state, loading: true, error: null });
363
+
364
+ // 2. 调用 API
365
+ const response = await this.api.getUserList(params);
366
+
367
+ // 3. 更新状态
368
+ this.emit({
369
+ users: response.list,
370
+ total: response.total,
371
+ page: response.page,
372
+ pageSize: response.pageSize,
373
+ loading: false,
374
+ error: null
375
+ });
219
376
  } catch (error) {
377
+ // 4. 错误处理
220
378
  this.emit({
221
379
  ...this.state,
222
- error: error.message,
223
- loading: false
380
+ loading: false,
381
+ error: error as Error
224
382
  });
225
383
  }
226
384
  }
227
- }
228
- ```
229
385
 
230
- ### 2. Store 使用
231
-
232
- ```tsx
233
- function UserProfile() {
234
- const userStore = IOC(UserStore);
235
- const user = useStore(userStore, userStore.selector.currentUser);
236
- const loading = useStore(userStore, userStore.selector.loading);
386
+ /**
387
+ * 搜索用户
388
+ */
389
+ async searchUsers(keyword: string): Promise<void> {
390
+ await this.fetchUsers({
391
+ page: 1,
392
+ pageSize: this.state.pageSize,
393
+ keyword
394
+ });
395
+ }
237
396
 
238
- return <div>{loading ? <Loading /> : <UserInfo user={user} />}</div>;
397
+ /**
398
+ * 刷新列表
399
+ */
400
+ async refreshUsers(): Promise<void> {
401
+ await this.fetchUsers({
402
+ page: this.state.page,
403
+ pageSize: this.state.pageSize
404
+ });
405
+ }
239
406
  }
240
407
  ```
241
408
 
242
- ## 路由开发规范
409
+ ### 6. 配置路由
243
410
 
244
- > 💡 这里仅列出基本规范,完整的路由开发指南请参考 [路由开发指南](./router.md)
245
-
246
- ### 1. 基本规范
247
-
248
- - 路由配置集中管理在 `config/app.router.ts` 中
249
- - 使用声明式路由配置
250
- - 路由组件放置在 `pages` 目录下
251
- - 支持路由级别的代码分割
252
- - 路由配置包含元数据支持
411
+ ```typescript
412
+ // config/app.router.ts
253
413
 
254
- ### 2. 示例
414
+ import * as i18nKeys from './Identifier/pages/page.users';
255
415
 
256
- ```typescript
257
- // 路由配置示例
258
416
  export const baseRoutes: RouteConfigValue[] = [
259
417
  {
260
418
  path: '/:lng',
261
419
  element: 'base/Layout',
262
- meta: {
263
- category: 'main'
264
- },
265
420
  children: [
421
+ // ... 其他路由
266
422
  {
267
423
  path: 'users',
268
- element: 'users/UserList',
424
+ element: 'users/UserListPage',
269
425
  meta: {
270
426
  title: i18nKeys.PAGE_USERS_TITLE,
271
- auth: true
427
+ requiresAuth: true, // 需要登录
428
+ category: 'main'
272
429
  }
273
430
  }
274
431
  ]
@@ -276,248 +433,767 @@ export const baseRoutes: RouteConfigValue[] = [
276
433
  ];
277
434
  ```
278
435
 
279
- 更多路由配置和使用示例,请参考 [路由开发指南](./router.md)。
436
+ ### 7. 实现页面组件
437
+
438
+ ```typescript
439
+ // pages/users/UserListPage.tsx
440
+
441
+ import { useEffect, useState } from 'react';
442
+ import { Table, Input, Button, Avatar, Space } from 'antd';
443
+ import { ReloadOutlined, EyeOutlined } from '@ant-design/icons';
444
+ import { useIOC } from '@/uikit/hooks/useIOC';
445
+ import { useStore } from '@brain-toolkit/react-kit/hooks/useStore';
446
+ import { useAppTranslation } from '@/uikit/hooks/useAppTranslation';
447
+ import { IOCIdentifier } from '@config/IOCIdentifier';
448
+ import * as i18nKeys from '@config/Identifier/pages/page.users';
449
+ import type { UserInfo } from '@/base/port/UserServiceInterface';
450
+
451
+ export default function UserListPage() {
452
+ // 1. 获取服务
453
+ const userService = useIOC(IOCIdentifier.UserServiceInterface);
454
+ const routeService = useIOC(IOCIdentifier.RouteServiceInterface);
455
+ const { t } = useAppTranslation();
456
+
457
+ // 2. 订阅状态
458
+ const users = useStore(userService, userService.selector.users);
459
+ const loading = useStore(userService, userService.selector.loading);
460
+ const total = useStore(userService, userService.selector.total);
461
+ const page = useStore(userService, userService.selector.page);
462
+ const pageSize = useStore(userService, userService.selector.pageSize);
463
+
464
+ // 3. 本地状态
465
+ const [keyword, setKeyword] = useState('');
466
+
467
+ // 4. 初始化加载
468
+ useEffect(() => {
469
+ userService.fetchUsers({ page: 1, pageSize: 10 });
470
+ }, []);
471
+
472
+ // 5. 事件处理
473
+ const handleSearch = () => {
474
+ userService.searchUsers(keyword);
475
+ };
476
+
477
+ const handleRefresh = () => {
478
+ userService.refreshUsers();
479
+ };
280
480
 
281
- ## 国际化开发规范
481
+ const handlePageChange = (newPage: number, newPageSize: number) => {
482
+ userService.fetchUsers({ page: newPage, pageSize: newPageSize, keyword });
483
+ };
282
484
 
283
- > 💡 这里仅列出基本规范,完整的国际化开发指南请参考 [国际化开发指南](./i18n.md)
485
+ const handleViewDetail = (userId: string) => {
486
+ routeService.push(`/users/${userId}`);
487
+ };
284
488
 
285
- ### 1. 基本规范
489
+ // 6. 表格列配置
490
+ const columns = [
491
+ {
492
+ title: t(i18nKeys.PAGE_USERS_COLUMN_AVATAR),
493
+ dataIndex: 'avatar',
494
+ key: 'avatar',
495
+ render: (avatar: string) => <Avatar src={avatar} />
496
+ },
497
+ {
498
+ title: t(i18nKeys.PAGE_USERS_COLUMN_NAME),
499
+ dataIndex: 'name',
500
+ key: 'name'
501
+ },
502
+ {
503
+ title: t(i18nKeys.PAGE_USERS_COLUMN_EMAIL),
504
+ dataIndex: 'email',
505
+ key: 'email'
506
+ },
507
+ {
508
+ title: t(i18nKeys.PAGE_USERS_COLUMN_ROLE),
509
+ dataIndex: 'role',
510
+ key: 'role',
511
+ render: (role: string) => t(`common.role.${role}`)
512
+ },
513
+ {
514
+ title: t(i18nKeys.PAGE_USERS_COLUMN_ACTIONS),
515
+ key: 'actions',
516
+ render: (_: any, record: UserInfo) => (
517
+ <Button
518
+ type="link"
519
+ icon={<EyeOutlined />}
520
+ onClick={() => handleViewDetail(record.id)}
521
+ >
522
+ {t(i18nKeys.PAGE_USERS_VIEW_DETAIL)}
523
+ </Button>
524
+ )
525
+ }
526
+ ];
286
527
 
287
- - 使用标识符常量管理翻译键
288
- - 通过 TypeScript 注释生成翻译资源
289
- - 支持多语言路由
290
- - 集中管理翻译文件
528
+ // 7. 渲染
529
+ return (
530
+ <div className="p-6">
531
+ {/* 页面标题 */}
532
+ <h1 className="text-2xl font-bold mb-4">
533
+ {t(i18nKeys.PAGE_USERS_TITLE)}
534
+ </h1>
535
+
536
+ {/* 搜索栏 */}
537
+ <div className="mb-4 flex gap-2">
538
+ <Input.Search
539
+ placeholder={t(i18nKeys.PAGE_USERS_SEARCH_PLACEHOLDER)}
540
+ value={keyword}
541
+ onChange={(e) => setKeyword(e.target.value)}
542
+ onSearch={handleSearch}
543
+ style={{ width: 300 }}
544
+ />
545
+ <Button
546
+ icon={<ReloadOutlined />}
547
+ onClick={handleRefresh}
548
+ loading={loading}
549
+ >
550
+ {t(i18nKeys.PAGE_USERS_REFRESH)}
551
+ </Button>
552
+ </div>
553
+
554
+ {/* 用户表格 */}
555
+ <Table
556
+ columns={columns}
557
+ dataSource={users}
558
+ rowKey="id"
559
+ loading={loading}
560
+ pagination={{
561
+ current: page,
562
+ pageSize: pageSize,
563
+ total: total,
564
+ onChange: handlePageChange,
565
+ showSizeChanger: true,
566
+ showTotal: (total) => `${t('common.total')} ${total} ${t('common.items')}`
567
+ }}
568
+ locale={{
569
+ emptyText: t(i18nKeys.PAGE_USERS_EMPTY)
570
+ }}
571
+ />
572
+ </div>
573
+ );
574
+ }
575
+ ```
291
576
 
292
- ### 2. 示例
577
+ ### 8. 注册到 IOC(如果是新服务)
293
578
 
294
579
  ```typescript
295
- /**
296
- * @description User list page title
297
- * @localZh 用户列表
298
- * @localEn User List
299
- */
300
- export const PAGE_USERS_TITLE = 'page.users.title';
580
+ // core/clientIoc/ClientIOCRegister.ts
581
+
582
+ export class ClientIOCRegister {
583
+ protected registerImplement(ioc: IOCContainerInterface): void {
584
+ // ... 其他服务注册
585
+
586
+ // 注册 UserService
587
+ ioc.bind(IOCIdentifier.UserServiceInterface, ioc.get(UserService));
588
+ }
589
+ }
301
590
  ```
302
591
 
303
- 更多国际化配置和使用示例,请参考 [国际化开发指南](./i18n.md)。
592
+ ### 9. 编写测试
304
593
 
305
- ## 主题样式规范
594
+ ```typescript
595
+ // __tests__/src/base/services/UserService.test.ts
306
596
 
307
- > 💡 这里仅列出基本规范,完整的主题开发指南请参考 [主题开发指南](./theme.md)
597
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
598
+ import { UserService } from '@/base/services/UserService';
308
599
 
309
- ### 1. 基本规范
600
+ describe('UserService', () => {
601
+ let userService: UserService;
602
+ let mockApi: any;
310
603
 
311
- - 使用 CSS 变量管理主题
312
- - 遵循 Tailwind CSS 使用规范
313
- - 组件样式模块化
314
- - 支持多主题切换
604
+ beforeEach(() => {
605
+ mockApi = {
606
+ getUserList: vi.fn()
607
+ };
315
608
 
316
- ### 2. 示例
609
+ userService = new UserService(mockApi);
610
+ });
317
611
 
318
- ```css
319
- :root {
320
- --color-brand: 37 99 235;
321
- --text-primary: 15 23 42;
322
- }
323
- ```
612
+ it('should fetch users and update state', async () => {
613
+ const mockResponse = {
614
+ list: [
615
+ {
616
+ id: '1',
617
+ name: 'John',
618
+ email: 'john@example.com',
619
+ avatar: '',
620
+ role: 'user'
621
+ }
622
+ ],
623
+ total: 1,
624
+ page: 1,
625
+ pageSize: 10
626
+ };
324
627
 
325
- 更多主题配置和使用示例,请参考 [主题开发指南](./theme.md)
628
+ mockApi.getUserList.mockResolvedValue(mockResponse);
326
629
 
327
- ## 测试规范
630
+ const states: any[] = [];
631
+ userService.subscribe((state) => states.push({ ...state }));
328
632
 
329
- > 💡 这里仅列出基本规范,完整的测试指南请参考 [测试开发指南](./testing.md)
633
+ await userService.fetchUsers({ page: 1, pageSize: 10 });
330
634
 
331
- ### 1. 基本规范
635
+ // 验证状态变化
636
+ expect(states).toHaveLength(2);
637
+ expect(states[0].loading).toBe(true);
638
+ expect(states[1].loading).toBe(false);
639
+ expect(states[1].users).toEqual(mockResponse.list);
640
+ expect(states[1].total).toBe(1);
641
+ });
332
642
 
333
- - 单元测试覆盖核心逻辑
334
- - 组件测试关注交互和渲染
335
- - 使用 Jest 和 Testing Library
336
- - 保持测试简单和可维护
643
+ it('should handle error when fetch fails', async () => {
644
+ mockApi.getUserList.mockRejectedValue(new Error('Network error'));
337
645
 
338
- ### 2. 示例
646
+ await userService.fetchUsers({ page: 1, pageSize: 10 });
647
+
648
+ expect(userService.getState().error).toBeTruthy();
649
+ expect(userService.getState().loading).toBe(false);
650
+ });
651
+ });
652
+ ```
339
653
 
340
654
  ```typescript
341
- describe('UserProfile', () => {
342
- it('should render user info', () => {
343
- const user = { id: '1', name: 'Test' };
344
- render(<UserProfile user={user} />);
345
- expect(screen.getByText(user.name)).toBeInTheDocument();
655
+ // __tests__/src/pages/users/UserListPage.test.tsx
656
+
657
+ import { describe, it, expect, vi } from 'vitest';
658
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
659
+ import UserListPage from '@/pages/users/UserListPage';
660
+ import { IOCProvider } from '@/uikit/contexts/IOCContext';
661
+
662
+ describe('UserListPage', () => {
663
+ it('should display user list', async () => {
664
+ const mockUsers = [
665
+ {
666
+ id: '1',
667
+ name: 'John',
668
+ email: 'john@example.com',
669
+ avatar: '',
670
+ role: 'user'
671
+ }
672
+ ];
673
+
674
+ const mockUserService = {
675
+ fetchUsers: vi.fn(),
676
+ searchUsers: vi.fn(),
677
+ refreshUsers: vi.fn(),
678
+ subscribe: vi.fn(),
679
+ getState: () => ({ users: mockUsers, loading: false, total: 1 }),
680
+ selector: {
681
+ users: (state: any) => state.users,
682
+ loading: (state: any) => state.loading,
683
+ total: (state: any) => state.total
684
+ }
685
+ };
686
+
687
+ const mockIOC = (identifier: string) => {
688
+ if (identifier === 'UserServiceInterface') return mockUserService;
689
+ if (identifier === 'RouteServiceInterface') return { push: vi.fn() };
690
+ };
691
+
692
+ render(
693
+ <IOCProvider value={mockIOC}>
694
+ <UserListPage />
695
+ </IOCProvider>
696
+ );
697
+
698
+ await waitFor(() => {
699
+ expect(screen.getByText('John')).toBeInTheDocument();
700
+ expect(screen.getByText('john@example.com')).toBeInTheDocument();
701
+ });
702
+ });
703
+
704
+ it('should search users when search button clicked', async () => {
705
+ const mockUserService = {
706
+ fetchUsers: vi.fn(),
707
+ searchUsers: vi.fn(),
708
+ subscribe: vi.fn(),
709
+ getState: () => ({ users: [], loading: false }),
710
+ selector: {
711
+ users: () => [],
712
+ loading: () => false,
713
+ total: () => 0
714
+ }
715
+ };
716
+
717
+ const mockIOC = (identifier: string) => {
718
+ if (identifier === 'UserServiceInterface') return mockUserService;
719
+ if (identifier === 'RouteServiceInterface') return { push: vi.fn() };
720
+ };
721
+
722
+ render(
723
+ <IOCProvider value={mockIOC}>
724
+ <UserListPage />
725
+ </IOCProvider>
726
+ );
727
+
728
+ const searchInput = screen.getByPlaceholderText(/search/i);
729
+ fireEvent.change(searchInput, { target: { value: 'John' } });
730
+
731
+ const searchButton = screen.getByRole('button', { name: /search/i });
732
+ fireEvent.click(searchButton);
733
+
734
+ expect(mockUserService.searchUsers).toHaveBeenCalledWith('John');
346
735
  });
347
736
  });
348
737
  ```
349
738
 
350
- 更多测试示例和最佳实践,请参考 [测试开发指南](./testing.md)。
739
+ ---
351
740
 
352
- ## 文档规范
741
+ ## 🎬 常见场景
353
742
 
354
- > 💡 这里仅列出基本规范,完整的文档编写指南请参考 [文档编写指南](./documentation.md)
743
+ ### 场景 1:添加一个新按钮功能
355
744
 
356
- ### 1. 代码注释
745
+ 假设要在用户列表页添加"批量删除"功能:
357
746
 
358
747
  ```typescript
748
+ // 1. 添加 i18n Key
359
749
  /**
360
- * 用户服务
361
- *
362
- * @description 处理用户相关的业务逻辑
363
- * @example
364
- * const userService = IOC(UserService);
365
- * await userService.login(credentials);
750
+ * @description Delete selected users
751
+ * @localZh 删除选中用户
752
+ * @localEn Delete Selected
366
753
  */
754
+ export const PAGE_USERS_DELETE_SELECTED = 'page.users.deleteSelected';
755
+
756
+ // 2. 在服务中添加方法
367
757
  @injectable()
368
- export class UserService {
369
- /**
370
- * 用户登录
371
- *
372
- * @param credentials - 登录凭证
373
- * @returns 登录成功的用户信息
374
- * @throws {AuthError} 认证失败时抛出
375
- */
376
- async login(credentials: Credentials): Promise<User> {
377
- // 实现
758
+ export class UserService extends UserServiceInterface {
759
+ async deleteUsers(userIds: string[]): Promise<void> {
760
+ try {
761
+ this.emit({ ...this.state, loading: true });
762
+ await this.api.deleteUsers(userIds);
763
+ await this.refreshUsers(); // 刷新列表
764
+ } catch (error) {
765
+ this.emit({ ...this.state, loading: false, error: error as Error });
766
+ }
378
767
  }
379
768
  }
769
+
770
+ // 3. 在页面中使用
771
+ function UserListPage() {
772
+ const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
773
+
774
+ const handleDelete = async () => {
775
+ await userService.deleteUsers(selectedRowKeys);
776
+ setSelectedRowKeys([]);
777
+ };
778
+
779
+ return (
780
+ <div>
781
+ <Button
782
+ danger
783
+ onClick={handleDelete}
784
+ disabled={selectedRowKeys.length === 0}
785
+ >
786
+ {t(i18nKeys.PAGE_USERS_DELETE_SELECTED)}
787
+ </Button>
788
+
789
+ <Table
790
+ rowSelection={{
791
+ selectedRowKeys,
792
+ onChange: setSelectedRowKeys
793
+ }}
794
+ // ...
795
+ />
796
+ </div>
797
+ );
798
+ }
380
799
  ```
381
800
 
382
- ### 2. 文档结构
801
+ ### 场景 2:添加一个弹窗表单
383
802
 
384
- - **README.md**:项目概述、安装说明、快速开始
385
- - **docs/**:
386
- - `zh/`:中文文档
387
- - `en/`:英文文档
388
- - 按功能模块组织文档文件
803
+ 假设要添加"编辑用户"弹窗:
389
804
 
390
- ### 3. 文档格式
805
+ ```typescript
806
+ // 1. 创建弹窗组件
807
+ // components/UserEditModal.tsx
808
+ interface UserEditModalProps {
809
+ user: UserInfo | null;
810
+ visible: boolean;
811
+ onClose: () => void;
812
+ onSubmit: (user: UserInfo) => void;
813
+ }
391
814
 
392
- ```markdown
393
- # 模块名称
815
+ export function UserEditModal({ user, visible, onClose, onSubmit }: UserEditModalProps) {
816
+ const [form] = Form.useForm();
817
+ const { t } = useAppTranslation();
394
818
 
395
- ## 概述
819
+ useEffect(() => {
820
+ if (user) {
821
+ form.setFieldsValue(user);
822
+ }
823
+ }, [user]);
396
824
 
397
- 简要说明模块的功能和用途。
825
+ const handleSubmit = async () => {
826
+ const values = await form.validateFields();
827
+ onSubmit(values);
828
+ };
398
829
 
399
- ## 使用方式
830
+ return (
831
+ <Modal
832
+ title={t(i18nKeys.PAGE_USERS_EDIT_TITLE)}
833
+ open={visible}
834
+ onCancel={onClose}
835
+ onOk={handleSubmit}
836
+ >
837
+ <Form form={form} layout="vertical">
838
+ <Form.Item
839
+ name="name"
840
+ label={t(i18nKeys.PAGE_USERS_FORM_NAME)}
841
+ rules={[{ required: true }]}
842
+ >
843
+ <Input />
844
+ </Form.Item>
845
+ <Form.Item
846
+ name="email"
847
+ label={t(i18nKeys.PAGE_USERS_FORM_EMAIL)}
848
+ rules={[{ required: true, type: 'email' }]}
849
+ >
850
+ <Input />
851
+ </Form.Item>
852
+ </Form>
853
+ </Modal>
854
+ );
855
+ }
400
856
 
401
- 代码示例和使用说明。
857
+ // 2. 在服务中添加更新方法
858
+ @injectable()
859
+ export class UserService extends UserServiceInterface {
860
+ async updateUser(userId: string, data: Partial<UserInfo>): Promise<void> {
861
+ this.emit({ ...this.state, loading: true });
862
+ await this.api.updateUser(userId, data);
863
+ await this.refreshUsers();
864
+ }
865
+ }
402
866
 
403
- ## API 文档
867
+ // 3. 在页面中使用
868
+ function UserListPage() {
869
+ const [editUser, setEditUser] = useState<UserInfo | null>(null);
870
+ const [modalVisible, setModalVisible] = useState(false);
404
871
 
405
- 详细的 API 说明。
872
+ const handleEdit = (user: UserInfo) => {
873
+ setEditUser(user);
874
+ setModalVisible(true);
875
+ };
406
876
 
407
- ## 最佳实践
877
+ const handleSubmit = async (values: UserInfo) => {
878
+ await userService.updateUser(editUser!.id, values);
879
+ setModalVisible(false);
880
+ setEditUser(null);
881
+ };
408
882
 
409
- 使用建议和注意事项。
883
+ return (
884
+ <div>
885
+ <Table
886
+ columns={[
887
+ // ...
888
+ {
889
+ title: 'Actions',
890
+ render: (_, record) => (
891
+ <Button onClick={() => handleEdit(record)}>Edit</Button>
892
+ )
893
+ }
894
+ ]}
895
+ // ...
896
+ />
897
+
898
+ <UserEditModal
899
+ user={editUser}
900
+ visible={modalVisible}
901
+ onClose={() => setModalVisible(false)}
902
+ onSubmit={handleSubmit}
903
+ />
904
+ </div>
905
+ );
906
+ }
410
907
  ```
411
908
 
412
- ## Git 提交规范
909
+ ### 场景 3:添加实时搜索
413
910
 
414
- > 💡 这里仅列出基本规范,完整的 Git 工作流程请参考 [Git 工作流指南](./git-workflow.md)
911
+ 假设要实现"输入时自动搜索":
415
912
 
416
- ### 1. 提交消息格式
913
+ ```typescript
914
+ function UserListPage() {
915
+ const [keyword, setKeyword] = useState('');
417
916
 
418
- ```
419
- <type>(<scope>): <subject>
917
+ // 使用 debounce 优化搜索
918
+ const debouncedKeyword = useDebounce(keyword, 500);
420
919
 
421
- <body>
920
+ useEffect(() => {
921
+ if (debouncedKeyword !== undefined) {
922
+ userService.searchUsers(debouncedKeyword);
923
+ }
924
+ }, [debouncedKeyword]);
422
925
 
423
- <footer>
424
- ```
926
+ return (
927
+ <Input
928
+ placeholder={t(i18nKeys.PAGE_USERS_SEARCH_PLACEHOLDER)}
929
+ value={keyword}
930
+ onChange={(e) => setKeyword(e.target.value)}
931
+ />
932
+ );
933
+ }
425
934
 
426
- - **type**:
427
- - `feat`:新功能
428
- - `fix`:修复
429
- - `docs`:文档更新
430
- - `style`:代码格式(不影响代码运行的变动)
431
- - `refactor`:重构
432
- - `test`:增加测试
433
- - `chore`:构建过程或辅助工具的变动
935
+ // 自定义 Hook
936
+ function useDebounce<T>(value: T, delay: number): T {
937
+ const [debouncedValue, setDebouncedValue] = useState(value);
434
938
 
435
- - **scope**:影响范围(可选)
436
- - **subject**:简短描述
437
- - **body**:详细描述(可选)
438
- - **footer**:不兼容变动、关闭 issue(可选)
939
+ useEffect(() => {
940
+ const timer = setTimeout(() => {
941
+ setDebouncedValue(value);
942
+ }, delay);
439
943
 
440
- ### 2. 示例
944
+ return () => {
945
+ clearTimeout(timer);
946
+ };
947
+ }, [value, delay]);
441
948
 
949
+ return debouncedValue;
950
+ }
442
951
  ```
443
- feat(auth): 添加用户角色管理功能
444
952
 
445
- - 添加角色创建和编辑界面
446
- - 实现角色权限配置
447
- - 添加角色分配功能
953
+ ---
448
954
 
449
- Closes #123
450
- ```
955
+ ## 📐 代码规范
451
956
 
452
- ## 性能优化规范
957
+ ### 1. 命名规范
453
958
 
454
- > 💡 这里仅列出基本规范,完整的性能优化指南请参考 [性能优化指南](./performance.md)
959
+ ```typescript
960
+ // ✅ 好的命名
961
+ const userService = useIOC('UserServiceInterface'); // 服务:小驼峰
962
+ const UserListPage = () => {
963
+ /* ... */
964
+ }; // 组件:大驼峰
965
+ const PAGE_USERS_TITLE = 'page.users.title'; // 常量:大写下划线
966
+ interface UserInfo {
967
+ /* ... */
968
+ } // 接口:大驼峰
969
+ type UserRole = 'admin' | 'user'; // 类型:大驼峰
970
+
971
+ // ❌ 不好的命名
972
+ const UserService = useIOC('UserServiceInterface'); // 应该是小驼峰
973
+ const userListPage = () => {
974
+ /* ... */
975
+ }; // 组件应该大驼峰
976
+ const pageUsersTitle = 'page.users.title'; // 常量应该大写
977
+ interface userInfo {
978
+ /* ... */
979
+ } // 接口应该大驼峰
980
+ ```
455
981
 
456
- ### 1. 代码分割
982
+ ### 2. 文件组织
457
983
 
458
984
  ```typescript
459
- // 路由级别的代码分割
460
- const UserModule = lazy(() => import('./pages/users'));
985
+ // ✅ 好的文件组织
986
+ import { FC, useEffect, useState } from 'react'; // React
987
+ import { Button, Table, Input } from 'antd'; // 第三方 UI
988
+ import { useIOC } from '@/uikit/hooks/useIOC'; // 项目内部
989
+ import { useAppTranslation } from '@/uikit/hooks/useAppTranslation';
990
+ import * as i18nKeys from '@config/Identifier/pages/page.users';
991
+ import './UserListPage.css'; // 样式
992
+
993
+ // 类型定义
994
+ interface Props {
995
+ /* ... */
996
+ }
461
997
 
462
- // 组件级别的代码分割
463
- const HeavyComponent = lazy(() => import('./components/Heavy'));
998
+ // 组件
999
+ export default function UserListPage() {
1000
+ /* ... */
1001
+ }
1002
+
1003
+ // ❌ 不好的文件组织
1004
+ import './UserListPage.css'; // 样式不应该在最前
1005
+ import * as i18nKeys from '@config/Identifier/pages/page.users';
1006
+ import { Button } from 'antd';
1007
+ import { useIOC } from '@/uikit/hooks/useIOC';
1008
+ import { FC } from 'react';
464
1009
  ```
465
1010
 
466
- ### 2. 性能考虑
1011
+ ### 3. 组件结构
467
1012
 
468
1013
  ```typescript
469
- // 使用 useMemo 缓存计算结果
470
- const sortedUsers = useMemo(() => {
471
- return users.sort((a, b) => a.name.localeCompare(b.name));
472
- }, [users]);
473
-
474
- // 使用 useCallback 缓存函数
475
- const handleUpdate = useCallback(() => {
476
- // 实现
477
- }, [dependencies]);
478
-
479
- // 使用 React.memo 避免不必要的重渲染
480
- const UserCard = React.memo(({ user }) => {
481
- return <div>{user.name}</div>;
482
- });
483
- ```
484
-
485
- ## 安全规范
1014
+ // 好的组件结构
1015
+ export default function UserListPage() {
1016
+ // 1. Hooks
1017
+ const userService = useIOC('UserServiceInterface');
1018
+ const { t } = useAppTranslation();
486
1019
 
487
- > 💡 这里仅列出基本规范,完整的安全开发指南请参考 [安全开发指南](./security.md)
1020
+ // 2. 状态
1021
+ const users = useStore(userService, userService.selector.users);
1022
+ const [keyword, setKeyword] = useState('');
488
1023
 
489
- ### 1. 数据处理
1024
+ // 3. 副作用
1025
+ useEffect(() => {
1026
+ userService.fetchUsers({ page: 1, pageSize: 10 });
1027
+ }, []);
490
1028
 
491
- ```typescript
492
- // 敏感数据加密
493
- const encryptedData = encrypt(sensitiveData);
1029
+ // 4. 事件处理
1030
+ const handleSearch = () => {
1031
+ userService.searchUsers(keyword);
1032
+ };
494
1033
 
495
- // XSS 防护
496
- const sanitizedHtml = sanitizeHtml(userInput);
1034
+ // 5. 渲染函数
1035
+ const renderActions = (record: UserInfo) => {
1036
+ return <Button onClick={() => handleEdit(record)}>Edit</Button>;
1037
+ };
497
1038
 
498
- // CSRF 防护
499
- api.defaults.headers['X-CSRF-Token'] = getCsrfToken();
1039
+ // 6. 返回 JSX
1040
+ return (
1041
+ <div>
1042
+ {/* ... */}
1043
+ </div>
1044
+ );
1045
+ }
500
1046
  ```
501
1047
 
502
- ### 2. 权限控制
1048
+ ### 4. 注释规范
503
1049
 
504
1050
  ```typescript
505
- // 路由权限
506
- const PrivateRoute: FC = ({ children }) => {
507
- const auth = useAuth();
508
- return auth.isAuthenticated ? children : <Navigate to="/login" />;
509
- };
1051
+ /**
1052
+ * 用户列表页面
1053
+ *
1054
+ * @description 显示用户列表,支持搜索、分页、查看详情等功能
1055
+ */
1056
+ export default function UserListPage() {
1057
+ /**
1058
+ * 处理搜索
1059
+ * 根据关键词搜索用户
1060
+ */
1061
+ const handleSearch = () => {
1062
+ userService.searchUsers(keyword);
1063
+ };
510
1064
 
511
- // 操作权限
512
- function AdminPanel() {
513
- const { hasPermission } = useAuth();
1065
+ // 初始化加载用户列表
1066
+ useEffect(() => {
1067
+ userService.fetchUsers({ page: 1, pageSize: 10 });
1068
+ }, []);
514
1069
 
515
1070
  return (
516
1071
  <div>
517
- {hasPermission('ADMIN') && (
518
- <button>管理员操作</button>
519
- )}
1072
+ {/* 搜索栏 */}
1073
+ <Input.Search onSearch={handleSearch} />
1074
+
1075
+ {/* 用户表格 */}
1076
+ <Table dataSource={users} />
520
1077
  </div>
521
1078
  );
522
1079
  }
523
1080
  ```
1081
+
1082
+ ---
1083
+
1084
+ ## 🛠️ 开发工具
1085
+
1086
+ ### 推荐的 VSCode 插件
1087
+
1088
+ ```
1089
+ ✅ ESLint - 代码检查
1090
+ ✅ Prettier - 代码格式化
1091
+ ✅ TypeScript Vue Plugin (Volar) - Vue/React 支持
1092
+ ✅ Tailwind CSS IntelliSense - Tailwind 智能提示
1093
+ ✅ i18n Ally - i18n 管理
1094
+ ✅ GitLens - Git 增强
1095
+ ✅ Error Lens - 错误提示
1096
+ ✅ Auto Rename Tag - 标签自动重命名
1097
+ ```
1098
+
1099
+ ### 快捷命令
1100
+
1101
+ ```bash
1102
+ # 开发
1103
+ npm run dev # 启动开发服务器
1104
+ npm run dev:staging # 启动测试环境
1105
+
1106
+ # 构建
1107
+ npm run build # 生产构建
1108
+ npm run preview # 预览构建结果
1109
+
1110
+ # 代码检查
1111
+ npm run lint # ESLint 检查
1112
+ npm run lint:fix # ESLint 自动修复
1113
+ npm run type-check # TypeScript 类型检查
1114
+
1115
+ # 测试
1116
+ npm run test # 运行测试
1117
+ npm run test:watch # 监听模式测试
1118
+ npm run test:coverage # 测试覆盖率
1119
+
1120
+ # i18n
1121
+ npm run i18n:generate # 生成翻译文件
1122
+ ```
1123
+
1124
+ ### 调试技巧
1125
+
1126
+ ```typescript
1127
+ // 1. 使用 logger
1128
+ import { logger } from '@/core/globals';
1129
+
1130
+ logger.debug('User data:', user);
1131
+ logger.error('Failed to fetch users:', error);
1132
+
1133
+ // 2. 使用 React DevTools
1134
+ // 安装 React Developer Tools 浏览器插件
1135
+
1136
+ // 3. 使用 Redux DevTools(如果需要)
1137
+ // 查看 Store 状态变化
1138
+
1139
+ // 4. 使用 VSCode 断点调试
1140
+ // 在代码行左侧点击设置断点,然后 F5 启动调试
1141
+ ```
1142
+
1143
+ ---
1144
+
1145
+ ## 🎯 开发 Checklist
1146
+
1147
+ ### 功能开发
1148
+
1149
+ - [ ] 定义 i18n Key
1150
+ - [ ] 定义接口和类型
1151
+ - [ ] 实现 API 适配器(如果需要)
1152
+ - [ ] 实现服务
1153
+ - [ ] 配置路由
1154
+ - [ ] 实现页面组件
1155
+ - [ ] 注册到 IOC(如果是新服务)
1156
+ - [ ] 功能自测
1157
+
1158
+ ### 代码质量
1159
+
1160
+ - [ ] 通过 ESLint 检查
1161
+ - [ ] 通过 TypeScript 类型检查
1162
+ - [ ] 代码格式化(Prettier)
1163
+ - [ ] 移除 console.log 和调试代码
1164
+ - [ ] 移除未使用的导入
1165
+
1166
+ ### 测试
1167
+
1168
+ - [ ] 编写服务测试
1169
+ - [ ] 编写 UI 测试
1170
+ - [ ] 测试覆盖率 > 80%
1171
+ - [ ] 所有测试通过
1172
+
1173
+ ### 文档
1174
+
1175
+ - [ ] 更新相关文档
1176
+ - [ ] 添加必要的代码注释
1177
+ - [ ] 更新 API 文档(如果有)
1178
+
1179
+ ### 提交
1180
+
1181
+ - [ ] Git commit 符合规范
1182
+ - [ ] 代码已 review
1183
+ - [ ] 合并到主分支
1184
+
1185
+ ---
1186
+
1187
+ ## 📚 相关文档
1188
+
1189
+ - **[项目架构设计](./index.md)** - 了解整体架构
1190
+ - **[IOC 容器](./ioc.md)** - 依赖注入和 UI 分离
1191
+ - **[Store 状态管理](./store.md)** - 应用层如何通知 UI 层
1192
+ - **[Bootstrap 启动器](./bootstrap.md)** - 应用启动和初始化
1193
+ - **[环境变量管理](./env.md)** - 多环境配置
1194
+ - **[国际化](./i18n.md)** - i18n Key 和翻译管理
1195
+
1196
+ ---
1197
+
1198
+ **问题反馈:**
1199
+ 如果你在开发过程中遇到任何问题,请在团队频道中讨论或提交 Issue。