@qlover/create-app 1.0.2 → 2.0.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.
- package/CHANGELOG.md +43 -0
- package/dist/index.cjs +9 -9
- package/dist/index.js +9 -9
- package/package.json +4 -3
- package/dist/configs/_common/.editorconfig +0 -23
- package/dist/configs/_common/.env.template +0 -13
- package/dist/configs/_common/.gitattributes +0 -2
- package/dist/configs/_common/.github/workflows/general-check.yml +0 -41
- package/dist/configs/_common/.github/workflows/release.yml +0 -81
- package/dist/configs/_common/.gitignore.template +0 -64
- package/dist/configs/_common/.husky/commit-msg +0 -3
- package/dist/configs/_common/.husky/pre-commit +0 -3
- package/dist/configs/_common/.prettierignore +0 -17
- package/dist/configs/_common/.prettierrc.js +0 -7
- package/dist/configs/_common/.vscode/extensions.json +0 -9
- package/dist/configs/_common/.vscode/react.code-snippets +0 -19
- package/dist/configs/_common/.vscode/settings.json +0 -16
- package/dist/configs/_common/commitlint.config.js +0 -10
- package/dist/configs/_common/package.json.template +0 -75
- package/dist/configs/node-lib/eslint.config.js +0 -50
- package/dist/templates/next-app/.env.template +0 -25
- package/dist/templates/next-app/.prettierignore +0 -58
- package/dist/templates/next-app/README.en.md +0 -130
- package/dist/templates/next-app/README.md +0 -130
- package/dist/templates/next-app/config/IOCIdentifier.ts +0 -74
- package/dist/templates/next-app/config/Identifier/api.ts +0 -41
- package/dist/templates/next-app/config/Identifier/common/admint.table.ts +0 -69
- package/dist/templates/next-app/config/Identifier/common/common.ts +0 -90
- package/dist/templates/next-app/config/Identifier/common/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/common/validators.ts +0 -34
- package/dist/templates/next-app/config/Identifier/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/pages/index.ts +0 -7
- package/dist/templates/next-app/config/Identifier/pages/page.about.ts +0 -20
- package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +0 -27
- package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +0 -266
- package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +0 -293
- package/dist/templates/next-app/config/Identifier/pages/page.home.ts +0 -56
- package/dist/templates/next-app/config/Identifier/pages/page.login.ts +0 -159
- package/dist/templates/next-app/config/Identifier/pages/page.register.ts +0 -177
- package/dist/templates/next-app/config/adminNavs.ts +0 -19
- package/dist/templates/next-app/config/common.ts +0 -43
- package/dist/templates/next-app/config/cookies.ts +0 -23
- package/dist/templates/next-app/config/i18n/AboutI18n.ts +0 -14
- package/dist/templates/next-app/config/i18n/HomeI18n.ts +0 -24
- package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +0 -51
- package/dist/templates/next-app/config/i18n/admin18n.ts +0 -75
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +0 -16
- package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +0 -36
- package/dist/templates/next-app/config/i18n/index.ts +0 -7
- package/dist/templates/next-app/config/i18n/loginI18n.ts +0 -50
- package/dist/templates/next-app/config/i18n/register18n.ts +0 -44
- package/dist/templates/next-app/config/route.ts +0 -9
- package/dist/templates/next-app/config/theme.ts +0 -28
- package/dist/templates/next-app/docs/en/api.md +0 -387
- package/dist/templates/next-app/docs/en/component.md +0 -544
- package/dist/templates/next-app/docs/en/database.md +0 -496
- package/dist/templates/next-app/docs/en/development-guide.md +0 -727
- package/dist/templates/next-app/docs/en/env.md +0 -563
- package/dist/templates/next-app/docs/en/i18n.md +0 -287
- package/dist/templates/next-app/docs/en/index.md +0 -165
- package/dist/templates/next-app/docs/en/page.md +0 -457
- package/dist/templates/next-app/docs/en/project-structure.md +0 -176
- package/dist/templates/next-app/docs/en/router.md +0 -427
- package/dist/templates/next-app/docs/en/theme.md +0 -532
- package/dist/templates/next-app/docs/en/validator.md +0 -478
- package/dist/templates/next-app/docs/zh/api.md +0 -387
- package/dist/templates/next-app/docs/zh/component.md +0 -544
- package/dist/templates/next-app/docs/zh/database.md +0 -496
- package/dist/templates/next-app/docs/zh/development-guide.md +0 -727
- package/dist/templates/next-app/docs/zh/env.md +0 -563
- package/dist/templates/next-app/docs/zh/i18n.md +0 -287
- package/dist/templates/next-app/docs/zh/index.md +0 -165
- package/dist/templates/next-app/docs/zh/page.md +0 -457
- package/dist/templates/next-app/docs/zh/project-structure.md +0 -176
- package/dist/templates/next-app/docs/zh/router.md +0 -427
- package/dist/templates/next-app/docs/zh/theme.md +0 -532
- package/dist/templates/next-app/docs/zh/validator.md +0 -476
- package/dist/templates/next-app/eslint.config.mjs +0 -285
- package/dist/templates/next-app/make/generateLocales.ts +0 -32
- package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +0 -15
- package/dist/templates/next-app/migrations/schema/UserSchema.ts +0 -38
- package/dist/templates/next-app/migrations/sql/1694244000000.sql +0 -21
- package/dist/templates/next-app/next.config.ts +0 -25
- package/dist/templates/next-app/package.json +0 -87
- package/dist/templates/next-app/postcss.config.mjs +0 -5
- package/dist/templates/next-app/public/favicon.ico +0 -0
- package/dist/templates/next-app/public/file.svg +0 -1
- package/dist/templates/next-app/public/globe.svg +0 -1
- package/dist/templates/next-app/public/locales/en.json +0 -182
- package/dist/templates/next-app/public/locales/zh.json +0 -182
- package/dist/templates/next-app/public/next.svg +0 -1
- package/dist/templates/next-app/public/vercel.svg +0 -1
- package/dist/templates/next-app/public/window.svg +0 -1
- package/dist/templates/next-app/src/app/[locale]/admin/AdminI18nProvider.tsx +0 -37
- package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +0 -42
- package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +0 -153
- package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +0 -20
- package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +0 -67
- package/dist/templates/next-app/src/app/[locale]/auth/layout.tsx +0 -18
- package/dist/templates/next-app/src/app/[locale]/auth/login/LoginForm.tsx +0 -126
- package/dist/templates/next-app/src/app/[locale]/auth/login/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/auth/page.tsx +0 -8
- package/dist/templates/next-app/src/app/[locale]/auth/register/RegisterForm.tsx +0 -197
- package/dist/templates/next-app/src/app/[locale]/auth/register/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +0 -63
- package/dist/templates/next-app/src/app/[locale]/not-found.tsx +0 -24
- package/dist/templates/next-app/src/app/[locale]/page.tsx +0 -98
- package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/users/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/ai/completions/route.ts +0 -32
- package/dist/templates/next-app/src/app/api/auth/callback/route.ts +0 -11
- package/dist/templates/next-app/src/app/api/callback/route.ts +0 -49
- package/dist/templates/next-app/src/app/api/locales/json/route.ts +0 -33
- package/dist/templates/next-app/src/app/api/user/login/route.ts +0 -10
- package/dist/templates/next-app/src/app/api/user/logout/route.ts +0 -8
- package/dist/templates/next-app/src/app/api/user/register/route.ts +0 -11
- package/dist/templates/next-app/src/app/manifest.ts +0 -16
- package/dist/templates/next-app/src/app/robots.txt +0 -2
- package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +0 -28
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +0 -40
- package/dist/templates/next-app/src/base/cases/Datetime.ts +0 -18
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +0 -57
- package/dist/templates/next-app/src/base/cases/DialogHandler.ts +0 -116
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +0 -32
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +0 -77
- package/dist/templates/next-app/src/base/cases/ResourceState.ts +0 -17
- package/dist/templates/next-app/src/base/cases/RouterService.ts +0 -52
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +0 -73
- package/dist/templates/next-app/src/base/cases/TranslateI18nUtil.ts +0 -53
- package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +0 -212
- package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +0 -26
- package/dist/templates/next-app/src/base/port/AppApiInterface.ts +0 -36
- package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +0 -27
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/IOCInterface.ts +0 -33
- package/dist/templates/next-app/src/base/port/RouterInterface.ts +0 -11
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +0 -8
- package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +0 -26
- package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +0 -42
- package/dist/templates/next-app/src/base/services/AppApiRequester.ts +0 -67
- package/dist/templates/next-app/src/base/services/AppUserGateway.ts +0 -110
- package/dist/templates/next-app/src/base/services/I18nService.ts +0 -87
- package/dist/templates/next-app/src/base/services/ResourceService.ts +0 -139
- package/dist/templates/next-app/src/base/services/UserService.ts +0 -68
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +0 -106
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +0 -87
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +0 -110
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +0 -52
- package/dist/templates/next-app/src/base/types/AppPageRouter.ts +0 -12
- package/dist/templates/next-app/src/base/types/PagesRouter.ts +0 -9
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +0 -76
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +0 -125
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -50
- package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +0 -18
- package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +0 -68
- package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +0 -100
- package/dist/templates/next-app/src/core/globals.ts +0 -28
- package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +0 -80
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +0 -66
- package/dist/templates/next-app/src/i18n/loadMessages.ts +0 -103
- package/dist/templates/next-app/src/i18n/request.ts +0 -31
- package/dist/templates/next-app/src/i18n/routing.ts +0 -35
- package/dist/templates/next-app/src/lib/supabase/client.ts +0 -8
- package/dist/templates/next-app/src/lib/supabase/conts.ts +0 -2
- package/dist/templates/next-app/src/lib/supabase/proxy.ts +0 -84
- package/dist/templates/next-app/src/lib/supabase/server.ts +0 -38
- package/dist/templates/next-app/src/pages/[locale]/about.tsx +0 -61
- package/dist/templates/next-app/src/pages/_app.tsx +0 -50
- package/dist/templates/next-app/src/pages/_document.tsx +0 -13
- package/dist/templates/next-app/src/proxy.ts +0 -33
- package/dist/templates/next-app/src/server/AppErrorApi.ts +0 -10
- package/dist/templates/next-app/src/server/AppPageRouteParams.ts +0 -110
- package/dist/templates/next-app/src/server/AppSuccessApi.ts +0 -7
- package/dist/templates/next-app/src/server/NextApiServer.ts +0 -61
- package/dist/templates/next-app/src/server/PagesRouteParams.ts +0 -145
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +0 -18
- package/dist/templates/next-app/src/server/ServerAuth.ts +0 -81
- package/dist/templates/next-app/src/server/SupabaseBridge.ts +0 -262
- package/dist/templates/next-app/src/server/UserCredentialToken.ts +0 -53
- package/dist/templates/next-app/src/server/controllers/AdminLocalesController.ts +0 -86
- package/dist/templates/next-app/src/server/controllers/AdminUserController.ts +0 -42
- package/dist/templates/next-app/src/server/controllers/LocalesController.ts +0 -36
- package/dist/templates/next-app/src/server/controllers/UserController.ts +0 -91
- package/dist/templates/next-app/src/server/port/AIControllerInterface.ts +0 -8
- package/dist/templates/next-app/src/server/port/AdminLocalesControllerInterface.ts +0 -21
- package/dist/templates/next-app/src/server/port/AdminUserControllerInterface.ts +0 -11
- package/dist/templates/next-app/src/server/port/CrentialTokenInterface.ts +0 -5
- package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +0 -36
- package/dist/templates/next-app/src/server/port/DBTableInterface.ts +0 -12
- package/dist/templates/next-app/src/server/port/LocalesControllerInterface.ts +0 -10
- package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +0 -43
- package/dist/templates/next-app/src/server/port/PaginationInterface.ts +0 -6
- package/dist/templates/next-app/src/server/port/RouteParamsnHandlerInterface.ts +0 -18
- package/dist/templates/next-app/src/server/port/ServerAuthInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +0 -23
- package/dist/templates/next-app/src/server/port/UserRepositoryInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +0 -14
- package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +0 -23
- package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +0 -216
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +0 -102
- package/dist/templates/next-app/src/server/services/AIService.ts +0 -45
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +0 -21
- package/dist/templates/next-app/src/server/services/AdminLocalesService.ts +0 -20
- package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +0 -137
- package/dist/templates/next-app/src/server/services/ApiUserService.ts +0 -29
- package/dist/templates/next-app/src/server/services/UserService.ts +0 -134
- package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +0 -6
- package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +0 -145
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +0 -82
- package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +0 -70
- package/dist/templates/next-app/src/server/validators/SignupVerifyValidator.ts +0 -68
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/next-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/next-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/next-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/next-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/next-app/src/styles/css/index.css +0 -6
- package/dist/templates/next-app/src/styles/css/page.css +0 -20
- package/dist/templates/next-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/next-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/next-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/next-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +0 -150
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +0 -39
- package/dist/templates/next-app/src/uikit/components/ClientRootProvider.tsx +0 -64
- package/dist/templates/next-app/src/uikit/components/ClientSeo.tsx +0 -36
- package/dist/templates/next-app/src/uikit/components/ClinetRenderProvider.tsx +0 -42
- package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +0 -118
- package/dist/templates/next-app/src/uikit/components/FeatureItem.tsx +0 -13
- package/dist/templates/next-app/src/uikit/components/IOCProvider.tsx +0 -34
- package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +0 -50
- package/dist/templates/next-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +0 -62
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +0 -28
- package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +0 -6
- package/dist/templates/next-app/src/uikit/components-app/AdminButton.tsx +0 -29
- package/dist/templates/next-app/src/uikit/components-app/AppBridge.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +0 -105
- package/dist/templates/next-app/src/uikit/components-app/AuthButton.tsx +0 -20
- package/dist/templates/next-app/src/uikit/components-app/LanguageSwitcher.tsx +0 -75
- package/dist/templates/next-app/src/uikit/components-app/LogoutButton.tsx +0 -45
- package/dist/templates/next-app/src/uikit/components-app/ThemeSwitcher.tsx +0 -144
- package/dist/templates/next-app/src/uikit/components-pages/LanguageSwitcher.tsx +0 -98
- package/dist/templates/next-app/src/uikit/components-pages/PagesRoutePage.tsx +0 -93
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +0 -25
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +0 -22
- package/dist/templates/next-app/src/uikit/hook/useIOC.ts +0 -37
- package/dist/templates/next-app/src/uikit/hook/useStrictEffect.ts +0 -32
- package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +0 -11
- package/dist/templates/next-app/src/uikit/utils/getHashParams.ts +0 -8
- package/dist/templates/next-app/src/uikit/utils/getHashVerifyEmailParams.ts +0 -42
- package/dist/templates/next-app/tailwind.config.ts +0 -8
- package/dist/templates/next-app/tsconfig.json +0 -39
- package/dist/templates/node-lib/__tests__/readJson.test.ts +0 -26
- package/dist/templates/node-lib/bin/test.js +0 -30
- package/dist/templates/node-lib/package.json +0 -66
- package/dist/templates/node-lib/rollup.config.js +0 -79
- package/dist/templates/node-lib/src/index.ts +0 -7
- package/dist/templates/node-lib/src/readJson.ts +0 -12
- package/dist/templates/node-lib/tsconfig.json +0 -23
- package/dist/templates/pack-app/README.md +0 -108
- package/dist/templates/pack-app/eslint.config.js +0 -97
- package/dist/templates/pack-app/fe-config.json +0 -35
- package/dist/templates/pack-app/package.json +0 -86
- package/dist/templates/pack-app/pnpm-workspace.yaml +0 -2
- package/dist/templates/pack-app/tsconfig.json +0 -9
- package/dist/templates/pack-app/tsconfig.test.json +0 -10
- package/dist/templates/pack-app/vite.config.ts +0 -14
- package/dist/templates/react-app/.env.template +0 -22
- package/dist/templates/react-app/.prettierignore +0 -17
- package/dist/templates/react-app/README.en.md +0 -274
- package/dist/templates/react-app/README.md +0 -273
- package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +0 -16
- package/dist/templates/react-app/__tests__/__mocks__/MockAppConfig.ts +0 -48
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +0 -17
- package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +0 -14
- package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +0 -38
- package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +0 -53
- package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +0 -46
- package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +0 -12
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +0 -96
- package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +0 -110
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +0 -55
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +0 -74
- package/dist/templates/react-app/__tests__/setup/index.ts +0 -1
- package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +0 -64
- package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +0 -115
- package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +0 -288
- package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +0 -226
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +0 -178
- package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +0 -181
- package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +0 -61
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +0 -177
- package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +0 -191
- package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +0 -245
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +0 -240
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +0 -242
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +0 -135
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +0 -74
- package/dist/templates/react-app/__tests__/src/main.test.tsx +0 -46
- package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +0 -97
- package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +0 -274
- package/dist/templates/react-app/config/IOCIdentifier.ts +0 -91
- package/dist/templates/react-app/config/Identifier/common/common.error.ts +0 -34
- package/dist/templates/react-app/config/Identifier/common/common.ts +0 -62
- package/dist/templates/react-app/config/Identifier/common/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +0 -56
- package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +0 -103
- package/dist/templates/react-app/config/Identifier/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/pages/index.ts +0 -9
- package/dist/templates/react-app/config/Identifier/pages/page.about.ts +0 -189
- package/dist/templates/react-app/config/Identifier/pages/page.executor.ts +0 -275
- package/dist/templates/react-app/config/Identifier/pages/page.home.ts +0 -71
- package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +0 -102
- package/dist/templates/react-app/config/Identifier/pages/page.jsonStorage.ts +0 -77
- package/dist/templates/react-app/config/Identifier/pages/page.login.ts +0 -162
- package/dist/templates/react-app/config/Identifier/pages/page.message.ts +0 -20
- package/dist/templates/react-app/config/Identifier/pages/page.register.ts +0 -159
- package/dist/templates/react-app/config/Identifier/pages/page.request.ts +0 -169
- package/dist/templates/react-app/config/app.router.ts +0 -338
- package/dist/templates/react-app/config/common.ts +0 -85
- package/dist/templates/react-app/config/feapi.mock.json +0 -34
- package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +0 -51
- package/dist/templates/react-app/config/i18n/aboutI18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +0 -17
- package/dist/templates/react-app/config/i18n/executorI18n.ts +0 -51
- package/dist/templates/react-app/config/i18n/homeI18n.ts +0 -24
- package/dist/templates/react-app/config/i18n/i18nConfig.ts +0 -30
- package/dist/templates/react-app/config/i18n/identifiter18n.ts +0 -30
- package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +0 -27
- package/dist/templates/react-app/config/i18n/login18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +0 -22
- package/dist/templates/react-app/config/i18n/messageI18n.ts +0 -14
- package/dist/templates/react-app/config/i18n/notFoundI18n.ts +0 -34
- package/dist/templates/react-app/config/i18n/register18n.ts +0 -40
- package/dist/templates/react-app/config/i18n/request18n.ts +0 -41
- package/dist/templates/react-app/config/theme.ts +0 -21
- package/dist/templates/react-app/docs/en/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/en/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/en/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/en/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/en/env.md +0 -1336
- package/dist/templates/react-app/docs/en/global.md +0 -509
- package/dist/templates/react-app/docs/en/i18n.md +0 -979
- package/dist/templates/react-app/docs/en/index.md +0 -802
- package/dist/templates/react-app/docs/en/ioc.md +0 -1365
- package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/en/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/en/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/en/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/en/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/en/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/en/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/en/request.md +0 -423
- package/dist/templates/react-app/docs/en/router.md +0 -404
- package/dist/templates/react-app/docs/en/store.md +0 -1331
- package/dist/templates/react-app/docs/en/test-guide.md +0 -976
- package/dist/templates/react-app/docs/en/theme.md +0 -424
- package/dist/templates/react-app/docs/en/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/en/why-no-globals.md +0 -797
- package/dist/templates/react-app/docs/zh/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/zh/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/zh/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/zh/env.md +0 -1336
- package/dist/templates/react-app/docs/zh/global.md +0 -511
- package/dist/templates/react-app/docs/zh/i18n.md +0 -979
- package/dist/templates/react-app/docs/zh/index.md +0 -786
- package/dist/templates/react-app/docs/zh/ioc.md +0 -1364
- package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/zh/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/zh/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/zh/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/zh/request.md +0 -427
- package/dist/templates/react-app/docs/zh/router.md +0 -408
- package/dist/templates/react-app/docs/zh/store.md +0 -1329
- package/dist/templates/react-app/docs/zh/test-guide.md +0 -976
- package/dist/templates/react-app/docs/zh/theme.md +0 -424
- package/dist/templates/react-app/docs/zh/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/zh/why-no-globals.md +0 -797
- package/dist/templates/react-app/e2e/App.spec.ts +0 -319
- package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +0 -40
- package/dist/templates/react-app/e2e/main.spec.ts +0 -20
- package/dist/templates/react-app/e2e/utils/test-helpers.ts +0 -19
- package/dist/templates/react-app/eslint.config.mjs +0 -325
- package/dist/templates/react-app/index.html +0 -13
- package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +0 -26
- package/dist/templates/react-app/package.json +0 -125
- package/dist/templates/react-app/playwright.config.ts +0 -79
- package/dist/templates/react-app/postcss.config.js +0 -5
- package/dist/templates/react-app/public/locales/en/common.json +0 -235
- package/dist/templates/react-app/public/locales/zh/common.json +0 -235
- package/dist/templates/react-app/public/logo.svg +0 -1
- package/dist/templates/react-app/public/router-root/logo.svg +0 -1
- package/dist/templates/react-app/src/App.tsx +0 -35
- package/dist/templates/react-app/src/assets/react.svg +0 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +0 -68
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +0 -29
- package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +0 -21
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +0 -142
- package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +0 -70
- package/dist/templates/react-app/src/base/cases/AppConfig.ts +0 -123
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +0 -115
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +0 -64
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +0 -55
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +0 -80
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +0 -40
- package/dist/templates/react-app/src/base/cases/ResourceState.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +0 -173
- package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +0 -26
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +0 -10
- package/dist/templates/react-app/src/base/port/IOCInterface.ts +0 -38
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +0 -21
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +0 -5
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +0 -29
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +0 -20
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +0 -61
- package/dist/templates/react-app/src/base/services/I18nService.ts +0 -146
- package/dist/templates/react-app/src/base/services/IdentifierService.ts +0 -162
- package/dist/templates/react-app/src/base/services/RouteService.ts +0 -115
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +0 -45
- package/dist/templates/react-app/src/base/services/UserService.ts +0 -88
- package/dist/templates/react-app/src/base/types/Page.ts +0 -47
- package/dist/templates/react-app/src/base/types/deprecated-antd.d.ts +0 -60
- package/dist/templates/react-app/src/base/types/global.d.ts +0 -8
- package/dist/templates/react-app/src/core/IOC.ts +0 -28
- package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +0 -108
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -54
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +0 -14
- package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +0 -28
- package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +0 -47
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +0 -142
- package/dist/templates/react-app/src/core/globals.ts +0 -47
- package/dist/templates/react-app/src/main.tsx +0 -19
- package/dist/templates/react-app/src/pages/404.tsx +0 -19
- package/dist/templates/react-app/src/pages/500.tsx +0 -18
- package/dist/templates/react-app/src/pages/NoRouteFound.tsx +0 -5
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +0 -27
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +0 -166
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +0 -226
- package/dist/templates/react-app/src/pages/base/AboutPage.tsx +0 -123
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +0 -467
- package/dist/templates/react-app/src/pages/base/HomePage.tsx +0 -81
- package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +0 -117
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +0 -132
- package/dist/templates/react-app/src/pages/base/Layout.tsx +0 -20
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +0 -71
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +0 -18
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +0 -193
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/react-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/react-app/src/styles/css/index.css +0 -6
- package/dist/templates/react-app/src/styles/css/page.css +0 -20
- package/dist/templates/react-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/react-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/react-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/react-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +0 -72
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +0 -41
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +0 -22
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +0 -136
- package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +0 -35
- package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +0 -51
- package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +0 -44
- package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +0 -18
- package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +0 -11
- package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +0 -62
- package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +0 -38
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +0 -78
- package/dist/templates/react-app/src/uikit/components/Loading.tsx +0 -49
- package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +0 -43
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +0 -58
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +0 -258
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +0 -19
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +0 -137
- package/dist/templates/react-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +0 -205
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +0 -108
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +0 -282
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +0 -102
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +0 -86
- package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +0 -42
- package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +0 -13
- package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +0 -26
- package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +0 -35
- package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +0 -21
- package/dist/templates/react-app/src/uikit/hooks/useRouterI18nGuard.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -31
- package/dist/templates/react-app/src/vite-env.d.ts +0 -1
- package/dist/templates/react-app/tailwind.config.js +0 -4
- package/dist/templates/react-app/tsconfig.app.json +0 -36
- package/dist/templates/react-app/tsconfig.e2e.json +0 -24
- package/dist/templates/react-app/tsconfig.json +0 -22
- package/dist/templates/react-app/tsconfig.node.json +0 -27
- package/dist/templates/react-app/tsconfig.test.json +0 -18
- package/dist/templates/react-app/vite.config.ts +0 -144
|
@@ -1,1199 +0,0 @@
|
|
|
1
|
-
# Development Guide
|
|
2
|
-
|
|
3
|
-
> **📖 This document provides a complete page development workflow and practical guide to help you quickly get started with project development.**
|
|
4
|
-
|
|
5
|
-
## 📋 Table of Contents
|
|
6
|
-
|
|
7
|
-
- [What's Needed to Develop a Page](#-whats-needed-to-develop-a-page)
|
|
8
|
-
- [Complete Development Workflow](#-complete-development-workflow)
|
|
9
|
-
- [Practical Example: User List Page](#-practical-example-user-list-page)
|
|
10
|
-
- [Common Scenarios](#-common-scenarios)
|
|
11
|
-
- [Code Standards](#-code-standards)
|
|
12
|
-
- [Development Tools](#-development-tools)
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 🎯 What's Needed to Develop a Page
|
|
17
|
-
|
|
18
|
-
### Core Checklist
|
|
19
|
-
|
|
20
|
-
A complete page typically requires the following components:
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
✅ 1. Interface Definition (Port) - base/port/XxxServiceInterface.ts
|
|
24
|
-
✅ 2. Service Implementation - base/services/XxxService.ts
|
|
25
|
-
✅ 3. API Adapter (Optional) - base/apis/xxxApi/XxxApi.ts
|
|
26
|
-
✅ 4. Route Configuration - config/app.router.ts
|
|
27
|
-
✅ 5. i18n Text Definition - config/Identifier/pages/page.xxx.ts
|
|
28
|
-
✅ 6. Page Component - pages/xxx/XxxPage.tsx
|
|
29
|
-
✅ 7. IOC Registration (New Services) - core/clientIoc/ClientIOCRegister.ts
|
|
30
|
-
✅ 8. Test Files - __tests__/src/pages/xxx/XxxPage.test.tsx
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Dependency Diagram
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
┌─────────────────────────────────────────┐
|
|
37
|
-
│ Route Configuration (app.router.ts) │
|
|
38
|
-
│ Define page paths and metadata │
|
|
39
|
-
└──────────────┬──────────────────────────┘
|
|
40
|
-
↓
|
|
41
|
-
┌─────────────────────────────────────────┐
|
|
42
|
-
│ Page Component (XxxPage.tsx) │
|
|
43
|
-
│ - Use useIOC to get services │
|
|
44
|
-
│ - Use useStore to subscribe to state │
|
|
45
|
-
│ - Use useAppTranslation for i18n │
|
|
46
|
-
│ - Handle UI rendering & interactions │
|
|
47
|
-
└──────────────┬──────────────────────────┘
|
|
48
|
-
↓
|
|
49
|
-
┌─────────────────────────────────────────┐
|
|
50
|
-
│ Service Layer (XxxService.ts) │
|
|
51
|
-
│ - Implement business logic │
|
|
52
|
-
│ - Extend StoreInterface │
|
|
53
|
-
│ - Dependency injection │
|
|
54
|
-
└──────────────┬──────────────────────────┘
|
|
55
|
-
↓
|
|
56
|
-
┌─────────────────────────────────────────┐
|
|
57
|
-
│ Interface Definition (XxxServiceInterface.ts) │
|
|
58
|
-
│ - Define service contract │
|
|
59
|
-
│ - Easy to test and mock │
|
|
60
|
-
└─────────────────────────────────────────┘
|
|
61
|
-
↓
|
|
62
|
-
┌─────────────────────────────────────────┐
|
|
63
|
-
│ API Adapter (XxxApi.ts) │
|
|
64
|
-
│ - Encapsulate HTTP requests │
|
|
65
|
-
│ - Transform data formats │
|
|
66
|
-
└─────────────────────────────────────────┘
|
|
67
|
-
↓
|
|
68
|
-
┌─────────────────────────────────────────┐
|
|
69
|
-
│ i18n Text (page.xxx.ts) │
|
|
70
|
-
│ - Define all text keys for page │
|
|
71
|
-
│ - Auto-generate translation files │
|
|
72
|
-
└─────────────────────────────────────────┘
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 🚀 Complete Development Workflow
|
|
78
|
-
|
|
79
|
-
### Workflow Diagram
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
📝 1. Requirements Analysis
|
|
83
|
-
├── Determine page features
|
|
84
|
-
├── Determine data sources (API)
|
|
85
|
-
└── Determine interaction logic
|
|
86
|
-
↓
|
|
87
|
-
🎨 2. Define i18n Keys
|
|
88
|
-
├── Page titles, button text, etc.
|
|
89
|
-
└── Error messages, success messages, etc.
|
|
90
|
-
↓
|
|
91
|
-
🔌 3. Define Interfaces (Port)
|
|
92
|
-
├── Service interfaces
|
|
93
|
-
└── Data types
|
|
94
|
-
↓
|
|
95
|
-
⚙️ 4. Implement Service
|
|
96
|
-
├── Extend StoreInterface
|
|
97
|
-
├── Implement business logic
|
|
98
|
-
└── Dependency injection
|
|
99
|
-
↓
|
|
100
|
-
🌐 5. Implement API Adapter (if needed)
|
|
101
|
-
├── Encapsulate HTTP requests
|
|
102
|
-
└── Data transformation
|
|
103
|
-
↓
|
|
104
|
-
🗺️ 6. Configure Routes
|
|
105
|
-
├── Add route configuration
|
|
106
|
-
└── Set metadata
|
|
107
|
-
↓
|
|
108
|
-
🎭 7. Implement Page Component
|
|
109
|
-
├── Use useIOC to get services
|
|
110
|
-
├── Use useStore to subscribe to state
|
|
111
|
-
└── Implement UI rendering
|
|
112
|
-
↓
|
|
113
|
-
🔗 8. Register to IOC (if new service)
|
|
114
|
-
└── Register in ClientIOCRegister
|
|
115
|
-
↓
|
|
116
|
-
🧪 9. Write Tests
|
|
117
|
-
├── Service tests (logic)
|
|
118
|
-
├── UI tests (rendering)
|
|
119
|
-
└── Integration tests (workflow)
|
|
120
|
-
↓
|
|
121
|
-
✅ 10. Self-test and Submit
|
|
122
|
-
├── Feature testing
|
|
123
|
-
├── Code review
|
|
124
|
-
└── Submit PR
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## 📚 Practical Example: User List Page
|
|
130
|
-
|
|
131
|
-
Let's assume we want to develop a user list page with the following features:
|
|
132
|
-
|
|
133
|
-
- Display user list
|
|
134
|
-
- Search users
|
|
135
|
-
- Pagination
|
|
136
|
-
- View user details
|
|
137
|
-
|
|
138
|
-
### 1. Requirements Analysis
|
|
139
|
-
|
|
140
|
-
**Feature List:**
|
|
141
|
-
|
|
142
|
-
- 📄 Display user list (avatar, name, email, role)
|
|
143
|
-
- 🔍 Search users (by name)
|
|
144
|
-
- 📃 Pagination (10 items per page)
|
|
145
|
-
- 👁️ View details (click to navigate to detail page)
|
|
146
|
-
- 🔄 Refresh list
|
|
147
|
-
|
|
148
|
-
**Data Source:**
|
|
149
|
-
|
|
150
|
-
- API: `GET /api/users?page=1&pageSize=10&keyword=xxx`
|
|
151
|
-
|
|
152
|
-
### 2. Define i18n Keys
|
|
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';
|
|
184
|
-
|
|
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';
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### 3. Define Interfaces and Types
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
// base/port/UserServiceInterface.ts
|
|
204
|
-
|
|
205
|
-
import { StoreInterface } from '@qlover/corekit-bridge';
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* User information
|
|
209
|
-
*/
|
|
210
|
-
export interface UserInfo {
|
|
211
|
-
id: string;
|
|
212
|
-
name: string;
|
|
213
|
-
email: string;
|
|
214
|
-
avatar: string;
|
|
215
|
-
role: 'admin' | 'user';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* User list query parameters
|
|
220
|
-
*/
|
|
221
|
-
export interface UserListParams {
|
|
222
|
-
page: number;
|
|
223
|
-
pageSize: number;
|
|
224
|
-
keyword?: string;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* User list response
|
|
229
|
-
*/
|
|
230
|
-
export interface UserListResponse {
|
|
231
|
-
list: UserInfo[];
|
|
232
|
-
total: number;
|
|
233
|
-
page: number;
|
|
234
|
-
pageSize: number;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* User service state
|
|
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;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* User service interface
|
|
251
|
-
*/
|
|
252
|
-
export abstract class UserServiceInterface extends StoreInterface<UserServiceState> {
|
|
253
|
-
/**
|
|
254
|
-
* Fetch user list
|
|
255
|
-
*/
|
|
256
|
-
abstract fetchUsers(params: UserListParams): Promise<void>;
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Search users
|
|
260
|
-
*/
|
|
261
|
-
abstract searchUsers(keyword: string): Promise<void>;
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Refresh list
|
|
265
|
-
*/
|
|
266
|
-
abstract refreshUsers(): Promise<void>;
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Selectors
|
|
270
|
-
*/
|
|
271
|
-
abstract selector: {
|
|
272
|
-
users: (state: UserServiceState) => UserInfo[];
|
|
273
|
-
loading: (state: UserServiceState) => boolean;
|
|
274
|
-
total: (state: UserServiceState) => number;
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### 4. Implement API Adapter
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
// base/apis/userApi/UserApi.ts
|
|
283
|
-
|
|
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';
|
|
290
|
-
|
|
291
|
-
@injectable()
|
|
292
|
-
export class UserApi {
|
|
293
|
-
constructor(@inject(HttpClient) private http: HttpClient) {}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Get user list
|
|
297
|
-
*/
|
|
298
|
-
async getUserList(params: UserListParams): Promise<UserListResponse> {
|
|
299
|
-
const response = await this.http.get('/api/users', { params });
|
|
300
|
-
|
|
301
|
-
// Transform backend data format
|
|
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
|
-
}
|
|
315
|
-
}
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### 5. Implement Service
|
|
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';
|
|
330
|
-
|
|
331
|
-
@injectable()
|
|
332
|
-
export class UserService extends UserServiceInterface {
|
|
333
|
-
constructor(@inject(UserApi) private api: UserApi) {
|
|
334
|
-
// Initialize state
|
|
335
|
-
super(() => ({
|
|
336
|
-
users: [],
|
|
337
|
-
total: 0,
|
|
338
|
-
page: 1,
|
|
339
|
-
pageSize: 10,
|
|
340
|
-
loading: false,
|
|
341
|
-
error: null
|
|
342
|
-
}));
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Selectors
|
|
347
|
-
*/
|
|
348
|
-
selector = {
|
|
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
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Fetch user list
|
|
358
|
-
*/
|
|
359
|
-
async fetchUsers(params: UserListParams): Promise<void> {
|
|
360
|
-
try {
|
|
361
|
-
// 1. Set loading state
|
|
362
|
-
this.emit({ ...this.state, loading: true, error: null });
|
|
363
|
-
|
|
364
|
-
// 2. Call API
|
|
365
|
-
const response = await this.api.getUserList(params);
|
|
366
|
-
|
|
367
|
-
// 3. Update state
|
|
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
|
-
});
|
|
376
|
-
} catch (error) {
|
|
377
|
-
// 4. Error handling
|
|
378
|
-
this.emit({
|
|
379
|
-
...this.state,
|
|
380
|
-
loading: false,
|
|
381
|
-
error: error as Error
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Search users
|
|
388
|
-
*/
|
|
389
|
-
async searchUsers(keyword: string): Promise<void> {
|
|
390
|
-
await this.fetchUsers({
|
|
391
|
-
page: 1,
|
|
392
|
-
pageSize: this.state.pageSize,
|
|
393
|
-
keyword
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Refresh list
|
|
399
|
-
*/
|
|
400
|
-
async refreshUsers(): Promise<void> {
|
|
401
|
-
await this.fetchUsers({
|
|
402
|
-
page: this.state.page,
|
|
403
|
-
pageSize: this.state.pageSize
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
### 6. Configure Routes
|
|
410
|
-
|
|
411
|
-
```typescript
|
|
412
|
-
// config/app.router.ts
|
|
413
|
-
|
|
414
|
-
import * as i18nKeys from './Identifier/pages/page.users';
|
|
415
|
-
|
|
416
|
-
export const baseRoutes: RouteConfigValue[] = [
|
|
417
|
-
{
|
|
418
|
-
path: '/:lng',
|
|
419
|
-
element: 'base/Layout',
|
|
420
|
-
children: [
|
|
421
|
-
// ... other routes
|
|
422
|
-
{
|
|
423
|
-
path: 'users',
|
|
424
|
-
element: 'users/UserListPage',
|
|
425
|
-
meta: {
|
|
426
|
-
title: i18nKeys.PAGE_USERS_TITLE,
|
|
427
|
-
requiresAuth: true, // Requires authentication
|
|
428
|
-
category: 'main'
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
]
|
|
432
|
-
}
|
|
433
|
-
];
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
### 7. Implement Page Component
|
|
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. Get services
|
|
453
|
-
const userService = useIOC(IOCIdentifier.UserServiceInterface);
|
|
454
|
-
const routeService = useIOC(IOCIdentifier.RouteServiceInterface);
|
|
455
|
-
const { t } = useAppTranslation();
|
|
456
|
-
|
|
457
|
-
// 2. Subscribe to state
|
|
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. Local state
|
|
465
|
-
const [keyword, setKeyword] = useState('');
|
|
466
|
-
|
|
467
|
-
// 4. Initialize loading
|
|
468
|
-
useEffect(() => {
|
|
469
|
-
userService.fetchUsers({ page: 1, pageSize: 10 });
|
|
470
|
-
}, []);
|
|
471
|
-
|
|
472
|
-
// 5. Event handlers
|
|
473
|
-
const handleSearch = () => {
|
|
474
|
-
userService.searchUsers(keyword);
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
const handleRefresh = () => {
|
|
478
|
-
userService.refreshUsers();
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
const handlePageChange = (newPage: number, newPageSize: number) => {
|
|
482
|
-
userService.fetchUsers({ page: newPage, pageSize: newPageSize, keyword });
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
const handleViewDetail = (userId: string) => {
|
|
486
|
-
routeService.push(`/users/${userId}`);
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
// 6. Table column configuration
|
|
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
|
-
];
|
|
527
|
-
|
|
528
|
-
// 7. Render
|
|
529
|
-
return (
|
|
530
|
-
<div className="p-6">
|
|
531
|
-
{/* Page title */}
|
|
532
|
-
<h1 className="text-2xl font-bold mb-4">
|
|
533
|
-
{t(i18nKeys.PAGE_USERS_TITLE)}
|
|
534
|
-
</h1>
|
|
535
|
-
|
|
536
|
-
{/* Search bar */}
|
|
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
|
-
{/* User table */}
|
|
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
|
-
```
|
|
576
|
-
|
|
577
|
-
### 8. Register to IOC (if new service)
|
|
578
|
-
|
|
579
|
-
```typescript
|
|
580
|
-
// core/clientIoc/ClientIOCRegister.ts
|
|
581
|
-
|
|
582
|
-
export class ClientIOCRegister {
|
|
583
|
-
protected registerImplement(ioc: IOCContainerInterface): void {
|
|
584
|
-
// ... other service registrations
|
|
585
|
-
|
|
586
|
-
// Register UserService
|
|
587
|
-
ioc.bind(IOCIdentifier.UserServiceInterface, ioc.get(UserService));
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
### 9. Write Tests
|
|
593
|
-
|
|
594
|
-
```typescript
|
|
595
|
-
// __tests__/src/base/services/UserService.test.ts
|
|
596
|
-
|
|
597
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
598
|
-
import { UserService } from '@/base/services/UserService';
|
|
599
|
-
|
|
600
|
-
describe('UserService', () => {
|
|
601
|
-
let userService: UserService;
|
|
602
|
-
let mockApi: any;
|
|
603
|
-
|
|
604
|
-
beforeEach(() => {
|
|
605
|
-
mockApi = {
|
|
606
|
-
getUserList: vi.fn()
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
userService = new UserService(mockApi);
|
|
610
|
-
});
|
|
611
|
-
|
|
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
|
-
};
|
|
627
|
-
|
|
628
|
-
mockApi.getUserList.mockResolvedValue(mockResponse);
|
|
629
|
-
|
|
630
|
-
const states: any[] = [];
|
|
631
|
-
userService.subscribe((state) => states.push({ ...state }));
|
|
632
|
-
|
|
633
|
-
await userService.fetchUsers({ page: 1, pageSize: 10 });
|
|
634
|
-
|
|
635
|
-
// Verify state changes
|
|
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
|
-
});
|
|
642
|
-
|
|
643
|
-
it('should handle error when fetch fails', async () => {
|
|
644
|
-
mockApi.getUserList.mockRejectedValue(new Error('Network error'));
|
|
645
|
-
|
|
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
|
-
```
|
|
653
|
-
|
|
654
|
-
```typescript
|
|
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');
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
```
|
|
738
|
-
|
|
739
|
-
---
|
|
740
|
-
|
|
741
|
-
## 🎬 Common Scenarios
|
|
742
|
-
|
|
743
|
-
### Scenario 1: Adding a New Button Feature
|
|
744
|
-
|
|
745
|
-
Suppose we want to add a "bulk delete" feature to the user list page:
|
|
746
|
-
|
|
747
|
-
```typescript
|
|
748
|
-
// 1. Add i18n Key
|
|
749
|
-
/**
|
|
750
|
-
* @description Delete selected users
|
|
751
|
-
* @localZh 删除选中用户
|
|
752
|
-
* @localEn Delete Selected
|
|
753
|
-
*/
|
|
754
|
-
export const PAGE_USERS_DELETE_SELECTED = 'page.users.deleteSelected';
|
|
755
|
-
|
|
756
|
-
// 2. Add method to service
|
|
757
|
-
@injectable()
|
|
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(); // Refresh list
|
|
764
|
-
} catch (error) {
|
|
765
|
-
this.emit({ ...this.state, loading: false, error: error as Error });
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
// 3. Use in page
|
|
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
|
-
}
|
|
799
|
-
```
|
|
800
|
-
|
|
801
|
-
### Scenario 2: Adding a Modal Form
|
|
802
|
-
|
|
803
|
-
Suppose we want to add an "edit user" modal:
|
|
804
|
-
|
|
805
|
-
```typescript
|
|
806
|
-
// 1. Create modal component
|
|
807
|
-
// components/UserEditModal.tsx
|
|
808
|
-
interface UserEditModalProps {
|
|
809
|
-
user: UserInfo | null;
|
|
810
|
-
visible: boolean;
|
|
811
|
-
onClose: () => void;
|
|
812
|
-
onSubmit: (user: UserInfo) => void;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
export function UserEditModal({ user, visible, onClose, onSubmit }: UserEditModalProps) {
|
|
816
|
-
const [form] = Form.useForm();
|
|
817
|
-
const { t } = useAppTranslation();
|
|
818
|
-
|
|
819
|
-
useEffect(() => {
|
|
820
|
-
if (user) {
|
|
821
|
-
form.setFieldsValue(user);
|
|
822
|
-
}
|
|
823
|
-
}, [user]);
|
|
824
|
-
|
|
825
|
-
const handleSubmit = async () => {
|
|
826
|
-
const values = await form.validateFields();
|
|
827
|
-
onSubmit(values);
|
|
828
|
-
};
|
|
829
|
-
|
|
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
|
-
}
|
|
856
|
-
|
|
857
|
-
// 2. Add update method to service
|
|
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
|
-
}
|
|
866
|
-
|
|
867
|
-
// 3. Use in page
|
|
868
|
-
function UserListPage() {
|
|
869
|
-
const [editUser, setEditUser] = useState<UserInfo | null>(null);
|
|
870
|
-
const [modalVisible, setModalVisible] = useState(false);
|
|
871
|
-
|
|
872
|
-
const handleEdit = (user: UserInfo) => {
|
|
873
|
-
setEditUser(user);
|
|
874
|
-
setModalVisible(true);
|
|
875
|
-
};
|
|
876
|
-
|
|
877
|
-
const handleSubmit = async (values: UserInfo) => {
|
|
878
|
-
await userService.updateUser(editUser!.id, values);
|
|
879
|
-
setModalVisible(false);
|
|
880
|
-
setEditUser(null);
|
|
881
|
-
};
|
|
882
|
-
|
|
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
|
-
}
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
### Scenario 3: Adding Real-time Search
|
|
910
|
-
|
|
911
|
-
Suppose we want to implement "auto-search while typing":
|
|
912
|
-
|
|
913
|
-
```typescript
|
|
914
|
-
function UserListPage() {
|
|
915
|
-
const [keyword, setKeyword] = useState('');
|
|
916
|
-
|
|
917
|
-
// Use debounce to optimize search
|
|
918
|
-
const debouncedKeyword = useDebounce(keyword, 500);
|
|
919
|
-
|
|
920
|
-
useEffect(() => {
|
|
921
|
-
if (debouncedKeyword !== undefined) {
|
|
922
|
-
userService.searchUsers(debouncedKeyword);
|
|
923
|
-
}
|
|
924
|
-
}, [debouncedKeyword]);
|
|
925
|
-
|
|
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
|
-
}
|
|
934
|
-
|
|
935
|
-
// Custom Hook
|
|
936
|
-
function useDebounce<T>(value: T, delay: number): T {
|
|
937
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
938
|
-
|
|
939
|
-
useEffect(() => {
|
|
940
|
-
const timer = setTimeout(() => {
|
|
941
|
-
setDebouncedValue(value);
|
|
942
|
-
}, delay);
|
|
943
|
-
|
|
944
|
-
return () => {
|
|
945
|
-
clearTimeout(timer);
|
|
946
|
-
};
|
|
947
|
-
}, [value, delay]);
|
|
948
|
-
|
|
949
|
-
return debouncedValue;
|
|
950
|
-
}
|
|
951
|
-
```
|
|
952
|
-
|
|
953
|
-
---
|
|
954
|
-
|
|
955
|
-
## 📐 Code Standards
|
|
956
|
-
|
|
957
|
-
### 1. Naming Conventions
|
|
958
|
-
|
|
959
|
-
```typescript
|
|
960
|
-
// ✅ Good naming
|
|
961
|
-
const userService = useIOC('UserServiceInterface'); // Service: camelCase
|
|
962
|
-
const UserListPage = () => {
|
|
963
|
-
/* ... */
|
|
964
|
-
}; // Component: PascalCase
|
|
965
|
-
const PAGE_USERS_TITLE = 'page.users.title'; // Constant: UPPER_SNAKE_CASE
|
|
966
|
-
interface UserInfo {
|
|
967
|
-
/* ... */
|
|
968
|
-
} // Interface: PascalCase
|
|
969
|
-
type UserRole = 'admin' | 'user'; // Type: PascalCase
|
|
970
|
-
|
|
971
|
-
// ❌ Bad naming
|
|
972
|
-
const UserService = useIOC('UserServiceInterface'); // Should be camelCase
|
|
973
|
-
const userListPage = () => {
|
|
974
|
-
/* ... */
|
|
975
|
-
}; // Component should be PascalCase
|
|
976
|
-
const pageUsersTitle = 'page.users.title'; // Constant should be UPPER_CASE
|
|
977
|
-
interface userInfo {
|
|
978
|
-
/* ... */
|
|
979
|
-
} // Interface should be PascalCase
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### 2. File Organization
|
|
983
|
-
|
|
984
|
-
```typescript
|
|
985
|
-
// ✅ Good file organization
|
|
986
|
-
import { FC, useEffect, useState } from 'react'; // React
|
|
987
|
-
import { Button, Table, Input } from 'antd'; // Third-party UI
|
|
988
|
-
import { useIOC } from '@/uikit/hooks/useIOC'; // Internal project
|
|
989
|
-
import { useAppTranslation } from '@/uikit/hooks/useAppTranslation';
|
|
990
|
-
import * as i18nKeys from '@config/Identifier/pages/page.users';
|
|
991
|
-
import './UserListPage.css'; // Styles
|
|
992
|
-
|
|
993
|
-
// Type definitions
|
|
994
|
-
interface Props {
|
|
995
|
-
/* ... */
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
// Component
|
|
999
|
-
export default function UserListPage() {
|
|
1000
|
-
/* ... */
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
// ❌ Bad file organization
|
|
1004
|
-
import './UserListPage.css'; // Styles shouldn't be first
|
|
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';
|
|
1009
|
-
```
|
|
1010
|
-
|
|
1011
|
-
### 3. Component Structure
|
|
1012
|
-
|
|
1013
|
-
```typescript
|
|
1014
|
-
// ✅ Good component structure
|
|
1015
|
-
export default function UserListPage() {
|
|
1016
|
-
// 1. Hooks
|
|
1017
|
-
const userService = useIOC('UserServiceInterface');
|
|
1018
|
-
const { t } = useAppTranslation();
|
|
1019
|
-
|
|
1020
|
-
// 2. State
|
|
1021
|
-
const users = useStore(userService, userService.selector.users);
|
|
1022
|
-
const [keyword, setKeyword] = useState('');
|
|
1023
|
-
|
|
1024
|
-
// 3. Side effects
|
|
1025
|
-
useEffect(() => {
|
|
1026
|
-
userService.fetchUsers({ page: 1, pageSize: 10 });
|
|
1027
|
-
}, []);
|
|
1028
|
-
|
|
1029
|
-
// 4. Event handlers
|
|
1030
|
-
const handleSearch = () => {
|
|
1031
|
-
userService.searchUsers(keyword);
|
|
1032
|
-
};
|
|
1033
|
-
|
|
1034
|
-
// 5. Render functions
|
|
1035
|
-
const renderActions = (record: UserInfo) => {
|
|
1036
|
-
return <Button onClick={() => handleEdit(record)}>Edit</Button>;
|
|
1037
|
-
};
|
|
1038
|
-
|
|
1039
|
-
// 6. Return JSX
|
|
1040
|
-
return (
|
|
1041
|
-
<div>
|
|
1042
|
-
{/* ... */}
|
|
1043
|
-
</div>
|
|
1044
|
-
);
|
|
1045
|
-
}
|
|
1046
|
-
```
|
|
1047
|
-
|
|
1048
|
-
### 4. Comment Standards
|
|
1049
|
-
|
|
1050
|
-
```typescript
|
|
1051
|
-
/**
|
|
1052
|
-
* User list page
|
|
1053
|
-
*
|
|
1054
|
-
* @description Display user list with search, pagination, and view details functionality
|
|
1055
|
-
*/
|
|
1056
|
-
export default function UserListPage() {
|
|
1057
|
-
/**
|
|
1058
|
-
* Handle search
|
|
1059
|
-
* Search users by keyword
|
|
1060
|
-
*/
|
|
1061
|
-
const handleSearch = () => {
|
|
1062
|
-
userService.searchUsers(keyword);
|
|
1063
|
-
};
|
|
1064
|
-
|
|
1065
|
-
// Initialize user list loading
|
|
1066
|
-
useEffect(() => {
|
|
1067
|
-
userService.fetchUsers({ page: 1, pageSize: 10 });
|
|
1068
|
-
}, []);
|
|
1069
|
-
|
|
1070
|
-
return (
|
|
1071
|
-
<div>
|
|
1072
|
-
{/* Search bar */}
|
|
1073
|
-
<Input.Search onSearch={handleSearch} />
|
|
1074
|
-
|
|
1075
|
-
{/* User table */}
|
|
1076
|
-
<Table dataSource={users} />
|
|
1077
|
-
</div>
|
|
1078
|
-
);
|
|
1079
|
-
}
|
|
1080
|
-
```
|
|
1081
|
-
|
|
1082
|
-
---
|
|
1083
|
-
|
|
1084
|
-
## 🛠️ Development Tools
|
|
1085
|
-
|
|
1086
|
-
### Recommended VSCode Extensions
|
|
1087
|
-
|
|
1088
|
-
```
|
|
1089
|
-
✅ ESLint - Code linting
|
|
1090
|
-
✅ Prettier - Code formatting
|
|
1091
|
-
✅ TypeScript Vue Plugin (Volar) - Vue/React support
|
|
1092
|
-
✅ Tailwind CSS IntelliSense - Tailwind autocomplete
|
|
1093
|
-
✅ i18n Ally - i18n management
|
|
1094
|
-
✅ GitLens - Git enhancement
|
|
1095
|
-
✅ Error Lens - Error display
|
|
1096
|
-
✅ Auto Rename Tag - Tag auto-rename
|
|
1097
|
-
```
|
|
1098
|
-
|
|
1099
|
-
### Quick Commands
|
|
1100
|
-
|
|
1101
|
-
```bash
|
|
1102
|
-
# Development
|
|
1103
|
-
npm run dev # Start dev server
|
|
1104
|
-
npm run dev:staging # Start staging environment
|
|
1105
|
-
|
|
1106
|
-
# Build
|
|
1107
|
-
npm run build # Production build
|
|
1108
|
-
npm run preview # Preview build result
|
|
1109
|
-
|
|
1110
|
-
# Code quality
|
|
1111
|
-
npm run lint # ESLint check
|
|
1112
|
-
npm run lint:fix # ESLint auto-fix
|
|
1113
|
-
npm run type-check # TypeScript type checking
|
|
1114
|
-
|
|
1115
|
-
# Testing
|
|
1116
|
-
npm run test # Run tests
|
|
1117
|
-
npm run test:watch # Watch mode testing
|
|
1118
|
-
npm run test:coverage # Test coverage
|
|
1119
|
-
|
|
1120
|
-
# i18n
|
|
1121
|
-
npm run i18n:generate # Generate translation files
|
|
1122
|
-
```
|
|
1123
|
-
|
|
1124
|
-
### Debugging Tips
|
|
1125
|
-
|
|
1126
|
-
```typescript
|
|
1127
|
-
// 1. Use 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. Use React DevTools
|
|
1134
|
-
// Install React Developer Tools browser extension
|
|
1135
|
-
|
|
1136
|
-
// 3. Use Redux DevTools (if needed)
|
|
1137
|
-
// View Store state changes
|
|
1138
|
-
|
|
1139
|
-
// 4. Use VSCode breakpoint debugging
|
|
1140
|
-
// Click on the left side of a code line to set breakpoint, then F5 to start debugging
|
|
1141
|
-
```
|
|
1142
|
-
|
|
1143
|
-
---
|
|
1144
|
-
|
|
1145
|
-
## 🎯 Development Checklist
|
|
1146
|
-
|
|
1147
|
-
### Feature Development
|
|
1148
|
-
|
|
1149
|
-
- [ ] Define i18n Keys
|
|
1150
|
-
- [ ] Define interfaces and types
|
|
1151
|
-
- [ ] Implement API adapter (if needed)
|
|
1152
|
-
- [ ] Implement service
|
|
1153
|
-
- [ ] Configure routes
|
|
1154
|
-
- [ ] Implement page component
|
|
1155
|
-
- [ ] Register to IOC (if new service)
|
|
1156
|
-
- [ ] Feature self-testing
|
|
1157
|
-
|
|
1158
|
-
### Code Quality
|
|
1159
|
-
|
|
1160
|
-
- [ ] Pass ESLint check
|
|
1161
|
-
- [ ] Pass TypeScript type check
|
|
1162
|
-
- [ ] Code formatting (Prettier)
|
|
1163
|
-
- [ ] Remove console.log and debug code
|
|
1164
|
-
- [ ] Remove unused imports
|
|
1165
|
-
|
|
1166
|
-
### Testing
|
|
1167
|
-
|
|
1168
|
-
- [ ] Write service tests
|
|
1169
|
-
- [ ] Write UI tests
|
|
1170
|
-
- [ ] Test coverage > 80%
|
|
1171
|
-
- [ ] All tests passing
|
|
1172
|
-
|
|
1173
|
-
### Documentation
|
|
1174
|
-
|
|
1175
|
-
- [ ] Update related documentation
|
|
1176
|
-
- [ ] Add necessary code comments
|
|
1177
|
-
- [ ] Update API documentation (if any)
|
|
1178
|
-
|
|
1179
|
-
### Submission
|
|
1180
|
-
|
|
1181
|
-
- [ ] Git commit follows conventions
|
|
1182
|
-
- [ ] Code reviewed
|
|
1183
|
-
- [ ] Merged to main branch
|
|
1184
|
-
|
|
1185
|
-
---
|
|
1186
|
-
|
|
1187
|
-
## 📚 Related Documentation
|
|
1188
|
-
|
|
1189
|
-
- **[Project Architecture Design](./index.md)** - Understand overall architecture
|
|
1190
|
-
- **[IOC Container](./ioc.md)** - Dependency injection and UI separation
|
|
1191
|
-
- **[Store State Management](./store.md)** - How application layer notifies UI layer
|
|
1192
|
-
- **[Bootstrap Initializer](./bootstrap.md)** - Application startup and initialization
|
|
1193
|
-
- **[Environment Variables](./env.md)** - Multi-environment configuration
|
|
1194
|
-
- **[Internationalization](./i18n.md)** - i18n Key and translation management
|
|
1195
|
-
|
|
1196
|
-
---
|
|
1197
|
-
|
|
1198
|
-
**Feedback:**
|
|
1199
|
-
If you encounter any problems during development, please discuss in the team channel or submit an Issue.
|