@qlover/create-app 0.10.1 → 0.10.3

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 (214) hide show
  1. package/CHANGELOG.md +178 -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/index.cjs +4 -4
  5. package/dist/index.js +4 -4
  6. package/dist/templates/next-app/config/IOCIdentifier.ts +2 -2
  7. package/dist/templates/next-app/config/Identifier/common/common.ts +14 -0
  8. package/dist/templates/next-app/config/Identifier/pages/index.ts +1 -0
  9. package/dist/templates/next-app/config/Identifier/pages/page.about.ts +20 -0
  10. package/dist/templates/next-app/config/common.ts +1 -1
  11. package/dist/templates/next-app/config/cookies.ts +23 -0
  12. package/dist/templates/next-app/config/i18n/AboutI18n.ts +14 -0
  13. package/dist/templates/next-app/config/i18n/i18nConfig.ts +3 -1
  14. package/dist/templates/next-app/config/i18n/index.ts +1 -0
  15. package/dist/templates/next-app/config/i18n/loginI18n.ts +8 -0
  16. package/dist/templates/next-app/config/theme.ts +4 -0
  17. package/dist/templates/next-app/eslint.config.mjs +9 -2
  18. package/dist/templates/next-app/next.config.ts +1 -0
  19. package/dist/templates/next-app/package.json +17 -6
  20. package/dist/templates/next-app/public/locales/en.json +5 -0
  21. package/dist/templates/next-app/public/locales/zh.json +5 -0
  22. package/dist/templates/next-app/src/app/[locale]/admin/AdminI18nProvider.tsx +37 -0
  23. package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +30 -6
  24. package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +1 -1
  25. package/dist/templates/next-app/src/app/[locale]/layout.tsx +47 -10
  26. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +1 -1
  27. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +22 -10
  28. package/dist/templates/next-app/src/app/[locale]/page.tsx +23 -8
  29. package/dist/templates/next-app/src/app/[locale]/register/page.tsx +21 -9
  30. package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +7 -28
  31. package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +7 -34
  32. package/dist/templates/next-app/src/app/api/admin/locales/route.ts +12 -34
  33. package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +7 -26
  34. package/dist/templates/next-app/src/app/api/admin/users/route.ts +14 -33
  35. package/dist/templates/next-app/src/app/api/locales/json/route.ts +13 -25
  36. package/dist/templates/next-app/src/app/api/user/login/route.ts +6 -46
  37. package/dist/templates/next-app/src/app/api/user/logout/route.ts +5 -24
  38. package/dist/templates/next-app/src/app/api/user/register/route.ts +6 -45
  39. package/dist/templates/next-app/src/app/manifest.ts +16 -0
  40. package/dist/templates/next-app/src/app/robots.txt +2 -0
  41. package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +3 -3
  42. package/dist/templates/next-app/src/base/cases/AppConfig.ts +14 -13
  43. package/dist/templates/next-app/src/base/cases/Datetime.ts +3 -3
  44. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +8 -2
  45. package/dist/templates/next-app/src/base/cases/DialogHandler.ts +30 -4
  46. package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +16 -4
  47. package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +20 -4
  48. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +8 -2
  49. package/dist/templates/next-app/src/base/cases/ResourceState.ts +3 -3
  50. package/dist/templates/next-app/src/base/cases/RouterService.ts +28 -10
  51. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +14 -2
  52. package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +1 -1
  53. package/dist/templates/next-app/src/base/cases/UserServiceApi.ts +20 -5
  54. package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +31 -8
  55. package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +4 -1
  56. package/dist/templates/next-app/src/base/port/AppApiInterface.ts +22 -0
  57. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +27 -7
  58. package/dist/templates/next-app/src/base/port/IOCInterface.ts +9 -0
  59. package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +1 -1
  60. package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +3 -3
  61. package/dist/templates/next-app/src/base/services/I18nService.ts +20 -10
  62. package/dist/templates/next-app/src/base/services/ResourceService.ts +32 -11
  63. package/dist/templates/next-app/src/base/services/UserService.ts +12 -3
  64. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +9 -6
  65. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +20 -5
  66. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +21 -4
  67. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +12 -3
  68. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +10 -2
  69. package/dist/templates/next-app/src/base/types/{PageProps.ts → AppPageRouter.ts} +4 -1
  70. package/dist/templates/next-app/src/base/types/PagesRouter.ts +9 -0
  71. package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +20 -6
  72. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +27 -9
  73. package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +6 -4
  74. package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +39 -9
  75. package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +9 -2
  76. package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +37 -10
  77. package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +9 -2
  78. package/dist/templates/next-app/src/i18n/loadMessages.ts +103 -0
  79. package/dist/templates/next-app/src/i18n/request.ts +3 -22
  80. package/dist/templates/next-app/src/pages/[locale]/about.tsx +61 -0
  81. package/dist/templates/next-app/src/pages/_app.tsx +50 -0
  82. package/dist/templates/next-app/src/pages/_document.tsx +13 -0
  83. package/dist/templates/next-app/src/{middleware.ts → proxy.ts} +2 -1
  84. package/dist/templates/next-app/src/server/AppErrorApi.ts +1 -1
  85. package/dist/templates/next-app/src/server/AppPageRouteParams.ts +107 -0
  86. package/dist/templates/next-app/src/server/AppSuccessApi.ts +1 -1
  87. package/dist/templates/next-app/src/server/NextApiServer.ts +62 -0
  88. package/dist/templates/next-app/src/server/PagesRouteParams.ts +146 -0
  89. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +8 -2
  90. package/dist/templates/next-app/src/server/ServerAuth.ts +20 -5
  91. package/dist/templates/next-app/src/server/{sqlBridges/SupabaseBridge.ts → SupabaseBridge.ts} +50 -8
  92. package/dist/templates/next-app/src/server/UserCredentialToken.ts +8 -2
  93. package/dist/templates/next-app/src/server/controllers/AdminLocalesController.ts +86 -0
  94. package/dist/templates/next-app/src/server/controllers/AdminUserController.ts +42 -0
  95. package/dist/templates/next-app/src/server/controllers/LocalesController.ts +36 -0
  96. package/dist/templates/next-app/src/server/controllers/UserController.ts +86 -0
  97. package/dist/templates/next-app/src/server/port/AIControllerInterface.ts +8 -0
  98. package/dist/templates/next-app/src/server/port/AdminLocalesControllerInterface.ts +21 -0
  99. package/dist/templates/next-app/src/server/port/AdminUserControllerInterface.ts +11 -0
  100. package/dist/templates/next-app/src/server/port/LocalesControllerInterface.ts +10 -0
  101. package/dist/templates/next-app/src/server/port/{ParamsHandlerInterface.ts → RouteParamsnHandlerInterface.ts} +9 -2
  102. package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
  103. package/dist/templates/next-app/src/server/port/UserControllerInerface.ts +8 -0
  104. package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +1 -1
  105. package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +2 -2
  106. package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +31 -9
  107. package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +15 -6
  108. package/dist/templates/next-app/src/server/services/AIService.ts +3 -1
  109. package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +5 -2
  110. package/dist/templates/next-app/src/{base → server}/services/AdminLocalesService.ts +2 -2
  111. package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +29 -14
  112. package/dist/templates/next-app/src/server/services/ApiUserService.ts +6 -3
  113. package/dist/templates/next-app/src/server/services/UserService.ts +12 -3
  114. package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +24 -7
  115. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +17 -5
  116. package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +17 -11
  117. package/dist/templates/next-app/src/styles/css/antd-themes/_common/_default.css +0 -44
  118. package/dist/templates/next-app/src/styles/css/antd-themes/_common/dark.css +0 -44
  119. package/dist/templates/next-app/src/styles/css/antd-themes/_common/pink.css +0 -44
  120. package/dist/templates/next-app/src/styles/css/index.css +1 -1
  121. package/dist/templates/next-app/src/styles/css/scrollbar.css +34 -0
  122. package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +34 -11
  123. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +69 -39
  124. package/dist/templates/next-app/src/uikit/components/ClientRootProvider.tsx +64 -0
  125. package/dist/templates/next-app/src/uikit/components/ClinetRenderProvider.tsx +42 -0
  126. package/dist/templates/next-app/src/uikit/components/IOCProvider.tsx +34 -0
  127. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +7 -1
  128. package/dist/templates/next-app/src/uikit/components-app/AppBridge.tsx +17 -0
  129. package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +112 -0
  130. package/dist/templates/next-app/src/uikit/{components → components-app}/LanguageSwitcher.tsx +15 -19
  131. package/dist/templates/next-app/src/uikit/{components → components-app}/ThemeSwitcher.tsx +53 -52
  132. package/dist/templates/next-app/src/uikit/components-pages/LanguageSwitcher.tsx +98 -0
  133. package/dist/templates/next-app/src/uikit/components-pages/PagesRoutePage.tsx +93 -0
  134. package/dist/templates/next-app/src/uikit/context/IOCContext.ts +16 -4
  135. package/dist/templates/next-app/src/uikit/hook/useStrictEffect.ts +32 -0
  136. package/dist/templates/next-app/tsconfig.json +3 -2
  137. package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +3 -1
  138. package/dist/templates/react-app/__tests__/__mocks__/MockAppConfig.ts +19 -19
  139. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +8 -8
  140. package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +9 -9
  141. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +1 -1
  142. package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +5 -5
  143. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +9 -5
  144. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +8 -4
  145. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +4 -4
  146. package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +5 -5
  147. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +3 -3
  148. package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +1 -1
  149. package/dist/templates/react-app/docs/en/components/chat-message-component.md +35 -29
  150. package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +18 -5
  151. package/dist/templates/react-app/docs/en/components/message-base-list-component.md +11 -12
  152. package/dist/templates/react-app/docs/en/request.md +1 -3
  153. package/dist/templates/react-app/docs/zh/components/chat-message-component.md +35 -29
  154. package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +18 -5
  155. package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +11 -12
  156. package/dist/templates/react-app/docs/zh/request.md +1 -3
  157. package/dist/templates/react-app/eslint.config.mjs +10 -5
  158. package/dist/templates/react-app/src/App.tsx +1 -1
  159. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +2 -2
  160. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +14 -11
  161. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -16
  162. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +12 -10
  163. package/dist/templates/react-app/src/base/cases/AppConfig.ts +19 -19
  164. package/dist/templates/react-app/src/base/cases/DialogHandler.ts +28 -5
  165. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +5 -2
  166. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +16 -4
  167. package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +1 -1
  168. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +6 -3
  169. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +17 -8
  170. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +4 -6
  171. package/dist/templates/react-app/src/base/cases/ResourceState.ts +3 -3
  172. package/dist/templates/react-app/src/base/cases/RouterLoader.ts +3 -3
  173. package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +1 -1
  174. package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +2 -2
  175. package/dist/templates/react-app/src/base/port/IOCInterface.ts +4 -2
  176. package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +5 -5
  177. package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +7 -7
  178. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +8 -8
  179. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +4 -2
  180. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +3 -3
  181. package/dist/templates/react-app/src/base/services/I18nService.ts +24 -13
  182. package/dist/templates/react-app/src/base/services/IdentifierService.ts +21 -26
  183. package/dist/templates/react-app/src/base/services/RouteService.ts +8 -8
  184. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +2 -2
  185. package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +9 -5
  186. package/dist/templates/react-app/src/base/services/UserService.ts +10 -4
  187. package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +3 -1
  188. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +5 -2
  189. package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +11 -4
  190. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +5 -4
  191. package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
  192. package/dist/templates/react-app/src/styles/css/antd-themes/_common/_default.css +0 -44
  193. package/dist/templates/react-app/src/styles/css/antd-themes/_common/dark.css +0 -44
  194. package/dist/templates/react-app/src/styles/css/antd-themes/_common/pink.css +0 -44
  195. package/dist/templates/react-app/src/styles/css/index.css +1 -1
  196. package/dist/templates/react-app/src/styles/css/scrollbar.css +34 -0
  197. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +2 -2
  198. package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +4 -4
  199. package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +8 -2
  200. package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +6 -6
  201. package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +1 -1
  202. package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +1 -3
  203. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +4 -1
  204. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +39 -16
  205. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +4 -2
  206. package/package.json +3 -3
  207. package/dist/templates/next-app/src/server/PageParams.ts +0 -66
  208. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +0 -80
  209. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +0 -65
  210. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +0 -58
  211. package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +0 -21
  212. package/dist/templates/react-app/makes/eslint-utils.mjs +0 -195
  213. /package/dist/templates/next-app/{src/app/[locale] → public}/favicon.ico +0 -0
  214. /package/dist/templates/next-app/src/uikit/{components → components-app}/LogoutButton.tsx +0 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @description About page title
3
+ * @localZh 关于我们
4
+ * @localEn About Us
5
+ */
6
+ export const PAGE_ABOUT_TITLE = 'page_about:title';
7
+
8
+ /**
9
+ * @description About page description
10
+ * @localZh 了解我们的团队和使命
11
+ * @localEn Learn about our team and mission
12
+ */
13
+ export const PAGE_ABOUT_DESCRIPTION = 'page_about:description';
14
+
15
+ /**
16
+ * @description About page keywords
17
+ * @localZh 关于我们, 团队, 使命
18
+ * @localEn About us, team, mission
19
+ */
20
+ export const PAGE_ABOUT_KEYWORDS = 'page_about:keywords';
@@ -26,7 +26,7 @@ export const useLocaleRoutes = true;
26
26
  * - true: 使用API获取本地化数据,可以在 /admin/locales 页面中对他进行修改
27
27
  * - false: 不使用API获取本地化数据,直接使用 `@brain-toolkit/ts2locales` 生成的json数据
28
28
  */
29
- export const useApiLocales = false;
29
+ export const useApiLocales = true;
30
30
 
31
31
  /**
32
32
  * 是否在在 useWarnTranslations 中警告缺失的翻译,而不是抛出错误
@@ -0,0 +1,23 @@
1
+ export const cookiesConfig: Cookies.CookieAttributes = {
2
+ domain: '',
3
+ path: '/',
4
+ expires: 30,
5
+ /**
6
+ * httpOnly 必须为 false,否则客户端 JavaScript 无法设置 cookie
7
+ * httpOnly: true 只能用于服务端设置的 cookie(如认证 token)
8
+ */
9
+ httpOnly: false,
10
+ /**
11
+ * 是否仅通过 HTTPS 传输
12
+ *
13
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#secure_cookie_attribute
14
+ */
15
+ secure: false,
16
+ /**
17
+ * 'strict':最严格,跨站请求(如从其他网站链接过来)不发送 Cookie
18
+ * 其他可选值:'lax'(部分允许)、'none'(允许,但需要 secure: true)
19
+ *
20
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#samesite_cookie_attribute
21
+ */
22
+ sameSite: 'strict'
23
+ };
@@ -0,0 +1,14 @@
1
+ import * as i18nKeys from '../Identifier/pages/page.about';
2
+
3
+ /**
4
+ * About page i18n interface
5
+ */
6
+ export type AboutI18nInterface = typeof aboutI18n;
7
+
8
+ export const aboutI18n = Object.freeze({
9
+ // basic meta properties
10
+ title: i18nKeys.PAGE_ABOUT_TITLE,
11
+ description: i18nKeys.PAGE_ABOUT_DESCRIPTION,
12
+ content: i18nKeys.PAGE_ABOUT_DESCRIPTION,
13
+ keywords: i18nKeys.PAGE_ABOUT_KEYWORDS
14
+ });
@@ -8,7 +8,9 @@ export const i18nConfig = {
8
8
  fallbackLng: 'en',
9
9
  debug: false,
10
10
  supportedLngs: ['en', 'zh'] as const,
11
- localeDetection: true
11
+ localeDetection: true,
12
+ defaultNamespaces: ['common', 'api'],
13
+ storageKey: 'NEXT_LOCALE'
12
14
  } as const;
13
15
 
14
16
  export type LocaleType = (typeof i18nConfig.supportedLngs)[number];
@@ -4,3 +4,4 @@ export * from './i18nConfig';
4
4
  export * from './loginI18n';
5
5
  export * from './PageI18nInterface';
6
6
  export * from './register18n';
7
+ export * from './AboutI18n';
@@ -8,6 +8,14 @@ import * as i18nKeys from '../Identifier/pages/page.login';
8
8
  */
9
9
  export type LoginI18nInterface = typeof loginI18n;
10
10
 
11
+ /**
12
+ * Login page i18n namespace
13
+ *
14
+ * - /login/page.tsx
15
+ *
16
+ */
17
+ export const NS_PAGE_LOGIN = 'page_login';
18
+
11
19
  export const loginI18n = Object.freeze({
12
20
  // basic meta properties
13
21
  title: i18nKeys.PAGE_LOGIN_TITLE,
@@ -5,7 +5,11 @@ import type { ThemeConfig } from 'antd';
5
5
  */
6
6
  export const themeConfig = {
7
7
  domAttribute: 'data-theme',
8
+ /**
9
+ * If `enableSystem` is false, the default theme is light
10
+ */
8
11
  defaultTheme: 'system',
12
+ enableSystem: true,
9
13
  target: 'html',
10
14
  supportedThemes: ['light', 'dark', 'pink'],
11
15
  storageKey: 'fe_theme',
@@ -105,7 +105,11 @@ const eslintConfig = [
105
105
  },
106
106
  rules: {
107
107
  '@qlover-eslint/ts-class-method-return': 'error',
108
- '@qlover-eslint/require-root-testid': 'error',
108
+ '@qlover-eslint/ts-class-member-accessibility': 'error',
109
+ '@qlover-eslint/ts-class-override': 'error',
110
+ '@qlover-eslint/require-root-testid': ['error', {
111
+ exclude: ['/Provider$/']
112
+ }],
109
113
  // 禁用原始的 no-unused-vars,使用 unused-imports 的规则替代
110
114
  '@typescript-eslint/no-unused-vars': 'off',
111
115
  // 强制使用 import type 导入类型
@@ -192,6 +196,9 @@ const eslintConfig = [
192
196
  'src/app/**/not-found.tsx',
193
197
  'src/i18n/request.ts',
194
198
  'src/middleware.ts',
199
+ 'src/pages/**/*.tsx',
200
+ 'src/app/manifest.ts',
201
+ 'src/proxy.ts',
195
202
  '**/*.config.*'
196
203
  ],
197
204
  rules: {
@@ -200,4 +207,4 @@ const eslintConfig = [
200
207
  }
201
208
  ];
202
209
 
203
- export default eslintConfig;
210
+ export default eslintConfig;
@@ -14,6 +14,7 @@ const nextConfig: NextConfig = {
14
14
  turbopack: {
15
15
  root: __dirname // 明确指定根目录
16
16
  },
17
+ transpilePackages: ['@qlover/corekit-bridge', '@qlover/fe-corekit'],
17
18
  env: {
18
19
  APP_ENV: process.env.APP_ENV
19
20
  }
@@ -10,15 +10,15 @@
10
10
  "build:staging": "cross-env APP_ENV=staging next build --turbopack",
11
11
  "build:prod": "cross-env APP_ENV=production next build --turbopack",
12
12
  "start": "next start --port 3101",
13
- "lint": "eslint ./src ./config ./make ./migrations",
14
- "lint:fix": "eslint ./src ./config ./make ./migrations --ext .ts,.tsx --fix",
13
+ "lint": "tsc --noEmit && eslint ./src ./config ./make ./migrations",
14
+ "lint:fix": "tsc --noEmit && eslint ./src ./config ./make ./migrations --ext .ts,.tsx --fix",
15
15
  "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
16
16
  "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
17
17
  "fix": "npm run lint:fix && npm run format"
18
18
  },
19
19
  "dependencies": {
20
20
  "@ant-design/icons": "^6.0.0",
21
- "@ant-design/nextjs-registry": "^1.1.0",
21
+ "@ant-design/nextjs-registry": "^1.3.0",
22
22
  "@ant-design/v5-patch-for-react-19": "^1.0.3",
23
23
  "@brain-toolkit/antd-blocks": "^0.0.1",
24
24
  "@brain-toolkit/antd-theme-override": "^0.0.3",
@@ -27,8 +27,10 @@
27
27
  "@qlover/corekit-bridge": "latest",
28
28
  "@qlover/fe-corekit": "latest",
29
29
  "@qlover/slice-store-react": "^1.4.1",
30
+ "@supabase/postgrest-js": "^2.87.1",
30
31
  "@supabase/ssr": "^0.7.0",
31
32
  "@supabase/supabase-js": "^2.57.2",
33
+ "@types/js-cookie": "^3.0.6",
32
34
  "@types/jsonwebtoken": "^9.0.10",
33
35
  "antd": "^5.27.1",
34
36
  "clsx": "^2.1.1",
@@ -36,8 +38,8 @@
36
38
  "inversify": "^7.8.1",
37
39
  "jsonwebtoken": "^9.0.2",
38
40
  "lodash": "^4.17.21",
39
- "next": "15.5.0",
40
- "next-intl": "^4.3.5",
41
+ "next": "^16.0.3",
42
+ "next-intl": "^4.5.8",
41
43
  "next-themes": "^0.4.6",
42
44
  "openai": "^5.23.0",
43
45
  "p-limit": "^7.2.0",
@@ -53,6 +55,7 @@
53
55
  "@qlover/eslint-plugin": "latest",
54
56
  "@tailwindcss/postcss": "^4",
55
57
  "@types/lodash": "^4.17.20",
58
+ "@types/ms": "^2.1.0",
56
59
  "@types/node": "^20",
57
60
  "@types/react": "^19",
58
61
  "@types/react-dom": "^19",
@@ -66,8 +69,16 @@
66
69
  "eslint-plugin-prettier": "^5.5.4",
67
70
  "eslint-plugin-unused-imports": "^4.2.0",
68
71
  "prettier": "^3.6.2",
69
- "supabase": "^2.40.7",
70
72
  "tailwindcss": "^4",
71
73
  "typescript": "^5"
74
+ },
75
+ "engines": {
76
+ "node": "^20.17.0 || >=22.9.0",
77
+ "npm": ">=10.0.0"
78
+ },
79
+ "prettier": {
80
+ "singleQuote": true,
81
+ "trailingComma": "none",
82
+ "endOfLine": "lf"
72
83
  }
73
84
  }
@@ -19,17 +19,22 @@
19
19
  "common:create": "Create",
20
20
  "common:detail": "Detail",
21
21
  "common:theme__default": "Default Theme",
22
+ "common:theme__light": "Light Theme",
22
23
  "common:theme__dark": "Dark Theme",
23
24
  "common:theme__pink": "Pink Theme",
24
25
  "common:admin__title": "Admin Backend",
25
26
  "common:logout__dialog__title": "Logout",
26
27
  "common:logout__dialog__content": "Are you sure you want to logout?",
27
28
  "common:i18n_key_invalid": "I18n key format is incorrect",
29
+ "common:manifest__name": "Application Name",
28
30
  "common:v:login_params_required": "Not a valid login parameter",
29
31
  "common:v:email_invalid": "Invalid email format validation message",
30
32
  "common:v:password_min_length": "Password minimum length validation message(6)",
31
33
  "common:v:password_max_length": "Password maximum length validation message(50)",
32
34
  "common:v:password_special_chars": "Password cannot contain whitespace characters validation message",
35
+ "page_about:title": "About Us",
36
+ "page_about:description": "Learn about our team and mission",
37
+ "page_about:keywords": "About us, team, mission",
33
38
  "admin_home:title": "Admin page",
34
39
  "admin_home:description": "Admin page",
35
40
  "admin_home:keywords": "Admin page",
@@ -19,17 +19,22 @@
19
19
  "common:create": "创建",
20
20
  "common:detail": "详情",
21
21
  "common:theme__default": "默认主题",
22
+ "common:theme__light": "亮色主题",
22
23
  "common:theme__dark": "暗色主题",
23
24
  "common:theme__pink": "粉色主题",
24
25
  "common:admin__title": "管理后台",
25
26
  "common:logout__dialog__title": "登出",
26
27
  "common:logout__dialog__content": "确定要登出吗?",
27
28
  "common:i18n_key_invalid": "i18n 键格式不正确",
29
+ "common:manifest__name": "应用名称",
28
30
  "common:v:login_params_required": "不是一个有效的登录参数",
29
31
  "common:v:email_invalid": "邮箱格式无效的验证消息",
30
32
  "common:v:password_min_length": "密码最小长度验证消息(6)",
31
33
  "common:v:password_max_length": "密码最大长度验证消息(50)",
32
34
  "common:v:password_special_chars": "密码不能包含空格的验证消息",
35
+ "page_about:title": "关于我们",
36
+ "page_about:description": "了解我们的团队和使命",
37
+ "page_about:keywords": "关于我们, 团队, 使命",
33
38
  "admin_home:title": "管理员页面",
34
39
  "admin_home:description": "管理员页面",
35
40
  "admin_home:keywords": "管理员页面关键词",
@@ -0,0 +1,37 @@
1
+ 'use client';
2
+
3
+ import { NextIntlClientProvider, useMessages } from 'next-intl';
4
+
5
+ /**
6
+ * Client component wrapper to merge admin i18n messages
7
+ * NextIntlClientProvider supports nesting and will merge messages from parent provider
8
+ */
9
+ export function AdminI18nProvider({
10
+ children,
11
+ locale,
12
+ adminMessages
13
+ }: {
14
+ children: React.ReactNode;
15
+ locale: string;
16
+ adminMessages: Record<string, string>;
17
+ }) {
18
+ // Get existing messages from parent NextIntlClientProvider (includes common, api)
19
+ const existingMessages = useMessages();
20
+
21
+ // Merge admin messages with existing messages
22
+ // Admin messages will override any existing keys with the same name
23
+ const mergedMessages = {
24
+ ...existingMessages,
25
+ ...adminMessages
26
+ };
27
+
28
+ return (
29
+ <NextIntlClientProvider
30
+ data-testid="AdminI18nProvider"
31
+ locale={locale}
32
+ messages={mergedMessages}
33
+ >
34
+ {children}
35
+ </NextIntlClientProvider>
36
+ );
37
+ }
@@ -1,18 +1,42 @@
1
- import type { PageLayoutProps } from '@/base/types/PageProps';
2
- import { PageParams } from '@/server/PageParams';
1
+ import type { PageLayoutProps } from '@/base/types/AppPageRouter';
2
+ import { AppPageRouteParams } from '@/server/AppPageRouteParams';
3
3
  import '@/styles/css/index.css';
4
4
  import { AdminLayout } from '@/uikit/components/AdminLayout';
5
+ import { ClinetRenderProvider } from '@/uikit/components/ClinetRenderProvider';
6
+ import { AdminI18nProvider } from './AdminI18nProvider';
5
7
 
6
8
  export default async function AdminRootLayout({
7
9
  children,
8
10
  params
9
11
  }: PageLayoutProps) {
10
- const pageParams = new PageParams(await params!);
12
+ const pageParams = new AppPageRouteParams(await params!);
11
13
  const locale = pageParams.getLocale();
12
14
 
15
+ // Load admin i18n namespaces for admin pages
16
+ // Note: getI18nMessages will merge with default namespaces (common, api)
17
+ // but we only need admin namespaces here since common/api are already in root layout
18
+ const adminNamespaces = ['admin_home', 'admin_locales', 'admin_users'];
19
+ const allMessages = await pageParams.getI18nMessages(adminNamespaces);
20
+
21
+ // Extract only admin messages (excluding common and api which are already in root layout)
22
+ // This avoids duplicate messages and ensures we only add what's needed
23
+ const adminMessages = Object.fromEntries(
24
+ Object.entries(allMessages).filter(([key]) =>
25
+ adminNamespaces.some((ns) => key.startsWith(`${ns}:`))
26
+ )
27
+ );
28
+
13
29
  return (
14
- <AdminLayout data-testid="AdminRootLayout" lang={locale}>
15
- {children}
16
- </AdminLayout>
30
+ <AdminI18nProvider
31
+ data-testid="AdminI18nProvider"
32
+ locale={locale}
33
+ adminMessages={adminMessages}
34
+ >
35
+ <ClinetRenderProvider>
36
+ <AdminLayout data-testid="AdminRootLayout" lang={locale}>
37
+ {children}
38
+ </AdminLayout>
39
+ </ClinetRenderProvider>
40
+ </AdminI18nProvider>
17
41
  );
18
42
  }
@@ -11,8 +11,8 @@ import { Form, Input } from 'antd';
11
11
  import { useCallback, useMemo } from 'react';
12
12
  import { ZodColumnBuilder } from '@/base/cases/ZodColumnBuilder';
13
13
  import type { AdminLocalesApi } from '@/base/services/adminApi/AdminLocalesApi';
14
- import { AdminLocalesService } from '@/base/services/AdminLocalesService';
15
14
  import { AdminPageEvent } from '@/base/services/AdminPageEvent';
15
+ import { AdminLocalesService } from '@/server/services/AdminLocalesService';
16
16
  import { ClientSeo } from '@/uikit/components/ClientSeo';
17
17
  import { EditableCell } from '@/uikit/components/EditableCell';
18
18
  import { LocalesImportButton } from '@/uikit/components/localesImportButton/LocalesImportButton';
@@ -1,25 +1,62 @@
1
1
  import { NextIntlClientProvider } from 'next-intl';
2
- import type { PageLayoutProps } from '@/base/types/PageProps';
3
- import { PageParams } from '@/server/PageParams';
4
- import { ComboProvider } from '@/uikit/components/ComboProvider';
5
- import { themeConfig } from '@config/theme';
2
+ import { setRequestLocale } from 'next-intl/server';
3
+ import type { PageLayoutProps } from '@/base/types/AppPageRouter';
4
+ import { AppPageRouteParams } from '@/server/AppPageRouteParams';
5
+ import { BootstrapsProvider } from '@/uikit/components/BootstrapsProvider';
6
+ import { ClientRootProvider } from '@/uikit/components/ClientRootProvider';
7
+ import { IOCProvider } from '@/uikit/components/IOCProvider';
8
+ import { i18nConfig } from '@config/i18n';
6
9
  import '@/styles/css/index.css';
10
+ import { themeConfig } from '@config/theme';
11
+
12
+ export function generateStaticParams() {
13
+ return i18nConfig.supportedLngs.map((locale) => ({ locale }));
14
+ }
7
15
 
16
+ /**
17
+ * RootLayout is the root layout for the app
18
+ *
19
+ * 注意事项:
20
+ *
21
+ * 1. Layout 组件建议不要使用类似客户端渲染, 比如 useMountedClient 等这样会导致重渲染时dom节点发生变化,
22
+ * 页面闪烁特别是切换语言时
23
+ *
24
+ * 2. Layout 组件内 IOCProvider 置于顶层, 因为整个项目依赖容器化
25
+ * 在 spa 中项目中,也就是前端渲染时是不需要要区分渲染环境(server 和 client)
26
+ *
27
+ * 3. 除了已有的 provider 外, 尽量使用 ClientRootProvider 包裹所有客户端组件
28
+ *
29
+ * @param children - The children components
30
+ * @param params - The page parameters
31
+ * @returns
32
+ */
8
33
  export default async function RootLayout({
9
34
  children,
10
35
  params
11
36
  }: PageLayoutProps) {
12
- const pageParams = new PageParams(await params!);
37
+ const pageParams = new AppPageRouteParams(await params!);
13
38
  const locale = pageParams.getLocale();
39
+ const theme = await pageParams.getTheme();
40
+
41
+ // Enable static rendering
42
+ setRequestLocale(locale);
43
+
44
+ // Get messages for the current locale to prevent flickering during language switch
45
+ // Load default namespaces (common, api) - admin namespaces are loaded in admin layout
14
46
  const messages = await pageParams.getI18nMessages();
15
47
 
16
- // TODO: suppressHydrationWarning 暂时解决 hydration 问题
17
48
  return (
18
- <html data-testid="RootLayout" lang={locale} suppressHydrationWarning>
49
+ <html data-testid="AppRoute-RootLayout" lang={locale} data-theme={theme}>
19
50
  <body>
20
- <NextIntlClientProvider locale={locale} messages={messages}>
21
- <ComboProvider themeConfig={themeConfig}>{children}</ComboProvider>
22
- </NextIntlClientProvider>
51
+ <IOCProvider>
52
+ <NextIntlClientProvider locale={locale} messages={messages}>
53
+ <BootstrapsProvider>
54
+ <ClientRootProvider themeConfig={themeConfig}>
55
+ {children}
56
+ </ClientRootProvider>
57
+ </BootstrapsProvider>
58
+ </NextIntlClientProvider>
59
+ </IOCProvider>
23
60
  </body>
24
61
  </html>
25
62
  );
@@ -28,7 +28,7 @@ export function LoginForm(props: { tt: LoginI18nInterface }) {
28
28
  try {
29
29
  setLoading(true);
30
30
  await userService.login(values);
31
- routerService.gotoHome();
31
+ routerService.replaceHome();
32
32
  } catch (error) {
33
33
  logger.error(error);
34
34
  } finally {
@@ -1,12 +1,16 @@
1
1
  import { notFound } from 'next/navigation';
2
- import type { PageParamsProps } from '@/base/types/PageProps';
2
+ import type { PageParamsProps } from '@/base/types/AppPageRouter';
3
3
  import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
4
  import { redirect } from '@/i18n/routing';
5
- import { PageParams, type PageParamsType } from '@/server/PageParams';
5
+ import {
6
+ AppPageRouteParams,
7
+ type PageParamsType
8
+ } from '@/server/AppPageRouteParams';
6
9
  import { ServerAuth } from '@/server/ServerAuth';
7
- import { BaseLayout } from '@/uikit/components/BaseLayout';
8
10
  import { FeatureItem } from '@/uikit/components/FeatureItem';
9
- import { loginI18n, i18nConfig } from '@config/i18n';
11
+ import { AppRoutePage } from '@/uikit/components-app/AppRoutePage';
12
+ import { loginI18n, i18nConfig, NS_PAGE_LOGIN } from '@config/i18n';
13
+ import { COMMON_ADMIN_TITLE } from '@config/Identifier';
10
14
  import { LoginForm } from './LoginForm';
11
15
  import type { Metadata } from 'next';
12
16
 
@@ -28,7 +32,7 @@ export async function generateMetadata({
28
32
  }: {
29
33
  params: Promise<PageParamsType>;
30
34
  }): Promise<Metadata> {
31
- const pageParams = new PageParams(await params);
35
+ const pageParams = new AppPageRouteParams(await params);
32
36
 
33
37
  return await pageParams.getI18nInterface(loginI18n);
34
38
  }
@@ -39,7 +43,7 @@ export default async function LoginPage(props: PageParamsProps) {
39
43
  }
40
44
 
41
45
  const params = await props.params;
42
- const pageParams = new PageParams(params);
46
+ const pageParams = new AppPageRouteParams(params);
43
47
 
44
48
  const server = new BootstrapServer();
45
49
 
@@ -47,11 +51,19 @@ export default async function LoginPage(props: PageParamsProps) {
47
51
  return redirect({ href: '/', locale: params.locale! });
48
52
  }
49
53
 
50
- const tt = await pageParams.getI18nInterface(loginI18n);
54
+ const tt = await pageParams.getI18nInterface(
55
+ { ...loginI18n, adminTitle: COMMON_ADMIN_TITLE },
56
+ NS_PAGE_LOGIN
57
+ );
51
58
 
52
59
  return (
53
- <BaseLayout
54
- data-testid="LoginPage"
60
+ <AppRoutePage
61
+ data-testid="AppRoute-LoginPage"
62
+ tt={{
63
+ title: tt.title,
64
+ adminTitle: tt.adminTitle
65
+ }}
66
+ headerHref="/login"
55
67
  mainProps={{
56
68
  className: 'text-xs1 bg-primary flex min-h-screen'
57
69
  }}
@@ -74,6 +86,6 @@ export default async function LoginPage(props: PageParamsProps) {
74
86
  <LoginForm tt={tt} />
75
87
  </div>
76
88
  </div>
77
- </BaseLayout>
89
+ </AppRoutePage>
78
90
  );
79
91
  }
@@ -1,11 +1,15 @@
1
1
  import { Button } from 'antd';
2
- import type { PageParamsProps } from '@/base/types/PageProps';
2
+ import type { PageParamsProps } from '@/base/types/AppPageRouter';
3
3
  import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
4
  import { redirect } from '@/i18n/routing';
5
- import { PageParams, type PageParamsType } from '@/server/PageParams';
5
+ import {
6
+ AppPageRouteParams,
7
+ type PageParamsType
8
+ } from '@/server/AppPageRouteParams';
6
9
  import { ServerAuth } from '@/server/ServerAuth';
7
- import { BaseLayout } from '@/uikit/components/BaseLayout';
10
+ import { AppRoutePage } from '@/uikit/components-app/AppRoutePage';
8
11
  import { i18nConfig, homeI18n } from '@config/i18n';
12
+ import { COMMON_ADMIN_TITLE } from '@config/Identifier';
9
13
  import type { Metadata } from 'next';
10
14
 
11
15
  // const navigationItems = [
@@ -34,22 +38,33 @@ export async function generateMetadata({
34
38
  }: {
35
39
  params: Promise<PageParamsType>;
36
40
  }): Promise<Metadata> {
37
- const pageParams = new PageParams(await params);
41
+ const pageParams = new AppPageRouteParams(await params);
38
42
  return await pageParams.getI18nInterface(homeI18n);
39
43
  }
40
44
 
41
45
  export default async function Home({ params }: PageParamsProps) {
42
46
  const server = new BootstrapServer();
43
- const pageParams = new PageParams(await params!);
47
+ const pageParams = new AppPageRouteParams(await params!);
44
48
  const locale = pageParams.getLocale();
45
- const tt = await pageParams.getI18nInterface(homeI18n);
49
+ const tt = await pageParams.getI18nInterface({
50
+ ...homeI18n,
51
+ adminTitle: COMMON_ADMIN_TITLE
52
+ });
46
53
 
47
54
  if (!(await server.getIOC(ServerAuth).hasAuth())) {
48
55
  return redirect({ href: '/login', locale });
49
56
  }
50
57
 
51
58
  return (
52
- <BaseLayout data-testid="HomePage" showLogoutButton showAdminButton>
59
+ <AppRoutePage
60
+ data-testid="AppRoute-HomePage"
61
+ showLogoutButton
62
+ showAdminButton
63
+ tt={{
64
+ title: tt.title,
65
+ adminTitle: tt.adminTitle
66
+ }}
67
+ >
53
68
  {/* Hero Section */}
54
69
  <section className="py-16 px-4">
55
70
  <div className="max-w-4xl mx-auto text-center">
@@ -105,6 +120,6 @@ export default async function Home({ params }: PageParamsProps) {
105
120
  </Button>
106
121
  </div>
107
122
  </section>
108
- </BaseLayout>
123
+ </AppRoutePage>
109
124
  );
110
125
  }
@@ -1,12 +1,16 @@
1
1
  import { notFound } from 'next/navigation';
2
- import type { PageParamsProps } from '@/base/types/PageProps';
2
+ import type { PageParamsProps } from '@/base/types/AppPageRouter';
3
3
  import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
4
  import { redirect } from '@/i18n/routing';
5
- import { PageParams, type PageParamsType } from '@/server/PageParams';
5
+ import {
6
+ AppPageRouteParams,
7
+ type PageParamsType
8
+ } from '@/server/AppPageRouteParams';
6
9
  import { ServerAuth } from '@/server/ServerAuth';
7
- import { BaseLayout } from '@/uikit/components/BaseLayout';
8
10
  import { FeatureItem } from '@/uikit/components/FeatureItem';
11
+ import { AppRoutePage } from '@/uikit/components-app/AppRoutePage';
9
12
  import { i18nConfig, register18n } from '@config/i18n';
13
+ import { COMMON_ADMIN_TITLE } from '@config/Identifier';
10
14
  import { RegisterForm } from './RegisterForm';
11
15
  import type { Metadata } from 'next';
12
16
 
@@ -28,7 +32,7 @@ export async function generateMetadata({
28
32
  }: {
29
33
  params: Promise<PageParamsType>;
30
34
  }): Promise<Metadata> {
31
- const pageParams = new PageParams(await params);
35
+ const pageParams = new AppPageRouteParams(await params);
32
36
 
33
37
  return await pageParams.getI18nInterface(register18n);
34
38
  }
@@ -39,7 +43,7 @@ export default async function LoginPage(props: PageParamsProps) {
39
43
  }
40
44
 
41
45
  const params = await props.params;
42
- const pageParams = new PageParams(params);
46
+ const pageParams = new AppPageRouteParams(params);
43
47
 
44
48
  const server = new BootstrapServer();
45
49
 
@@ -47,11 +51,19 @@ export default async function LoginPage(props: PageParamsProps) {
47
51
  return redirect({ href: '/', locale: params.locale! });
48
52
  }
49
53
 
50
- const tt = await pageParams.getI18nInterface(register18n);
54
+ const tt = await pageParams.getI18nInterface({
55
+ ...register18n,
56
+ adminTitle: COMMON_ADMIN_TITLE
57
+ });
51
58
 
52
59
  return (
53
- <BaseLayout
54
- data-testid="RegisterPage"
60
+ <AppRoutePage
61
+ data-testid="AppRoute-RegisterPage"
62
+ tt={{
63
+ title: tt.title,
64
+ adminTitle: tt.adminTitle
65
+ }}
66
+ headerHref="/login"
55
67
  mainProps={{
56
68
  className: 'text-xs1 bg-primary flex min-h-screen'
57
69
  }}
@@ -74,6 +86,6 @@ export default async function LoginPage(props: PageParamsProps) {
74
86
  <RegisterForm tt={tt} />
75
87
  </div>
76
88
  </div>
77
- </BaseLayout>
89
+ </AppRoutePage>
78
90
  );
79
91
  }