@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.
- package/CHANGELOG.md +178 -0
- package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
- package/dist/configs/_common/.github/workflows/release.yml +2 -2
- package/dist/index.cjs +4 -4
- package/dist/index.js +4 -4
- package/dist/templates/next-app/config/IOCIdentifier.ts +2 -2
- package/dist/templates/next-app/config/Identifier/common/common.ts +14 -0
- package/dist/templates/next-app/config/Identifier/pages/index.ts +1 -0
- package/dist/templates/next-app/config/Identifier/pages/page.about.ts +20 -0
- package/dist/templates/next-app/config/common.ts +1 -1
- package/dist/templates/next-app/config/cookies.ts +23 -0
- package/dist/templates/next-app/config/i18n/AboutI18n.ts +14 -0
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +3 -1
- package/dist/templates/next-app/config/i18n/index.ts +1 -0
- package/dist/templates/next-app/config/i18n/loginI18n.ts +8 -0
- package/dist/templates/next-app/config/theme.ts +4 -0
- package/dist/templates/next-app/eslint.config.mjs +9 -2
- package/dist/templates/next-app/next.config.ts +1 -0
- package/dist/templates/next-app/package.json +17 -6
- package/dist/templates/next-app/public/locales/en.json +5 -0
- package/dist/templates/next-app/public/locales/zh.json +5 -0
- package/dist/templates/next-app/src/app/[locale]/admin/AdminI18nProvider.tsx +37 -0
- package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +30 -6
- package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +47 -10
- package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/login/page.tsx +22 -10
- package/dist/templates/next-app/src/app/[locale]/page.tsx +23 -8
- package/dist/templates/next-app/src/app/[locale]/register/page.tsx +21 -9
- package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +7 -28
- package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +7 -34
- package/dist/templates/next-app/src/app/api/admin/locales/route.ts +12 -34
- package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +7 -26
- package/dist/templates/next-app/src/app/api/admin/users/route.ts +14 -33
- package/dist/templates/next-app/src/app/api/locales/json/route.ts +13 -25
- package/dist/templates/next-app/src/app/api/user/login/route.ts +6 -46
- package/dist/templates/next-app/src/app/api/user/logout/route.ts +5 -24
- package/dist/templates/next-app/src/app/api/user/register/route.ts +6 -45
- package/dist/templates/next-app/src/app/manifest.ts +16 -0
- package/dist/templates/next-app/src/app/robots.txt +2 -0
- package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +3 -3
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +14 -13
- package/dist/templates/next-app/src/base/cases/Datetime.ts +3 -3
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +8 -2
- package/dist/templates/next-app/src/base/cases/DialogHandler.ts +30 -4
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +16 -4
- package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +20 -4
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +8 -2
- package/dist/templates/next-app/src/base/cases/ResourceState.ts +3 -3
- package/dist/templates/next-app/src/base/cases/RouterService.ts +28 -10
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +14 -2
- package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +1 -1
- package/dist/templates/next-app/src/base/cases/UserServiceApi.ts +20 -5
- package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +31 -8
- package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +4 -1
- package/dist/templates/next-app/src/base/port/AppApiInterface.ts +22 -0
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +27 -7
- package/dist/templates/next-app/src/base/port/IOCInterface.ts +9 -0
- package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +1 -1
- package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +3 -3
- package/dist/templates/next-app/src/base/services/I18nService.ts +20 -10
- package/dist/templates/next-app/src/base/services/ResourceService.ts +32 -11
- package/dist/templates/next-app/src/base/services/UserService.ts +12 -3
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +9 -6
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +20 -5
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +21 -4
- package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +12 -3
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +10 -2
- package/dist/templates/next-app/src/base/types/{PageProps.ts → AppPageRouter.ts} +4 -1
- package/dist/templates/next-app/src/base/types/PagesRouter.ts +9 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +20 -6
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +27 -9
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +6 -4
- package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +39 -9
- package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +9 -2
- package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +37 -10
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +9 -2
- package/dist/templates/next-app/src/i18n/loadMessages.ts +103 -0
- package/dist/templates/next-app/src/i18n/request.ts +3 -22
- package/dist/templates/next-app/src/pages/[locale]/about.tsx +61 -0
- package/dist/templates/next-app/src/pages/_app.tsx +50 -0
- package/dist/templates/next-app/src/pages/_document.tsx +13 -0
- package/dist/templates/next-app/src/{middleware.ts → proxy.ts} +2 -1
- package/dist/templates/next-app/src/server/AppErrorApi.ts +1 -1
- package/dist/templates/next-app/src/server/AppPageRouteParams.ts +107 -0
- package/dist/templates/next-app/src/server/AppSuccessApi.ts +1 -1
- package/dist/templates/next-app/src/server/NextApiServer.ts +62 -0
- package/dist/templates/next-app/src/server/PagesRouteParams.ts +146 -0
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +8 -2
- package/dist/templates/next-app/src/server/ServerAuth.ts +20 -5
- package/dist/templates/next-app/src/server/{sqlBridges/SupabaseBridge.ts → SupabaseBridge.ts} +50 -8
- package/dist/templates/next-app/src/server/UserCredentialToken.ts +8 -2
- package/dist/templates/next-app/src/server/controllers/AdminLocalesController.ts +86 -0
- package/dist/templates/next-app/src/server/controllers/AdminUserController.ts +42 -0
- package/dist/templates/next-app/src/server/controllers/LocalesController.ts +36 -0
- package/dist/templates/next-app/src/server/controllers/UserController.ts +86 -0
- package/dist/templates/next-app/src/server/port/AIControllerInterface.ts +8 -0
- package/dist/templates/next-app/src/server/port/AdminLocalesControllerInterface.ts +21 -0
- package/dist/templates/next-app/src/server/port/AdminUserControllerInterface.ts +11 -0
- package/dist/templates/next-app/src/server/port/LocalesControllerInterface.ts +10 -0
- package/dist/templates/next-app/src/server/port/{ParamsHandlerInterface.ts → RouteParamsnHandlerInterface.ts} +9 -2
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
- package/dist/templates/next-app/src/server/port/UserControllerInerface.ts +8 -0
- package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +1 -1
- package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +2 -2
- package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +31 -9
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +15 -6
- package/dist/templates/next-app/src/server/services/AIService.ts +3 -1
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +5 -2
- package/dist/templates/next-app/src/{base → server}/services/AdminLocalesService.ts +2 -2
- package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +29 -14
- package/dist/templates/next-app/src/server/services/ApiUserService.ts +6 -3
- package/dist/templates/next-app/src/server/services/UserService.ts +12 -3
- package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +24 -7
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +17 -5
- package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +17 -11
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/_default.css +0 -44
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/dark.css +0 -44
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/pink.css +0 -44
- package/dist/templates/next-app/src/styles/css/index.css +1 -1
- package/dist/templates/next-app/src/styles/css/scrollbar.css +34 -0
- package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +34 -11
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +69 -39
- package/dist/templates/next-app/src/uikit/components/ClientRootProvider.tsx +64 -0
- package/dist/templates/next-app/src/uikit/components/ClinetRenderProvider.tsx +42 -0
- package/dist/templates/next-app/src/uikit/components/IOCProvider.tsx +34 -0
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +7 -1
- package/dist/templates/next-app/src/uikit/components-app/AppBridge.tsx +17 -0
- package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +112 -0
- package/dist/templates/next-app/src/uikit/{components → components-app}/LanguageSwitcher.tsx +15 -19
- package/dist/templates/next-app/src/uikit/{components → components-app}/ThemeSwitcher.tsx +53 -52
- package/dist/templates/next-app/src/uikit/components-pages/LanguageSwitcher.tsx +98 -0
- package/dist/templates/next-app/src/uikit/components-pages/PagesRoutePage.tsx +93 -0
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +16 -4
- package/dist/templates/next-app/src/uikit/hook/useStrictEffect.ts +32 -0
- package/dist/templates/next-app/tsconfig.json +3 -2
- package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +3 -1
- package/dist/templates/react-app/__tests__/__mocks__/MockAppConfig.ts +19 -19
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +8 -8
- package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +9 -9
- package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +1 -1
- package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +5 -5
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +9 -5
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +8 -4
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +4 -4
- package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +5 -5
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +3 -3
- package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +1 -1
- package/dist/templates/react-app/docs/en/components/chat-message-component.md +35 -29
- package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +18 -5
- package/dist/templates/react-app/docs/en/components/message-base-list-component.md +11 -12
- package/dist/templates/react-app/docs/en/request.md +1 -3
- package/dist/templates/react-app/docs/zh/components/chat-message-component.md +35 -29
- package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +18 -5
- package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +11 -12
- package/dist/templates/react-app/docs/zh/request.md +1 -3
- package/dist/templates/react-app/eslint.config.mjs +10 -5
- package/dist/templates/react-app/src/App.tsx +1 -1
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +2 -2
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +14 -11
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -16
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +12 -10
- package/dist/templates/react-app/src/base/cases/AppConfig.ts +19 -19
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +28 -5
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +5 -2
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +16 -4
- package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +1 -1
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +6 -3
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +17 -8
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +4 -6
- package/dist/templates/react-app/src/base/cases/ResourceState.ts +3 -3
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +3 -3
- package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +1 -1
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +2 -2
- package/dist/templates/react-app/src/base/port/IOCInterface.ts +4 -2
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +5 -5
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +7 -7
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +8 -8
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +4 -2
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +3 -3
- package/dist/templates/react-app/src/base/services/I18nService.ts +24 -13
- package/dist/templates/react-app/src/base/services/IdentifierService.ts +21 -26
- package/dist/templates/react-app/src/base/services/RouteService.ts +8 -8
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +2 -2
- package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +9 -5
- package/dist/templates/react-app/src/base/services/UserService.ts +10 -4
- package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +3 -1
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +5 -2
- package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +11 -4
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +5 -4
- package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/_default.css +0 -44
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/dark.css +0 -44
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/pink.css +0 -44
- package/dist/templates/react-app/src/styles/css/index.css +1 -1
- package/dist/templates/react-app/src/styles/css/scrollbar.css +34 -0
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +2 -2
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +4 -4
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +8 -2
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +6 -6
- package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +1 -1
- package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +1 -3
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +4 -1
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +39 -16
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +4 -2
- package/package.json +3 -3
- package/dist/templates/next-app/src/server/PageParams.ts +0 -66
- package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +0 -80
- package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +0 -65
- package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +0 -58
- package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +0 -21
- package/dist/templates/react-app/makes/eslint-utils.mjs +0 -195
- /package/dist/templates/next-app/{src/app/[locale] → public}/favicon.ico +0 -0
- /package/dist/templates/next-app/src/uikit/{components → components-app}/LogoutButton.tsx +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
html,
|
|
2
|
+
.fe-theme {
|
|
3
|
+
--scrollbar-track-color: var(--color-secondary);
|
|
4
|
+
--scrollbar-thumb-color: var(--color-text-secondary);
|
|
5
|
+
--scrollbar-thumb-hover-color: var(--color-brand-hover);
|
|
6
|
+
|
|
7
|
+
/* Webkit browsers (Chrome, Safari, Edge) - 全局样式,使用最高优先级 */
|
|
8
|
+
body *::-webkit-scrollbar,
|
|
9
|
+
*::-webkit-scrollbar {
|
|
10
|
+
width: 10px;
|
|
11
|
+
height: 10px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body *::-webkit-scrollbar-track,
|
|
15
|
+
*::-webkit-scrollbar-track {
|
|
16
|
+
background: var(--scrollbar-track-color);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
body *::-webkit-scrollbar-thumb,
|
|
20
|
+
*::-webkit-scrollbar-thumb {
|
|
21
|
+
background-color: var(--scrollbar-thumb-color);
|
|
22
|
+
border-radius: 6px;
|
|
23
|
+
border: 1px solid var(--scrollbar-track-color);
|
|
24
|
+
transition: background-color 0.2s ease;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body *::-webkit-scrollbar-thumb:hover {
|
|
28
|
+
background-color: var(--scrollbar-thumb-hover-color) !important;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
32
|
+
background-color: var(--scrollbar-thumb-hover-color) !important;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -13,12 +13,13 @@ import { clsx } from 'clsx';
|
|
|
13
13
|
import { usePathname } from 'next/navigation';
|
|
14
14
|
import React, { useMemo, type HTMLAttributes } from 'react';
|
|
15
15
|
import { AdminPageManager } from '@/base/cases/AdminPageManager';
|
|
16
|
-
import {
|
|
17
|
-
import { LanguageSwitcher } from './LanguageSwitcher';
|
|
16
|
+
import { COMMON_ADMIN_TITLE } from '@config/Identifier';
|
|
18
17
|
import { LocaleLink } from './LocaleLink';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
18
|
+
import { LanguageSwitcher } from '../components-app/LanguageSwitcher';
|
|
19
|
+
import { LogoutButton } from '../components-app/LogoutButton';
|
|
20
|
+
import { ThemeSwitcher } from '../components-app/ThemeSwitcher';
|
|
21
21
|
import { useIOC } from '../hook/useIOC';
|
|
22
|
+
import { useWarnTranslations } from '../hook/useWarnTranslations';
|
|
22
23
|
import type { ItemType } from 'antd/es/menu/interface';
|
|
23
24
|
|
|
24
25
|
const { Sider } = Layout;
|
|
@@ -41,10 +42,13 @@ export function AdminLayout(props: AdminLayoutProps) {
|
|
|
41
42
|
const page = useIOC(AdminPageManager);
|
|
42
43
|
const collapsedSidebar = useStore(page, page.selectors.collapsedSidebar);
|
|
43
44
|
const navItems = useStore(page, page.selectors.navItems);
|
|
45
|
+
const t = useWarnTranslations();
|
|
46
|
+
|
|
47
|
+
const title = useMemo(() => t(COMMON_ADMIN_TITLE), [t]);
|
|
44
48
|
|
|
45
49
|
const selectedKey = useMemo(() => {
|
|
46
50
|
// 移除语言前缀,例如 /en/admin/users -> /admin/users
|
|
47
|
-
const normalizedPath = pathname
|
|
51
|
+
const normalizedPath = pathname?.replace(/^\/[^/]+/, '') ?? '';
|
|
48
52
|
return navItems.find((item) => item.pathname === normalizedPath)?.key || '';
|
|
49
53
|
}, [pathname, navItems]);
|
|
50
54
|
|
|
@@ -81,7 +85,7 @@ export function AdminLayout(props: AdminLayoutProps) {
|
|
|
81
85
|
|
|
82
86
|
return (
|
|
83
87
|
<Layout data-testid="AdminLayout" className={className} {...rest}>
|
|
84
|
-
<div className="overflow-y-auto overflow-x-hidden h-screen sticky top-0 bottom-0
|
|
88
|
+
<div className="overflow-y-auto overflow-x-hidden h-screen sticky top-0 bottom-0">
|
|
85
89
|
<Sider
|
|
86
90
|
className="h-full relative"
|
|
87
91
|
onCollapse={() => page.toggleSidebar()}
|
|
@@ -111,11 +115,30 @@ export function AdminLayout(props: AdminLayoutProps) {
|
|
|
111
115
|
</div>
|
|
112
116
|
|
|
113
117
|
<Layout>
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
className="
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
<header
|
|
119
|
+
data-testid="AdminLayoutHeader"
|
|
120
|
+
className="h-14 bg-secondary border-b border-c-border sticky top-0 z-50"
|
|
121
|
+
>
|
|
122
|
+
<div
|
|
123
|
+
className={clsx(
|
|
124
|
+
'flex items-center justify-between h-full px-4 mx-auto max-w-7xl',
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
>
|
|
128
|
+
<div className="flex items-center">
|
|
129
|
+
<LocaleLink
|
|
130
|
+
href="/admin"
|
|
131
|
+
title={title}
|
|
132
|
+
className="flex items-center hover:opacity-80 transition-opacity"
|
|
133
|
+
>
|
|
134
|
+
<span className="text-lg font-semibold text-text">{title}</span>
|
|
135
|
+
</LocaleLink>
|
|
136
|
+
</div>
|
|
137
|
+
<div className="flex items-center gap-2 md:gap-4">
|
|
138
|
+
{rightActions}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</header>
|
|
119
142
|
<main
|
|
120
143
|
className={clsx('p-2 bg-primary text-text flex-1', mainClassName)}
|
|
121
144
|
>
|
|
@@ -1,45 +1,75 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import '@ant-design/v5-patch-for-react-19';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { useEffect } from 'react';
|
|
6
|
-
import { NavigateBridge } from '@/base/cases/NavigateBridge';
|
|
7
|
-
import type { I18nServiceLocale } from '@/base/port/I18nServiceInterface';
|
|
3
|
+
|
|
4
|
+
import { useState } from 'react';
|
|
8
5
|
import { BootstrapClient } from '@/core/bootstraps/BootstrapClient';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { IOCContext } from '../context/IOCContext';
|
|
12
|
-
import { useWarnTranslations } from '../hook/useWarnTranslations';
|
|
6
|
+
import { useIOC } from '../hook/useIOC';
|
|
7
|
+
import { useStrictEffect } from '../hook/useStrictEffect';
|
|
13
8
|
|
|
14
9
|
export function BootstrapsProvider(props: { children: React.ReactNode }) {
|
|
15
|
-
const IOC =
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
10
|
+
const IOC = useIOC();
|
|
11
|
+
|
|
12
|
+
const [, setIocMounted] = useState(false);
|
|
13
|
+
|
|
14
|
+
useStrictEffect(() => {
|
|
15
|
+
// clientIOC.register({
|
|
16
|
+
// appConfig: appConfig
|
|
17
|
+
// });
|
|
18
|
+
BootstrapClient.main({
|
|
19
|
+
root: window,
|
|
20
|
+
pathname: window.location.pathname,
|
|
21
|
+
IOC: IOC
|
|
22
|
+
}).then(() => {
|
|
23
|
+
setIocMounted(true);
|
|
24
|
+
});
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
// useEffect(() => {
|
|
28
|
+
// const register = new ClientIOCRegister({
|
|
29
|
+
// appConfig: appConfig
|
|
30
|
+
// });
|
|
31
|
+
|
|
32
|
+
// // 启动前注册所有依赖
|
|
33
|
+
// // clientIOC.register(register);
|
|
34
|
+
|
|
35
|
+
// BootstrapClient.main({
|
|
36
|
+
// root: window,
|
|
37
|
+
// pathname: window.location.pathname,
|
|
38
|
+
// IOC: IOC,
|
|
39
|
+
// register: register
|
|
40
|
+
// }).then(() => {
|
|
41
|
+
// setIocMounted(true);
|
|
42
|
+
// });
|
|
43
|
+
// }, []);
|
|
44
|
+
|
|
45
|
+
// if (!register) {
|
|
46
|
+
// return <div data-testid="BootstrapsProviderLoading">Loading...</div>;
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// const IOC = clientIOC.create();
|
|
50
|
+
// const locale = useLocale();
|
|
51
|
+
// const router = useRouter();
|
|
52
|
+
// const t = useWarnTranslations();
|
|
53
|
+
|
|
54
|
+
// useEffect(() => {
|
|
55
|
+
// IOC(I.RouterServiceInterface).setLocale(locale);
|
|
56
|
+
// IOC(NavigateBridge).setUIBridge(router);
|
|
57
|
+
// }, [locale, router, IOC]);
|
|
58
|
+
|
|
59
|
+
// useEffect(() => {
|
|
60
|
+
// IOC(I.I18nServiceInterface).changeLanguage(locale as I18nServiceLocale);
|
|
61
|
+
// IOC(I.I18nServiceInterface).setTranslator(t);
|
|
62
|
+
// }, [t, IOC, locale]);
|
|
63
|
+
|
|
64
|
+
// useEffect(() => {
|
|
65
|
+
// if (typeof window !== 'undefined') {
|
|
66
|
+
// BootstrapClient.main({
|
|
67
|
+
// root: window,
|
|
68
|
+
// pathname: window.location.pathname,
|
|
69
|
+
// IOC: IOC
|
|
70
|
+
// });
|
|
71
|
+
// }
|
|
72
|
+
// }, [IOC]);
|
|
73
|
+
|
|
74
|
+
return props.children;
|
|
45
75
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import '@ant-design/v5-patch-for-react-19';
|
|
3
|
+
import { AntdRegistry } from '@ant-design/nextjs-registry';
|
|
4
|
+
import { AntdThemeProvider } from '@brain-toolkit/antd-theme-override/react';
|
|
5
|
+
import { ThemeProvider } from 'next-themes';
|
|
6
|
+
import { I } from '@config/IOCIdentifier';
|
|
7
|
+
import type { CommonThemeConfig } from '@config/theme';
|
|
8
|
+
import { useIOC } from '../hook/useIOC';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ClientRootProvider is a provider for the client components
|
|
12
|
+
*
|
|
13
|
+
* - ThemeProvider
|
|
14
|
+
* - AntdProvider
|
|
15
|
+
*
|
|
16
|
+
* TODO: 存在问题:
|
|
17
|
+
*
|
|
18
|
+
* 1. antd 样式存在闪烁问题, 目前没有解决, 可能是因为 cssinjs 的技术性问题
|
|
19
|
+
*
|
|
20
|
+
* 目前能将完美解决的就是完全使用客户端渲染,也就是引入 useMountedClient 当客户端渲染时才渲染, 这样就不会出现闪烁问题
|
|
21
|
+
* 但是他会导致国际化切换闪烁问题
|
|
22
|
+
*
|
|
23
|
+
* 可能需要等待 antd 官方解决这个问题
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const mounted = useMountedClient();
|
|
29
|
+
*
|
|
30
|
+
* return mounted && children;
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
*
|
|
34
|
+
* @param themeConfig - The theme config
|
|
35
|
+
* @param children - The children components
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
export function ClientRootProvider(props: {
|
|
39
|
+
themeConfig: CommonThemeConfig;
|
|
40
|
+
children: React.ReactNode;
|
|
41
|
+
}) {
|
|
42
|
+
const { themeConfig, children } = props;
|
|
43
|
+
|
|
44
|
+
const IOC = useIOC();
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<AntdThemeProvider
|
|
48
|
+
data-testid="ComboProvider"
|
|
49
|
+
theme={themeConfig.antdTheme}
|
|
50
|
+
staticApi={IOC(I.DialogHandler)}
|
|
51
|
+
>
|
|
52
|
+
<ThemeProvider
|
|
53
|
+
themes={themeConfig.supportedThemes as unknown as string[]}
|
|
54
|
+
attribute={themeConfig.domAttribute}
|
|
55
|
+
defaultTheme={themeConfig.defaultTheme}
|
|
56
|
+
enableSystem={themeConfig.enableSystem}
|
|
57
|
+
enableColorScheme={false}
|
|
58
|
+
storageKey={themeConfig.storageKey}
|
|
59
|
+
>
|
|
60
|
+
<AntdRegistry>{children}</AntdRegistry>
|
|
61
|
+
</ThemeProvider>
|
|
62
|
+
</AntdThemeProvider>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMountedClient } from '@brain-toolkit/react-kit';
|
|
4
|
+
|
|
5
|
+
export interface ClinetRenderProviderProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* ClinetRenderProvider is a provider for the client components
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
* 当前组件仅用于需要客户端渲染的组件, 比如 adminLayout 等完全客户端渲染的组件
|
|
14
|
+
*
|
|
15
|
+
*
|
|
16
|
+
* @param children - The children components
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
export function ClinetRenderProvider(props: ClinetRenderProviderProps) {
|
|
20
|
+
const { children } = props;
|
|
21
|
+
|
|
22
|
+
const mounted = useMountedClient();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
{children}
|
|
27
|
+
|
|
28
|
+
{/* 为了防止语言切换时页面闪烁, 使用一个固定定位的div, 当客户端渲染时才渲染 */}
|
|
29
|
+
{!mounted && (
|
|
30
|
+
<div
|
|
31
|
+
role="status"
|
|
32
|
+
aria-label="Loading..."
|
|
33
|
+
aria-busy="true"
|
|
34
|
+
style={{
|
|
35
|
+
zIndex: '99999 !important'
|
|
36
|
+
}}
|
|
37
|
+
className="fixed inset-0 overflow-hidden cursor-wait no-scrollbar bg-primary pointer-events-none"
|
|
38
|
+
></div>
|
|
39
|
+
)}
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { appConfig } from '@/core/globals';
|
|
5
|
+
import { clientIOC, IOCContext, IOCInstance } from '../context/IOCContext';
|
|
6
|
+
|
|
7
|
+
export function IOCProvider(props: { children: React.ReactNode }) {
|
|
8
|
+
/**
|
|
9
|
+
* 加载组件就立即注册
|
|
10
|
+
*
|
|
11
|
+
* 这样在渲染子组件时保证 IOC.get 正常工作
|
|
12
|
+
*
|
|
13
|
+
* 但是这样会导致注册时无法传递浏览器端的依赖, 比如 window.location.pathname
|
|
14
|
+
*
|
|
15
|
+
* - 如果有需要,可以将注册放在下面 useStrictEffect 中, 然后 IocMounted=true 时在渲染子节点
|
|
16
|
+
*
|
|
17
|
+
* **但是这样会有一个问题, 组件会重新挂载渲染,当切换语言时会闪烁**
|
|
18
|
+
*
|
|
19
|
+
* 因为页面初始化时有些组件可能已经使用了容器注入,这样就会丢失注册的依赖
|
|
20
|
+
*
|
|
21
|
+
* TODO: 这是一个需要解决的问题
|
|
22
|
+
*/
|
|
23
|
+
useMemo(() => {
|
|
24
|
+
clientIOC.register({
|
|
25
|
+
appConfig: appConfig
|
|
26
|
+
});
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<IOCContext.Provider value={IOCInstance}>
|
|
31
|
+
{props.children}
|
|
32
|
+
</IOCContext.Provider>
|
|
33
|
+
);
|
|
34
|
+
}
|
package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts
CHANGED
|
@@ -10,13 +10,19 @@ export class LocalesImportEvent extends StoreInterface<LocalesImportEventState>
|
|
|
10
10
|
super(() => new LocalesImportEventState());
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @override
|
|
15
|
+
*/
|
|
13
16
|
protected validate(file: File): void {
|
|
14
17
|
if (file.type !== 'application/json') {
|
|
15
18
|
throw new Error('File must be a JSON file');
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
public async onImport(type: LocaleType, file: File): Promise<void> {
|
|
20
26
|
try {
|
|
21
27
|
this.validate(file);
|
|
22
28
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { NavigateBridge } from '@/base/cases/NavigateBridge';
|
|
5
|
+
import { useRouter } from '@/i18n/routing';
|
|
6
|
+
import { useIOC } from '../hook/useIOC';
|
|
7
|
+
|
|
8
|
+
export function AppBridge() {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const navigateBridge = useIOC(NavigateBridge);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
navigateBridge.setUIBridge(router);
|
|
14
|
+
}, [router, navigateBridge]);
|
|
15
|
+
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { TeamOutlined } from '@ant-design/icons';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { useLocale } from 'next-intl';
|
|
4
|
+
import { useMemo, type HTMLAttributes } from 'react';
|
|
5
|
+
import { AppBridge } from './AppBridge';
|
|
6
|
+
import { LanguageSwitcher } from './LanguageSwitcher';
|
|
7
|
+
import { LogoutButton } from './LogoutButton';
|
|
8
|
+
import { ThemeSwitcher } from './ThemeSwitcher';
|
|
9
|
+
import { LocaleLink } from '../components/LocaleLink';
|
|
10
|
+
|
|
11
|
+
export interface AppRoutePageTT {
|
|
12
|
+
title: string;
|
|
13
|
+
adminTitle: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AppRoutePageProps extends HTMLAttributes<HTMLDivElement> {
|
|
17
|
+
showLogoutButton?: boolean;
|
|
18
|
+
showAdminButton?: boolean;
|
|
19
|
+
mainProps?: HTMLAttributes<HTMLElement>;
|
|
20
|
+
headerClassName?: string;
|
|
21
|
+
headerHref?: string;
|
|
22
|
+
tt: AppRoutePageTT;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* App Route Page
|
|
27
|
+
*
|
|
28
|
+
* 主要用于 /src/app 目录下页面的基础布局,包含头部、主体内容等
|
|
29
|
+
*
|
|
30
|
+
* @description
|
|
31
|
+
* - /src/app/[locale]/page.tsx
|
|
32
|
+
* - /src/app/[locale]/login/page.tsx
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
export function AppRoutePage({
|
|
36
|
+
children,
|
|
37
|
+
showLogoutButton,
|
|
38
|
+
showAdminButton,
|
|
39
|
+
mainProps,
|
|
40
|
+
headerClassName,
|
|
41
|
+
tt,
|
|
42
|
+
headerHref = '/',
|
|
43
|
+
...props
|
|
44
|
+
}: AppRoutePageProps) {
|
|
45
|
+
const locale = useLocale();
|
|
46
|
+
const adminTitle = tt.adminTitle;
|
|
47
|
+
|
|
48
|
+
const actions = useMemo(() => {
|
|
49
|
+
return [
|
|
50
|
+
showAdminButton && (
|
|
51
|
+
<LocaleLink
|
|
52
|
+
key="admin-button"
|
|
53
|
+
href="/admin"
|
|
54
|
+
title={adminTitle}
|
|
55
|
+
locale={locale}
|
|
56
|
+
className="text-text hover:text-text-hover cursor-pointer text-lg transition-colors"
|
|
57
|
+
>
|
|
58
|
+
<TeamOutlined className="text-lg text-text" />
|
|
59
|
+
</LocaleLink>
|
|
60
|
+
),
|
|
61
|
+
|
|
62
|
+
<LanguageSwitcher key="language-switcher" />,
|
|
63
|
+
|
|
64
|
+
<ThemeSwitcher key="theme-switcher" />,
|
|
65
|
+
|
|
66
|
+
showLogoutButton && <LogoutButton key="logout-button" />
|
|
67
|
+
].filter(Boolean);
|
|
68
|
+
}, [adminTitle, showAdminButton, showLogoutButton, locale]);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
data-testid="AppRoutePage"
|
|
73
|
+
className="flex flex-col min-h-screen"
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
<AppBridge />
|
|
77
|
+
<header
|
|
78
|
+
data-testid="BaseHeader"
|
|
79
|
+
className="h-14 bg-secondary border-b border-c-border sticky top-0 z-50"
|
|
80
|
+
>
|
|
81
|
+
<div
|
|
82
|
+
className={clsx(
|
|
83
|
+
'flex items-center justify-between h-full px-4 mx-auto max-w-7xl',
|
|
84
|
+
headerClassName
|
|
85
|
+
)}
|
|
86
|
+
>
|
|
87
|
+
<div className="flex items-center">
|
|
88
|
+
<LocaleLink
|
|
89
|
+
data-testid="BaseHeaderLogo"
|
|
90
|
+
title={tt.title}
|
|
91
|
+
href={headerHref}
|
|
92
|
+
locale={locale}
|
|
93
|
+
className="flex items-center hover:opacity-80 transition-opacity"
|
|
94
|
+
>
|
|
95
|
+
<span
|
|
96
|
+
data-testid="base-header-app-name"
|
|
97
|
+
className="text-lg font-semibold text-text"
|
|
98
|
+
>
|
|
99
|
+
{tt.title}
|
|
100
|
+
</span>
|
|
101
|
+
</LocaleLink>
|
|
102
|
+
</div>
|
|
103
|
+
<div className="flex items-center gap-2 md:gap-4">{actions}</div>
|
|
104
|
+
</div>
|
|
105
|
+
</header>
|
|
106
|
+
|
|
107
|
+
<main className="flex flex-1 flex-col bg-primary" {...mainProps}>
|
|
108
|
+
{children}
|
|
109
|
+
</main>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
package/dist/templates/next-app/src/uikit/{components → components-app}/LanguageSwitcher.tsx
RENAMED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import { TranslationOutlined } from '@ant-design/icons';
|
|
4
4
|
import { Dropdown } from 'antd';
|
|
5
|
+
import { useParams } from 'next/navigation';
|
|
5
6
|
import { useLocale } from 'next-intl';
|
|
6
|
-
import { useCallback, useMemo } from 'react';
|
|
7
|
-
import type { I18nServiceLocale } from '@/base/port/I18nServiceInterface';
|
|
7
|
+
import { useCallback, useMemo, useTransition } from 'react';
|
|
8
8
|
import { usePathname, useRouter } from '@/i18n/routing';
|
|
9
9
|
import { i18nConfig } from '@config/i18n';
|
|
10
10
|
import type { LocaleType } from '@config/i18n';
|
|
11
|
-
import { I } from '@config/IOCIdentifier';
|
|
12
|
-
import { useIOC } from '../hook/useIOC';
|
|
13
11
|
import type { ItemType } from 'antd/es/menu/interface';
|
|
14
12
|
|
|
15
13
|
export function LanguageSwitcher() {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
14
|
+
const pathname = usePathname();
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const currentLocale = useLocale() as LocaleType;
|
|
17
|
+
const [isPending, startTransition] = useTransition();
|
|
18
|
+
const params = useParams();
|
|
21
19
|
|
|
22
20
|
const options: ItemType[] = useMemo(() => {
|
|
23
21
|
return i18nConfig.supportedLngs.map(
|
|
@@ -34,18 +32,16 @@ export function LanguageSwitcher() {
|
|
|
34
32
|
|
|
35
33
|
const handleLanguageChange = useCallback(
|
|
36
34
|
async (value: string) => {
|
|
37
|
-
|
|
38
|
-
document.cookie = `NEXT_LOCALE=${value}; path=/; max-age=31536000; SameSite=Lax`;
|
|
39
|
-
// Route to the same page in the selected locale
|
|
40
|
-
router.replace(pathname, { locale: value });
|
|
35
|
+
if (isPending) return;
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
startTransition(() => {
|
|
38
|
+
// @ts-expect-error -- TypeScript will validate that only known `params`
|
|
39
|
+
// are used in combination with a given `pathname`. Since the two will
|
|
40
|
+
// always match for the current route, we can skip runtime checks.
|
|
41
|
+
router.replace({ pathname, params }, { locale: value });
|
|
42
|
+
});
|
|
47
43
|
},
|
|
48
|
-
[
|
|
44
|
+
[pathname, router, isPending, params]
|
|
49
45
|
);
|
|
50
46
|
|
|
51
47
|
const nextLocale = useMemo(() => {
|