From 039eeb667081dcce07536a8e00ffed22eddcd447 Mon Sep 17 00:00:00 2001 From: cli <377476583@qq.com> Date: Tue, 11 Mar 2025 10:29:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .browserslistrc | 4 + .commitlintrc.js | 1 + .dockerignore | 7 + .editorconfig | 18 + .gitattributes | 11 + .gitconfig | 2 + .gitignore | 56 + .gitpod.yml | 6 + .lintstagedrc.mjs | 20 + .node-version | 1 + .npmrc | 13 + .prettierignore | 18 + .prettierrc.mjs | 1 + .stylelintignore | 4 + .vscode/extensions.json | 30 + .vscode/global.code-snippets | 37 + .vscode/launch.json | 42 + .vscode/settings.json | 227 + Dockerfile | 44 + LICENSE | 24 + README.md | 109 + _nginx/nginx.conf | 75 + apps/web-antd/.env | 5 + apps/web-antd/.env.analyze | 7 + apps/web-antd/.env.development | 29 + apps/web-antd/.env.production | 28 + apps/web-antd/index.html | 35 + apps/web-antd/package.json | 61 + apps/web-antd/postcss.config.mjs | 1 + apps/web-antd/public/favicon.ico | Bin 0 -> 5430 bytes apps/web-antd/src/adapter/component/index.ts | 169 + apps/web-antd/src/adapter/form.ts | 47 + apps/web-antd/src/adapter/vxe-table.ts | 67 + apps/web-antd/src/api-client-config/config.ts | 7 + .../src/api-client-config/index-blob.ts | 102 + apps/web-antd/src/api-client-config/index.ts | 114 + apps/web-antd/src/api-client/index.ts | 4 + apps/web-antd/src/api-client/schemas.gen.ts | 4927 ++++ apps/web-antd/src/api-client/services.gen.ts | 777 + apps/web-antd/src/api-client/types.gen.ts | 2080 ++ apps/web-antd/src/api/core/auth.ts | 51 + apps/web-antd/src/api/core/index.ts | 3 + apps/web-antd/src/api/core/menu.ts | 10 + apps/web-antd/src/api/core/user.ts | 10 + apps/web-antd/src/api/index.ts | 1 + apps/web-antd/src/api/request.ts | 113 + apps/web-antd/src/app.vue | 39 + apps/web-antd/src/bootstrap.ts | 68 + apps/web-antd/src/components/Loading/index.ts | 4 + .../src/components/Loading/src/Loading.vue | 78 + .../components/Loading/src/createLoading.ts | 84 + .../src/components/Loading/src/typing.ts | 14 + .../src/components/Loading/src/useLoading.ts | 61 + apps/web-antd/src/components/icon/icon.vue | 51 + apps/web-antd/src/components/icon/index.ts | 1 + .../src/components/table-action/index.ts | 2 + .../components/table-action/table-action.vue | 225 + .../src/components/table-action/types.d.ts | 26 + apps/web-antd/src/hooks/useSignalR.ts | 125 + apps/web-antd/src/layouts/NotifyItem.vue | 207 + apps/web-antd/src/layouts/auth.vue | 23 + apps/web-antd/src/layouts/basic.vue | 256 + apps/web-antd/src/layouts/index.ts | 6 + apps/web-antd/src/layouts/my-profile.vue | 216 + apps/web-antd/src/locales/README.md | 3 + apps/web-antd/src/locales/index.ts | 102 + .../web-antd/src/locales/langs/en-US/abp.json | 131 + .../src/locales/langs/en-US/code.json | 37 + .../src/locales/langs/en-US/common.json | 39 + .../src/locales/langs/en-US/page.json | 15 + .../web-antd/src/locales/langs/zh-CN/abp.json | 131 + .../src/locales/langs/zh-CN/code.json | 37 + .../src/locales/langs/zh-CN/common.json | 39 + .../src/locales/langs/zh-CN/page.json | 15 + apps/web-antd/src/main.ts | 35 + apps/web-antd/src/preferences.ts | 23 + apps/web-antd/src/router/access.ts | 42 + apps/web-antd/src/router/guard.ts | 138 + apps/web-antd/src/router/index.ts | 37 + apps/web-antd/src/router/routes/core.ts | 96 + apps/web-antd/src/router/routes/index.ts | 37 + .../src/router/routes/modules/dashboard.ts | 38 + .../src/router/routes/modules/system.ts | 144 + .../src/router/routes/modules/tenant.ts | 32 + apps/web-antd/src/store/auth.ts | 152 + apps/web-antd/src/store/index.ts | 1 + apps/web-antd/src/views/_core/README.md | 3 + apps/web-antd/src/views/_core/about/index.vue | 9 + .../views/_core/authentication/code-login.vue | 69 + .../_core/authentication/forget-password.vue | 43 + .../src/views/_core/authentication/login.vue | 76 + .../_core/authentication/qrcode-login.vue | 10 + .../views/_core/authentication/register.vue | 96 + .../src/views/_core/fallback/coming-soon.vue | 7 + .../src/views/_core/fallback/forbidden.vue | 9 + .../views/_core/fallback/internal-error.vue | 9 + .../src/views/_core/fallback/not-found.vue | 9 + .../src/views/_core/fallback/offline.vue | 9 + .../dashboard/analytics/analytics-trends.vue | 98 + .../analytics/analytics-visits-data.vue | 82 + .../analytics/analytics-visits-sales.vue | 46 + .../analytics/analytics-visits-source.vue | 65 + .../dashboard/analytics/analytics-visits.vue | 55 + .../src/views/dashboard/analytics/index.vue | 90 + .../src/views/dashboard/workspace/index.vue | 266 + .../DataDictionaryDetailModal.vue | 125 + .../abpdatadictionary/DataDictionaryModal.vue | 100 + .../views/system/abpdatadictionary/index.vue | 355 + .../src/views/system/abpfeature/index.vue | 134 + .../abplanguage/AddLanguageTextModal.vue | 72 + .../abplanguage/EditLanguageTextModal.vue | 63 + .../src/views/system/abplanguage/language.vue | 72 + .../views/system/abplanguage/languagetext.vue | 147 + .../src/views/system/abplanguage/schema.ts | 163 + .../src/views/system/abplog/audit.vue | 82 + .../src/views/system/abplog/login.vue | 62 + .../src/views/system/abplog/schema.ts | 114 + .../views/system/abpnotification/message.vue | 269 + .../system/abpnotification/notification.vue | 157 + .../views/system/abpnotification/schema.ts | 284 + .../abporganizationunit/ContextMenu.vue | 55 + .../abporganizationunit/OrgTreeAddModal.vue | 83 + .../abporganizationunit/OrgTreeEditModal.vue | 71 + .../system/abporganizationunit/index.vue | 693 + .../src/views/system/abprole/index.vue | 337 + .../src/views/system/abprole/schema.ts | 62 + .../src/views/system/abpsetting/index.vue | 138 + .../views/system/abptenant/AddEditModal.vue | 63 + .../abptenant/ConnectionStringModal.vue | 136 + .../system/abptenant/FeatureManageModal.vue | 132 + .../src/views/system/abptenant/index.vue | 245 + .../src/views/system/abptenant/schema.ts | 74 + .../src/views/system/abpuser/index.vue | 331 + .../src/views/system/abpuser/schema.ts | 166 + apps/web-antd/tailwind.config.mjs | 1 + apps/web-antd/tsconfig.json | 12 + apps/web-antd/tsconfig.node.json | 10 + apps/web-antd/vite.config.mts | 32 + cspell.json | 68 + eslint.config.mjs | 5 + .../lint-configs/commitlint-config/index.mjs | 153 + .../commitlint-config/package.json | 33 + .../eslint-config/build.config.ts | 7 + .../lint-configs/eslint-config/package.json | 56 + .../eslint-config/src/configs/command.ts | 10 + .../eslint-config/src/configs/comments.ts | 24 + .../eslint-config/src/configs/disableds.ts | 28 + .../eslint-config/src/configs/ignores.ts | 52 + .../eslint-config/src/configs/import.ts | 25 + .../eslint-config/src/configs/index.ts | 17 + .../eslint-config/src/configs/javascript.ts | 241 + .../eslint-config/src/configs/jsdoc.ts | 34 + .../eslint-config/src/configs/jsonc.ts | 258 + .../eslint-config/src/configs/node.ts | 57 + .../src/configs/perfectionist.ts | 89 + .../eslint-config/src/configs/prettier.ts | 19 + .../eslint-config/src/configs/regexp.ts | 20 + .../eslint-config/src/configs/test.ts | 45 + .../eslint-config/src/configs/turbo.ts | 18 + .../eslint-config/src/configs/typescript.ts | 72 + .../eslint-config/src/configs/unicorn.ts | 45 + .../eslint-config/src/configs/vue.ts | 149 + .../eslint-config/src/custom-config.ts | 161 + .../lint-configs/eslint-config/src/index.ts | 60 + .../lint-configs/eslint-config/src/util.ts | 8 + .../lint-configs/eslint-config/tsconfig.json | 6 + .../lint-configs/prettier-config/index.mjs | 18 + .../lint-configs/prettier-config/package.json | 28 + .../lint-configs/stylelint-config/index.mjs | 140 + .../stylelint-config/package.json | 43 + internal/node-utils/build.config.ts | 7 + internal/node-utils/package.json | 43 + .../node-utils/src/__tests__/hash.test.ts | 52 + .../node-utils/src/__tests__/path.test.ts | 67 + internal/node-utils/src/constants.ts | 6 + internal/node-utils/src/date.ts | 12 + internal/node-utils/src/fs.ts | 39 + internal/node-utils/src/git.ts | 34 + internal/node-utils/src/hash.ts | 18 + internal/node-utils/src/index.ts | 19 + internal/node-utils/src/monorepo.ts | 46 + internal/node-utils/src/path.ts | 11 + internal/node-utils/src/prettier.ts | 21 + internal/node-utils/src/spinner.ts | 26 + internal/node-utils/tsconfig.json | 6 + internal/tailwind-config/build.config.ts | 10 + internal/tailwind-config/package.json | 66 + internal/tailwind-config/src/index.ts | 266 + internal/tailwind-config/src/module.d.ts | 3 + internal/tailwind-config/src/plugins/entry.ts | 53 + .../tailwind-config/src/postcss.config.ts | 15 + internal/tailwind-config/tsconfig.json | 6 + internal/tsconfig/base.json | 40 + internal/tsconfig/library.json | 13 + internal/tsconfig/node.json | 12 + internal/tsconfig/package.json | 25 + internal/tsconfig/web-app.json | 8 + internal/tsconfig/web.json | 14 + internal/vite-config/build.config.ts | 7 + internal/vite-config/package.json | 59 + .../vite-config/src/config/application.ts | 125 + internal/vite-config/src/config/common.ts | 13 + internal/vite-config/src/config/index.ts | 37 + internal/vite-config/src/config/library.ts | 59 + internal/vite-config/src/index.ts | 4 + internal/vite-config/src/options.ts | 45 + internal/vite-config/src/plugins/archiver.ts | 75 + .../src/plugins/extra-app-config.ts | 92 + internal/vite-config/src/plugins/importmap.ts | 245 + internal/vite-config/src/plugins/index.ts | 247 + .../src/plugins/inject-app-loading/README.md | 3 + .../default-loading-antd.html | 107 + .../inject-app-loading/default-loading.html | 113 + .../src/plugins/inject-app-loading/index.ts | 66 + .../src/plugins/inject-metadata.ts | 111 + internal/vite-config/src/plugins/license.ts | 63 + .../vite-config/src/plugins/nitro-mock.ts | 98 + internal/vite-config/src/plugins/print.ts | 28 + internal/vite-config/src/plugins/vxe-table.ts | 20 + internal/vite-config/src/typing.ts | 164 + internal/vite-config/src/utils/env.ts | 110 + internal/vite-config/tsconfig.json | 6 + package.json | 118 + packages/@core/README.md | 3 + packages/@core/base/README.md | 5 + packages/@core/base/design/package.json | 41 + packages/@core/base/design/src/css/global.css | 160 + .../@core/base/design/src/css/nprogress.css | 59 + .../@core/base/design/src/css/transition.css | 236 + packages/@core/base/design/src/css/ui.css | 87 + .../base/design/src/design-tokens/dark.css | 446 + .../base/design/src/design-tokens/default.css | 381 + .../base/design/src/design-tokens/index.ts | 4 + packages/@core/base/design/src/index.ts | 8 + .../@core/base/design/src/scss-bem/bem.scss | 34 + .../base/design/src/scss-bem/constants.scss | 5 + packages/@core/base/design/tsconfig.json | 6 + packages/@core/base/design/vite.config.mts | 9 + packages/@core/base/icons/build.config.ts | 7 + packages/@core/base/icons/package.json | 41 + packages/@core/base/icons/src/create-icon.ts | 14 + packages/@core/base/icons/src/index.ts | 11 + packages/@core/base/icons/src/lucide.ts | 60 + packages/@core/base/icons/tsconfig.json | 6 + packages/@core/base/shared/build.config.ts | 14 + packages/@core/base/shared/package.json | 101 + .../cache/__tests__/storage-manager.test.ts | 130 + packages/@core/base/shared/src/cache/index.ts | 1 + .../base/shared/src/cache/storage-manager.ts | 118 + packages/@core/base/shared/src/cache/types.ts | 17 + .../src/color/__tests__/convert.test.ts | 58 + packages/@core/base/shared/src/color/color.ts | 9 + .../@core/base/shared/src/color/convert.ts | 62 + .../@core/base/shared/src/color/generator.ts | 45 + packages/@core/base/shared/src/color/index.ts | 3 + .../base/shared/src/constants/globals.ts | 16 + .../@core/base/shared/src/constants/index.ts | 2 + .../@core/base/shared/src/constants/vben.ts | 26 + .../@core/base/shared/src/global-state.ts | 45 + packages/@core/base/shared/src/store.ts | 1 + .../shared/src/utils/__tests__/diff.test.ts | 53 + .../shared/src/utils/__tests__/dom.test.ts | 127 + .../src/utils/__tests__/inference.test.ts | 183 + .../shared/src/utils/__tests__/letter.test.ts | 116 + .../src/utils/__tests__/state-handler.test.ts | 60 + .../shared/src/utils/__tests__/tree.test.ts | 196 + .../shared/src/utils/__tests__/unique.test.ts | 60 + .../__tests__/update-css-variables.test.ts | 30 + .../shared/src/utils/__tests__/util.test.ts | 156 + .../shared/src/utils/__tests__/window.test.ts | 33 + packages/@core/base/shared/src/utils/cn.ts | 10 + packages/@core/base/shared/src/utils/date.ts | 26 + packages/@core/base/shared/src/utils/diff.ts | 96 + packages/@core/base/shared/src/utils/dom.ts | 95 + .../@core/base/shared/src/utils/download.ts | 157 + packages/@core/base/shared/src/utils/index.ts | 19 + .../@core/base/shared/src/utils/inference.ts | 164 + .../@core/base/shared/src/utils/letter.ts | 47 + packages/@core/base/shared/src/utils/merge.ts | 10 + .../@core/base/shared/src/utils/nprogress.ts | 43 + .../base/shared/src/utils/state-handler.ts | 50 + packages/@core/base/shared/src/utils/to.ts | 21 + packages/@core/base/shared/src/utils/tree.ts | 97 + .../@core/base/shared/src/utils/unique.ts | 15 + .../shared/src/utils/update-css-variables.ts | 35 + packages/@core/base/shared/src/utils/util.ts | 44 + .../@core/base/shared/src/utils/window.ts | 37 + packages/@core/base/shared/tsconfig.json | 6 + packages/@core/base/typings/build.config.ts | 7 + packages/@core/base/typings/package.json | 44 + packages/@core/base/typings/src/app.d.ts | 110 + packages/@core/base/typings/src/basic.d.ts | 35 + packages/@core/base/typings/src/helper.d.ts | 132 + packages/@core/base/typings/src/index.ts | 6 + .../@core/base/typings/src/menu-record.ts | 76 + packages/@core/base/typings/src/tabs.ts | 3 + .../@core/base/typings/src/vue-router.d.ts | 149 + packages/@core/base/typings/tsconfig.json | 6 + packages/@core/base/typings/vue-router.d.ts | 9 + packages/@core/composables/build.config.ts | 7 + packages/@core/composables/package.json | 47 + .../src/__tests__/use-sortable.test.ts | 48 + packages/@core/composables/src/index.ts | 13 + .../@core/composables/src/use-is-mobile.ts | 7 + .../@core/composables/src/use-layout-style.ts | 87 + .../@core/composables/src/use-namespace.ts | 106 + .../composables/src/use-priority-value.ts | 94 + .../@core/composables/src/use-scroll-lock.ts | 54 + .../src/use-simple-locale/README.md | 3 + .../src/use-simple-locale/index.ts | 27 + .../src/use-simple-locale/messages.ts | 22 + .../@core/composables/src/use-sortable.ts | 29 + packages/@core/composables/tsconfig.json | 6 + .../__snapshots__/config.test.ts.snap | 119 + .../preferences/__tests__/config.test.ts | 10 + .../preferences/__tests__/preferences.test.ts | 253 + packages/@core/preferences/build.config.ts | 7 + packages/@core/preferences/package.json | 37 + packages/@core/preferences/src/config.ts | 120 + packages/@core/preferences/src/constants.ts | 88 + packages/@core/preferences/src/index.ts | 35 + packages/@core/preferences/src/preferences.ts | 228 + packages/@core/preferences/src/types.ts | 290 + .../preferences/src/update-css-variables.ts | 116 + .../@core/preferences/src/use-preferences.ts | 254 + packages/@core/preferences/tsconfig.json | 6 + packages/@core/ui-kit/README.md | 3 + .../ui-kit/form-ui/__tests__/form-api.test.ts | 189 + packages/@core/ui-kit/form-ui/build.config.ts | 21 + packages/@core/ui-kit/form-ui/package.json | 51 + .../@core/ui-kit/form-ui/postcss.config.mjs | 1 + .../form-ui/src/components/form-actions.vue | 160 + packages/@core/ui-kit/form-ui/src/config.ts | 87 + packages/@core/ui-kit/form-ui/src/form-api.ts | 412 + .../ui-kit/form-ui/src/form-render/context.ts | 24 + .../form-ui/src/form-render/dependencies.ts | 124 + .../form-ui/src/form-render/expandable.ts | 99 + .../form-ui/src/form-render/form-field.vue | 357 + .../form-ui/src/form-render/form-label.vue | 22 + .../ui-kit/form-ui/src/form-render/form.vue | 165 + .../ui-kit/form-ui/src/form-render/helper.ts | 60 + .../ui-kit/form-ui/src/form-render/index.ts | 3 + packages/@core/ui-kit/form-ui/src/index.ts | 12 + packages/@core/ui-kit/form-ui/src/types.ts | 414 + .../ui-kit/form-ui/src/use-form-context.ts | 65 + .../@core/ui-kit/form-ui/src/use-vben-form.ts | 50 + .../@core/ui-kit/form-ui/src/vben-form.vue | 77 + .../ui-kit/form-ui/src/vben-use-form.vue | 110 + .../@core/ui-kit/form-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/form-ui/tsconfig.json | 6 + .../@core/ui-kit/layout-ui/build.config.ts | 21 + packages/@core/ui-kit/layout-ui/package.json | 48 + .../@core/ui-kit/layout-ui/postcss.config.mjs | 1 + .../ui-kit/layout-ui/src/components/index.ts | 5 + .../src/components/layout-content.vue | 64 + .../src/components/layout-footer.vue | 44 + .../src/components/layout-header.vue | 77 + .../src/components/layout-sidebar.vue | 316 + .../src/components/layout-tabbar.vue | 30 + .../layout-ui/src/components/widgets/index.ts | 2 + .../widgets/sidebar-collapse-button.vue | 19 + .../widgets/sidebar-fixed-button.vue | 19 + .../ui-kit/layout-ui/src/hooks/use-layout.ts | 53 + packages/@core/ui-kit/layout-ui/src/index.ts | 2 + .../@core/ui-kit/layout-ui/src/vben-layout.ts | 165 + .../ui-kit/layout-ui/src/vben-layout.vue | 606 + .../ui-kit/layout-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/layout-ui/tsconfig.json | 6 + packages/@core/ui-kit/menu-ui/README.md | 1 + packages/@core/ui-kit/menu-ui/build.config.ts | 26 + packages/@core/ui-kit/menu-ui/package.json | 48 + .../@core/ui-kit/menu-ui/postcss.config.mjs | 1 + .../src/components/collapse-transition.vue | 96 + .../ui-kit/menu-ui/src/components/index.ts | 4 + .../menu-ui/src/components/menu-badge-dot.vue | 28 + .../menu-ui/src/components/menu-badge.vue | 57 + .../menu-ui/src/components/menu-item.vue | 122 + .../ui-kit/menu-ui/src/components/menu.vue | 860 + .../src/components/normal-menu/index.ts | 2 + .../src/components/normal-menu/normal-menu.ts | 27 + .../components/normal-menu/normal-menu.vue | 161 + .../src/components/sub-menu-content.vue | 105 + .../menu-ui/src/components/sub-menu.vue | 273 + .../@core/ui-kit/menu-ui/src/hooks/index.ts | 2 + .../menu-ui/src/hooks/use-menu-context.ts | 55 + .../ui-kit/menu-ui/src/hooks/use-menu.ts | 48 + packages/@core/ui-kit/menu-ui/src/index.ts | 4 + packages/@core/ui-kit/menu-ui/src/menu.vue | 38 + .../@core/ui-kit/menu-ui/src/sub-menu.vue | 71 + packages/@core/ui-kit/menu-ui/src/types.ts | 139 + .../@core/ui-kit/menu-ui/src/utils/index.ts | 52 + .../@core/ui-kit/menu-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/menu-ui/tsconfig.json | 6 + .../@core/ui-kit/popup-ui/build.config.ts | 21 + packages/@core/ui-kit/popup-ui/package.json | 48 + .../@core/ui-kit/popup-ui/postcss.config.mjs | 1 + .../src/drawer/__tests__/drawer-api.test.ts | 117 + .../ui-kit/popup-ui/src/drawer/drawer-api.ts | 159 + .../ui-kit/popup-ui/src/drawer/drawer.ts | 175 + .../ui-kit/popup-ui/src/drawer/drawer.vue | 277 + .../@core/ui-kit/popup-ui/src/drawer/index.ts | 3 + .../ui-kit/popup-ui/src/drawer/use-drawer.ts | 139 + packages/@core/ui-kit/popup-ui/src/index.ts | 2 + .../src/modal/__tests__/modal-api.test.ts | 117 + .../@core/ui-kit/popup-ui/src/modal/index.ts | 3 + .../ui-kit/popup-ui/src/modal/modal-api.ts | 183 + .../@core/ui-kit/popup-ui/src/modal/modal.ts | 189 + .../@core/ui-kit/popup-ui/src/modal/modal.vue | 319 + .../popup-ui/src/modal/use-modal-draggable.ts | 117 + .../ui-kit/popup-ui/src/modal/use-modal.ts | 147 + .../@core/ui-kit/popup-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/popup-ui/tsconfig.json | 6 + .../@core/ui-kit/shadcn-ui/build.config.ts | 27 + .../@core/ui-kit/shadcn-ui/components.json | 16 + packages/@core/ui-kit/shadcn-ui/package.json | 54 + .../@core/ui-kit/shadcn-ui/postcss.config.mjs | 1 + .../src/components/avatar/avatar.vue | 50 + .../shadcn-ui/src/components/avatar/index.ts | 1 + .../src/components/back-top/back-top.vue | 43 + .../src/components/back-top/backtop.ts | 38 + .../src/components/back-top/index.ts | 1 + .../src/components/back-top/use-backtop.ts | 45 + .../breadcrumb/breadcrumb-background.vue | 109 + .../components/breadcrumb/breadcrumb-view.vue | 22 + .../src/components/breadcrumb/breadcrumb.vue | 98 + .../src/components/breadcrumb/index.ts | 3 + .../src/components/breadcrumb/types.ts | 17 + .../shadcn-ui/src/components/button/button.ts | 24 + .../src/components/button/button.vue | 42 + .../src/components/button/icon-button.vue | 68 + .../shadcn-ui/src/components/button/index.ts | 3 + .../src/components/checkbox/checkbox.vue | 26 + .../src/components/checkbox/index.ts | 1 + .../components/context-menu/context-menu.vue | 97 + .../src/components/context-menu/index.ts | 3 + .../src/components/context-menu/interface.ts | 38 + .../count-to-animator/count-to-animator.vue | 111 + .../src/components/count-to-animator/index.ts | 1 + .../dropdown-menu/dropdown-menu.vue | 49 + .../dropdown-menu/dropdown-radio-menu.vue | 52 + .../src/components/dropdown-menu/index.ts | 4 + .../src/components/dropdown-menu/interface.ts | 32 + .../expandable-arrow/expandable-arrow.vue | 31 + .../src/components/expandable-arrow/index.ts | 1 + .../components/full-screen/full-screen.vue | 28 + .../src/components/full-screen/index.ts | 1 + .../src/components/hover-card/hover-card.vue | 55 + .../src/components/hover-card/index.ts | 2 + .../shadcn-ui/src/components/icon/icon.vue | 35 + .../shadcn-ui/src/components/icon/index.ts | 1 + .../ui-kit/shadcn-ui/src/components/index.ts | 23 + .../src/components/input-password/index.ts | 1 + .../input-password/input-password.vue | 57 + .../input-password/password-strength.vue | 66 + .../shadcn-ui/src/components/logo/index.ts | 1 + .../shadcn-ui/src/components/logo/logo.vue | 65 + .../src/components/pin-input/index.ts | 3 + .../src/components/pin-input/input.vue | 120 + .../src/components/pin-input/types.ts | 30 + .../shadcn-ui/src/components/popover/index.ts | 1 + .../src/components/popover/popover.vue | 58 + .../src/components/render-content/index.ts | 1 + .../render-content/render-content.vue | 40 + .../src/components/scrollbar/index.ts | 1 + .../src/components/scrollbar/scrollbar.vue | 153 + .../src/components/segmented/index.ts | 3 + .../src/components/segmented/segmented.vue | 59 + .../components/segmented/tabs-indicator.vue | 37 + .../src/components/segmented/types.ts | 6 + .../shadcn-ui/src/components/select/index.ts | 1 + .../src/components/select/select.vue | 35 + .../src/components/spine-text/index.ts | 1 + .../src/components/spine-text/spine-text.vue | 49 + .../shadcn-ui/src/components/spinner/index.ts | 2 + .../src/components/spinner/loading.vue | 137 + .../src/components/spinner/spinner.vue | 136 + .../src/components/tooltip/help-tooltip.vue | 31 + .../shadcn-ui/src/components/tooltip/index.ts | 2 + .../src/components/tooltip/tooltip.vue | 44 + packages/@core/ui-kit/shadcn-ui/src/index.ts | 3 + .../shadcn-ui/src/ui/accordion/Accordion.vue | 16 + .../src/ui/accordion/AccordionContent.vue | 28 + .../src/ui/accordion/AccordionItem.vue | 25 + .../src/ui/accordion/AccordionTrigger.vue | 39 + .../shadcn-ui/src/ui/accordion/index.ts | 4 + .../ui-kit/shadcn-ui/src/ui/avatar/Avatar.vue | 27 + .../src/ui/avatar/AvatarFallback.vue | 13 + .../shadcn-ui/src/ui/avatar/AvatarImage.vue | 11 + .../ui-kit/shadcn-ui/src/ui/avatar/avatar.ts | 22 + .../ui-kit/shadcn-ui/src/ui/avatar/index.ts | 4 + .../ui-kit/shadcn-ui/src/ui/badge/Badge.vue | 18 + .../ui-kit/shadcn-ui/src/ui/badge/badge.ts | 25 + .../ui-kit/shadcn-ui/src/ui/badge/index.ts | 3 + .../src/ui/breadcrumb/Breadcrumb.vue | 11 + .../src/ui/breadcrumb/BreadcrumbEllipsis.vue | 22 + .../src/ui/breadcrumb/BreadcrumbItem.vue | 17 + .../src/ui/breadcrumb/BreadcrumbLink.vue | 21 + .../src/ui/breadcrumb/BreadcrumbList.vue | 20 + .../src/ui/breadcrumb/BreadcrumbPage.vue | 18 + .../src/ui/breadcrumb/BreadcrumbSeparator.vue | 21 + .../shadcn-ui/src/ui/breadcrumb/index.ts | 7 + .../ui-kit/shadcn-ui/src/ui/button/Button.vue | 32 + .../ui-kit/shadcn-ui/src/ui/button/button.ts | 34 + .../ui-kit/shadcn-ui/src/ui/button/index.ts | 5 + .../ui-kit/shadcn-ui/src/ui/button/types.ts | 20 + .../ui-kit/shadcn-ui/src/ui/card/Card.vue | 20 + .../shadcn-ui/src/ui/card/CardContent.vue | 13 + .../shadcn-ui/src/ui/card/CardDescription.vue | 13 + .../shadcn-ui/src/ui/card/CardFooter.vue | 13 + .../shadcn-ui/src/ui/card/CardHeader.vue | 13 + .../shadcn-ui/src/ui/card/CardTitle.vue | 13 + .../ui-kit/shadcn-ui/src/ui/card/index.ts | 6 + .../shadcn-ui/src/ui/checkbox/Checkbox.vue | 45 + .../ui-kit/shadcn-ui/src/ui/checkbox/index.ts | 1 + .../src/ui/context-menu/ContextMenu.vue | 18 + .../context-menu/ContextMenuCheckboxItem.vue | 47 + .../ui/context-menu/ContextMenuContent.vue | 43 + .../src/ui/context-menu/ContextMenuGroup.vue | 13 + .../src/ui/context-menu/ContextMenuItem.vue | 37 + .../src/ui/context-menu/ContextMenuLabel.vue | 34 + .../src/ui/context-menu/ContextMenuPortal.vue | 13 + .../ui/context-menu/ContextMenuRadioGroup.vue | 19 + .../ui/context-menu/ContextMenuRadioItem.vue | 47 + .../ui/context-menu/ContextMenuSeparator.vue | 24 + .../ui/context-menu/ContextMenuShortcut.vue | 17 + .../src/ui/context-menu/ContextMenuSub.vue | 16 + .../ui/context-menu/ContextMenuSubContent.vue | 37 + .../ui/context-menu/ContextMenuSubTrigger.vue | 41 + .../ui/context-menu/ContextMenuTrigger.vue | 15 + .../shadcn-ui/src/ui/context-menu/index.ts | 14 + .../ui-kit/shadcn-ui/src/ui/dialog/Dialog.vue | 16 + .../shadcn-ui/src/ui/dialog/DialogClose.vue | 13 + .../shadcn-ui/src/ui/dialog/DialogContent.vue | 123 + .../src/ui/dialog/DialogDescription.vue | 28 + .../shadcn-ui/src/ui/dialog/DialogFooter.vue | 15 + .../shadcn-ui/src/ui/dialog/DialogHeader.vue | 15 + .../shadcn-ui/src/ui/dialog/DialogOverlay.vue | 11 + .../src/ui/dialog/DialogScrollContent.vue | 71 + .../shadcn-ui/src/ui/dialog/DialogTitle.vue | 30 + .../shadcn-ui/src/ui/dialog/DialogTrigger.vue | 13 + .../ui-kit/shadcn-ui/src/ui/dialog/index.ts | 9 + .../src/ui/dropdown-menu/DropdownMenu.vue | 18 + .../DropdownMenuCheckboxItem.vue | 47 + .../ui/dropdown-menu/DropdownMenuContent.vue | 48 + .../ui/dropdown-menu/DropdownMenuGroup.vue | 13 + .../src/ui/dropdown-menu/DropdownMenuItem.vue | 36 + .../ui/dropdown-menu/DropdownMenuLabel.vue | 32 + .../dropdown-menu/DropdownMenuRadioGroup.vue | 19 + .../dropdown-menu/DropdownMenuRadioItem.vue | 48 + .../dropdown-menu/DropdownMenuSeparator.vue | 28 + .../ui/dropdown-menu/DropdownMenuShortcut.vue | 13 + .../src/ui/dropdown-menu/DropdownMenuSub.vue | 16 + .../dropdown-menu/DropdownMenuSubContent.vue | 37 + .../dropdown-menu/DropdownMenuSubTrigger.vue | 35 + .../ui/dropdown-menu/DropdownMenuTrigger.vue | 15 + .../shadcn-ui/src/ui/dropdown-menu/index.ts | 16 + .../shadcn-ui/src/ui/form/FormControl.vue | 19 + .../shadcn-ui/src/ui/form/FormDescription.vue | 20 + .../ui-kit/shadcn-ui/src/ui/form/FormItem.vue | 20 + .../shadcn-ui/src/ui/form/FormLabel.vue | 18 + .../shadcn-ui/src/ui/form/FormMessage.vue | 18 + .../ui-kit/shadcn-ui/src/ui/form/index.ts | 11 + .../shadcn-ui/src/ui/form/injectionKeys.ts | 4 + .../shadcn-ui/src/ui/form/useFormField.ts | 38 + .../shadcn-ui/src/ui/hover-card/HoverCard.vue | 16 + .../src/ui/hover-card/HoverCardContent.vue | 40 + .../src/ui/hover-card/HoverCardTrigger.vue | 13 + .../shadcn-ui/src/ui/hover-card/index.ts | 3 + .../@core/ui-kit/shadcn-ui/src/ui/index.ts | 29 + .../ui-kit/shadcn-ui/src/ui/input/Input.vue | 32 + .../ui-kit/shadcn-ui/src/ui/input/index.ts | 1 + .../ui-kit/shadcn-ui/src/ui/label/Label.vue | 31 + .../ui-kit/shadcn-ui/src/ui/label/index.ts | 1 + .../src/ui/number-field/NumberField.vue | 26 + .../ui/number-field/NumberFieldContent.vue | 20 + .../ui/number-field/NumberFieldDecrement.vue | 37 + .../ui/number-field/NumberFieldIncrement.vue | 37 + .../src/ui/number-field/NumberFieldInput.vue | 16 + .../shadcn-ui/src/ui/number-field/index.ts | 5 + .../src/ui/pagination/PaginationEllipsis.vue | 29 + .../src/ui/pagination/PaginationFirst.vue | 35 + .../src/ui/pagination/PaginationLast.vue | 35 + .../src/ui/pagination/PaginationNext.vue | 35 + .../src/ui/pagination/PaginationPrev.vue | 35 + .../shadcn-ui/src/ui/pagination/index.ts | 10 + .../shadcn-ui/src/ui/pin-input/PinInput.vue | 28 + .../src/ui/pin-input/PinInputGroup.vue | 25 + .../src/ui/pin-input/PinInputInput.vue | 30 + .../src/ui/pin-input/PinInputSeparator.vue | 17 + .../shadcn-ui/src/ui/pin-input/index.ts | 4 + .../shadcn-ui/src/ui/popover/Popover.vue | 16 + .../src/ui/popover/PopoverContent.vue | 46 + .../src/ui/popover/PopoverTrigger.vue | 13 + .../ui-kit/shadcn-ui/src/ui/popover/index.ts | 4 + .../src/ui/radio-group/RadioGroup.vue | 26 + .../src/ui/radio-group/RadioGroupItem.vue | 40 + .../shadcn-ui/src/ui/radio-group/index.ts | 2 + .../src/ui/resizable/ResizableHandle.vue | 50 + .../src/ui/resizable/ResizablePanelGroup.vue | 37 + .../shadcn-ui/src/ui/resizable/index.ts | 3 + .../src/ui/scroll-area/ScrollArea.vue | 50 + .../src/ui/scroll-area/ScrollBar.vue | 40 + .../shadcn-ui/src/ui/scroll-area/index.ts | 2 + .../ui-kit/shadcn-ui/src/ui/select/Select.vue | 16 + .../shadcn-ui/src/ui/select/SelectContent.vue | 67 + .../shadcn-ui/src/ui/select/SelectGroup.vue | 23 + .../shadcn-ui/src/ui/select/SelectItem.vue | 47 + .../src/ui/select/SelectItemText.vue | 13 + .../shadcn-ui/src/ui/select/SelectLabel.vue | 15 + .../src/ui/select/SelectScrollDownButton.vue | 33 + .../src/ui/select/SelectScrollUpButton.vue | 33 + .../src/ui/select/SelectSeparator.vue | 24 + .../shadcn-ui/src/ui/select/SelectTrigger.vue | 37 + .../shadcn-ui/src/ui/select/SelectValue.vue | 13 + .../ui-kit/shadcn-ui/src/ui/select/index.ts | 11 + .../shadcn-ui/src/ui/separator/Separator.vue | 44 + .../shadcn-ui/src/ui/separator/index.ts | 1 + .../ui-kit/shadcn-ui/src/ui/sheet/Sheet.vue | 16 + .../shadcn-ui/src/ui/sheet/SheetClose.vue | 13 + .../shadcn-ui/src/ui/sheet/SheetContent.vue | 107 + .../src/ui/sheet/SheetDescription.vue | 26 + .../shadcn-ui/src/ui/sheet/SheetFooter.vue | 15 + .../shadcn-ui/src/ui/sheet/SheetHeader.vue | 11 + .../shadcn-ui/src/ui/sheet/SheetOverlay.vue | 11 + .../shadcn-ui/src/ui/sheet/SheetTitle.vue | 26 + .../shadcn-ui/src/ui/sheet/SheetTrigger.vue | 13 + .../ui-kit/shadcn-ui/src/ui/sheet/index.ts | 10 + .../ui-kit/shadcn-ui/src/ui/sheet/sheet.ts | 24 + .../ui-kit/shadcn-ui/src/ui/switch/Switch.vue | 41 + .../ui-kit/shadcn-ui/src/ui/switch/index.ts | 1 + .../ui-kit/shadcn-ui/src/ui/tabs/Tabs.vue | 16 + .../shadcn-ui/src/ui/tabs/TabsContent.vue | 31 + .../ui-kit/shadcn-ui/src/ui/tabs/TabsList.vue | 31 + .../shadcn-ui/src/ui/tabs/TabsTrigger.vue | 33 + .../ui-kit/shadcn-ui/src/ui/tabs/index.ts | 5 + .../shadcn-ui/src/ui/textarea/Textarea.vue | 32 + .../ui-kit/shadcn-ui/src/ui/textarea/index.ts | 1 + .../src/ui/toggle-group/ToggleGroup.vue | 44 + .../src/ui/toggle-group/ToggleGroupItem.vue | 48 + .../shadcn-ui/src/ui/toggle-group/index.ts | 2 + .../ui-kit/shadcn-ui/src/ui/toggle/Toggle.vue | 47 + .../ui-kit/shadcn-ui/src/ui/toggle/index.ts | 2 + .../ui-kit/shadcn-ui/src/ui/toggle/toggle.ts | 27 + .../shadcn-ui/src/ui/tooltip/Tooltip.vue | 16 + .../src/ui/tooltip/TooltipContent.vue | 48 + .../src/ui/tooltip/TooltipProvider.vue | 13 + .../src/ui/tooltip/TooltipTrigger.vue | 13 + .../ui-kit/shadcn-ui/src/ui/tooltip/index.ts | 4 + .../ui-kit/shadcn-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/shadcn-ui/tsconfig.json | 12 + packages/@core/ui-kit/tabs-ui/build.config.ts | 21 + packages/@core/ui-kit/tabs-ui/package.json | 47 + .../@core/ui-kit/tabs-ui/postcss.config.mjs | 1 + .../ui-kit/tabs-ui/src/components/index.ts | 2 + .../src/components/tabs-chrome/tabs.vue | 210 + .../tabs-ui/src/components/tabs/tabs.vue | 148 + .../tabs-ui/src/components/widgets/index.ts | 2 + .../src/components/widgets/tool-more.vue | 18 + .../src/components/widgets/tool-screen.vue | 19 + packages/@core/ui-kit/tabs-ui/src/index.ts | 3 + .../@core/ui-kit/tabs-ui/src/tabs-view.vue | 106 + packages/@core/ui-kit/tabs-ui/src/types.ts | 73 + .../@core/ui-kit/tabs-ui/src/use-tabs-drag.ts | 124 + .../tabs-ui/src/use-tabs-view-scroll.ts | 202 + .../@core/ui-kit/tabs-ui/tailwind.config.mjs | 1 + packages/@core/ui-kit/tabs-ui/tsconfig.json | 6 + packages/constants/README.md | 19 + packages/constants/package.json | 25 + packages/constants/src/core.ts | 28 + packages/constants/src/index.ts | 2 + packages/constants/tsconfig.json | 6 + packages/effects/README.md | 10 + packages/effects/access/package.json | 29 + .../effects/access/src/access-control.vue | 47 + packages/effects/access/src/accessible.ts | 104 + packages/effects/access/src/directive.ts | 42 + packages/effects/access/src/index.ts | 4 + packages/effects/access/src/use-access.ts | 53 + packages/effects/access/tsconfig.json | 6 + packages/effects/common-ui/package.json | 44 + .../api-component/api-component.vue | 206 + .../src/components/api-component/index.ts | 1 + .../captcha/hooks/useCaptchaPoints.ts | 19 + .../common-ui/src/components/captcha/index.ts | 6 + .../captcha/point-selection-captcha/index.vue | 176 + .../point-selection-captcha-card.vue | 84 + .../captcha/slider-captcha/index.vue | 244 + .../slider-captcha/slider-captcha-action.vue | 65 + .../slider-captcha/slider-captcha-bar.vue | 40 + .../slider-captcha/slider-captcha-content.vue | 53 + .../captcha/slider-rotate-captcha/index.vue | 213 + .../common-ui/src/components/captcha/types.ts | 175 + .../src/components/col-page/col-page.vue | 107 + .../src/components/col-page/index.ts | 2 + .../src/components/col-page/types.ts | 26 + .../ellipsis-text/ellipsis-text.vue | 144 + .../src/components/ellipsis-text/index.ts | 1 + .../components/icon-picker/icon-picker.vue | 304 + .../src/components/icon-picker/icons.ts | 56 + .../src/components/icon-picker/index.ts | 1 + .../effects/common-ui/src/components/index.ts | 22 + .../components/page/__tests__/page.test.ts | 89 + .../common-ui/src/components/page/index.ts | 2 + .../common-ui/src/components/page/page.vue | 105 + .../common-ui/src/components/page/types.ts | 11 + .../common-ui/src/components/resize/index.ts | 1 + .../src/components/resize/resize.vue | 1122 + .../src/components/tippy/directive.ts | 100 + .../common-ui/src/components/tippy/index.ts | 67 + packages/effects/common-ui/src/index.ts | 2 + .../effects/common-ui/src/ui/about/about.ts | 14 + .../effects/common-ui/src/ui/about/about.vue | 183 + .../effects/common-ui/src/ui/about/index.ts | 1 + .../src/ui/authentication/auth-title.vue | 13 + .../src/ui/authentication/code-login.vue | 120 + .../src/ui/authentication/forget-password.vue | 116 + .../common-ui/src/ui/authentication/index.ts | 7 + .../ui/authentication/login-expired-modal.vue | 79 + .../common-ui/src/ui/authentication/login.vue | 205 + .../src/ui/authentication/qrcode-login.vue | 95 + .../src/ui/authentication/register.vue | 121 + .../ui/authentication/third-party-login.vue | 42 + .../common-ui/src/ui/authentication/types.ts | 80 + .../analysis/analysis-chart-card.vue | 24 + .../analysis/analysis-charts-tabs.vue | 40 + .../dashboard/analysis/analysis-overview.vue | 55 + .../src/ui/dashboard/analysis/index.ts | 3 + .../common-ui/src/ui/dashboard/index.ts | 3 + .../common-ui/src/ui/dashboard/typing.ts | 48 + .../src/ui/dashboard/workbench/index.ts | 5 + .../dashboard/workbench/workbench-header.vue | 46 + .../dashboard/workbench/workbench-project.vue | 63 + .../workbench/workbench-quick-nav.vue | 54 + .../ui/dashboard/workbench/workbench-todo.vue | 63 + .../dashboard/workbench/workbench-trends.vue | 64 + .../common-ui/src/ui/fallback/fallback.ts | 25 + .../common-ui/src/ui/fallback/fallback.vue | 164 + .../src/ui/fallback/icons/icon-403.vue | 151 + .../src/ui/fallback/icons/icon-404.vue | 154 + .../src/ui/fallback/icons/icon-500.vue | 215 + .../ui/fallback/icons/icon-coming-soon.vue | 262 + .../src/ui/fallback/icons/icon-offline.vue | 112 + .../src/ui/fallback/icons/warning.svg | 1 + .../common-ui/src/ui/fallback/index.ts | 2 + packages/effects/common-ui/src/ui/index.ts | 4 + packages/effects/common-ui/tsconfig.json | 6 + packages/effects/hooks/README.md | 19 + packages/effects/hooks/package.json | 34 + packages/effects/hooks/src/index.ts | 10 + packages/effects/hooks/src/use-app-config.ts | 23 + .../effects/hooks/src/use-content-maximize.ts | 24 + .../effects/hooks/src/use-design-tokens.ts | 281 + packages/effects/hooks/src/use-event-bus.ts | 44 + .../effects/hooks/src/use-hover-toggle.ts | 64 + packages/effects/hooks/src/use-pagination.ts | 58 + packages/effects/hooks/src/use-refresh.ts | 16 + packages/effects/hooks/src/use-tabs.ts | 115 + packages/effects/hooks/src/use-watermark.ts | 88 + packages/effects/hooks/tsconfig.json | 9 + packages/effects/layouts/package.json | 43 + .../src/authentication/authentication.vue | 156 + .../layouts/src/authentication/form.vue | 33 + .../src/authentication/icons/slogan.vue | 4568 ++++ .../layouts/src/authentication/index.ts | 1 + .../layouts/src/authentication/toolbar.vue | 49 + .../layouts/src/authentication/types.ts | 1 + packages/effects/layouts/src/basic/README.md | 7 + .../src/basic/content/content-spinner.vue | 12 + .../layouts/src/basic/content/content.vue | 114 + .../layouts/src/basic/content/index.ts | 2 + .../src/basic/content/use-content-spinner.ts | 50 + .../layouts/src/basic/copyright/copyright.vue | 48 + .../layouts/src/basic/copyright/index.ts | 1 + .../layouts/src/basic/footer/footer.vue | 11 + .../effects/layouts/src/basic/footer/index.ts | 1 + .../layouts/src/basic/header/header.vue | 185 + .../effects/layouts/src/basic/header/index.ts | 1 + packages/effects/layouts/src/basic/index.ts | 1 + packages/effects/layouts/src/basic/layout.vue | 356 + .../layouts/src/basic/menu/extra-menu.vue | 41 + .../effects/layouts/src/basic/menu/index.ts | 5 + .../effects/layouts/src/basic/menu/menu.vue | 44 + .../layouts/src/basic/menu/mixed-menu.vue | 46 + .../layouts/src/basic/menu/use-extra-menu.ts | 129 + .../layouts/src/basic/menu/use-mixed-menu.ts | 165 + .../layouts/src/basic/menu/use-navigation.ts | 35 + .../effects/layouts/src/basic/tabbar/index.ts | 2 + .../layouts/src/basic/tabbar/tabbar.vue | 75 + .../layouts/src/basic/tabbar/use-tabbar.ts | 222 + .../layouts/src/iframe/iframe-router-view.vue | 86 + .../layouts/src/iframe/iframe-view.vue | 3 + packages/effects/layouts/src/iframe/index.ts | 2 + packages/effects/layouts/src/index.ts | 4 + .../layouts/src/widgets/breadcrumb.vue | 74 + .../widgets/check-updates/check-updates.vue | 135 + .../src/widgets/check-updates/index.ts | 1 + .../layouts/src/widgets/color-toggle.vue | 64 + .../widgets/global-search/global-search.vue | 157 + .../src/widgets/global-search/index.ts | 1 + .../widgets/global-search/search-panel.vue | 288 + packages/effects/layouts/src/widgets/index.ts | 11 + .../layouts/src/widgets/language-toggle.vue | 38 + .../layouts/src/widgets/layout-toggle.vue | 63 + .../layouts/src/widgets/lock-screen/index.ts | 2 + .../widgets/lock-screen/lock-screen-modal.vue | 102 + .../src/widgets/lock-screen/lock-screen.vue | 156 + .../layouts/src/widgets/notification/index.ts | 3 + .../src/widgets/notification/notification.vue | 195 + .../layouts/src/widgets/notification/types.ts | 10 + .../src/widgets/preferences/blocks/block.vue | 22 + .../preferences/blocks/general/animation.vue | 51 + .../preferences/blocks/general/general.vue | 31 + .../src/widgets/preferences/blocks/index.ts | 19 + .../widgets/preferences/blocks/input-item.vue | 52 + .../preferences/blocks/layout/breadcrumb.vue | 56 + .../preferences/blocks/layout/content.vue | 53 + .../preferences/blocks/layout/copyright.vue | 44 + .../preferences/blocks/layout/footer.vue | 17 + .../preferences/blocks/layout/header.vue | 74 + .../preferences/blocks/layout/layout.vue | 112 + .../preferences/blocks/layout/navigation.vue | 45 + .../preferences/blocks/layout/sidebar.vue | 65 + .../preferences/blocks/layout/tabbar.vue | 82 + .../preferences/blocks/layout/widget.vue | 71 + .../preferences/blocks/number-field-item.vue | 66 + .../preferences/blocks/select-item.vue | 68 + .../blocks/shortcut-keys/global.vue | 50 + .../preferences/blocks/switch-item.vue | 55 + .../preferences/blocks/theme/builtin.vue | 150 + .../preferences/blocks/theme/color-mode.vue | 26 + .../preferences/blocks/theme/radius.vue | 38 + .../preferences/blocks/theme/theme.vue | 83 + .../preferences/blocks/toggle-item.vue | 46 + .../preferences/icons/content-compact.vue | 119 + .../preferences/icons/full-content.vue | 50 + .../preferences/icons/header-mixed-nav.vue | 202 + .../widgets/preferences/icons/header-nav.vue | 119 + .../preferences/icons/header-sidebar-nav.vue | 177 + .../src/widgets/preferences/icons/index.ts | 12 + .../widgets/preferences/icons/mixed-nav.vue | 161 + .../src/widgets/preferences/icons/setting.vue | 12 + .../preferences/icons/sidebar-mixed-nav.vue | 173 + .../widgets/preferences/icons/sidebar-nav.vue | 153 + .../layouts/src/widgets/preferences/index.ts | 3 + .../preferences/preferences-button.vue | 20 + .../preferences/preferences-drawer.vue | 444 + .../src/widgets/preferences/preferences.vue | 72 + .../preferences/use-open-preferences.ts | 16 + .../layouts/src/widgets/theme-toggle/index.ts | 1 + .../src/widgets/theme-toggle/theme-button.vue | 185 + .../src/widgets/theme-toggle/theme-toggle.vue | 83 + .../src/widgets/user-dropdown/index.ts | 1 + .../widgets/user-dropdown/user-dropdown.vue | 258 + packages/effects/layouts/tsconfig.json | 6 + packages/effects/plugins/README.md | 28 + packages/effects/plugins/package.json | 42 + .../plugins/src/echarts/echarts-ui.vue | 15 + .../effects/plugins/src/echarts/echarts.ts | 59 + packages/effects/plugins/src/echarts/index.ts | 3 + .../plugins/src/echarts/use-echarts.ts | 122 + packages/effects/plugins/src/vxe-table/api.ts | 128 + .../effects/plugins/src/vxe-table/extends.ts | 81 + .../effects/plugins/src/vxe-table/index.ts | 6 + .../effects/plugins/src/vxe-table/init.ts | 131 + .../effects/plugins/src/vxe-table/style.css | 104 + .../effects/plugins/src/vxe-table/types.ts | 78 + .../plugins/src/vxe-table/use-vxe-grid.ts | 45 + .../plugins/src/vxe-table/use-vxe-grid.vue | 401 + packages/effects/plugins/tsconfig.json | 6 + packages/effects/request/package.json | 30 + packages/effects/request/src/index.ts | 2 + .../request/src/request-client/index.ts | 3 + .../request-client/modules/downloader.test.ts | 86 + .../src/request-client/modules/downloader.ts | 41 + .../src/request-client/modules/interceptor.ts | 40 + .../request-client/modules/uploader.test.ts | 118 + .../src/request-client/modules/uploader.ts | 34 + .../src/request-client/preset-interceptors.ts | 165 + .../src/request-client/request-client.test.ts | 99 + .../src/request-client/request-client.ts | 119 + .../request/src/request-client/types.ts | 67 + packages/effects/request/tsconfig.json | 6 + packages/icons/README.md | 19 + packages/icons/package.json | 22 + packages/icons/src/iconify/index.ts | 17 + packages/icons/src/icons/empty-icon.vue | 27 + packages/icons/src/index.ts | 3 + packages/icons/src/svg/icons/antdv-logo.svg | 29 + packages/icons/src/svg/icons/avatar-1.svg | 1 + packages/icons/src/svg/icons/avatar-2.svg | 1 + packages/icons/src/svg/icons/avatar-3.svg | 1 + packages/icons/src/svg/icons/avatar-4.svg | 1 + packages/icons/src/svg/icons/bell.svg | 1 + packages/icons/src/svg/icons/cake.svg | 1 + packages/icons/src/svg/icons/card.svg | 1 + packages/icons/src/svg/icons/download.svg | 1 + packages/icons/src/svg/index.ts | 25 + packages/icons/src/svg/load.ts | 61 + packages/icons/tsconfig.json | 6 + packages/locales/package.json | 28 + packages/locales/src/i18n.ts | 147 + packages/locales/src/index.ts | 28 + .../src/langs/en-US/authentication.json | 56 + packages/locales/src/langs/en-US/common.json | 14 + .../locales/src/langs/en-US/preferences.json | 184 + packages/locales/src/langs/en-US/ui.json | 81 + .../src/langs/zh-CN/authentication.json | 56 + packages/locales/src/langs/zh-CN/common.json | 14 + .../locales/src/langs/zh-CN/preferences.json | 184 + packages/locales/src/langs/zh-CN/ui.json | 81 + packages/locales/src/typing.ts | 25 + packages/locales/tsconfig.json | 6 + packages/preferences/package.json | 26 + packages/preferences/src/index.ts | 17 + packages/preferences/tsconfig.json | 6 + packages/stores/package.json | 31 + packages/stores/shim-pinia.d.ts | 9 + packages/stores/src/index.ts | 3 + packages/stores/src/modules/access.test.ts | 46 + packages/stores/src/modules/access.ts | 111 + packages/stores/src/modules/index.ts | 4 + packages/stores/src/modules/lock.test.ts | 31 + packages/stores/src/modules/lock.ts | 33 + packages/stores/src/modules/tabbar.test.ts | 295 + packages/stores/src/modules/tabbar.ts | 559 + packages/stores/src/modules/user.test.ts | 37 + packages/stores/src/modules/user.ts | 118 + packages/stores/src/setup.ts | 43 + packages/stores/tsconfig.json | 5 + packages/styles/README.md | 19 + packages/styles/package.json | 34 + packages/styles/src/antd/index.css | 65 + packages/styles/src/ele/index.css | 44 + packages/styles/src/global/index.scss | 1 + packages/styles/src/index.ts | 1 + packages/styles/src/naive/index.css | 20 + packages/styles/tsconfig.json | 6 + packages/types/README.md | 20 + packages/types/global.d.ts | 22 + packages/types/package.json | 27 + packages/types/src/index.ts | 2 + packages/types/src/user.ts | 20 + packages/types/tsconfig.json | 6 + packages/utils/README.md | 19 + packages/utils/package.json | 27 + .../__tests__/find-menu-by-path.test.ts | 88 + .../helpers/__tests__/generate-menus.test.ts | 236 + .../generate-routes-frontend.test.ts | 105 + .../__tests__/merge-route-modules.test.ts | 68 + .../utils/src/helpers/find-menu-by-path.ts | 37 + packages/utils/src/helpers/generate-menus.ts | 81 + .../src/helpers/generate-routes-backend.ts | 83 + .../src/helpers/generate-routes-frontend.ts | 58 + .../utils/src/helpers/get-popup-container.ts | 6 + packages/utils/src/helpers/index.ts | 8 + .../utils/src/helpers/merge-route-modules.ts | 28 + packages/utils/src/helpers/reset-routes.ts | 31 + .../src/helpers/unmount-global-loading.ts | 31 + packages/utils/src/index.ts | 4 + packages/utils/tsconfig.json | 9 + pnpm-lock.yaml | 18776 ++++++++++++++++ pnpm-workspace.yaml | 187 + scripts/clean.mjs | 53 + scripts/deploy/Dockerfile | 31 + scripts/deploy/build-local-docker-image.sh | 55 + scripts/deploy/nginx.conf | 75 + scripts/turbo-run/README.md | 3 + scripts/turbo-run/bin/turbo-run.mjs | 3 + scripts/turbo-run/build.config.ts | 7 + scripts/turbo-run/package.json | 29 + scripts/turbo-run/src/index.ts | 29 + scripts/turbo-run/src/run.ts | 67 + scripts/turbo-run/tsconfig.json | 6 + scripts/vsh/README.md | 3 + scripts/vsh/bin/vsh.mjs | 3 + scripts/vsh/build.config.ts | 7 + scripts/vsh/package.json | 31 + scripts/vsh/src/check-circular/index.ts | 80 + scripts/vsh/src/check-dep/index.ts | 85 + scripts/vsh/src/code-workspace/index.ts | 78 + scripts/vsh/src/index.ts | 41 + scripts/vsh/src/lint/index.ts | 48 + scripts/vsh/src/publint/index.ts | 185 + scripts/vsh/tsconfig.json | 6 + stylelint.config.mjs | 4 + tea.yaml | 6 + turbo.json | 49 + vben-admin.code-workspace | 172 + vitest.config.ts | 11 + vitest.workspace.ts | 3 + 990 files changed, 90217 insertions(+) create mode 100644 .browserslistrc create mode 100644 .commitlintrc.js create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitconfig create mode 100644 .gitignore create mode 100644 .gitpod.yml create mode 100644 .lintstagedrc.mjs create mode 100644 .node-version create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.mjs create mode 100644 .stylelintignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/global.code-snippets create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 _nginx/nginx.conf create mode 100644 apps/web-antd/.env create mode 100644 apps/web-antd/.env.analyze create mode 100644 apps/web-antd/.env.development create mode 100644 apps/web-antd/.env.production create mode 100644 apps/web-antd/index.html create mode 100644 apps/web-antd/package.json create mode 100644 apps/web-antd/postcss.config.mjs create mode 100644 apps/web-antd/public/favicon.ico create mode 100644 apps/web-antd/src/adapter/component/index.ts create mode 100644 apps/web-antd/src/adapter/form.ts create mode 100644 apps/web-antd/src/adapter/vxe-table.ts create mode 100644 apps/web-antd/src/api-client-config/config.ts create mode 100644 apps/web-antd/src/api-client-config/index-blob.ts create mode 100644 apps/web-antd/src/api-client-config/index.ts create mode 100644 apps/web-antd/src/api-client/index.ts create mode 100644 apps/web-antd/src/api-client/schemas.gen.ts create mode 100644 apps/web-antd/src/api-client/services.gen.ts create mode 100644 apps/web-antd/src/api-client/types.gen.ts create mode 100644 apps/web-antd/src/api/core/auth.ts create mode 100644 apps/web-antd/src/api/core/index.ts create mode 100644 apps/web-antd/src/api/core/menu.ts create mode 100644 apps/web-antd/src/api/core/user.ts create mode 100644 apps/web-antd/src/api/index.ts create mode 100644 apps/web-antd/src/api/request.ts create mode 100644 apps/web-antd/src/app.vue create mode 100644 apps/web-antd/src/bootstrap.ts create mode 100644 apps/web-antd/src/components/Loading/index.ts create mode 100644 apps/web-antd/src/components/Loading/src/Loading.vue create mode 100644 apps/web-antd/src/components/Loading/src/createLoading.ts create mode 100644 apps/web-antd/src/components/Loading/src/typing.ts create mode 100644 apps/web-antd/src/components/Loading/src/useLoading.ts create mode 100644 apps/web-antd/src/components/icon/icon.vue create mode 100644 apps/web-antd/src/components/icon/index.ts create mode 100644 apps/web-antd/src/components/table-action/index.ts create mode 100644 apps/web-antd/src/components/table-action/table-action.vue create mode 100644 apps/web-antd/src/components/table-action/types.d.ts create mode 100644 apps/web-antd/src/hooks/useSignalR.ts create mode 100644 apps/web-antd/src/layouts/NotifyItem.vue create mode 100644 apps/web-antd/src/layouts/auth.vue create mode 100644 apps/web-antd/src/layouts/basic.vue create mode 100644 apps/web-antd/src/layouts/index.ts create mode 100644 apps/web-antd/src/layouts/my-profile.vue create mode 100644 apps/web-antd/src/locales/README.md create mode 100644 apps/web-antd/src/locales/index.ts create mode 100644 apps/web-antd/src/locales/langs/en-US/abp.json create mode 100644 apps/web-antd/src/locales/langs/en-US/code.json create mode 100644 apps/web-antd/src/locales/langs/en-US/common.json create mode 100644 apps/web-antd/src/locales/langs/en-US/page.json create mode 100644 apps/web-antd/src/locales/langs/zh-CN/abp.json create mode 100644 apps/web-antd/src/locales/langs/zh-CN/code.json create mode 100644 apps/web-antd/src/locales/langs/zh-CN/common.json create mode 100644 apps/web-antd/src/locales/langs/zh-CN/page.json create mode 100644 apps/web-antd/src/main.ts create mode 100644 apps/web-antd/src/preferences.ts create mode 100644 apps/web-antd/src/router/access.ts create mode 100644 apps/web-antd/src/router/guard.ts create mode 100644 apps/web-antd/src/router/index.ts create mode 100644 apps/web-antd/src/router/routes/core.ts create mode 100644 apps/web-antd/src/router/routes/index.ts create mode 100644 apps/web-antd/src/router/routes/modules/dashboard.ts create mode 100644 apps/web-antd/src/router/routes/modules/system.ts create mode 100644 apps/web-antd/src/router/routes/modules/tenant.ts create mode 100644 apps/web-antd/src/store/auth.ts create mode 100644 apps/web-antd/src/store/index.ts create mode 100644 apps/web-antd/src/views/_core/README.md create mode 100644 apps/web-antd/src/views/_core/about/index.vue create mode 100644 apps/web-antd/src/views/_core/authentication/code-login.vue create mode 100644 apps/web-antd/src/views/_core/authentication/forget-password.vue create mode 100644 apps/web-antd/src/views/_core/authentication/login.vue create mode 100644 apps/web-antd/src/views/_core/authentication/qrcode-login.vue create mode 100644 apps/web-antd/src/views/_core/authentication/register.vue create mode 100644 apps/web-antd/src/views/_core/fallback/coming-soon.vue create mode 100644 apps/web-antd/src/views/_core/fallback/forbidden.vue create mode 100644 apps/web-antd/src/views/_core/fallback/internal-error.vue create mode 100644 apps/web-antd/src/views/_core/fallback/not-found.vue create mode 100644 apps/web-antd/src/views/_core/fallback/offline.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue create mode 100644 apps/web-antd/src/views/dashboard/analytics/index.vue create mode 100644 apps/web-antd/src/views/dashboard/workspace/index.vue create mode 100644 apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryDetailModal.vue create mode 100644 apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryModal.vue create mode 100644 apps/web-antd/src/views/system/abpdatadictionary/index.vue create mode 100644 apps/web-antd/src/views/system/abpfeature/index.vue create mode 100644 apps/web-antd/src/views/system/abplanguage/AddLanguageTextModal.vue create mode 100644 apps/web-antd/src/views/system/abplanguage/EditLanguageTextModal.vue create mode 100644 apps/web-antd/src/views/system/abplanguage/language.vue create mode 100644 apps/web-antd/src/views/system/abplanguage/languagetext.vue create mode 100644 apps/web-antd/src/views/system/abplanguage/schema.ts create mode 100644 apps/web-antd/src/views/system/abplog/audit.vue create mode 100644 apps/web-antd/src/views/system/abplog/login.vue create mode 100644 apps/web-antd/src/views/system/abplog/schema.ts create mode 100644 apps/web-antd/src/views/system/abpnotification/message.vue create mode 100644 apps/web-antd/src/views/system/abpnotification/notification.vue create mode 100644 apps/web-antd/src/views/system/abpnotification/schema.ts create mode 100644 apps/web-antd/src/views/system/abporganizationunit/ContextMenu.vue create mode 100644 apps/web-antd/src/views/system/abporganizationunit/OrgTreeAddModal.vue create mode 100644 apps/web-antd/src/views/system/abporganizationunit/OrgTreeEditModal.vue create mode 100644 apps/web-antd/src/views/system/abporganizationunit/index.vue create mode 100644 apps/web-antd/src/views/system/abprole/index.vue create mode 100644 apps/web-antd/src/views/system/abprole/schema.ts create mode 100644 apps/web-antd/src/views/system/abpsetting/index.vue create mode 100644 apps/web-antd/src/views/system/abptenant/AddEditModal.vue create mode 100644 apps/web-antd/src/views/system/abptenant/ConnectionStringModal.vue create mode 100644 apps/web-antd/src/views/system/abptenant/FeatureManageModal.vue create mode 100644 apps/web-antd/src/views/system/abptenant/index.vue create mode 100644 apps/web-antd/src/views/system/abptenant/schema.ts create mode 100644 apps/web-antd/src/views/system/abpuser/index.vue create mode 100644 apps/web-antd/src/views/system/abpuser/schema.ts create mode 100644 apps/web-antd/tailwind.config.mjs create mode 100644 apps/web-antd/tsconfig.json create mode 100644 apps/web-antd/tsconfig.node.json create mode 100644 apps/web-antd/vite.config.mts create mode 100644 cspell.json create mode 100644 eslint.config.mjs create mode 100644 internal/lint-configs/commitlint-config/index.mjs create mode 100644 internal/lint-configs/commitlint-config/package.json create mode 100644 internal/lint-configs/eslint-config/build.config.ts create mode 100644 internal/lint-configs/eslint-config/package.json create mode 100644 internal/lint-configs/eslint-config/src/configs/command.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/comments.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/disableds.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/ignores.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/import.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/index.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/javascript.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/jsdoc.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/jsonc.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/node.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/perfectionist.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/prettier.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/regexp.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/test.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/turbo.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/typescript.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/unicorn.ts create mode 100644 internal/lint-configs/eslint-config/src/configs/vue.ts create mode 100644 internal/lint-configs/eslint-config/src/custom-config.ts create mode 100644 internal/lint-configs/eslint-config/src/index.ts create mode 100644 internal/lint-configs/eslint-config/src/util.ts create mode 100644 internal/lint-configs/eslint-config/tsconfig.json create mode 100644 internal/lint-configs/prettier-config/index.mjs create mode 100644 internal/lint-configs/prettier-config/package.json create mode 100644 internal/lint-configs/stylelint-config/index.mjs create mode 100644 internal/lint-configs/stylelint-config/package.json create mode 100644 internal/node-utils/build.config.ts create mode 100644 internal/node-utils/package.json create mode 100644 internal/node-utils/src/__tests__/hash.test.ts create mode 100644 internal/node-utils/src/__tests__/path.test.ts create mode 100644 internal/node-utils/src/constants.ts create mode 100644 internal/node-utils/src/date.ts create mode 100644 internal/node-utils/src/fs.ts create mode 100644 internal/node-utils/src/git.ts create mode 100644 internal/node-utils/src/hash.ts create mode 100644 internal/node-utils/src/index.ts create mode 100644 internal/node-utils/src/monorepo.ts create mode 100644 internal/node-utils/src/path.ts create mode 100644 internal/node-utils/src/prettier.ts create mode 100644 internal/node-utils/src/spinner.ts create mode 100644 internal/node-utils/tsconfig.json create mode 100644 internal/tailwind-config/build.config.ts create mode 100644 internal/tailwind-config/package.json create mode 100644 internal/tailwind-config/src/index.ts create mode 100644 internal/tailwind-config/src/module.d.ts create mode 100644 internal/tailwind-config/src/plugins/entry.ts create mode 100644 internal/tailwind-config/src/postcss.config.ts create mode 100644 internal/tailwind-config/tsconfig.json create mode 100644 internal/tsconfig/base.json create mode 100644 internal/tsconfig/library.json create mode 100644 internal/tsconfig/node.json create mode 100644 internal/tsconfig/package.json create mode 100644 internal/tsconfig/web-app.json create mode 100644 internal/tsconfig/web.json create mode 100644 internal/vite-config/build.config.ts create mode 100644 internal/vite-config/package.json create mode 100644 internal/vite-config/src/config/application.ts create mode 100644 internal/vite-config/src/config/common.ts create mode 100644 internal/vite-config/src/config/index.ts create mode 100644 internal/vite-config/src/config/library.ts create mode 100644 internal/vite-config/src/index.ts create mode 100644 internal/vite-config/src/options.ts create mode 100644 internal/vite-config/src/plugins/archiver.ts create mode 100644 internal/vite-config/src/plugins/extra-app-config.ts create mode 100644 internal/vite-config/src/plugins/importmap.ts create mode 100644 internal/vite-config/src/plugins/index.ts create mode 100644 internal/vite-config/src/plugins/inject-app-loading/README.md create mode 100644 internal/vite-config/src/plugins/inject-app-loading/default-loading-antd.html create mode 100644 internal/vite-config/src/plugins/inject-app-loading/default-loading.html create mode 100644 internal/vite-config/src/plugins/inject-app-loading/index.ts create mode 100644 internal/vite-config/src/plugins/inject-metadata.ts create mode 100644 internal/vite-config/src/plugins/license.ts create mode 100644 internal/vite-config/src/plugins/nitro-mock.ts create mode 100644 internal/vite-config/src/plugins/print.ts create mode 100644 internal/vite-config/src/plugins/vxe-table.ts create mode 100644 internal/vite-config/src/typing.ts create mode 100644 internal/vite-config/src/utils/env.ts create mode 100644 internal/vite-config/tsconfig.json create mode 100644 package.json create mode 100644 packages/@core/README.md create mode 100644 packages/@core/base/README.md create mode 100644 packages/@core/base/design/package.json create mode 100644 packages/@core/base/design/src/css/global.css create mode 100644 packages/@core/base/design/src/css/nprogress.css create mode 100644 packages/@core/base/design/src/css/transition.css create mode 100644 packages/@core/base/design/src/css/ui.css create mode 100644 packages/@core/base/design/src/design-tokens/dark.css create mode 100644 packages/@core/base/design/src/design-tokens/default.css create mode 100644 packages/@core/base/design/src/design-tokens/index.ts create mode 100644 packages/@core/base/design/src/index.ts create mode 100644 packages/@core/base/design/src/scss-bem/bem.scss create mode 100644 packages/@core/base/design/src/scss-bem/constants.scss create mode 100644 packages/@core/base/design/tsconfig.json create mode 100644 packages/@core/base/design/vite.config.mts create mode 100644 packages/@core/base/icons/build.config.ts create mode 100644 packages/@core/base/icons/package.json create mode 100644 packages/@core/base/icons/src/create-icon.ts create mode 100644 packages/@core/base/icons/src/index.ts create mode 100644 packages/@core/base/icons/src/lucide.ts create mode 100644 packages/@core/base/icons/tsconfig.json create mode 100644 packages/@core/base/shared/build.config.ts create mode 100644 packages/@core/base/shared/package.json create mode 100644 packages/@core/base/shared/src/cache/__tests__/storage-manager.test.ts create mode 100644 packages/@core/base/shared/src/cache/index.ts create mode 100644 packages/@core/base/shared/src/cache/storage-manager.ts create mode 100644 packages/@core/base/shared/src/cache/types.ts create mode 100644 packages/@core/base/shared/src/color/__tests__/convert.test.ts create mode 100644 packages/@core/base/shared/src/color/color.ts create mode 100644 packages/@core/base/shared/src/color/convert.ts create mode 100644 packages/@core/base/shared/src/color/generator.ts create mode 100644 packages/@core/base/shared/src/color/index.ts create mode 100644 packages/@core/base/shared/src/constants/globals.ts create mode 100644 packages/@core/base/shared/src/constants/index.ts create mode 100644 packages/@core/base/shared/src/constants/vben.ts create mode 100644 packages/@core/base/shared/src/global-state.ts create mode 100644 packages/@core/base/shared/src/store.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/diff.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/dom.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/inference.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/letter.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/state-handler.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/tree.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/unique.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/update-css-variables.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/util.test.ts create mode 100644 packages/@core/base/shared/src/utils/__tests__/window.test.ts create mode 100644 packages/@core/base/shared/src/utils/cn.ts create mode 100644 packages/@core/base/shared/src/utils/date.ts create mode 100644 packages/@core/base/shared/src/utils/diff.ts create mode 100644 packages/@core/base/shared/src/utils/dom.ts create mode 100644 packages/@core/base/shared/src/utils/download.ts create mode 100644 packages/@core/base/shared/src/utils/index.ts create mode 100644 packages/@core/base/shared/src/utils/inference.ts create mode 100644 packages/@core/base/shared/src/utils/letter.ts create mode 100644 packages/@core/base/shared/src/utils/merge.ts create mode 100644 packages/@core/base/shared/src/utils/nprogress.ts create mode 100644 packages/@core/base/shared/src/utils/state-handler.ts create mode 100644 packages/@core/base/shared/src/utils/to.ts create mode 100644 packages/@core/base/shared/src/utils/tree.ts create mode 100644 packages/@core/base/shared/src/utils/unique.ts create mode 100644 packages/@core/base/shared/src/utils/update-css-variables.ts create mode 100644 packages/@core/base/shared/src/utils/util.ts create mode 100644 packages/@core/base/shared/src/utils/window.ts create mode 100644 packages/@core/base/shared/tsconfig.json create mode 100644 packages/@core/base/typings/build.config.ts create mode 100644 packages/@core/base/typings/package.json create mode 100644 packages/@core/base/typings/src/app.d.ts create mode 100644 packages/@core/base/typings/src/basic.d.ts create mode 100644 packages/@core/base/typings/src/helper.d.ts create mode 100644 packages/@core/base/typings/src/index.ts create mode 100644 packages/@core/base/typings/src/menu-record.ts create mode 100644 packages/@core/base/typings/src/tabs.ts create mode 100644 packages/@core/base/typings/src/vue-router.d.ts create mode 100644 packages/@core/base/typings/tsconfig.json create mode 100644 packages/@core/base/typings/vue-router.d.ts create mode 100644 packages/@core/composables/build.config.ts create mode 100644 packages/@core/composables/package.json create mode 100644 packages/@core/composables/src/__tests__/use-sortable.test.ts create mode 100644 packages/@core/composables/src/index.ts create mode 100644 packages/@core/composables/src/use-is-mobile.ts create mode 100644 packages/@core/composables/src/use-layout-style.ts create mode 100644 packages/@core/composables/src/use-namespace.ts create mode 100644 packages/@core/composables/src/use-priority-value.ts create mode 100644 packages/@core/composables/src/use-scroll-lock.ts create mode 100644 packages/@core/composables/src/use-simple-locale/README.md create mode 100644 packages/@core/composables/src/use-simple-locale/index.ts create mode 100644 packages/@core/composables/src/use-simple-locale/messages.ts create mode 100644 packages/@core/composables/src/use-sortable.ts create mode 100644 packages/@core/composables/tsconfig.json create mode 100644 packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap create mode 100644 packages/@core/preferences/__tests__/config.test.ts create mode 100644 packages/@core/preferences/__tests__/preferences.test.ts create mode 100644 packages/@core/preferences/build.config.ts create mode 100644 packages/@core/preferences/package.json create mode 100644 packages/@core/preferences/src/config.ts create mode 100644 packages/@core/preferences/src/constants.ts create mode 100644 packages/@core/preferences/src/index.ts create mode 100644 packages/@core/preferences/src/preferences.ts create mode 100644 packages/@core/preferences/src/types.ts create mode 100644 packages/@core/preferences/src/update-css-variables.ts create mode 100644 packages/@core/preferences/src/use-preferences.ts create mode 100644 packages/@core/preferences/tsconfig.json create mode 100644 packages/@core/ui-kit/README.md create mode 100644 packages/@core/ui-kit/form-ui/__tests__/form-api.test.ts create mode 100644 packages/@core/ui-kit/form-ui/build.config.ts create mode 100644 packages/@core/ui-kit/form-ui/package.json create mode 100644 packages/@core/ui-kit/form-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/form-ui/src/components/form-actions.vue create mode 100644 packages/@core/ui-kit/form-ui/src/config.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-api.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/context.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/dependencies.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/expandable.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/form-field.vue create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/form-label.vue create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/form.vue create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/helper.ts create mode 100644 packages/@core/ui-kit/form-ui/src/form-render/index.ts create mode 100644 packages/@core/ui-kit/form-ui/src/index.ts create mode 100644 packages/@core/ui-kit/form-ui/src/types.ts create mode 100644 packages/@core/ui-kit/form-ui/src/use-form-context.ts create mode 100644 packages/@core/ui-kit/form-ui/src/use-vben-form.ts create mode 100644 packages/@core/ui-kit/form-ui/src/vben-form.vue create mode 100644 packages/@core/ui-kit/form-ui/src/vben-use-form.vue create mode 100644 packages/@core/ui-kit/form-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/form-ui/tsconfig.json create mode 100644 packages/@core/ui-kit/layout-ui/build.config.ts create mode 100644 packages/@core/ui-kit/layout-ui/package.json create mode 100644 packages/@core/ui-kit/layout-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/layout-ui/src/components/index.ts create mode 100644 packages/@core/ui-kit/layout-ui/src/components/layout-content.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/layout-footer.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/layout-header.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/layout-tabbar.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/widgets/index.ts create mode 100644 packages/@core/ui-kit/layout-ui/src/components/widgets/sidebar-collapse-button.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/components/widgets/sidebar-fixed-button.vue create mode 100644 packages/@core/ui-kit/layout-ui/src/hooks/use-layout.ts create mode 100644 packages/@core/ui-kit/layout-ui/src/index.ts create mode 100644 packages/@core/ui-kit/layout-ui/src/vben-layout.ts create mode 100644 packages/@core/ui-kit/layout-ui/src/vben-layout.vue create mode 100644 packages/@core/ui-kit/layout-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/layout-ui/tsconfig.json create mode 100644 packages/@core/ui-kit/menu-ui/README.md create mode 100644 packages/@core/ui-kit/menu-ui/build.config.ts create mode 100644 packages/@core/ui-kit/menu-ui/package.json create mode 100644 packages/@core/ui-kit/menu-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/menu-ui/src/components/collapse-transition.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/index.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/components/menu-badge-dot.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/menu-badge.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/menu-item.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/menu.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/normal-menu/index.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/components/normal-menu/normal-menu.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/components/normal-menu/normal-menu.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/sub-menu-content.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/hooks/index.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/index.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/menu.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/sub-menu.vue create mode 100644 packages/@core/ui-kit/menu-ui/src/types.ts create mode 100644 packages/@core/ui-kit/menu-ui/src/utils/index.ts create mode 100644 packages/@core/ui-kit/menu-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/menu-ui/tsconfig.json create mode 100644 packages/@core/ui-kit/popup-ui/build.config.ts create mode 100644 packages/@core/ui-kit/popup-ui/package.json create mode 100644 packages/@core/ui-kit/popup-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/__tests__/drawer-api.test.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/drawer-api.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/drawer.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/index.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/index.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/__tests__/modal-api.test.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/index.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/modal.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/modal.vue create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts create mode 100644 packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts create mode 100644 packages/@core/ui-kit/popup-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/popup-ui/tsconfig.json create mode 100644 packages/@core/ui-kit/shadcn-ui/build.config.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/components.json create mode 100644 packages/@core/ui-kit/shadcn-ui/package.json create mode 100644 packages/@core/ui-kit/shadcn-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/avatar/avatar.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/avatar/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/back-top/back-top.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/back-top/backtop.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/back-top/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/back-top/use-backtop.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/breadcrumb/breadcrumb-background.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/breadcrumb/breadcrumb-view.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/breadcrumb/breadcrumb.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/breadcrumb/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/breadcrumb/types.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/button/button.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/button/button.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/button/icon-button.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/button/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/checkbox/checkbox.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/checkbox/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/context-menu/context-menu.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/context-menu/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/context-menu/interface.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/count-to-animator/count-to-animator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/count-to-animator/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/dropdown-menu/dropdown-menu.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/dropdown-menu/dropdown-radio-menu.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/dropdown-menu/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/dropdown-menu/interface.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/expandable-arrow/expandable-arrow.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/expandable-arrow/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/full-screen/full-screen.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/full-screen/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/hover-card/hover-card.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/hover-card/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/icon/icon.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/icon/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/input-password/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/input-password/input-password.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/input-password/password-strength.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/logo/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/logo/logo.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/pin-input/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/pin-input/input.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/pin-input/types.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/popover/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/popover/popover.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/render-content/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/render-content/render-content.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/segmented/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/segmented/tabs-indicator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/segmented/types.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/select/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/select/select.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/spine-text/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/spine-text/spine-text.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/spinner/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/spinner/loading.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/spinner/spinner.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/tooltip/help-tooltip.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/tooltip/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/components/tooltip/tooltip.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/accordion/Accordion.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/accordion/AccordionContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/accordion/AccordionItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/accordion/AccordionTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/accordion/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/avatar/Avatar.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/avatar/AvatarFallback.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/avatar/AvatarImage.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/avatar/avatar.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/avatar/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/badge/Badge.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/badge/badge.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/badge/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/Breadcrumb.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbEllipsis.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbLink.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbList.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbPage.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/BreadcrumbSeparator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/breadcrumb/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/button/Button.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/button/button.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/button/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/button/types.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/Card.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/CardContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/CardDescription.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/CardFooter.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/CardHeader.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/CardTitle.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/card/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/checkbox/Checkbox.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/checkbox/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenu.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuCheckboxItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuLabel.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuPortal.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuRadioGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuRadioItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuSeparator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuShortcut.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuSub.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuSubContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuSubTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/ContextMenuTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/context-menu/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/Dialog.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogClose.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogDescription.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogFooter.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogHeader.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogOverlay.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogScrollContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogTitle.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dialog/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenu.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuCheckboxItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuLabel.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuRadioGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuRadioItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuSeparator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuShortcut.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuSub.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuSubContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuSubTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/DropdownMenuTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/dropdown-menu/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/FormControl.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/FormDescription.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/FormItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/FormLabel.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/FormMessage.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/injectionKeys.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/form/useFormField.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/hover-card/HoverCard.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/hover-card/HoverCardContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/hover-card/HoverCardTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/hover-card/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/input/Input.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/input/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/label/Label.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/label/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/NumberField.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/NumberFieldContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/NumberFieldDecrement.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/NumberFieldIncrement.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/NumberFieldInput.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/number-field/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/PaginationEllipsis.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/PaginationFirst.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/PaginationLast.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/PaginationNext.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/PaginationPrev.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pagination/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pin-input/PinInput.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pin-input/PinInputGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pin-input/PinInputInput.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pin-input/PinInputSeparator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/pin-input/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/popover/Popover.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/popover/PopoverContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/popover/PopoverTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/popover/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/radio-group/RadioGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/radio-group/RadioGroupItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/radio-group/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/resizable/ResizableHandle.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/resizable/ResizablePanelGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/resizable/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/scroll-area/ScrollArea.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/scroll-area/ScrollBar.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/scroll-area/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/Select.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectItemText.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectLabel.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectScrollDownButton.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectScrollUpButton.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectSeparator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/SelectValue.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/select/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/separator/Separator.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/separator/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/Sheet.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetClose.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetDescription.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetFooter.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetHeader.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetOverlay.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetTitle.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/sheet/sheet.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/switch/Switch.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/switch/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tabs/Tabs.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tabs/TabsContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tabs/TabsList.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tabs/TabsTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tabs/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/textarea/Textarea.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/textarea/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle-group/ToggleGroup.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle-group/ToggleGroupItem.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle-group/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle/Toggle.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/toggle/toggle.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tooltip/Tooltip.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tooltip/TooltipContent.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tooltip/TooltipProvider.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tooltip/TooltipTrigger.vue create mode 100644 packages/@core/ui-kit/shadcn-ui/src/ui/tooltip/index.ts create mode 100644 packages/@core/ui-kit/shadcn-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/shadcn-ui/tsconfig.json create mode 100644 packages/@core/ui-kit/tabs-ui/build.config.ts create mode 100644 packages/@core/ui-kit/tabs-ui/package.json create mode 100644 packages/@core/ui-kit/tabs-ui/postcss.config.mjs create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/index.ts create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/tabs-chrome/tabs.vue create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/tabs/tabs.vue create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/widgets/index.ts create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/widgets/tool-more.vue create mode 100644 packages/@core/ui-kit/tabs-ui/src/components/widgets/tool-screen.vue create mode 100644 packages/@core/ui-kit/tabs-ui/src/index.ts create mode 100644 packages/@core/ui-kit/tabs-ui/src/tabs-view.vue create mode 100644 packages/@core/ui-kit/tabs-ui/src/types.ts create mode 100644 packages/@core/ui-kit/tabs-ui/src/use-tabs-drag.ts create mode 100644 packages/@core/ui-kit/tabs-ui/src/use-tabs-view-scroll.ts create mode 100644 packages/@core/ui-kit/tabs-ui/tailwind.config.mjs create mode 100644 packages/@core/ui-kit/tabs-ui/tsconfig.json create mode 100644 packages/constants/README.md create mode 100644 packages/constants/package.json create mode 100644 packages/constants/src/core.ts create mode 100644 packages/constants/src/index.ts create mode 100644 packages/constants/tsconfig.json create mode 100644 packages/effects/README.md create mode 100644 packages/effects/access/package.json create mode 100644 packages/effects/access/src/access-control.vue create mode 100644 packages/effects/access/src/accessible.ts create mode 100644 packages/effects/access/src/directive.ts create mode 100644 packages/effects/access/src/index.ts create mode 100644 packages/effects/access/src/use-access.ts create mode 100644 packages/effects/access/tsconfig.json create mode 100644 packages/effects/common-ui/package.json create mode 100644 packages/effects/common-ui/src/components/api-component/api-component.vue create mode 100644 packages/effects/common-ui/src/components/api-component/index.ts create mode 100644 packages/effects/common-ui/src/components/captcha/hooks/useCaptchaPoints.ts create mode 100644 packages/effects/common-ui/src/components/captcha/index.ts create mode 100644 packages/effects/common-ui/src/components/captcha/point-selection-captcha/index.vue create mode 100644 packages/effects/common-ui/src/components/captcha/point-selection-captcha/point-selection-captcha-card.vue create mode 100644 packages/effects/common-ui/src/components/captcha/slider-captcha/index.vue create mode 100644 packages/effects/common-ui/src/components/captcha/slider-captcha/slider-captcha-action.vue create mode 100644 packages/effects/common-ui/src/components/captcha/slider-captcha/slider-captcha-bar.vue create mode 100644 packages/effects/common-ui/src/components/captcha/slider-captcha/slider-captcha-content.vue create mode 100644 packages/effects/common-ui/src/components/captcha/slider-rotate-captcha/index.vue create mode 100644 packages/effects/common-ui/src/components/captcha/types.ts create mode 100644 packages/effects/common-ui/src/components/col-page/col-page.vue create mode 100644 packages/effects/common-ui/src/components/col-page/index.ts create mode 100644 packages/effects/common-ui/src/components/col-page/types.ts create mode 100644 packages/effects/common-ui/src/components/ellipsis-text/ellipsis-text.vue create mode 100644 packages/effects/common-ui/src/components/ellipsis-text/index.ts create mode 100644 packages/effects/common-ui/src/components/icon-picker/icon-picker.vue create mode 100644 packages/effects/common-ui/src/components/icon-picker/icons.ts create mode 100644 packages/effects/common-ui/src/components/icon-picker/index.ts create mode 100644 packages/effects/common-ui/src/components/index.ts create mode 100644 packages/effects/common-ui/src/components/page/__tests__/page.test.ts create mode 100644 packages/effects/common-ui/src/components/page/index.ts create mode 100644 packages/effects/common-ui/src/components/page/page.vue create mode 100644 packages/effects/common-ui/src/components/page/types.ts create mode 100644 packages/effects/common-ui/src/components/resize/index.ts create mode 100644 packages/effects/common-ui/src/components/resize/resize.vue create mode 100644 packages/effects/common-ui/src/components/tippy/directive.ts create mode 100644 packages/effects/common-ui/src/components/tippy/index.ts create mode 100644 packages/effects/common-ui/src/index.ts create mode 100644 packages/effects/common-ui/src/ui/about/about.ts create mode 100644 packages/effects/common-ui/src/ui/about/about.vue create mode 100644 packages/effects/common-ui/src/ui/about/index.ts create mode 100644 packages/effects/common-ui/src/ui/authentication/auth-title.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/code-login.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/forget-password.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/index.ts create mode 100644 packages/effects/common-ui/src/ui/authentication/login-expired-modal.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/login.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/qrcode-login.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/register.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/third-party-login.vue create mode 100644 packages/effects/common-ui/src/ui/authentication/types.ts create mode 100644 packages/effects/common-ui/src/ui/dashboard/analysis/analysis-chart-card.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/analysis/analysis-charts-tabs.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/analysis/index.ts create mode 100644 packages/effects/common-ui/src/ui/dashboard/index.ts create mode 100644 packages/effects/common-ui/src/ui/dashboard/typing.ts create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/index.ts create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/workbench-header.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/workbench-project.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/workbench-quick-nav.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/workbench-todo.vue create mode 100644 packages/effects/common-ui/src/ui/dashboard/workbench/workbench-trends.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/fallback.ts create mode 100644 packages/effects/common-ui/src/ui/fallback/fallback.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/icon-403.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/icon-404.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/icon-500.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/icon-coming-soon.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/icon-offline.vue create mode 100644 packages/effects/common-ui/src/ui/fallback/icons/warning.svg create mode 100644 packages/effects/common-ui/src/ui/fallback/index.ts create mode 100644 packages/effects/common-ui/src/ui/index.ts create mode 100644 packages/effects/common-ui/tsconfig.json create mode 100644 packages/effects/hooks/README.md create mode 100644 packages/effects/hooks/package.json create mode 100644 packages/effects/hooks/src/index.ts create mode 100644 packages/effects/hooks/src/use-app-config.ts create mode 100644 packages/effects/hooks/src/use-content-maximize.ts create mode 100644 packages/effects/hooks/src/use-design-tokens.ts create mode 100644 packages/effects/hooks/src/use-event-bus.ts create mode 100644 packages/effects/hooks/src/use-hover-toggle.ts create mode 100644 packages/effects/hooks/src/use-pagination.ts create mode 100644 packages/effects/hooks/src/use-refresh.ts create mode 100644 packages/effects/hooks/src/use-tabs.ts create mode 100644 packages/effects/hooks/src/use-watermark.ts create mode 100644 packages/effects/hooks/tsconfig.json create mode 100644 packages/effects/layouts/package.json create mode 100644 packages/effects/layouts/src/authentication/authentication.vue create mode 100644 packages/effects/layouts/src/authentication/form.vue create mode 100644 packages/effects/layouts/src/authentication/icons/slogan.vue create mode 100644 packages/effects/layouts/src/authentication/index.ts create mode 100644 packages/effects/layouts/src/authentication/toolbar.vue create mode 100644 packages/effects/layouts/src/authentication/types.ts create mode 100644 packages/effects/layouts/src/basic/README.md create mode 100644 packages/effects/layouts/src/basic/content/content-spinner.vue create mode 100644 packages/effects/layouts/src/basic/content/content.vue create mode 100644 packages/effects/layouts/src/basic/content/index.ts create mode 100644 packages/effects/layouts/src/basic/content/use-content-spinner.ts create mode 100644 packages/effects/layouts/src/basic/copyright/copyright.vue create mode 100644 packages/effects/layouts/src/basic/copyright/index.ts create mode 100644 packages/effects/layouts/src/basic/footer/footer.vue create mode 100644 packages/effects/layouts/src/basic/footer/index.ts create mode 100644 packages/effects/layouts/src/basic/header/header.vue create mode 100644 packages/effects/layouts/src/basic/header/index.ts create mode 100644 packages/effects/layouts/src/basic/index.ts create mode 100644 packages/effects/layouts/src/basic/layout.vue create mode 100644 packages/effects/layouts/src/basic/menu/extra-menu.vue create mode 100644 packages/effects/layouts/src/basic/menu/index.ts create mode 100644 packages/effects/layouts/src/basic/menu/menu.vue create mode 100644 packages/effects/layouts/src/basic/menu/mixed-menu.vue create mode 100644 packages/effects/layouts/src/basic/menu/use-extra-menu.ts create mode 100644 packages/effects/layouts/src/basic/menu/use-mixed-menu.ts create mode 100644 packages/effects/layouts/src/basic/menu/use-navigation.ts create mode 100644 packages/effects/layouts/src/basic/tabbar/index.ts create mode 100644 packages/effects/layouts/src/basic/tabbar/tabbar.vue create mode 100644 packages/effects/layouts/src/basic/tabbar/use-tabbar.ts create mode 100644 packages/effects/layouts/src/iframe/iframe-router-view.vue create mode 100644 packages/effects/layouts/src/iframe/iframe-view.vue create mode 100644 packages/effects/layouts/src/iframe/index.ts create mode 100644 packages/effects/layouts/src/index.ts create mode 100644 packages/effects/layouts/src/widgets/breadcrumb.vue create mode 100644 packages/effects/layouts/src/widgets/check-updates/check-updates.vue create mode 100644 packages/effects/layouts/src/widgets/check-updates/index.ts create mode 100644 packages/effects/layouts/src/widgets/color-toggle.vue create mode 100644 packages/effects/layouts/src/widgets/global-search/global-search.vue create mode 100644 packages/effects/layouts/src/widgets/global-search/index.ts create mode 100644 packages/effects/layouts/src/widgets/global-search/search-panel.vue create mode 100644 packages/effects/layouts/src/widgets/index.ts create mode 100644 packages/effects/layouts/src/widgets/language-toggle.vue create mode 100644 packages/effects/layouts/src/widgets/layout-toggle.vue create mode 100644 packages/effects/layouts/src/widgets/lock-screen/index.ts create mode 100644 packages/effects/layouts/src/widgets/lock-screen/lock-screen-modal.vue create mode 100644 packages/effects/layouts/src/widgets/lock-screen/lock-screen.vue create mode 100644 packages/effects/layouts/src/widgets/notification/index.ts create mode 100644 packages/effects/layouts/src/widgets/notification/notification.vue create mode 100644 packages/effects/layouts/src/widgets/notification/types.ts create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/block.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/general/animation.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/index.ts create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/input-item.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/breadcrumb.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/content.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/copyright.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/footer.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/header.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/layout.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/navigation.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/sidebar.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/layout/widget.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/number-field-item.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/select-item.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/shortcut-keys/global.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/switch-item.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/theme/builtin.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/theme/color-mode.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/theme/radius.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/theme/theme.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/blocks/toggle-item.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/content-compact.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/full-content.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/header-mixed-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/header-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/header-sidebar-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/index.ts create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/mixed-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/setting.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/sidebar-mixed-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/icons/sidebar-nav.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/index.ts create mode 100644 packages/effects/layouts/src/widgets/preferences/preferences-button.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/preferences.vue create mode 100644 packages/effects/layouts/src/widgets/preferences/use-open-preferences.ts create mode 100644 packages/effects/layouts/src/widgets/theme-toggle/index.ts create mode 100644 packages/effects/layouts/src/widgets/theme-toggle/theme-button.vue create mode 100644 packages/effects/layouts/src/widgets/theme-toggle/theme-toggle.vue create mode 100644 packages/effects/layouts/src/widgets/user-dropdown/index.ts create mode 100644 packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue create mode 100644 packages/effects/layouts/tsconfig.json create mode 100644 packages/effects/plugins/README.md create mode 100644 packages/effects/plugins/package.json create mode 100644 packages/effects/plugins/src/echarts/echarts-ui.vue create mode 100644 packages/effects/plugins/src/echarts/echarts.ts create mode 100644 packages/effects/plugins/src/echarts/index.ts create mode 100644 packages/effects/plugins/src/echarts/use-echarts.ts create mode 100644 packages/effects/plugins/src/vxe-table/api.ts create mode 100644 packages/effects/plugins/src/vxe-table/extends.ts create mode 100644 packages/effects/plugins/src/vxe-table/index.ts create mode 100644 packages/effects/plugins/src/vxe-table/init.ts create mode 100644 packages/effects/plugins/src/vxe-table/style.css create mode 100644 packages/effects/plugins/src/vxe-table/types.ts create mode 100644 packages/effects/plugins/src/vxe-table/use-vxe-grid.ts create mode 100644 packages/effects/plugins/src/vxe-table/use-vxe-grid.vue create mode 100644 packages/effects/plugins/tsconfig.json create mode 100644 packages/effects/request/package.json create mode 100644 packages/effects/request/src/index.ts create mode 100644 packages/effects/request/src/request-client/index.ts create mode 100644 packages/effects/request/src/request-client/modules/downloader.test.ts create mode 100644 packages/effects/request/src/request-client/modules/downloader.ts create mode 100644 packages/effects/request/src/request-client/modules/interceptor.ts create mode 100644 packages/effects/request/src/request-client/modules/uploader.test.ts create mode 100644 packages/effects/request/src/request-client/modules/uploader.ts create mode 100644 packages/effects/request/src/request-client/preset-interceptors.ts create mode 100644 packages/effects/request/src/request-client/request-client.test.ts create mode 100644 packages/effects/request/src/request-client/request-client.ts create mode 100644 packages/effects/request/src/request-client/types.ts create mode 100644 packages/effects/request/tsconfig.json create mode 100644 packages/icons/README.md create mode 100644 packages/icons/package.json create mode 100644 packages/icons/src/iconify/index.ts create mode 100644 packages/icons/src/icons/empty-icon.vue create mode 100644 packages/icons/src/index.ts create mode 100644 packages/icons/src/svg/icons/antdv-logo.svg create mode 100644 packages/icons/src/svg/icons/avatar-1.svg create mode 100644 packages/icons/src/svg/icons/avatar-2.svg create mode 100644 packages/icons/src/svg/icons/avatar-3.svg create mode 100644 packages/icons/src/svg/icons/avatar-4.svg create mode 100644 packages/icons/src/svg/icons/bell.svg create mode 100644 packages/icons/src/svg/icons/cake.svg create mode 100644 packages/icons/src/svg/icons/card.svg create mode 100644 packages/icons/src/svg/icons/download.svg create mode 100644 packages/icons/src/svg/index.ts create mode 100644 packages/icons/src/svg/load.ts create mode 100644 packages/icons/tsconfig.json create mode 100644 packages/locales/package.json create mode 100644 packages/locales/src/i18n.ts create mode 100644 packages/locales/src/index.ts create mode 100644 packages/locales/src/langs/en-US/authentication.json create mode 100644 packages/locales/src/langs/en-US/common.json create mode 100644 packages/locales/src/langs/en-US/preferences.json create mode 100644 packages/locales/src/langs/en-US/ui.json create mode 100644 packages/locales/src/langs/zh-CN/authentication.json create mode 100644 packages/locales/src/langs/zh-CN/common.json create mode 100644 packages/locales/src/langs/zh-CN/preferences.json create mode 100644 packages/locales/src/langs/zh-CN/ui.json create mode 100644 packages/locales/src/typing.ts create mode 100644 packages/locales/tsconfig.json create mode 100644 packages/preferences/package.json create mode 100644 packages/preferences/src/index.ts create mode 100644 packages/preferences/tsconfig.json create mode 100644 packages/stores/package.json create mode 100644 packages/stores/shim-pinia.d.ts create mode 100644 packages/stores/src/index.ts create mode 100644 packages/stores/src/modules/access.test.ts create mode 100644 packages/stores/src/modules/access.ts create mode 100644 packages/stores/src/modules/index.ts create mode 100644 packages/stores/src/modules/lock.test.ts create mode 100644 packages/stores/src/modules/lock.ts create mode 100644 packages/stores/src/modules/tabbar.test.ts create mode 100644 packages/stores/src/modules/tabbar.ts create mode 100644 packages/stores/src/modules/user.test.ts create mode 100644 packages/stores/src/modules/user.ts create mode 100644 packages/stores/src/setup.ts create mode 100644 packages/stores/tsconfig.json create mode 100644 packages/styles/README.md create mode 100644 packages/styles/package.json create mode 100644 packages/styles/src/antd/index.css create mode 100644 packages/styles/src/ele/index.css create mode 100644 packages/styles/src/global/index.scss create mode 100644 packages/styles/src/index.ts create mode 100644 packages/styles/src/naive/index.css create mode 100644 packages/styles/tsconfig.json create mode 100644 packages/types/README.md create mode 100644 packages/types/global.d.ts create mode 100644 packages/types/package.json create mode 100644 packages/types/src/index.ts create mode 100644 packages/types/src/user.ts create mode 100644 packages/types/tsconfig.json create mode 100644 packages/utils/README.md create mode 100644 packages/utils/package.json create mode 100644 packages/utils/src/helpers/__tests__/find-menu-by-path.test.ts create mode 100644 packages/utils/src/helpers/__tests__/generate-menus.test.ts create mode 100644 packages/utils/src/helpers/__tests__/generate-routes-frontend.test.ts create mode 100644 packages/utils/src/helpers/__tests__/merge-route-modules.test.ts create mode 100644 packages/utils/src/helpers/find-menu-by-path.ts create mode 100644 packages/utils/src/helpers/generate-menus.ts create mode 100644 packages/utils/src/helpers/generate-routes-backend.ts create mode 100644 packages/utils/src/helpers/generate-routes-frontend.ts create mode 100644 packages/utils/src/helpers/get-popup-container.ts create mode 100644 packages/utils/src/helpers/index.ts create mode 100644 packages/utils/src/helpers/merge-route-modules.ts create mode 100644 packages/utils/src/helpers/reset-routes.ts create mode 100644 packages/utils/src/helpers/unmount-global-loading.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 scripts/clean.mjs create mode 100644 scripts/deploy/Dockerfile create mode 100644 scripts/deploy/build-local-docker-image.sh create mode 100644 scripts/deploy/nginx.conf create mode 100644 scripts/turbo-run/README.md create mode 100644 scripts/turbo-run/bin/turbo-run.mjs create mode 100644 scripts/turbo-run/build.config.ts create mode 100644 scripts/turbo-run/package.json create mode 100644 scripts/turbo-run/src/index.ts create mode 100644 scripts/turbo-run/src/run.ts create mode 100644 scripts/turbo-run/tsconfig.json create mode 100644 scripts/vsh/README.md create mode 100644 scripts/vsh/bin/vsh.mjs create mode 100644 scripts/vsh/build.config.ts create mode 100644 scripts/vsh/package.json create mode 100644 scripts/vsh/src/check-circular/index.ts create mode 100644 scripts/vsh/src/check-dep/index.ts create mode 100644 scripts/vsh/src/code-workspace/index.ts create mode 100644 scripts/vsh/src/index.ts create mode 100644 scripts/vsh/src/lint/index.ts create mode 100644 scripts/vsh/src/publint/index.ts create mode 100644 scripts/vsh/tsconfig.json create mode 100644 stylelint.config.mjs create mode 100644 tea.yaml create mode 100644 turbo.json create mode 100644 vben-admin.code-workspace create mode 100644 vitest.config.ts create mode 100644 vitest.workspace.ts diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..dc3bc09 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..02e33fa --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1 @@ +export { default } from '@vben/commitlint-config'; diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..52b833a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +.git +.gitignore +*.md +dist +.turbo +dist.zip diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..179aec6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=2 +max_line_length = 100 +trim_trailing_whitespace = true +quote_type = single + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d4e5bd3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings + +# Automatically normalize line endings (to LF) for all text-based files. +* text=auto eol=lf + +# Declare files that will always have CRLF line endings on checkout. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary \ No newline at end of file diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..4b28a69 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,2 @@ +[core] + ignorecase = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d49651 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +node_modules +.DS_Store +dist +dist-ssr +dist.zip +dist.tar +dist.war +.nitro +.output +*-dist.zip +*-dist.tar +*-dist.war +coverage +*.local +**/.vitepress/cache +.cache +.turbo +.temp +dev-dist +.stylelintcache +yarn.lock +package-lock.json +.VSCodeCounter +**/backend-mock/data + +# local env files +.env.local +.env.*.local +.eslintcache + +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +vite.config.mts.* +vite.config.mjs.* +vite.config.js.* +vite.config.ts.* + +# Editor directories and files +.idea +# .vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.history +/docs +/playground +/apps/backend-mock +/playground +/docs diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..fb75b43 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: + - port: 5555 + onOpen: open-preview +tasks: + - init: corepack enable && pnpm install + command: pnpm run dev:play diff --git a/.lintstagedrc.mjs b/.lintstagedrc.mjs new file mode 100644 index 0000000..94b0192 --- /dev/null +++ b/.lintstagedrc.mjs @@ -0,0 +1,20 @@ +export default { + '*.md': ['prettier --cache --ignore-unknown --write'], + '*.vue': [ + 'prettier --write', + 'eslint --cache --fix', + 'stylelint --fix --allow-empty-input', + ], + '*.{js,jsx,ts,tsx}': [ + 'prettier --cache --ignore-unknown --write', + 'eslint --cache --fix', + ], + '*.{scss,less,styl,html,vue,css}': [ + 'prettier --cache --ignore-unknown --write', + 'stylelint --fix --allow-empty-input', + ], + 'package.json': ['prettier --cache --write'], + '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [ + 'prettier --cache --write--parser json', + ], +}; diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..48b14e6 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +20.14.0 diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..f4a1ad4 --- /dev/null +++ b/.npmrc @@ -0,0 +1,13 @@ +registry = "https://registry.npmmirror.com" +public-hoist-pattern[]=husky +public-hoist-pattern[]=eslint +public-hoist-pattern[]=prettier +public-hoist-pattern[]=prettier-plugin-tailwindcss +public-hoist-pattern[]=stylelint +public-hoist-pattern[]=*postcss* +public-hoist-pattern[]=@commitlint/* +public-hoist-pattern[]=czg + +strict-peer-dependencies=false +auto-install-peers=true +dedupe-peer-dependents=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d0b0ca1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,18 @@ +dist +dev-dist +.local +.output.js +node_modules +.nvmrc +coverage +CODEOWNERS +.nitro +.output + + +**/*.svg +**/*.sh + +public +.npmrc +*-lock.yaml diff --git a/.prettierrc.mjs b/.prettierrc.mjs new file mode 100644 index 0000000..3e25d2c --- /dev/null +++ b/.prettierrc.mjs @@ -0,0 +1 @@ +export { default } from '@vben/prettier-config'; diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..f4b2db2 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,4 @@ +dist +public +__tests__ +coverage diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..e8dc9ed --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,30 @@ +{ + "recommendations": [ + // Vue 3 的语言支持 + "Vue.volar", + // 将 ESLint JavaScript 集成到 VS Code 中。 + "dbaeumer.vscode-eslint", + // Visual Studio Code 的官方 Stylelint 扩展 + "stylelint.vscode-stylelint", + // 使用 Prettier 的代码格式化程序 + "esbenp.prettier-vscode", + // 支持 dotenv 文件语法 + "mikestead.dotenv", + // 源代码的拼写检查器 + "streetsidesoftware.code-spell-checker", + // Tailwind CSS 的官方 VS Code 插件 + "bradlc.vscode-tailwindcss", + // iconify 图标插件 + "antfu.iconify", + // i18n 插件 + "Lokalise.i18n-ally", + // CSS 变量提示 + "vunguyentuan.vscode-css-variables", + // 在 package.json 中显示 PNPM catalog 的版本 + "antfu.pnpm-catalog-lens" + ], + "unwantedRecommendations": [ + // 和 volar 冲突 + "octref.vetur" + ] +} diff --git a/.vscode/global.code-snippets b/.vscode/global.code-snippets new file mode 100644 index 0000000..7604b01 --- /dev/null +++ b/.vscode/global.code-snippets @@ -0,0 +1,37 @@ +{ + "import": { + "scope": "javascript,typescript", + "prefix": "im", + "body": ["import { $2 } from '$1';"], + "description": "Import a module", + }, + "export-all": { + "scope": "javascript,typescript", + "prefix": "ex", + "body": ["export * from '$1';"], + "description": "Export a module", + }, + "vue-script-setup": { + "scope": "vue", + "prefix": "", + "const props = defineProps<{", + " modelValue?: boolean,", + "}>()", + "$1", + "", + "", + "", + ], + }, + "vue-computed": { + "scope": "javascript,typescript,vue", + "prefix": "com", + "body": ["computed(() => { $1 })"], + }, +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e967330 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "name": "vben admin playground dev", + "request": "launch", + "url": "http://localhost:5555", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/playground" + }, + { + "type": "chrome", + "name": "vben admin antd dev", + "request": "launch", + "url": "http://localhost:5666", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-antd" + }, + { + "type": "chrome", + "name": "vben admin ele dev", + "request": "launch", + "url": "http://localhost:5777", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-ele" + }, + { + "type": "chrome", + "name": "vben admin naive dev", + "request": "launch", + "url": "http://localhost:5888", + "env": { "NODE_ENV": "development" }, + "sourceMaps": true, + "webRoot": "${workspaceFolder}/apps/web-naive" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9d6169e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,227 @@ +{ + "tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts", + // workbench + "workbench.list.smoothScrolling": true, + "workbench.startupEditor": "newUntitledFile", + "workbench.tree.indent": 10, + "workbench.editor.highlightModifiedTabs": true, + "workbench.editor.closeOnFileDelete": true, + "workbench.editor.limit.enabled": true, + "workbench.editor.limit.perEditorGroup": true, + "workbench.editor.limit.value": 5, + + // editor + "editor.tabSize": 2, + "editor.detectIndentation": false, + "editor.cursorBlinking": "expand", + "editor.largeFileOptimizations": false, + "editor.accessibilitySupport": "off", + "editor.cursorSmoothCaretAnimation": "on", + "editor.guides.bracketPairs": "active", + "editor.inlineSuggest.enabled": true, + "editor.suggestSelection": "recentlyUsedByPrefix", + "editor.acceptSuggestionOnEnter": "smart", + "editor.suggest.snippetsPreventQuickSuggestions": false, + "editor.stickyScroll.enabled": true, + "editor.hover.sticky": true, + "editor.suggest.insertMode": "replace", + "editor.bracketPairColorization.enabled": true, + "editor.autoClosingBrackets": "beforeWhitespace", + "editor.autoClosingDelete": "always", + "editor.autoClosingOvertype": "always", + "editor.autoClosingQuotes": "beforeWhitespace", + "editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.fixAll.stylelint": "explicit", + "source.organizeImports": "never" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[css]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[scss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[markdown]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[vue]": { + "editor.defaultFormatter": "Vue.volar" + }, + // extensions + "extensions.ignoreRecommendations": true, + + // terminal + "terminal.integrated.cursorBlinking": true, + "terminal.integrated.persistentSessionReviveProcess": "never", + "terminal.integrated.tabs.enabled": true, + "terminal.integrated.scrollback": 10000, + "terminal.integrated.stickyScroll.enabled": true, + + // files + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.simpleDialog.enable": true, + "files.associations": { + "*.ejs": "html", + "*.art": "html", + "**/tsconfig.json": "jsonc", + "*.json": "jsonc", + "package.json": "json" + }, + + "files.exclude": { + "**/.eslintcache": true, + "**/bower_components": true, + "**/.turbo": true, + "**/.idea": true, + "**/tmp": true, + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.stylelintcache": true, + "**/.DS_Store": true, + "**/vite.config.mts.*": true, + "**/tea.yaml": true + }, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/.vscode/**": true, + "**/node_modules/**": true, + "**/tmp/**": true, + "**/bower_components/**": true, + "**/dist/**": true, + "**/yarn.lock": true + }, + + // search + "search.searchEditor.singleClickBehaviour": "peekDefinition", + "search.followSymlinks": false, + // 在使用搜索功能时,将这些文件夹/文件排除在外 + "search.exclude": { + "**/node_modules": true, + "**/*.log": true, + "**/*.log*": true, + "**/bower_components": true, + "**/dist": true, + "**/elehukouben": true, + "**/.git": true, + "**/.github": true, + "**/.gitignore": true, + "**/.svn": true, + "**/.DS_Store": true, + "**/.vitepress/cache": true, + "**/.idea": true, + "**/.vscode": false, + "**/.yarn": true, + "**/tmp": true, + "*.xml": true, + "out": true, + "dist": true, + "node_modules": true, + "CHANGELOG.md": true, + "**/pnpm-lock.yaml": true, + "**/yarn.lock": true + }, + + "debug.onTaskErrors": "debugAnyway", + "diffEditor.ignoreTrimWhitespace": false, + "npm.packageManager": "pnpm", + + "css.validate": false, + "less.validate": false, + "scss.validate": false, + + // extension + "emmet.showSuggestionsAsSnippets": true, + "emmet.triggerExpansionOnTab": false, + + "errorLens.enabledDiagnosticLevels": ["warning", "error"], + "errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"], + + "stylelint.enable": true, + "stylelint.packageManager": "pnpm", + "stylelint.validate": ["css", "less", "postcss", "scss", "vue"], + "stylelint.customSyntax": "postcss-html", + "stylelint.snippet": ["css", "less", "postcss", "scss", "vue"], + + "typescript.inlayHints.enumMemberValues.enabled": true, + "typescript.preferences.preferTypeOnlyAutoImports": true, + "typescript.preferences.includePackageJsonAutoImports": "on", + + "eslint.validate": [ + "javascript", + "typescript", + "javascriptreact", + "typescriptreact", + "vue", + "html", + "markdown", + "json", + "jsonc", + "json5" + ], + + "tailwindCSS.experimental.classRegex": [ + ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] + ], + + "github.copilot.enable": { + "*": true, + "markdown": true, + "plaintext": false, + "yaml": false + }, + + "cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"], + + "i18n-ally.localesPaths": [ + "packages/locales/src/langs", + "playground/src/locales/langs", + "apps/*/src/locales/langs" + ], + "i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}", + "i18n-ally.enabledParsers": ["json"], + "i18n-ally.sourceLanguage": "en", + "i18n-ally.displayLanguage": "zh-CN", + "i18n-ally.enabledFrameworks": ["vue", "react"], + "i18n-ally.keystyle": "nested", + "i18n-ally.sortKeys": true, + "i18n-ally.namespace": true, + + // 控制相关文件嵌套展示 + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.ts": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx, $(capture).d.ts", + "*.tsx": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx,$(capture).d.ts", + "*.env": "$(capture).env.*", + "README.md": "README*,CHANGELOG*,LICENSE,CNAME", + "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json", + "eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json", + "tailwind.config.mjs": "postcss.*" + }, + "commentTranslate.hover.enabled": false, + "commentTranslate.multiLineMerge": true, + "vue.server.hybridMode": true, + "typescript.tsdk": "node_modules/typescript/lib", + "oxc.enable": false +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ffa6f81 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +FROM node:22-alpine AS builder +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV NODE_OPTIONS=--max-old-space-size=8192 +ENV TZ=Asia/Shanghai + +RUN corepack enable + +WORKDIR /vben5 + +# copy package.json and pnpm-lock.yaml to workspace +COPY . /vben5 + +RUN pnpm install --frozen-lockfile +# 如果你的项目中使用了 antd,需要执行下面的命令 +RUN pnpm build:antd + +# 如果你的项目中使用了 element-ui,需要执行下面的命令 +#RUN pnpm build:ele + +# 如果你的项目中使用了 naive,需要执行下面的命令 +#RUN pnpm build:naive + +RUN echo "Builder Success 🎉" + +FROM nginx:stable-alpine AS production + +RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf + +# 如果你的项目中使用了 antd,需要执行下面的命令 +COPY --from=builder /vben5/apps/web-antd/dist /usr/share/nginx/html + +# 如果你的项目中使用了 element-ui,需要执行下面的命令 +#COPY --from=builder /vben5/apps/web-ele/dist /usr/share/nginx/html + +# 如果你的项目中使用了 naive,需要执行下面的命令 +#COPY --from=builder /vben5/apps/web-naive/dist /usr/share/nginx/html + +COPY --from=builder /vben5/_nginx/nginx.conf /etc/nginx/nginx.conf + +EXPOSE 8080 + +# start nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..809cb92 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +BSD 2-Clause License + +Copyright (c) 2024, WangJunZzz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3c813a7 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +

+ + + +

+ +

Abp Vnext Pro Vben5 ...

+ + + +## 🔗 链接 + +- [AbpPro Vben2预览](http://182.43.18.151:44318/) +- [AbpPro Vben5预览](http://182.43.18.151:44320/) +- [代码生成器预览](http://182.43.18.151:44311/) +- [文档地址](http://doc.cncore.club/) +- [国内文档地址](http://doc.china.cncore.club:81/) +- [视频教程](https://www.bilibili.com/video/BV1pt4y1E7aZ) +- [代码生成器仓库地址](https://github.com/WangJunZzz/abp-vnext-pro-suite) + +## 📦 快速开始 + +- 安装Cli +```bash +dotnet tool install Lion.AbpPro.Cli -g +``` + +- 更新Cli +```bash +dotnet tool update Lion.AbpPro.Cli -g +``` + +### 三个项目模板 +- 源码版本 + +```bash +lion.abp new -t pro -c 公司名称 -p 项目名称 -v 版本(默认LastRelease) -o 默认当前控制台执行目录 +``` + +- nuget版本 + +```bash +lion.abp new -t pro.all -c 公司名称 -p 项目名称 -v 版本(默认LastRelease) -o 默认当前控制台执行目录 +``` + + +- 模块 + +```bash +lion.abp new -t pro.module -c 公司名称 -p 项目名称 -v 版本(默认LastRelease) -o 默认当前控制台执行目录 +``` + + +## ✨ 系统功能 + +- [x] 用户管理 +- [x] 角色管理 +- [x] 审计日志 +- [x] 后台任务 +- [x] 集成事件 +- [x] SinglaR 消息通知(站内信) +- [x] 多语言 +- [x] 数据字典 +- [x] 容器化部署 +- [x] 单元测试 +- [x] ES 日志 +- [x] Setting 管理 +- [x] 多租户 +- [x] 文件管理 + + +## 🤝 如何贡献 + +非常欢迎你的加入!提一个 Issue 或者提交一个 Pull Request。 + +**Pull Request:** + +1. Fork 代码! +2. 创建自己的分支: `git checkout -b feat/xxxx` +3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'` +4. 推送您的分支: `git push origin feat/xxxx` +5. 提交`pull request` + +## Git 贡献提交规范 + +- 参考 + - `feat` 增加新功能 + - `fix` 修复问题/BUG + - `style` 代码风格相关无影响运行结果的 + - `perf` 优化/性能提升 + - `refactor` 重构 + - `revert` 撤销修改 + - `test` 测试相关 + - `docs` 文档/注释 + - `chore` 依赖更新/脚手架配置修改等 + - `workflow` 工作流改进 + - `ci` 持续集成 + - `types` 类型定义文件更改 + - `wip` 开发中 + +## ✒️交流 +- QQ 1群:686933575(已满) +- QQ 2群:862717726 + +## 💖赞助 +- Star就是对该项目的最大肯定! +- 如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持! +![](https://blog-resouce.oss-cn-shenzhen.aliyuncs.com/images/donate.png) + diff --git a/_nginx/nginx.conf b/_nginx/nginx.conf new file mode 100644 index 0000000..8e6ab10 --- /dev/null +++ b/_nginx/nginx.conf @@ -0,0 +1,75 @@ + +#user nobody; +worker_processes 1; + +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + types { + application/javascript js mjs; + text/css css; + text/html html; + } + + sendfile on; + # tcp_nopush on; + + #keepalive_timeout 0; + # keepalive_timeout 65; + + # gzip on; + # gzip_buffers 32 16k; + # gzip_comp_level 6; + # gzip_min_length 1k; + # gzip_static on; + # gzip_types text/plain + # text/css + # application/javascript + # application/json + # application/x-javascript + # text/xml + # application/xml + # application/xml+rss + # text/javascript; #设置压缩的文件类型 + # gzip_vary on; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; + index index.html; + # Enable CORS + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + } + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/apps/web-antd/.env b/apps/web-antd/.env new file mode 100644 index 0000000..2207a82 --- /dev/null +++ b/apps/web-antd/.env @@ -0,0 +1,5 @@ +# 应用标题 +VITE_APP_TITLE=采集端综合管理 + +# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 +VITE_APP_NAMESPACE=abp-vnext-pro-vben5-antd diff --git a/apps/web-antd/.env.analyze b/apps/web-antd/.env.analyze new file mode 100644 index 0000000..ffafa8d --- /dev/null +++ b/apps/web-antd/.env.analyze @@ -0,0 +1,7 @@ +# public path +VITE_BASE=/ + +# Basic interface address SPA +VITE_GLOB_API_URL=/api + +VITE_VISUALIZER=true diff --git a/apps/web-antd/.env.development b/apps/web-antd/.env.development new file mode 100644 index 0000000..0267bae --- /dev/null +++ b/apps/web-antd/.env.development @@ -0,0 +1,29 @@ +# 端口号 +VITE_PORT=4200 + +VITE_BASE=/ + +# 接口地址 +VITE_GLOB_API_URL=/api + +# 是否开启 Nitro Mock服务,true 为开启,false 为关闭 +VITE_NITRO_MOCK=true + +# vue-router 的模式 +VITE_ROUTER_HISTORY=history + + +# 是否打开 devtools,true 为打开,false 为关闭 +VITE_DEVTOOLS=false + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 是否打开刷新浏览器检查用户角色信息 +VITE_REFRESH_ROLE = true + +# 后端接口地址 +VITE_APP_API_ADDRESS=http://localhost:44315/ + +# websocket地址 +VITE_WEBSOCKET_URL=http://localhost:44315/signalr/notification diff --git a/apps/web-antd/.env.production b/apps/web-antd/.env.production new file mode 100644 index 0000000..ef60e7c --- /dev/null +++ b/apps/web-antd/.env.production @@ -0,0 +1,28 @@ +VITE_BASE=/ + +# 接口地址 +VITE_GLOB_API_URL=https://mock-napi.vben.pro/api + +# 是否开启压缩,可以设置为 none, brotli, gzip +VITE_COMPRESS=none + +# 是否开启 PWA +VITE_PWA=false + +# vue-router 的模式 +VITE_ROUTER_HISTORY=history + +# 是否注入全局loading +VITE_INJECT_APP_LOADING=true + +# 打包后是否生成dist.zip +VITE_ARCHIVER=true + +# 是否打开刷新浏览器检查用户角色信息 +VITE_REFRESH_ROLE = true + +# 后端接口地址 +VITE_APP_API_ADDRESS=http://118.190.144.92:9110/ + +# websocket地址 +VITE_WEBSOCKET_URL=http://118.190.144.92:9110/signalr/notification diff --git a/apps/web-antd/index.html b/apps/web-antd/index.html new file mode 100644 index 0000000..480eb84 --- /dev/null +++ b/apps/web-antd/index.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + <%= VITE_APP_TITLE %> + + + + +
+ + + diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json new file mode 100644 index 0000000..ce67d79 --- /dev/null +++ b/apps/web-antd/package.json @@ -0,0 +1,61 @@ +{ + "name": "@vben/web-antd", + "version": "5.5.3", + "homepage": "https://vben.pro", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "apps/web-antd" + }, + "license": "MIT", + "author": { + "name": "vben", + "email": "ann.vben@gmail.com", + "url": "https://github.com/anncwb" + }, + "type": "module", + "scripts": { + "nswag": "openapi-ts -f ./src/api-client-config/config.ts", + "build": "pnpm vite build --mode production", + "build:analyze": "pnpm vite build --mode analyze", + "dev": "pnpm vite --mode development", + "preview": "vite preview", + "typecheck": "vue-tsc --noEmit --skipLibCheck" + }, + "imports": { + "#/*": "./src/*" + }, + "dependencies": { + "@microsoft/signalr": "^8.0.7", + "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/constants": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/layouts": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/plugins": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/request": "workspace:*", + "@vben/stores": "workspace:*", + "@vben/styles": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "ant-design-vue": "catalog:", + "axios": "^1.7.7", + "clipboard": "^2.0.11", + "codemirror-editor-vue3": "^2.8.0", + "dayjs": "catalog:", + "pinia": "catalog:", + "vue": "catalog:", + "vue-request": "^2.0.4", + "vue-router": "catalog:", + "vue3-json-viewer": "^2.2.2" + }, + "devDependencies": { + "@hey-api/client-axios": "^0.2.10", + "@hey-api/openapi-ts": "^0.55.3" + } +} diff --git a/apps/web-antd/postcss.config.mjs b/apps/web-antd/postcss.config.mjs new file mode 100644 index 0000000..3d80704 --- /dev/null +++ b/apps/web-antd/postcss.config.mjs @@ -0,0 +1 @@ +export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-antd/public/favicon.ico b/apps/web-antd/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fcf9818e2cf855039b272bdbfbb202d3ff3fa159 GIT binary patch literal 5430 zcmbtY33L=y7JY$12T+8gBk14=GU5gfn~Es=nm`C4AtVq2WF`B)l8}u>kcfdG`xZh7 z1QH@k!WNbQA}Y8rB4pn?Rn^_qRo&T0_nY^tI}C`PBiiTO^QwMT{dfQSKkwZa04wMM zy?X=M0kG_E0D}QwzyR}o4vl|CV{g(JUD6xoaWVij{_9_Z+hnMBoj6eCWqqZ|bDG3? zP1V)7jjOBM^TxNWH(wK5z8fU#uMgCSB?DD--$H2RPrcYwmDwZk?iT=9oB(QH+axi3 z9?DS*P#;M)Y%a>#V-YKdAXdDsz*NrcJ2dtV8t=Z2nsdGH*5&qiyUE>Vm@dqrLZt6> z(Th+Yvk>*s^HEHlg>AP+S>_mmri!6xDj#NlJ7oxWQ{b1Xzn%o3F2 zJy4EYjGB~r*z(;Z#Hz7qs`{9|A<#8ejX|uNj3&YMhCXf82Xb<7t(@Sce5a-F#rS2Y zPw=KW-BEkM4vp1Q(NsN!FqN*!*3f;EooLj|vHO`eL|&WtiJTISa&ibti29;|D&^HFD6dLJF=aUl zQK_g7S%X4w3TiekkUA=zPMK5-kDF8rPMA1{9Ua2-!AA8AkaE6;=1?EdZ_7=RH)f)o zz6YhW?I?uqK+bnR@_w194oGPgLT0)mW_M}f{ky5|&9E|QX9CL8LEd)~4EqY9IqS?o z{kEgO$QcJ|@3tc!kcFIoHX)1V*p0kb)a5#dX?;}TF3?iv0EkJTD|G@qe-~Pce+GHo zUNGz}jFvZLqdGDZxqw5+`{xi25@;Up%^i&{5ngJKR4B7`edHK7AGr+82hKvv;WMv@ zYYyG!LyjO9l#6`eVdBv_&jI9pw_i|sXY^1l+y2P+cXkv&)3*J<2c8E_(&=zM;!EU0 z@{kKYf_xCoLGuVSpE^80voR>Un<^;hk?+}!ZdX2t>o0=%S;@=7@}lqg@B-vQ^J$Kw z$kRMRNM0isbo4zwI1l*X$GyH9LO9vCUO3gaUR~I)UQ^VszB=pq zJ72ARzCd00QaRnLwP*Ti2{J*f&gxTfBdPm^TdR65(H6Yc<=&PT;fM6WaKmm2a4u7z zY0)I8b)GPl_qG;vVa_N8*`pjZ+l*jlZISnwfl zwR4>1*Y=-YMWLuCHstj@R+ZJSN6o<(K)=KqG#)n4uxOg27&xazjC4dT`IKUoTJp9N z>Z6DU%ij@>sEM{gL&=Bc{L6Cp!%%!u97-9Vcg-A>{BGewG17na4{SQ#y`>@VSqJV! zcc^fj1ovi-e@^h8bzUMLBKgvWJD@glA>~?k%K0vo`<)5%mHaPJ4dFIT#QUX`ua$K_ zv`!@kR1+xvrt;y$@z-$}g2rF|jbd>xY&y~NLfzpPo|paXq0w!|VqJ(syG(v`(M}c) z^C(YyQq5S5hFBLgC>)$ACQisl+Msy;Bg*%~&Gm=YYGUiHG=tS7V<~&aI8v>n*qgzw zhhqDW|3clxUTvDQeS)f;roW`|oBNea>y*ilMC(*IP%N}m_vCnQ;y|^Jp0PN{>^bdE zL)sKg8Kh+_=+ri~?4IeHdE|Qz-@)6CF{)<) zjs-BRjtBk54es*F==&1+kV)$>F7gULf-mibH*%4rpOQ!mtq3B}^A+qlAw8#G}T>Y-?wcHN#jlo%oSHYH%Rm4ro+cZ_?b3=+aWV5Y&5fK;E$%$f_)8BCDP)cJNdD z5dR5M*#fwd?XFZ~Zg(zdGj@V{^PXPPhOKAhPts6cvkv9eYc2Rhv0`cpHiRc5w`?T^8l1Q&Crn*oxsRVg_ar{VE#)>+#dL67hLvPFyvkW!mt=0{?cCmWIH@mr+o(*k>E2{86CkHbRwjbs_ z;eGcaw{!*8Il9N8dkTDGI}Ok+=`mlwH&Byx8Vtv-fuZ&9*o3w*^g`-N}!37fsOYgx4us+7ZgITsO%AU}9@c0~6uE~i8yCA6W+4Kb70q*X~ z1AYEAXs;5x${9Jk)G_2cgnE{cP7c&Z5fA?1UP|ew%;$pjW$KWFCzc8j?yl(;c%DQUTT-YW=pQN6P`YqPGu^v$A11)>exgV^rWIbW%QR)c`>QsTb zBe+27tpc;3*gyL~x0Us6C9H27sZKoG$VZs_K92Q$ojlmNVC%O)pq^6AVikBK30GD_ zMZkWz8Mfn3`Trp!2gH5Xq1C9d64zZy7vc&@^BhNW56d_Z=v?p=3wAyk1d0(Kly|Gn zJG*~_Zw}N39{f|jJ3rFxybe;vRgkt^8=^@)U&}|GR5-Byw=)jB5)0x%RtPO( + component: T, + type: 'input' | 'select', +) => { + return (props: any, { attrs, slots }: Omit) => { + const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); + return h(component, { ...props, ...attrs, placeholder }, slots); + }; +}; + +// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 +export type ComponentType = + | 'ApiSelect' + | 'ApiTreeSelect' + | 'AutoComplete' + | 'Checkbox' + | 'CheckboxGroup' + | 'DatePicker' + | 'DefaultButton' + | 'Divider' + | 'IconPicker' + | 'Input' + | 'InputNumber' + | 'InputPassword' + | 'Mentions' + | 'PrimaryButton' + | 'Radio' + | 'RadioGroup' + | 'RangePicker' + | 'Rate' + | 'Select' + | 'Space' + | 'Switch' + | 'Textarea' + | 'TimePicker' + | 'TreeSelect' + | 'Upload' + | BaseFormComponentType; + +async function initComponentAdapter() { + const components: Partial> = { + // 如果你的组件体积比较大,可以使用异步加载 + // Button: () => + // import('xxx').then((res) => res.Button), + ApiSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: Select, + loadingSlot: 'suffixIcon', + visibleEvent: 'onDropdownVisibleChange', + modelPropName: 'value', + }, + slots, + ); + }, + ApiTreeSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: TreeSelect, + fieldNames: { label: 'label', value: 'value', children: 'children' }, + loadingSlot: 'suffixIcon', + modelPropName: 'value', + optionsPropName: 'treeData', + visibleEvent: 'onVisibleChange', + }, + slots, + ); + }, + AutoComplete, + Checkbox, + CheckboxGroup, + DatePicker, + // 自定义默认按钮 + DefaultButton: (props, { attrs, slots }) => { + return h(Button, { ...props, attrs, type: 'default' }, slots); + }, + Divider, + IconPicker: (props, { attrs, slots }) => { + return h( + IconPicker, + { iconSlot: 'addonAfter', inputComponent: Input, ...props, ...attrs }, + slots, + ); + }, + Input: withDefaultPlaceholder(Input, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputPassword: withDefaultPlaceholder(InputPassword, 'input'), + Mentions: withDefaultPlaceholder(Mentions, 'input'), + // 自定义主要按钮 + PrimaryButton: (props, { attrs, slots }) => { + return h(Button, { ...props, attrs, type: 'primary' }, slots); + }, + Radio, + RadioGroup, + RangePicker, + Rate, + Select: withDefaultPlaceholder(Select, 'select'), + Space, + Switch, + Textarea: withDefaultPlaceholder(Textarea, 'input'), + TimePicker, + TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), + Upload, + }; + + // 将组件注册到全局共享状态中 + globalShareState.setComponents(components); + + // 定义全局共享状态中的消息提示 + globalShareState.defineMessage({ + // 复制成功消息提示 + copyPreferencesSuccess: (title, content) => { + notification.success({ + description: content, + message: title, + placement: 'bottomRight', + }); + }, + }); +} + +export { initComponentAdapter }; diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts new file mode 100644 index 0000000..65ff793 --- /dev/null +++ b/apps/web-antd/src/adapter/form.ts @@ -0,0 +1,47 @@ +import type { + VbenFormSchema as FormSchema, + VbenFormProps, +} from '@vben/common-ui'; + +import type { ComponentType } from './component'; + +import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; +import { $t } from '@vben/locales'; + +setupVbenForm({ + config: { + // ant design vue组件库默认都是 v-model:value + baseModelPropName: 'value', + + // 一些组件是 v-model:checked 或者 v-model:fileList + modelPropNameMap: { + Checkbox: 'checked', + Radio: 'checked', + Switch: 'checked', + Upload: 'fileList', + }, + }, + defineRules: { + // 输入项目必填国际化适配 + required: (value, _params, ctx) => { + if (value === undefined || value === null || value.length === 0) { + return $t('ui.formRules.required', [ctx.label]); + } + return true; + }, + // 选择项目必填国际化适配 + selectRequired: (value, _params, ctx) => { + if (value === undefined || value === null) { + return $t('ui.formRules.selectRequired', [ctx.label]); + } + return true; + }, + }, +}); + +const useVbenForm = useForm; + +export { useVbenForm, z }; + +export type VbenFormSchema = FormSchema; +export type { VbenFormProps }; diff --git a/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts new file mode 100644 index 0000000..c29f08f --- /dev/null +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -0,0 +1,67 @@ +import { h } from 'vue'; + +import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; + +import { Button, Image } from 'ant-design-vue'; + +import { useVbenForm } from './form'; + +setupVbenVxeTable({ + configVxeTable: (vxeUI) => { + vxeUI.setConfig({ + grid: { + align: 'center', + border: true, + columnConfig: { + resizable: true, + }, + minHeight: 180, + formConfig: { + // 全局禁用vxe-table的表单配置,使用formOptions + enabled: false, + }, + proxyConfig: { + autoLoad: true, + response: { + result: 'items', + total: 'totalCount', + list: 'items', + }, + showActiveMsg: true, + showResponseMsg: false, + }, + round: true, + showOverflow: true, + size: 'small', // medium / small / mini + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellImage' }, + vxeUI.renderer.add('CellImage', { + renderTableDefault(_renderOpts, params) { + const { column, row } = params; + return h(Image, { src: row[column.field] }); + }, + }); + + // 表格配置项可以用 cellRender: { name: 'CellLink' }, + vxeUI.renderer.add('CellLink', { + renderTableDefault(renderOpts) { + const { props } = renderOpts; + return h( + Button, + { size: 'small', type: 'link' }, + { default: () => props?.text }, + ); + }, + }); + + // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 + // vxeUI.formats.add + }, + useVbenForm, +}); + +export { useVbenVxeGrid }; + +export type * from '@vben/plugins/vxe-table'; diff --git a/apps/web-antd/src/api-client-config/config.ts b/apps/web-antd/src/api-client-config/config.ts new file mode 100644 index 0000000..7c56fd6 --- /dev/null +++ b/apps/web-antd/src/api-client-config/config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from '@hey-api/openapi-ts'; + +export default defineConfig({ + client: '@hey-api/client-axios', + input: 'http://localhost:44315/swagger/IOT/swagger.json', + output: 'src/api-client', +}); diff --git a/apps/web-antd/src/api-client-config/index-blob.ts b/apps/web-antd/src/api-client-config/index-blob.ts new file mode 100644 index 0000000..19177db --- /dev/null +++ b/apps/web-antd/src/api-client-config/index-blob.ts @@ -0,0 +1,102 @@ +import { useUserStore } from '@vben/stores'; + +import { message as Message } from 'ant-design-vue'; +import axios from 'axios'; + +import { $t } from '#/locales'; +import { antdLocale } from '#/locales/index'; +import { useAuthStore } from '#/store'; + +const api = axios.create({ + baseURL: import.meta.env.DEV + ? '/proxy/' + : import.meta.env.VITE_APP_API_ADDRESS, + timeout: 1000 * 60, + responseType: 'blob', // 设置响应数据类型为blob +}); + +api.interceptors.request.use((request) => { + // 全局拦截请求发送前提交的参数 + const userStore = useUserStore(); + const authStore = useAuthStore(); + const token = userStore.userInfo?.token; + // 设置请求头 + if (request.headers) { + request.headers.__tenant = userStore.tenant?.tenantId; + request.headers['accept-language'] = antdLocale.value.locale; + } + // 如果token过期,则跳转到登录页面 + if (token && userStore.checkUserLoginExpire()) { + authStore.logout(); + + return Promise.reject($t('common.mesage401')); + } + + // 设置请求头 + if (request.headers) { + request.headers.Authorization = `Bearer ${token}`; + } + + return request; +}); + +api.interceptors.response.use( + (response) => { + /** + * 全局拦截请求发送后返回的数据,如果数据有报错则在这做全局的错误提示 + * 假设返回数据格式为:{ status: 1, error: '', data: '' } + * 规则是当 status 为 1 时表示请求成功,为 0 时表示接口需要登录或者登录状态失效,需要重新登录 + * 请求出错时 error 会返回错误信息 + */ + if (response.data.status === 1) { + if (response.data.error !== '') { + // 错误提示 + Message.error(response.data.error); + return Promise.reject(response.data); + } + } else { + // useUserStore().logout() + } + return Promise.resolve(response); + }, + (error) => { + let message = error.message; + if (message === 'Network Error') { + message = $t('common.mesage500'); + } else if (message.includes('timeout')) { + message = $t('common.timeOut'); + } else + switch (error.status) { + case 400: { + message = error.response.data.error?.validationErrors[0].message; + + break; + } + case 401: { + message = $t('common.mesage401'); + // useUserStore().logout() + + break; + } + case 403: { + message = $t('common.mesage403'); + + break; + } + case 500: { + message = error.response.data.error?.message; + + break; + } + default: { + if (message.includes('Request failed with status code')) { + message = $t('common.mesage500'); + } + } + } + Message.error(message); + return Promise.reject(error); + }, +); + +export default api; diff --git a/apps/web-antd/src/api-client-config/index.ts b/apps/web-antd/src/api-client-config/index.ts new file mode 100644 index 0000000..fd36417 --- /dev/null +++ b/apps/web-antd/src/api-client-config/index.ts @@ -0,0 +1,114 @@ +import { useUserStore } from '@vben/stores'; + +import { message as Message } from 'ant-design-vue'; + +import { $t } from '#/locales'; +import { antdLocale } from '#/locales/index'; +import { useAuthStore } from '#/store'; + +import { client } from '../api-client/services.gen'; + +client.setConfig({ + baseURL: import.meta.env.DEV + ? '/proxy/' + : import.meta.env.VITE_APP_API_ADDRESS, + timeout: 1000 * 60, + responseType: 'json', + throwOnError: true, +}); + +client.instance.interceptors.request.use((request) => { + // 全局拦截请求发送前提交的参数 + const userStore = useUserStore(); + const token = userStore.userInfo?.token; + // 设置请求头 + if (request.headers) { + request.headers.__tenant = userStore.tenant?.tenantId; + // todo vben5 没有提供统一获取当前语言的方式 + request.headers['accept-language'] = antdLocale.value.locale; + } + + // 如果token过期,则跳转到登录页面 + if ( + request.url !== undefined && + request.url.includes('/api/app/account/login') + ) { + return request; + } + + if (token && userStore.checkUserLoginExpire()) { + const authStore = useAuthStore(); + authStore.logout(); + Message.warn($t('common.mesage401')); + + return Promise.reject($t('common.mesage401')); + } + + // 设置请求头 + if (request.headers) { + request.headers.Authorization = `Bearer ${token}`; + } + + return request; +}); + +client.instance.interceptors.response.use( + (response) => { + /** + * 全局拦截请求发送后返回的数据,如果数据有报错则在这做全局的错误提示 + * 假设返回数据格式为:{ status: 1, error: '', data: '' } + * 规则是当 status 为 1 时表示请求成功,为 0 时表示接口需要登录或者登录状态失效,需要重新登录 + * 请求出错时 error 会返回错误信息 + */ + if (response.data.status === 1) { + if (response.data.error !== '') { + // 错误提示 + Message.error(response.data.error); + return Promise.reject(response.data); + } + } else { + // useUserStore().logout() + } + return Promise.resolve(response); + }, + (error) => { + let message = error.message; + if (message === 'Network Error') { + message = $t('common.mesage500'); + } else if (message.includes('timeout')) { + message = $t('common.timeOut'); + } else + switch (error.status) { + case 400: { + message = error.response.data.error?.validationErrors[0].message; + + break; + } + case 401: { + message = $t('common.mesage401'); + // useUserStore().logout() + + break; + } + case 403: { + message = $t('common.mesage403'); + + break; + } + case 500: { + message = error.response.data.error?.message; + + break; + } + default: { + if (message.includes('Request failed with status code')) { + message = $t('common.mesage500'); + } + } + } + Message.error(message); + return Promise.reject(error); + }, +); + +export default client; diff --git a/apps/web-antd/src/api-client/index.ts b/apps/web-antd/src/api-client/index.ts new file mode 100644 index 0000000..0a2b84b --- /dev/null +++ b/apps/web-antd/src/api-client/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './schemas.gen'; +export * from './services.gen'; +export * from './types.gen'; \ No newline at end of file diff --git a/apps/web-antd/src/api-client/schemas.gen.ts b/apps/web-antd/src/api-client/schemas.gen.ts new file mode 100644 index 0000000..6bb1395 --- /dev/null +++ b/apps/web-antd/src/api-client/schemas.gen.ts @@ -0,0 +1,4927 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export const AbpLoginResultSchema = { + type: 'object', + properties: { + result: { + '$ref': '#/components/schemas/LoginResultType' + }, + description: { + type: 'string', + nullable: true, + readOnly: true + } + }, + additionalProperties: false +} as const; + +export const ActionApiDescriptionModelSchema = { + type: 'object', + properties: { + uniqueName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + httpMethod: { + type: 'string', + nullable: true + }, + url: { + type: 'string', + nullable: true + }, + supportedVersions: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + parametersOnMethod: { + type: 'array', + items: { + '$ref': '#/components/schemas/MethodParameterApiDescriptionModel' + }, + nullable: true + }, + parameters: { + type: 'array', + items: { + '$ref': '#/components/schemas/ParameterApiDescriptionModel' + }, + nullable: true + }, + returnValue: { + '$ref': '#/components/schemas/ReturnValueApiDescriptionModel' + }, + allowAnonymous: { + type: 'boolean', + nullable: true + }, + implementFrom: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const AddOrUpdateConnectionStringInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const AddRoleToOrganizationUnitInputSchema = { + type: 'object', + properties: { + roleId: { + type: 'array', + items: { + type: 'string', + format: 'uuid' + }, + nullable: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const AddUserToOrganizationUnitInputSchema = { + type: 'object', + properties: { + userId: { + type: 'array', + items: { + type: 'string', + format: 'uuid' + }, + nullable: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const AggregateRouteConfigSchema = { + type: 'object', + properties: { + routeKey: { + type: 'string', + nullable: true + }, + parameter: { + type: 'string', + nullable: true + }, + jsonPath: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationApiDescriptionModelSchema = { + type: 'object', + properties: { + modules: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ModuleApiDescriptionModel' + }, + nullable: true + }, + types: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/TypeApiDescriptionModel' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationAuthConfigurationDtoSchema = { + type: 'object', + properties: { + grantedPolicies: { + type: 'object', + additionalProperties: { + type: 'boolean' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationConfigurationDtoSchema = { + type: 'object', + properties: { + localization: { + '$ref': '#/components/schemas/ApplicationLocalizationConfigurationDto' + }, + auth: { + '$ref': '#/components/schemas/ApplicationAuthConfigurationDto' + }, + setting: { + '$ref': '#/components/schemas/ApplicationSettingConfigurationDto' + }, + currentUser: { + '$ref': '#/components/schemas/CurrentUserDto' + }, + features: { + '$ref': '#/components/schemas/ApplicationFeatureConfigurationDto' + }, + globalFeatures: { + '$ref': '#/components/schemas/ApplicationGlobalFeatureConfigurationDto' + }, + multiTenancy: { + '$ref': '#/components/schemas/MultiTenancyInfoDto' + }, + currentTenant: { + '$ref': '#/components/schemas/CurrentTenantDto' + }, + timing: { + '$ref': '#/components/schemas/TimingDto' + }, + clock: { + '$ref': '#/components/schemas/ClockDto' + }, + objectExtensions: { + '$ref': '#/components/schemas/ObjectExtensionsDto' + }, + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationFeatureConfigurationDtoSchema = { + type: 'object', + properties: { + values: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationGlobalFeatureConfigurationDtoSchema = { + type: 'object', + properties: { + enabledFeatures: { + uniqueItems: true, + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationLocalizationConfigurationDtoSchema = { + type: 'object', + properties: { + values: { + type: 'object', + additionalProperties: { + type: 'object', + additionalProperties: { + type: 'string' + } + }, + nullable: true + }, + resources: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ApplicationLocalizationResourceDto' + }, + nullable: true + }, + languages: { + type: 'array', + items: { + '$ref': '#/components/schemas/LanguageInfo' + }, + nullable: true + }, + currentCulture: { + '$ref': '#/components/schemas/CurrentCultureDto' + }, + defaultResourceName: { + type: 'string', + nullable: true + }, + languagesMap: { + type: 'object', + additionalProperties: { + type: 'array', + items: { + '$ref': '#/components/schemas/NameValue' + } + }, + nullable: true + }, + languageFilesMap: { + type: 'object', + additionalProperties: { + type: 'array', + items: { + '$ref': '#/components/schemas/NameValue' + } + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationLocalizationDtoSchema = { + type: 'object', + properties: { + resources: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ApplicationLocalizationResourceDto' + }, + nullable: true + }, + currentCulture: { + '$ref': '#/components/schemas/CurrentCultureDto' + } + }, + additionalProperties: false +} as const; + +export const ApplicationLocalizationResourceDtoSchema = { + type: 'object', + properties: { + texts: { + type: 'object', + additionalProperties: { + type: 'string' + }, + nullable: true + }, + baseResources: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ApplicationSettingConfigurationDtoSchema = { + type: 'object', + properties: { + values: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ChangePasswordInputSchema = { + required: ['newPassword'], + type: 'object', + properties: { + currentPassword: { + maxLength: 128, + minLength: 0, + type: 'string', + nullable: true + }, + newPassword: { + maxLength: 128, + minLength: 0, + type: 'string' + } + }, + additionalProperties: false +} as const; + +export const ClockDtoSchema = { + type: 'object', + properties: { + kind: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ControllerApiDescriptionModelSchema = { + type: 'object', + properties: { + controllerName: { + type: 'string', + nullable: true + }, + controllerGroupName: { + type: 'string', + nullable: true + }, + isRemoteService: { + type: 'boolean' + }, + isIntegrationService: { + type: 'boolean' + }, + apiVersion: { + type: 'string', + nullable: true + }, + type: { + type: 'string', + nullable: true + }, + interfaces: { + type: 'array', + items: { + '$ref': '#/components/schemas/ControllerInterfaceApiDescriptionModel' + }, + nullable: true + }, + actions: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ActionApiDescriptionModel' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ControllerInterfaceApiDescriptionModelSchema = { + type: 'object', + properties: { + type: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + methods: { + type: 'array', + items: { + '$ref': '#/components/schemas/InterfaceMethodApiDescriptionModel' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const CreateDataDictinaryDetailInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + code: { + type: 'string', + nullable: true + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + }, + order: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const CreateDataDictinaryInputSchema = { + type: 'object', + properties: { + code: { + type: 'string', + nullable: true + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const CreateLanguageInputSchema = { + type: 'object', + properties: { + cultureName: { + type: 'string', + nullable: true + }, + uiCultureName: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + flagIcon: { + type: 'string', + nullable: true + }, + isEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const CreateLanguageTextInputSchema = { + type: 'object', + properties: { + resourceName: { + type: 'string', + nullable: true + }, + cultureName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const CreateOrganizationUnitInputSchema = { + type: 'object', + properties: { + displayName: { + type: 'string', + nullable: true + }, + parentId: { + type: 'string', + format: 'uuid', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const CurrentCultureDtoSchema = { + type: 'object', + properties: { + displayName: { + type: 'string', + nullable: true + }, + englishName: { + type: 'string', + nullable: true + }, + threeLetterIsoLanguageName: { + type: 'string', + nullable: true + }, + twoLetterIsoLanguageName: { + type: 'string', + nullable: true + }, + isRightToLeft: { + type: 'boolean' + }, + cultureName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + nativeName: { + type: 'string', + nullable: true + }, + dateTimeFormat: { + '$ref': '#/components/schemas/DateTimeFormatDto' + } + }, + additionalProperties: false +} as const; + +export const CurrentTenantDtoSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + isAvailable: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const CurrentUserDtoSchema = { + type: 'object', + properties: { + isAuthenticated: { + type: 'boolean' + }, + id: { + type: 'string', + format: 'uuid', + nullable: true + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + impersonatorUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + impersonatorTenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + impersonatorUserName: { + type: 'string', + nullable: true + }, + impersonatorTenantName: { + type: 'string', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + surName: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + }, + emailVerified: { + type: 'boolean' + }, + phoneNumber: { + type: 'string', + nullable: true + }, + phoneNumberVerified: { + type: 'boolean' + }, + roles: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + sessionId: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const DateTimeFormatDtoSchema = { + type: 'object', + properties: { + calendarAlgorithmType: { + type: 'string', + nullable: true + }, + dateTimeFormatLong: { + type: 'string', + nullable: true + }, + shortDatePattern: { + type: 'string', + nullable: true + }, + fullDateTimePattern: { + type: 'string', + nullable: true + }, + dateSeparator: { + type: 'string', + nullable: true + }, + shortTimePattern: { + type: 'string', + nullable: true + }, + longTimePattern: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const DeleteConnectionStringInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + tenantId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const DeleteDataDictionaryDetailInputSchema = { + type: 'object', + properties: { + dataDictionaryId: { + type: 'string', + format: 'uuid' + }, + dataDictionayDetailId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const DeleteFeatureInputSchema = { + type: 'object', + properties: { + providerName: { + type: 'string', + nullable: true + }, + providerKey: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const DeleteLanguageInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const EntityChangeTypeSchema = { + enum: [0, 1, 2], + type: 'integer', + format: 'int32', + 'x-enumNames': ['Created', 'Updated', 'Deleted'], + 'x-enum-varnames': ['Created', 'Updated', 'Deleted'] +} as const; + +export const EntityExtensionDtoSchema = { + type: 'object', + properties: { + properties: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ExtensionPropertyDto' + }, + nullable: true + }, + configuration: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionEnumDtoSchema = { + type: 'object', + properties: { + fields: { + type: 'array', + items: { + '$ref': '#/components/schemas/ExtensionEnumFieldDto' + }, + nullable: true + }, + localizationResource: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionEnumFieldDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + value: { + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyApiCreateDtoSchema = { + type: 'object', + properties: { + isAvailable: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyApiDtoSchema = { + type: 'object', + properties: { + onGet: { + '$ref': '#/components/schemas/ExtensionPropertyApiGetDto' + }, + onCreate: { + '$ref': '#/components/schemas/ExtensionPropertyApiCreateDto' + }, + onUpdate: { + '$ref': '#/components/schemas/ExtensionPropertyApiUpdateDto' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyApiGetDtoSchema = { + type: 'object', + properties: { + isAvailable: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyApiUpdateDtoSchema = { + type: 'object', + properties: { + isAvailable: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyAttributeDtoSchema = { + type: 'object', + properties: { + typeSimple: { + type: 'string', + nullable: true + }, + config: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyDtoSchema = { + type: 'object', + properties: { + type: { + type: 'string', + nullable: true + }, + typeSimple: { + type: 'string', + nullable: true + }, + displayName: { + '$ref': '#/components/schemas/LocalizableStringDto' + }, + api: { + '$ref': '#/components/schemas/ExtensionPropertyApiDto' + }, + ui: { + '$ref': '#/components/schemas/ExtensionPropertyUiDto' + }, + policy: { + '$ref': '#/components/schemas/ExtensionPropertyPolicyDto' + }, + attributes: { + type: 'array', + items: { + '$ref': '#/components/schemas/ExtensionPropertyAttributeDto' + }, + nullable: true + }, + configuration: { + type: 'object', + additionalProperties: {}, + nullable: true + }, + defaultValue: { + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyFeaturePolicyDtoSchema = { + type: 'object', + properties: { + features: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + requiresAll: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyGlobalFeaturePolicyDtoSchema = { + type: 'object', + properties: { + features: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + requiresAll: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyPermissionPolicyDtoSchema = { + type: 'object', + properties: { + permissionNames: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + requiresAll: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyPolicyDtoSchema = { + type: 'object', + properties: { + globalFeatures: { + '$ref': '#/components/schemas/ExtensionPropertyGlobalFeaturePolicyDto' + }, + features: { + '$ref': '#/components/schemas/ExtensionPropertyFeaturePolicyDto' + }, + permissions: { + '$ref': '#/components/schemas/ExtensionPropertyPermissionPolicyDto' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyUiDtoSchema = { + type: 'object', + properties: { + onTable: { + '$ref': '#/components/schemas/ExtensionPropertyUiTableDto' + }, + onCreateForm: { + '$ref': '#/components/schemas/ExtensionPropertyUiFormDto' + }, + onEditForm: { + '$ref': '#/components/schemas/ExtensionPropertyUiFormDto' + }, + lookup: { + '$ref': '#/components/schemas/ExtensionPropertyUiLookupDto' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyUiFormDtoSchema = { + type: 'object', + properties: { + isVisible: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyUiLookupDtoSchema = { + type: 'object', + properties: { + url: { + type: 'string', + nullable: true + }, + resultListPropertyName: { + type: 'string', + nullable: true + }, + displayPropertyName: { + type: 'string', + nullable: true + }, + valuePropertyName: { + type: 'string', + nullable: true + }, + filterParamName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ExtensionPropertyUiTableDtoSchema = { + type: 'object', + properties: { + isVisible: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const FeatureDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + }, + provider: { + '$ref': '#/components/schemas/FeatureProviderDto' + }, + description: { + type: 'string', + nullable: true + }, + valueType: { + '$ref': '#/components/schemas/IStringValueType' + }, + depth: { + type: 'integer', + format: 'int32' + }, + parentName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FeatureGroupDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + features: { + type: 'array', + items: { + '$ref': '#/components/schemas/FeatureDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FeatureProviderDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + key: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileAggregateRouteSchema = { + type: 'object', + properties: { + routeKeys: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + routeKeysConfig: { + type: 'array', + items: { + '$ref': '#/components/schemas/AggregateRouteConfig' + }, + nullable: true + }, + upstreamPathTemplate: { + type: 'string', + nullable: true + }, + upstreamHost: { + type: 'string', + nullable: true + }, + routeIsCaseSensitive: { + type: 'boolean' + }, + aggregator: { + type: 'string', + nullable: true + }, + upstreamHttpMethod: { + type: 'array', + items: { + type: 'string' + }, + nullable: true, + readOnly: true + }, + priority: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileAuthenticationOptionsSchema = { + type: 'object', + properties: { + authenticationProviderKey: { + type: 'string', + nullable: true + }, + allowedScopes: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileCacheOptionsSchema = { + type: 'object', + properties: { + ttlSeconds: { + type: 'integer', + format: 'int32' + }, + region: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileConfigurationSchema = { + type: 'object', + properties: { + routes: { + type: 'array', + items: { + '$ref': '#/components/schemas/FileRoute' + }, + nullable: true + }, + dynamicRoutes: { + type: 'array', + items: { + '$ref': '#/components/schemas/FileDynamicRoute' + }, + nullable: true + }, + aggregates: { + type: 'array', + items: { + '$ref': '#/components/schemas/FileAggregateRoute' + }, + nullable: true + }, + globalConfiguration: { + '$ref': '#/components/schemas/FileGlobalConfiguration' + } + }, + additionalProperties: false +} as const; + +export const FileDynamicRouteSchema = { + type: 'object', + properties: { + serviceName: { + type: 'string', + nullable: true + }, + rateLimitRule: { + '$ref': '#/components/schemas/FileRateLimitRule' + }, + downstreamHttpVersion: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileGlobalConfigurationSchema = { + type: 'object', + properties: { + requestIdKey: { + type: 'string', + nullable: true + }, + serviceDiscoveryProvider: { + '$ref': '#/components/schemas/FileServiceDiscoveryProvider' + }, + rateLimitOptions: { + '$ref': '#/components/schemas/FileRateLimitOptions' + }, + qoSOptions: { + '$ref': '#/components/schemas/FileQoSOptions' + }, + baseUrl: { + type: 'string', + nullable: true + }, + loadBalancerOptions: { + '$ref': '#/components/schemas/FileLoadBalancerOptions' + }, + downstreamScheme: { + type: 'string', + nullable: true + }, + httpHandlerOptions: { + '$ref': '#/components/schemas/FileHttpHandlerOptions' + }, + downstreamHttpVersion: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileHostAndPortSchema = { + type: 'object', + properties: { + host: { + type: 'string', + nullable: true + }, + port: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileHttpHandlerOptionsSchema = { + type: 'object', + properties: { + allowAutoRedirect: { + type: 'boolean' + }, + useCookieContainer: { + type: 'boolean' + }, + useTracing: { + type: 'boolean' + }, + useProxy: { + type: 'boolean' + }, + maxConnectionsPerServer: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileLoadBalancerOptionsSchema = { + type: 'object', + properties: { + type: { + type: 'string', + nullable: true + }, + key: { + type: 'string', + nullable: true + }, + expiry: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileQoSOptionsSchema = { + type: 'object', + properties: { + exceptionsAllowedBeforeBreaking: { + type: 'integer', + format: 'int32' + }, + durationOfBreak: { + type: 'integer', + format: 'int32' + }, + timeoutValue: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileRateLimitOptionsSchema = { + type: 'object', + properties: { + clientIdHeader: { + type: 'string', + nullable: true + }, + quotaExceededMessage: { + type: 'string', + nullable: true + }, + rateLimitCounterPrefix: { + type: 'string', + nullable: true + }, + disableRateLimitHeaders: { + type: 'boolean' + }, + httpStatusCode: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const FileRateLimitRuleSchema = { + type: 'object', + properties: { + clientWhitelist: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + enableRateLimiting: { + type: 'boolean' + }, + period: { + type: 'string', + nullable: true + }, + periodTimespan: { + type: 'number', + format: 'double' + }, + limit: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const FileRouteSchema = { + type: 'object', + properties: { + downstreamPathTemplate: { + type: 'string', + nullable: true + }, + upstreamPathTemplate: { + type: 'string', + nullable: true + }, + upstreamHttpMethod: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + downstreamHttpMethod: { + type: 'string', + nullable: true + }, + addHeadersToRequest: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + upstreamHeaderTransform: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + downstreamHeaderTransform: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + addClaimsToRequest: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + routeClaimsRequirement: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + addQueriesToRequest: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + changeDownstreamPathTemplate: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + }, + requestIdKey: { + type: 'string', + nullable: true + }, + fileCacheOptions: { + '$ref': '#/components/schemas/FileCacheOptions' + }, + routeIsCaseSensitive: { + type: 'boolean' + }, + serviceName: { + type: 'string', + nullable: true + }, + serviceNamespace: { + type: 'string', + nullable: true + }, + downstreamScheme: { + type: 'string', + nullable: true + }, + qoSOptions: { + '$ref': '#/components/schemas/FileQoSOptions' + }, + loadBalancerOptions: { + '$ref': '#/components/schemas/FileLoadBalancerOptions' + }, + rateLimitOptions: { + '$ref': '#/components/schemas/FileRateLimitRule' + }, + authenticationOptions: { + '$ref': '#/components/schemas/FileAuthenticationOptions' + }, + httpHandlerOptions: { + '$ref': '#/components/schemas/FileHttpHandlerOptions' + }, + downstreamHostAndPorts: { + type: 'array', + items: { + '$ref': '#/components/schemas/FileHostAndPort' + }, + nullable: true + }, + upstreamHost: { + type: 'string', + nullable: true + }, + key: { + type: 'string', + nullable: true + }, + delegatingHandlers: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + priority: { + type: 'integer', + format: 'int32' + }, + timeout: { + type: 'integer', + format: 'int32' + }, + dangerousAcceptAnyServerCertificateValidator: { + type: 'boolean' + }, + securityOptions: { + '$ref': '#/components/schemas/FileSecurityOptions' + }, + downstreamHttpVersion: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileSecurityOptionsSchema = { + type: 'object', + properties: { + ipAllowedList: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + ipBlockedList: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FileServiceDiscoveryProviderSchema = { + type: 'object', + properties: { + scheme: { + type: 'string', + nullable: true + }, + host: { + type: 'string', + nullable: true + }, + port: { + type: 'integer', + format: 'int32' + }, + type: { + type: 'string', + nullable: true + }, + token: { + type: 'string', + nullable: true + }, + configurationKey: { + type: 'string', + nullable: true + }, + pollingInterval: { + type: 'integer', + format: 'int32' + }, + namespace: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FindByUserNameInputSchema = { + type: 'object', + properties: { + userName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FindTenantByNameInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const FindTenantResultDtoSchema = { + type: 'object', + properties: { + success: { + type: 'boolean' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + normalizedName: { + type: 'string', + nullable: true + }, + isActive: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const GetFeatureListResultDtoSchema = { + type: 'object', + properties: { + groups: { + type: 'array', + items: { + '$ref': '#/components/schemas/FeatureGroupDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetFeatureListResultInputSchema = { + type: 'object', + properties: { + providerName: { + type: 'string', + nullable: true + }, + providerKey: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitRoleInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitRoleOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitRoleOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/GetOrganizationUnitRoleOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitUserInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitUserOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + userName: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetOrganizationUnitUserOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/GetOrganizationUnitUserOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const GetPermissionInputSchema = { + type: 'object', + properties: { + providerName: { + type: 'string', + nullable: true + }, + providerKey: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetUnAddRoleInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetUnAddRoleOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetUnAddRoleOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/GetUnAddRoleOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const GetUnAddUserInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetUnAddUserOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + userName: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const GetUnAddUserOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/GetUnAddUserOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const HttpStatusCodeSchema = { + enum: [100, 101, 102, 103, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511], + type: 'integer', + format: 'int32', + 'x-enumNames': ['Continue', 'SwitchingProtocols', 'Processing', 'EarlyHints', 'OK', 'Created', 'Accepted', 'NonAuthoritativeInformation', 'NoContent', 'ResetContent', 'PartialContent', 'MultiStatus', 'AlreadyReported', 'IMUsed', 'MultipleChoices', 'Ambiguous', 'MovedPermanently', 'Moved', 'Found', 'Redirect', 'SeeOther', 'RedirectMethod', 'NotModified', 'UseProxy', 'Unused', 'TemporaryRedirect', 'RedirectKeepVerb', 'PermanentRedirect', 'BadRequest', 'Unauthorized', 'PaymentRequired', 'Forbidden', 'NotFound', 'MethodNotAllowed', 'NotAcceptable', 'ProxyAuthenticationRequired', 'RequestTimeout', 'Conflict', 'Gone', 'LengthRequired', 'PreconditionFailed', 'RequestEntityTooLarge', 'RequestUriTooLong', 'UnsupportedMediaType', 'RequestedRangeNotSatisfiable', 'ExpectationFailed', 'MisdirectedRequest', 'UnprocessableEntity', 'UnprocessableContent', 'Locked', 'FailedDependency', 'UpgradeRequired', 'PreconditionRequired', 'TooManyRequests', 'RequestHeaderFieldsTooLarge', 'UnavailableForLegalReasons', 'InternalServerError', 'NotImplemented', 'BadGateway', 'ServiceUnavailable', 'GatewayTimeout', 'HttpVersionNotSupported', 'VariantAlsoNegotiates', 'InsufficientStorage', 'LoopDetected', 'NotExtended', 'NetworkAuthenticationRequired'], + 'x-enum-varnames': ['Continue', 'SwitchingProtocols', 'Processing', 'EarlyHints', 'OK', 'Created', 'Accepted', 'NonAuthoritativeInformation', 'NoContent', 'ResetContent', 'PartialContent', 'MultiStatus', 'AlreadyReported', 'IMUsed', 'MultipleChoices', 'Ambiguous', 'MovedPermanently', 'Moved', 'Found', 'Redirect', 'SeeOther', 'RedirectMethod', 'NotModified', 'UseProxy', 'Unused', 'TemporaryRedirect', 'RedirectKeepVerb', 'PermanentRedirect', 'BadRequest', 'Unauthorized', 'PaymentRequired', 'Forbidden', 'NotFound', 'MethodNotAllowed', 'NotAcceptable', 'ProxyAuthenticationRequired', 'RequestTimeout', 'Conflict', 'Gone', 'LengthRequired', 'PreconditionFailed', 'RequestEntityTooLarge', 'RequestUriTooLong', 'UnsupportedMediaType', 'RequestedRangeNotSatisfiable', 'ExpectationFailed', 'MisdirectedRequest', 'UnprocessableEntity', 'UnprocessableContent', 'Locked', 'FailedDependency', 'UpgradeRequired', 'PreconditionRequired', 'TooManyRequests', 'RequestHeaderFieldsTooLarge', 'UnavailableForLegalReasons', 'InternalServerError', 'NotImplemented', 'BadGateway', 'ServiceUnavailable', 'GatewayTimeout', 'HttpVersionNotSupported', 'VariantAlsoNegotiates', 'InsufficientStorage', 'LoopDetected', 'NotExtended', 'NetworkAuthenticationRequired'] +} as const; + +export const IStringValueTypeSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true, + readOnly: true + }, + properties: { + type: 'object', + additionalProperties: { + nullable: true + }, + nullable: true, + readOnly: true + }, + validator: { + '$ref': '#/components/schemas/IValueValidator' + } + }, + additionalProperties: false +} as const; + +export const IValueValidatorSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true, + readOnly: true + }, + properties: { + type: 'object', + additionalProperties: { + nullable: true + }, + nullable: true, + readOnly: true + } + }, + additionalProperties: false +} as const; + +export const IanaTimeZoneSchema = { + type: 'object', + properties: { + timeZoneName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const IdInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const IdentityRoleCreateDtoSchema = { + required: ['name'], + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + name: { + maxLength: 256, + minLength: 0, + type: 'string' + }, + isDefault: { + type: 'boolean' + }, + isPublic: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const IdentityRoleDtoSchema = { + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + isDefault: { + type: 'boolean' + }, + isStatic: { + type: 'boolean' + }, + isPublic: { + type: 'boolean' + }, + concurrencyStamp: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const IdentityRoleDtoListResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/IdentityRoleDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const IdentityRoleDtoPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/IdentityRoleDto' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const IdentityRoleUpdateDtoSchema = { + required: ['name'], + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + name: { + maxLength: 256, + minLength: 0, + type: 'string' + }, + isDefault: { + type: 'boolean' + }, + isPublic: { + type: 'boolean' + }, + concurrencyStamp: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const IdentityUserCreateDtoSchema = { + required: ['email', 'password', 'userName'], + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + userName: { + maxLength: 256, + minLength: 0, + type: 'string' + }, + name: { + maxLength: 64, + minLength: 0, + type: 'string', + nullable: true + }, + surname: { + maxLength: 64, + minLength: 0, + type: 'string', + nullable: true + }, + email: { + maxLength: 256, + minLength: 0, + type: 'string', + format: 'email' + }, + phoneNumber: { + maxLength: 16, + minLength: 0, + type: 'string', + nullable: true + }, + isActive: { + type: 'boolean' + }, + lockoutEnabled: { + type: 'boolean' + }, + roleNames: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + password: { + maxLength: 128, + minLength: 0, + type: 'string' + } + }, + additionalProperties: false +} as const; + +export const IdentityUserDtoSchema = { + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + id: { + type: 'string', + format: 'uuid' + }, + creationTime: { + type: 'string', + format: 'date-time' + }, + creatorId: { + type: 'string', + format: 'uuid', + nullable: true + }, + lastModificationTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + lastModifierId: { + type: 'string', + format: 'uuid', + nullable: true + }, + isDeleted: { + type: 'boolean' + }, + deleterId: { + type: 'string', + format: 'uuid', + nullable: true + }, + deletionTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + surname: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + }, + emailConfirmed: { + type: 'boolean' + }, + phoneNumber: { + type: 'string', + nullable: true + }, + phoneNumberConfirmed: { + type: 'boolean' + }, + isActive: { + type: 'boolean' + }, + lockoutEnabled: { + type: 'boolean' + }, + accessFailedCount: { + type: 'integer', + format: 'int32' + }, + lockoutEnd: { + type: 'string', + format: 'date-time', + nullable: true + }, + concurrencyStamp: { + type: 'string', + nullable: true + }, + entityVersion: { + type: 'integer', + format: 'int32' + }, + lastPasswordChangeTime: { + type: 'string', + format: 'date-time', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const IdentityUserUpdateDtoSchema = { + required: ['email', 'userName'], + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + userName: { + maxLength: 256, + minLength: 0, + type: 'string' + }, + name: { + maxLength: 64, + minLength: 0, + type: 'string', + nullable: true + }, + surname: { + maxLength: 64, + minLength: 0, + type: 'string', + nullable: true + }, + email: { + maxLength: 256, + minLength: 0, + type: 'string', + format: 'email' + }, + phoneNumber: { + maxLength: 16, + minLength: 0, + type: 'string', + nullable: true + }, + isActive: { + type: 'boolean' + }, + lockoutEnabled: { + type: 'boolean' + }, + roleNames: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + password: { + maxLength: 128, + minLength: 0, + type: 'string', + nullable: true + }, + concurrencyStamp: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const InterfaceMethodApiDescriptionModelSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + parametersOnMethod: { + type: 'array', + items: { + '$ref': '#/components/schemas/MethodParameterApiDescriptionModel' + }, + nullable: true + }, + returnValue: { + '$ref': '#/components/schemas/ReturnValueApiDescriptionModel' + } + }, + additionalProperties: false +} as const; + +export const LanguageInfoSchema = { + type: 'object', + properties: { + cultureName: { + type: 'string', + nullable: true + }, + uiCultureName: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + twoLetterISOLanguageName: { + type: 'string', + nullable: true, + readOnly: true + } + }, + additionalProperties: false +} as const; + +export const LocalizableStringDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + resource: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const LockUserInputSchema = { + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid' + }, + locked: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const LoginInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + password: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const LoginOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + token: { + type: 'string', + nullable: true + }, + roles: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const LoginResultTypeSchema = { + enum: [1, 2, 3, 4, 5], + type: 'integer', + format: 'int32', + 'x-enumNames': ['Success', 'InvalidUserNameOrPassword', 'NotAllowed', 'LockedOut', 'RequiresTwoFactor'], + 'x-enum-varnames': ['Success', 'InvalidUserNameOrPassword', 'NotAllowed', 'LockedOut', 'RequiresTwoFactor'] +} as const; + +export const MessageLevelSchema = { + enum: [10, 20, 30], + type: 'integer', + format: 'int32', + 'x-enumNames': ['Warning', 'Information', 'Error'], + 'x-enum-varnames': ['Warning', 'Information', 'Error'] +} as const; + +export const MessageTypeSchema = { + enum: [10, 20], + type: 'integer', + format: 'int32', + 'x-enumNames': ['BroadCast', 'Common'], + 'x-enum-varnames': ['BroadCast', 'Common'] +} as const; + +export const MethodParameterApiDescriptionModelSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + typeAsString: { + type: 'string', + nullable: true + }, + type: { + type: 'string', + nullable: true + }, + typeSimple: { + type: 'string', + nullable: true + }, + isOptional: { + type: 'boolean' + }, + defaultValue: { + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ModuleApiDescriptionModelSchema = { + type: 'object', + properties: { + rootPath: { + type: 'string', + nullable: true + }, + remoteServiceName: { + type: 'string', + nullable: true + }, + controllers: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ControllerApiDescriptionModel' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ModuleExtensionDtoSchema = { + type: 'object', + properties: { + entities: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/EntityExtensionDto' + }, + nullable: true + }, + configuration: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const MultiTenancyInfoDtoSchema = { + type: 'object', + properties: { + isEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const MyProfileOutputSchema = { + type: 'object', + properties: { + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + surname: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + }, + phoneNumber: { + type: 'string', + nullable: true + }, + isActive: { + type: 'boolean' + }, + twoFactorEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const NameValueSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ObjectExtensionsDtoSchema = { + type: 'object', + properties: { + modules: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ModuleExtensionDto' + }, + nullable: true + }, + enums: { + type: 'object', + additionalProperties: { + '$ref': '#/components/schemas/ExtensionEnumDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageIdentityUserOutputSchema = { + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + id: { + type: 'string', + format: 'uuid' + }, + creationTime: { + type: 'string', + format: 'date-time' + }, + creatorId: { + type: 'string', + format: 'uuid', + nullable: true + }, + lastModificationTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + lastModifierId: { + type: 'string', + format: 'uuid', + nullable: true + }, + isDeleted: { + type: 'boolean' + }, + deleterId: { + type: 'string', + format: 'uuid', + nullable: true + }, + deletionTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + surname: { + type: 'string', + nullable: true + }, + email: { + type: 'string', + nullable: true + }, + emailConfirmed: { + type: 'boolean' + }, + phoneNumber: { + type: 'string', + nullable: true + }, + phoneNumberConfirmed: { + type: 'boolean' + }, + isActive: { + type: 'boolean' + }, + lockoutEnabled: { + type: 'boolean' + }, + accessFailedCount: { + type: 'integer', + format: 'int32' + }, + lockoutEnd: { + type: 'string', + format: 'date-time', + nullable: true + }, + concurrencyStamp: { + type: 'string', + nullable: true + }, + entityVersion: { + type: 'integer', + format: 'int32' + }, + lastPasswordChangeTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + twoFactorEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const PageIdentityUserOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PageIdentityUserOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PageLanguageInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageLanguageOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + cultureName: { + type: 'string', + nullable: true + }, + uiCultureName: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + flagIcon: { + type: 'string', + nullable: true + }, + isEnabled: { + type: 'boolean' + }, + creationTime: { + type: 'string', + format: 'date-time' + }, + isDefault: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const PageLanguageOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PageLanguageOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PageLanguageTextInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + cultureName: { + type: 'string', + nullable: true + }, + resourceName: { + type: 'string', + nullable: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageLanguageTextOutputSchema = { + type: 'object', + properties: { + resourceName: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageLanguageTextOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PageLanguageTextOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PageTenantConnectionStringInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageTenantConnectionStringOutputSchema = { + type: 'object', + properties: { + tenantId: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PageTenantConnectionStringOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PageTenantConnectionStringOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingAuditLogActionOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + auditLogId: { + type: 'string', + format: 'uuid' + }, + serviceName: { + type: 'string', + nullable: true + }, + methodName: { + type: 'string', + nullable: true + }, + parameters: { + type: 'string', + nullable: true + }, + executionTime: { + type: 'string', + nullable: true + }, + executionDuration: { + type: 'integer', + format: 'int32' + }, + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingAuditLogInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + sorting: { + type: 'string', + nullable: true + }, + startTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + endTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + httpMethod: { + type: 'string', + nullable: true + }, + url: { + type: 'string', + nullable: true + }, + userId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + applicationName: { + type: 'string', + nullable: true + }, + correlationId: { + type: 'string', + nullable: true + }, + maxExecutionDuration: { + type: 'integer', + format: 'int32', + nullable: true + }, + minExecutionDuration: { + type: 'integer', + format: 'int32', + nullable: true + }, + hasException: { + type: 'boolean', + nullable: true + }, + httpStatusCode: { + '$ref': '#/components/schemas/HttpStatusCode' + }, + clientIpAddress: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingAuditLogOutputSchema = { + type: 'object', + properties: { + applicationName: { + type: 'string', + nullable: true + }, + userId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + tenantName: { + type: 'string', + nullable: true + }, + impersonatorUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + impersonatorTenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + executionTime: { + type: 'string', + nullable: true + }, + executionDuration: { + type: 'integer', + format: 'int32' + }, + clientIpAddress: { + type: 'string', + nullable: true + }, + clientName: { + type: 'string', + nullable: true + }, + clientId: { + type: 'string', + nullable: true + }, + correlationId: { + type: 'string', + nullable: true + }, + browserInfo: { + type: 'string', + nullable: true + }, + httpMethod: { + type: 'string', + nullable: true + }, + url: { + type: 'string', + nullable: true + }, + exceptions: { + type: 'string', + nullable: true + }, + comments: { + type: 'string', + nullable: true + }, + httpStatusCode: { + type: 'integer', + format: 'int32', + nullable: true + }, + entityChanges: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingEntityChangeOutput' + }, + nullable: true + }, + actions: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingAuditLogActionOutput' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingAuditLogOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingAuditLogOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryDetailInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + dataDictionaryId: { + type: 'string', + format: 'uuid' + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryDetailOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + dataDictionaryId: { + type: 'string', + format: 'uuid' + }, + code: { + type: 'string', + nullable: true + }, + order: { + type: 'integer', + format: 'int32' + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + }, + isEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryDetailOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingDataDictionaryDetailOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + code: { + type: 'string', + nullable: true + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingDataDictionaryOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingDataDictionaryOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingEntityChangeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + auditLogId: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + changeTime: { + type: 'string', + nullable: true + }, + changeType: { + '$ref': '#/components/schemas/EntityChangeType' + }, + changeTypeDescription: { + type: 'string', + nullable: true + }, + entityTenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + entityId: { + type: 'string', + nullable: true + }, + entityTypeFullName: { + type: 'string', + nullable: true + }, + propertyChanges: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingEntityPropertyChangeOutput' + }, + nullable: true + }, + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingEntityPropertyChangeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + entityChangeId: { + type: 'string', + format: 'uuid' + }, + newValue: { + type: 'string', + nullable: true + }, + originalValue: { + type: 'string', + nullable: true + }, + propertyName: { + type: 'string', + nullable: true + }, + propertyTypeFullName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingIdentitySecurityLogInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + sorting: { + type: 'string', + nullable: true + }, + startTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + endTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + identity: { + type: 'string', + nullable: true + }, + action: { + type: 'string', + nullable: true + }, + userId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + applicationName: { + type: 'string', + nullable: true + }, + correlationId: { + type: 'string', + nullable: true + }, + clientId: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingIdentitySecurityLogOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + applicationName: { + type: 'string', + nullable: true + }, + identity: { + type: 'string', + nullable: true + }, + action: { + type: 'string', + nullable: true + }, + userId: { + type: 'string', + format: 'uuid', + nullable: true + }, + userName: { + type: 'string', + nullable: true + }, + tenantName: { + type: 'string', + nullable: true + }, + clientId: { + type: 'string', + nullable: true + }, + correlationId: { + type: 'string', + nullable: true + }, + clientIpAddress: { + type: 'string', + nullable: true + }, + browserInfo: { + type: 'string', + nullable: true + }, + creationTime: { + type: 'string', + format: 'date-time' + } + }, + additionalProperties: false +} as const; + +export const PagingIdentitySecurityLogOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingIdentitySecurityLogOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + title: { + type: 'string', + nullable: true + }, + content: { + type: 'string', + nullable: true + }, + senderUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + senderUserName: { + type: 'string', + nullable: true + }, + receiverUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + receiverUserName: { + type: 'string', + nullable: true + }, + read: { + type: 'boolean', + nullable: true + }, + startReadTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + endReadTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + messageType: { + '$ref': '#/components/schemas/MessageType' + }, + messageLevel: { + '$ref': '#/components/schemas/MessageLevel' + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + title: { + type: 'string', + nullable: true + }, + content: { + type: 'string', + nullable: true + }, + messageType: { + '$ref': '#/components/schemas/MessageType' + }, + messageTypeName: { + type: 'string', + nullable: true, + readOnly: true + }, + messageLevel: { + '$ref': '#/components/schemas/MessageLevel' + }, + messageLevelName: { + type: 'string', + nullable: true, + readOnly: true + }, + senderUserId: { + type: 'string', + format: 'uuid' + }, + senderUserName: { + type: 'string', + nullable: true + }, + receiveUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + receiveUserName: { + type: 'string', + nullable: true + }, + read: { + type: 'boolean' + }, + readTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + creationTime: { + type: 'string', + format: 'date-time' + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingNotificationOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationSubscriptionInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + notificationId: { + type: 'string', + format: 'uuid' + }, + receiverUserId: { + type: 'string', + format: 'uuid', + nullable: true + }, + receiverUserName: { + type: 'string', + nullable: true + }, + read: { + type: 'boolean', + nullable: true + }, + startReadTime: { + type: 'string', + format: 'date-time', + nullable: true + }, + endReadTime: { + type: 'string', + format: 'date-time', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationSubscriptionOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true + }, + notificationId: { + type: 'string', + format: 'uuid' + }, + receiveUserId: { + type: 'string', + format: 'uuid' + }, + receiveUserName: { + type: 'string', + nullable: true + }, + read: { + type: 'boolean' + }, + readTime: { + type: 'string', + format: 'date-time' + }, + title: { + type: 'string', + nullable: true + }, + content: { + type: 'string', + nullable: true + }, + messageType: { + '$ref': '#/components/schemas/MessageType' + }, + messageTypeName: { + type: 'string', + nullable: true, + readOnly: true + }, + messageLevel: { + '$ref': '#/components/schemas/MessageLevel' + }, + messageLevelName: { + type: 'string', + nullable: true, + readOnly: true + }, + senderUserId: { + type: 'string', + format: 'uuid' + }, + senderUserName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingNotificationSubscriptionOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/PagingNotificationSubscriptionOutput' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const PagingRoleListInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingTenantInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PagingUserListInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + format: 'int32' + }, + pageSize: { + type: 'integer', + format: 'int32' + }, + skipCount: { + type: 'integer', + format: 'int32', + readOnly: true + }, + filter: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const ParameterApiDescriptionModelSchema = { + type: 'object', + properties: { + nameOnMethod: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + jsonName: { + type: 'string', + nullable: true + }, + type: { + type: 'string', + nullable: true + }, + typeSimple: { + type: 'string', + nullable: true + }, + isOptional: { + type: 'boolean' + }, + defaultValue: { + nullable: true + }, + constraintTypes: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + bindingSourceId: { + type: 'string', + nullable: true + }, + descriptorName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PermissionOutputSchema = { + type: 'object', + properties: { + grants: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + allGrants: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + permissions: { + type: 'array', + items: { + '$ref': '#/components/schemas/PermissionTreeDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PermissionTreeDtoSchema = { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true + }, + key: { + type: 'string', + nullable: true + }, + children: { + type: 'array', + items: { + '$ref': '#/components/schemas/PermissionTreeDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const PropertyApiDescriptionModelSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + jsonName: { + type: 'string', + nullable: true + }, + type: { + type: 'string', + nullable: true + }, + typeSimple: { + type: 'string', + nullable: true + }, + isRequired: { + type: 'boolean' + }, + minLength: { + type: 'integer', + format: 'int32', + nullable: true + }, + maxLength: { + type: 'integer', + format: 'int32', + nullable: true + }, + minimum: { + type: 'string', + nullable: true + }, + maximum: { + type: 'string', + nullable: true + }, + regex: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const RemoteServiceErrorInfoSchema = { + type: 'object', + properties: { + code: { + type: 'string', + nullable: true + }, + message: { + type: 'string', + nullable: true + }, + details: { + type: 'string', + nullable: true + }, + data: { + type: 'object', + additionalProperties: {}, + nullable: true + }, + validationErrors: { + type: 'array', + items: { + '$ref': '#/components/schemas/RemoteServiceValidationErrorInfo' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const RemoteServiceErrorResponseSchema = { + type: 'object', + properties: { + error: { + '$ref': '#/components/schemas/RemoteServiceErrorInfo' + } + }, + additionalProperties: false +} as const; + +export const RemoteServiceValidationErrorInfoSchema = { + type: 'object', + properties: { + message: { + type: 'string', + nullable: true + }, + members: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const RemoveRoleToOrganizationUnitInputSchema = { + type: 'object', + properties: { + roleId: { + type: 'string', + format: 'uuid' + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const RemoveUserToOrganizationUnitInputSchema = { + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid' + }, + organizationUnitId: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const ReturnValueApiDescriptionModelSchema = { + type: 'object', + properties: { + type: { + type: 'string', + nullable: true + }, + typeSimple: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const SendBroadCastMessageInputSchema = { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true + }, + content: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const SendCommonMessageInputSchema = { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true + }, + content: { + type: 'string', + nullable: true + }, + receiveUserId: { + type: 'string', + format: 'uuid' + }, + receiveUserName: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const SetBatchReadInputSchema = { + type: 'object', + properties: { + ids: { + type: 'array', + items: { + type: 'string', + format: 'uuid' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const SetDataDictinaryDetailInputSchema = { + required: ['isEnabled'], + type: 'object', + properties: { + dataDictionaryId: { + type: 'string', + format: 'uuid' + }, + dataDictionayDetailId: { + type: 'string', + format: 'uuid' + }, + isEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const SetReadInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const SettingItemOutputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + }, + type: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const SettingOutputSchema = { + type: 'object', + properties: { + group: { + type: 'string', + nullable: true + }, + groupDisplayName: { + type: 'string', + nullable: true + }, + settingItemOutput: { + type: 'array', + items: { + '$ref': '#/components/schemas/SettingItemOutput' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const StringStringFromSelectorSchema = { + type: 'object', + properties: { + value: { + type: 'string', + nullable: true, + readOnly: true + }, + label: { + type: 'string', + nullable: true, + readOnly: true + } + }, + additionalProperties: false +} as const; + +export const TenantCreateDtoSchema = { + required: ['adminEmailAddress', 'adminPassword', 'name'], + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + name: { + maxLength: 64, + minLength: 0, + type: 'string' + }, + adminEmailAddress: { + maxLength: 256, + minLength: 1, + type: 'string', + format: 'email' + }, + adminPassword: { + maxLength: 128, + minLength: 1, + type: 'string' + } + }, + additionalProperties: false +} as const; + +export const TenantDtoSchema = { + type: 'object', + properties: { + extraProperties: { + type: 'object', + additionalProperties: {}, + nullable: true, + readOnly: true + }, + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + }, + concurrencyStamp: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const TenantDtoPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + '$ref': '#/components/schemas/TenantDto' + }, + nullable: true + }, + totalCount: { + type: 'integer', + format: 'int64' + } + }, + additionalProperties: false +} as const; + +export const TimeZoneSchema = { + type: 'object', + properties: { + iana: { + '$ref': '#/components/schemas/IanaTimeZone' + }, + windows: { + '$ref': '#/components/schemas/WindowsTimeZone' + } + }, + additionalProperties: false +} as const; + +export const TimingDtoSchema = { + type: 'object', + properties: { + timeZone: { + '$ref': '#/components/schemas/TimeZone' + } + }, + additionalProperties: false +} as const; + +export const TreeOutputSchema = { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true + }, + key: { + type: 'string', + format: 'uuid' + }, + children: { + type: 'array', + items: { + '$ref': '#/components/schemas/TreeOutput' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const TypeApiDescriptionModelSchema = { + type: 'object', + properties: { + baseType: { + type: 'string', + nullable: true + }, + isEnum: { + type: 'boolean' + }, + enumNames: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + enumValues: { + type: 'array', + items: {}, + nullable: true + }, + genericArguments: { + type: 'array', + items: { + type: 'string' + }, + nullable: true + }, + properties: { + type: 'array', + items: { + '$ref': '#/components/schemas/PropertyApiDescriptionModel' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateDataDictinaryInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + code: { + type: 'string', + nullable: true + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateDetailInputSchema = { + type: 'object', + properties: { + dataDictionaryId: { + type: 'string', + format: 'uuid' + }, + id: { + type: 'string', + format: 'uuid' + }, + displayText: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + }, + order: { + type: 'integer', + format: 'int32' + } + }, + additionalProperties: false +} as const; + +export const UpdateFeatureDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + value: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateFeatureInputSchema = { + type: 'object', + properties: { + providerName: { + type: 'string', + nullable: true + }, + providerKey: { + type: 'string', + nullable: true + }, + updateFeaturesDto: { + '$ref': '#/components/schemas/UpdateFeaturesDto' + } + }, + additionalProperties: false +} as const; + +export const UpdateFeaturesDtoSchema = { + type: 'object', + properties: { + features: { + type: 'array', + items: { + '$ref': '#/components/schemas/UpdateFeatureDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateLanguageInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + cultureName: { + type: 'string', + nullable: true + }, + uiCultureName: { + type: 'string', + nullable: true + }, + displayName: { + type: 'string', + nullable: true + }, + flagIcon: { + type: 'string', + nullable: true + }, + isEnabled: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const UpdateLanguageTextInputSchema = { + required: ['cultureName', 'name', 'resourceName', 'value'], + type: 'object', + properties: { + resourceName: { + minLength: 1, + type: 'string' + }, + cultureName: { + minLength: 1, + type: 'string' + }, + name: { + minLength: 1, + type: 'string' + }, + value: { + minLength: 1, + type: 'string' + } + }, + additionalProperties: false +} as const; + +export const UpdateOrganizationUnitInputSchema = { + type: 'object', + properties: { + displayName: { + type: 'string', + nullable: true + }, + id: { + type: 'string', + format: 'uuid' + } + }, + additionalProperties: false +} as const; + +export const UpdatePermissionDtoSchema = { + type: 'object', + properties: { + name: { + type: 'string', + nullable: true + }, + isGranted: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const UpdatePermissionsDtoSchema = { + type: 'object', + properties: { + permissions: { + type: 'array', + items: { + '$ref': '#/components/schemas/UpdatePermissionDto' + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateRoleInputSchema = { + type: 'object', + properties: { + roleId: { + type: 'string', + format: 'uuid' + }, + roleInfo: { + '$ref': '#/components/schemas/IdentityRoleUpdateDto' + } + }, + additionalProperties: false +} as const; + +export const UpdateRolePermissionsInputSchema = { + type: 'object', + properties: { + providerName: { + type: 'string', + nullable: true + }, + providerKey: { + type: 'string', + nullable: true + }, + updatePermissionsDto: { + '$ref': '#/components/schemas/UpdatePermissionsDto' + } + }, + additionalProperties: false +} as const; + +export const UpdateSettingInputSchema = { + type: 'object', + properties: { + values: { + type: 'object', + additionalProperties: { + type: 'string', + nullable: true + }, + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateTenantInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid' + }, + name: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; + +export const UpdateUserInputSchema = { + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid' + }, + userInfo: { + '$ref': '#/components/schemas/IdentityUserUpdateDto' + } + }, + additionalProperties: false +} as const; + +export const UserLoginInfoSchema = { + required: ['password', 'userNameOrEmailAddress'], + type: 'object', + properties: { + userNameOrEmailAddress: { + maxLength: 255, + minLength: 0, + type: 'string' + }, + password: { + maxLength: 32, + minLength: 0, + type: 'string', + format: 'password' + }, + rememberMe: { + type: 'boolean' + } + }, + additionalProperties: false +} as const; + +export const WindowsTimeZoneSchema = { + type: 'object', + properties: { + timeZoneId: { + type: 'string', + nullable: true + } + }, + additionalProperties: false +} as const; \ No newline at end of file diff --git a/apps/web-antd/src/api-client/services.gen.ts b/apps/web-antd/src/api-client/services.gen.ts new file mode 100644 index 0000000..9cfc978 --- /dev/null +++ b/apps/web-antd/src/api-client/services.gen.ts @@ -0,0 +1,777 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createClient, createConfig, type Options } from '@hey-api/client-axios'; +import type { GetApiAbpApiDefinitionData, GetApiAbpApiDefinitionError, GetApiAbpApiDefinitionResponse, GetApiAbpApplicationConfigurationData, GetApiAbpApplicationConfigurationError, GetApiAbpApplicationConfigurationResponse, GetApiAbpApplicationLocalizationData, GetApiAbpApplicationLocalizationError, GetApiAbpApplicationLocalizationResponse, PostApiAppAccountLoginData, PostApiAppAccountLoginError, PostApiAppAccountLoginResponse, PostAuditLogsPageData, PostAuditLogsPageError, PostAuditLogsPageResponse, PostDataDictionaryPageData, PostDataDictionaryPageError, PostDataDictionaryPageResponse, PostDataDictionaryPageDetailData, PostDataDictionaryPageDetailError, PostDataDictionaryPageDetailResponse, PostDataDictionaryCreateData, PostDataDictionaryCreateError, PostDataDictionaryCreateResponse, PostDataDictionaryCreateDetailData, PostDataDictionaryCreateDetailError, PostDataDictionaryCreateDetailResponse, PostDataDictionaryStatusData, PostDataDictionaryStatusError, PostDataDictionaryStatusResponse, PostDataDictionaryUpdateDetailData, PostDataDictionaryUpdateDetailError, PostDataDictionaryUpdateDetailResponse, PostDataDictionaryDeleteData, PostDataDictionaryDeleteError, PostDataDictionaryDeleteResponse, PostDataDictionaryDeleteDataDictionaryTypeData, PostDataDictionaryDeleteDataDictionaryTypeError, PostDataDictionaryDeleteDataDictionaryTypeResponse, PostDataDictionaryUpdateData, PostDataDictionaryUpdateError, PostDataDictionaryUpdateResponse, PostFeaturesListData, PostFeaturesListError, PostFeaturesListResponse, PostFeaturesUpdateData, PostFeaturesUpdateError, PostFeaturesUpdateResponse, PostFeaturesDeleteData, PostFeaturesDeleteError, PostFeaturesDeleteResponse, PostIdentitySecurityLogsPageData, PostIdentitySecurityLogsPageError, PostIdentitySecurityLogsPageResponse, PostLanguagesAllError, PostLanguagesAllResponse, PostLanguagesPageData, PostLanguagesPageError, PostLanguagesPageResponse, PostLanguagesCreateData, PostLanguagesCreateError, PostLanguagesCreateResponse, PostLanguagesUpdateData, PostLanguagesUpdateError, PostLanguagesUpdateResponse, PostLanguagesDeleteData, PostLanguagesDeleteError, PostLanguagesDeleteResponse, PostLanguagesSetDefaultData, PostLanguagesSetDefaultError, PostLanguagesSetDefaultResponse, PostLanguageTextsAllResourceError, PostLanguageTextsAllResourceResponse, PostLanguageTextsPageData, PostLanguageTextsPageError, PostLanguageTextsPageResponse, PostLanguageTextsCreateData, PostLanguageTextsCreateError, PostLanguageTextsCreateResponse, PostLanguageTextsUpdateData, PostLanguageTextsUpdateError, PostLanguageTextsUpdateResponse, PostNotificationNotificationPageData, PostNotificationNotificationPageError, PostNotificationNotificationPageResponse, PostNotificationNotificationSubscriptionPageData, PostNotificationNotificationSubscriptionPageError, PostNotificationNotificationSubscriptionPageResponse, PostNotificationSendCommonWarningMessageData, PostNotificationSendCommonWarningMessageError, PostNotificationSendCommonWarningMessageResponse, PostNotificationSendCommonInformationMessageData, PostNotificationSendCommonInformationMessageError, PostNotificationSendCommonInformationMessageResponse, PostNotificationSendCommonErrorMessageData, PostNotificationSendCommonErrorMessageError, PostNotificationSendCommonErrorMessageResponse, PostNotificationSendBroadCastWarningMessageData, PostNotificationSendBroadCastWarningMessageError, PostNotificationSendBroadCastWarningMessageResponse, PostNotificationSendBroadCastInformationMessageData, PostNotificationSendBroadCastInformationMessageError, PostNotificationSendBroadCastInformationMessageResponse, PostNotificationSendBroadCastErrorMessageData, PostNotificationSendBroadCastErrorMessageError, PostNotificationSendBroadCastErrorMessageResponse, PostNotificationReadData, PostNotificationReadError, PostNotificationReadResponse, PostNotificationBatchReadData, PostNotificationBatchReadError, PostNotificationBatchReadResponse, PostOrganizationUnitsTreeError, PostOrganizationUnitsTreeResponse, PostOrganizationUnitsCreateData, PostOrganizationUnitsCreateError, PostOrganizationUnitsCreateResponse, PostOrganizationUnitsDeleteData, PostOrganizationUnitsDeleteError, PostOrganizationUnitsDeleteResponse, PostOrganizationUnitsUpdateData, PostOrganizationUnitsUpdateError, PostOrganizationUnitsUpdateResponse, PostOrganizationUnitsAddRoleToOrganizationUnitAsyncData, PostOrganizationUnitsAddRoleToOrganizationUnitAsyncError, PostOrganizationUnitsAddRoleToOrganizationUnitAsyncResponse, PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncData, PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncError, PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncResponse, PostOrganizationUnitsAddUserToOrganizationUnitData, PostOrganizationUnitsAddUserToOrganizationUnitError, PostOrganizationUnitsAddUserToOrganizationUnitResponse, PostOrganizationUnitsRemoveUserFromOrganizationUnitData, PostOrganizationUnitsRemoveUserFromOrganizationUnitError, PostOrganizationUnitsRemoveUserFromOrganizationUnitResponse, PostOrganizationUnitsGetUsersData, PostOrganizationUnitsGetUsersError, PostOrganizationUnitsGetUsersResponse, PostOrganizationUnitsGetRolesData, PostOrganizationUnitsGetRolesError, PostOrganizationUnitsGetRolesResponse, PostOrganizationUnitsGetUnAddUsersData, PostOrganizationUnitsGetUnAddUsersError, PostOrganizationUnitsGetUnAddUsersResponse, PostOrganizationUnitsGetUnAddRolesData, PostOrganizationUnitsGetUnAddRolesError, PostOrganizationUnitsGetUnAddRolesResponse, PostPermissionsTreeData, PostPermissionsTreeError, PostPermissionsTreeResponse, PostPermissionsUpdateData, PostPermissionsUpdateError, PostPermissionsUpdateResponse, PostRolesAllError, PostRolesAllResponse, PostRolesPageData, PostRolesPageError, PostRolesPageResponse, PostRolesCreateData, PostRolesCreateError, PostRolesCreateResponse, PostRolesUpdateData, PostRolesUpdateError, PostRolesUpdateResponse, PostRolesDeleteData, PostRolesDeleteError, PostRolesDeleteResponse, PostSettingsAllError, PostSettingsAllResponse, PostSettingsUpdateData, PostSettingsUpdateError, PostSettingsUpdateResponse, PostTenantsFindData, PostTenantsFindError, PostTenantsFindResponse, PostTenantsPageData, PostTenantsPageError, PostTenantsPageResponse, PostTenantsCreateData, PostTenantsCreateError, PostTenantsCreateResponse, PostTenantsUpdateData, PostTenantsUpdateError, PostTenantsUpdateResponse, PostTenantsDeleteData, PostTenantsDeleteError, PostTenantsDeleteResponse, PostTenantsPageConnectionStringData, PostTenantsPageConnectionStringError, PostTenantsPageConnectionStringResponse, PostTenantsAddOrUpdateConnectionStringData, PostTenantsAddOrUpdateConnectionStringError, PostTenantsAddOrUpdateConnectionStringResponse, PostTenantsDeleteConnectionStringData, PostTenantsDeleteConnectionStringError, PostTenantsDeleteConnectionStringResponse, PostUsersPageData, PostUsersPageError, PostUsersPageResponse, PostUsersListData, PostUsersListError, PostUsersListResponse, PostUsersExportData, PostUsersExportError, PostUsersExportResponse, PostUsersCreateData, PostUsersCreateError, PostUsersCreateResponse, PostUsersUpdateData, PostUsersUpdateError, PostUsersUpdateResponse, PostUsersDeleteData, PostUsersDeleteError, PostUsersDeleteResponse, PostUsersRoleData, PostUsersRoleError, PostUsersRoleResponse, PostUsersChangePasswordData, PostUsersChangePasswordError, PostUsersChangePasswordResponse, PostUsersLockData, PostUsersLockError, PostUsersLockResponse, PostUsersFindByUserNameData, PostUsersFindByUserNameError, PostUsersFindByUserNameResponse, PostUsersMyProfileError, PostUsersMyProfileResponse } from './types.gen'; + +export const client = createClient(createConfig()); + +export const getApiAbpApiDefinition = (options?: Options) => { + return (options?.client ?? client).get({ + ...options, + url: '/api/abp/api-definition' + }); +}; + +export const getApiAbpApplicationConfiguration = (options?: Options) => { + return (options?.client ?? client).get({ + ...options, + url: '/api/abp/application-configuration' + }); +}; + +export const getApiAbpApplicationLocalization = (options: Options) => { + return (options?.client ?? client).get({ + ...options, + url: '/api/abp/application-localization' + }); +}; + +/** + * 登录 + */ +export const postApiAppAccountLogin = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/api/app/account/login' + }); +}; + +/** + * 分页获取审计日志信息 + */ +export const postAuditLogsPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/AuditLogs/page' + }); +}; + +/** + * 分页字典类型 + */ +export const postDataDictionaryPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/page' + }); +}; + +/** + * 分页字典明细 + */ +export const postDataDictionaryPageDetail = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/pageDetail' + }); +}; + +/** + * 创建字典类型 + */ +export const postDataDictionaryCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/create' + }); +}; + +/** + * 创建字典明细 + */ +export const postDataDictionaryCreateDetail = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/createDetail' + }); +}; + +/** + * 设置字典明细状态 + */ +export const postDataDictionaryStatus = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/status' + }); +}; + +/** + * 更新字典明细 + */ +export const postDataDictionaryUpdateDetail = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/updateDetail' + }); +}; + +/** + * 删除字典明细 + */ +export const postDataDictionaryDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/delete' + }); +}; + +/** + * 删除字典类型 + */ +export const postDataDictionaryDeleteDataDictionaryType = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/deleteDataDictionaryType' + }); +}; + +/** + * 修改字典类型 + */ +export const postDataDictionaryUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/DataDictionary/update' + }); +}; + +/** + * 获取Features + */ +export const postFeaturesList = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Features/list' + }); +}; + +/** + * 更新Features + */ +export const postFeaturesUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Features/update' + }); +}; + +/** + * 删除Features + */ +export const postFeaturesDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Features/delete' + }); +}; + +/** + * 分页获取登录日志信息 + */ +export const postIdentitySecurityLogsPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/IdentitySecurityLogs/page' + }); +}; + +/** + * 获取所有语言 + */ +export const postLanguagesAll = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/All' + }); +}; + +/** + * 分页查询语言 + */ +export const postLanguagesPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/Page' + }); +}; + +/** + * 创建语言 + */ +export const postLanguagesCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/Create' + }); +}; + +/** + * 编辑语言 + */ +export const postLanguagesUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/Update' + }); +}; + +/** + * 删除语言 + */ +export const postLanguagesDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/Delete' + }); +}; + +/** + * 设置默认语言 + */ +export const postLanguagesSetDefault = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Languages/SetDefault' + }); +}; + +/** + * 获取所有资源 + */ +export const postLanguageTextsAllResource = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/LanguageTexts/AllResource' + }); +}; + +/** + * 分页查询语言文本 + */ +export const postLanguageTextsPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/LanguageTexts/Page' + }); +}; + +/** + * 创建语言文本 + */ +export const postLanguageTextsCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/LanguageTexts/Create' + }); +}; + +/** + * 编辑语言文本 + */ +export const postLanguageTextsUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/LanguageTexts/Update' + }); +}; + +/** + * 分页查询消息 + */ +export const postNotificationNotificationPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/NotificationPage' + }); +}; + +/** + * 分页获取广播消息已读人数 + */ +export const postNotificationNotificationSubscriptionPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/NotificationSubscriptionPage' + }); +}; + +/** + * 发送警告文本消息 + */ +export const postNotificationSendCommonWarningMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendCommonWarningMessage' + }); +}; + +/** + * 发送普通文本消息 + */ +export const postNotificationSendCommonInformationMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendCommonInformationMessage' + }); +}; + +/** + * 发送错误文本消息 + */ +export const postNotificationSendCommonErrorMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendCommonErrorMessage' + }); +}; + +/** + * 发送警告广播消息 + */ +export const postNotificationSendBroadCastWarningMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendBroadCastWarningMessage' + }); +}; + +/** + * 发送正常广播消息 + */ +export const postNotificationSendBroadCastInformationMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendBroadCastInformationMessage' + }); +}; + +/** + * 发送错误广播消息 + */ +export const postNotificationSendBroadCastErrorMessage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/SendBroadCastErrorMessage' + }); +}; + +/** + * 消息设置为已读 + */ +export const postNotificationRead = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/Read' + }); +}; + +/** + * 消息批量设置为已读 + */ +export const postNotificationBatchRead = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Notification/BatchRead' + }); +}; + +/** + * 获取组织机构树 + */ +export const postOrganizationUnitsTree = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/tree' + }); +}; + +/** + * 创建组织机构 + */ +export const postOrganizationUnitsCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/create' + }); +}; + +/** + * 删除组织机构 + */ +export const postOrganizationUnitsDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/delete' + }); +}; + +/** + * 编辑组织机构 + */ +export const postOrganizationUnitsUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/update' + }); +}; + +/** + * 向组织机构添加角色 + */ +export const postOrganizationUnitsAddRoleToOrganizationUnitAsync = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/addRoleToOrganizationUnitAsync' + }); +}; + +/** + * 向组织机构删除角色 + */ +export const postOrganizationUnitsRemoveRoleFromOrganizationUnitAsync = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/removeRoleFromOrganizationUnitAsync' + }); +}; + +/** + * 向组织机构添加用户 + */ +export const postOrganizationUnitsAddUserToOrganizationUnit = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/addUserToOrganizationUnit' + }); +}; + +/** + * 向组织机构删除用户 + */ +export const postOrganizationUnitsRemoveUserFromOrganizationUnit = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/removeUserFromOrganizationUnit' + }); +}; + +/** + * 分页获取组织机构下用户 + */ +export const postOrganizationUnitsGetUsers = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/getUsers' + }); +}; + +/** + * 分页获取组织机构下角色 + */ +export const postOrganizationUnitsGetRoles = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/getRoles' + }); +}; + +/** + * 获取不在组织机构的用户 + */ +export const postOrganizationUnitsGetUnAddUsers = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/getUnAddUsers' + }); +}; + +/** + * 获取不在组织机构的角色 + */ +export const postOrganizationUnitsGetUnAddRoles = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/OrganizationUnits/getUnAddRoles' + }); +}; + +/** + * 获取角色权限 + */ +export const postPermissionsTree = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Permissions/tree' + }); +}; + +/** + * 更新角色 + */ +export const postPermissionsUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Permissions/update' + }); +}; + +/** + * 获取所有角色 + */ +export const postRolesAll = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Roles/all' + }); +}; + +/** + * 分页获取角色 + */ +export const postRolesPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Roles/page' + }); +}; + +/** + * 创建角色 + */ +export const postRolesCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Roles/create' + }); +}; + +/** + * 更新角色 + */ +export const postRolesUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Roles/update' + }); +}; + +/** + * 删除角色 + */ +export const postRolesDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Roles/delete' + }); +}; + +/** + * 获取所有Setting + */ +export const postSettingsAll = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Settings/all' + }); +}; + +/** + * 更新Setting + */ +export const postSettingsUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Settings/update' + }); +}; + +/** + * 通过名称获取租户信息 + */ +export const postTenantsFind = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/find' + }); +}; + +/** + * 分页获取租户信息 + */ +export const postTenantsPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/page' + }); +}; + +/** + * 创建租户 + */ +export const postTenantsCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/create' + }); +}; + +/** + * 更新租户 + */ +export const postTenantsUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/update' + }); +}; + +/** + * 删除租户 + */ +export const postTenantsDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/delete' + }); +}; + +/** + * 分页租户连接字符串 + */ +export const postTenantsPageConnectionString = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/pageConnectionString' + }); +}; + +/** + * 新增或者更新租户所有连接字符串 + */ +export const postTenantsAddOrUpdateConnectionString = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/addOrUpdateConnectionString' + }); +}; + +/** + * 删除租户连接字符串 + */ +export const postTenantsDeleteConnectionString = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Tenants/deleteConnectionString' + }); +}; + +/** + * 分页获取用户信息 + */ +export const postUsersPage = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/page' + }); +}; + +/** + * 分页获取用户信息 + */ +export const postUsersList = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/list' + }); +}; + +/** + * 导出用户列表 + */ +export const postUsersExport = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/export' + }); +}; + +/** + * 创建用户 + */ +export const postUsersCreate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/create' + }); +}; + +/** + * 编辑用户 + */ +export const postUsersUpdate = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/update' + }); +}; + +/** + * 删除用户 + */ +export const postUsersDelete = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/delete' + }); +}; + +/** + * 获取用户角色信息 + */ +export const postUsersRole = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/role' + }); +}; + +/** + * 修改当前用户密码 + */ +export const postUsersChangePassword = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/changePassword' + }); +}; + +/** + * 锁定用户 + */ +export const postUsersLock = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/lock' + }); +}; + +/** + * 通过用户名查找用户 + */ +export const postUsersFindByUserName = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/findByUserName' + }); +}; + +/** + * 获取个人信息 + */ +export const postUsersMyProfile = (options?: Options) => { + return (options?.client ?? client).post({ + ...options, + url: '/Users/myProfile' + }); +}; \ No newline at end of file diff --git a/apps/web-antd/src/api-client/types.gen.ts b/apps/web-antd/src/api-client/types.gen.ts new file mode 100644 index 0000000..8452b02 --- /dev/null +++ b/apps/web-antd/src/api-client/types.gen.ts @@ -0,0 +1,2080 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AbpLoginResult = { + result?: LoginResultType; + readonly description?: (string) | null; +}; + +export type ActionApiDescriptionModel = { + uniqueName?: (string) | null; + name?: (string) | null; + httpMethod?: (string) | null; + url?: (string) | null; + supportedVersions?: Array<(string)> | null; + parametersOnMethod?: Array | null; + parameters?: Array | null; + returnValue?: ReturnValueApiDescriptionModel; + allowAnonymous?: (boolean) | null; + implementFrom?: (string) | null; +}; + +export type AddOrUpdateConnectionStringInput = { + id?: string; + name?: (string) | null; + value?: (string) | null; +}; + +export type AddRoleToOrganizationUnitInput = { + roleId?: Array<(string)> | null; + organizationUnitId?: string; +}; + +export type AddUserToOrganizationUnitInput = { + userId?: Array<(string)> | null; + organizationUnitId?: string; +}; + +export type AggregateRouteConfig = { + routeKey?: (string) | null; + parameter?: (string) | null; + jsonPath?: (string) | null; +}; + +export type ApplicationApiDescriptionModel = { + modules?: { + [key: string]: ModuleApiDescriptionModel; + } | null; + types?: { + [key: string]: TypeApiDescriptionModel; + } | null; +}; + +export type ApplicationAuthConfigurationDto = { + grantedPolicies?: { + [key: string]: (boolean); + } | null; +}; + +export type ApplicationConfigurationDto = { + localization?: ApplicationLocalizationConfigurationDto; + auth?: ApplicationAuthConfigurationDto; + setting?: ApplicationSettingConfigurationDto; + currentUser?: CurrentUserDto; + features?: ApplicationFeatureConfigurationDto; + globalFeatures?: ApplicationGlobalFeatureConfigurationDto; + multiTenancy?: MultiTenancyInfoDto; + currentTenant?: CurrentTenantDto; + timing?: TimingDto; + clock?: ClockDto; + objectExtensions?: ObjectExtensionsDto; + extraProperties?: { + [key: string]: unknown; + } | null; +}; + +export type ApplicationFeatureConfigurationDto = { + values?: { + [key: string]: ((string) | null); + } | null; +}; + +export type ApplicationGlobalFeatureConfigurationDto = { + enabledFeatures?: Array<(string)> | null; +}; + +export type ApplicationLocalizationConfigurationDto = { + values?: { + [key: string]: { + [key: string]: (string); + }; + } | null; + resources?: { + [key: string]: ApplicationLocalizationResourceDto; + } | null; + languages?: Array | null; + currentCulture?: CurrentCultureDto; + defaultResourceName?: (string) | null; + languagesMap?: { + [key: string]: Array; + } | null; + languageFilesMap?: { + [key: string]: Array; + } | null; +}; + +export type ApplicationLocalizationDto = { + resources?: { + [key: string]: ApplicationLocalizationResourceDto; + } | null; + currentCulture?: CurrentCultureDto; +}; + +export type ApplicationLocalizationResourceDto = { + texts?: { + [key: string]: (string); + } | null; + baseResources?: Array<(string)> | null; +}; + +export type ApplicationSettingConfigurationDto = { + values?: { + [key: string]: ((string) | null); + } | null; +}; + +export type ChangePasswordInput = { + currentPassword?: (string) | null; + newPassword: string; +}; + +export type ClockDto = { + kind?: (string) | null; +}; + +export type ControllerApiDescriptionModel = { + controllerName?: (string) | null; + controllerGroupName?: (string) | null; + isRemoteService?: boolean; + isIntegrationService?: boolean; + apiVersion?: (string) | null; + type?: (string) | null; + interfaces?: Array | null; + actions?: { + [key: string]: ActionApiDescriptionModel; + } | null; +}; + +export type ControllerInterfaceApiDescriptionModel = { + type?: (string) | null; + name?: (string) | null; + methods?: Array | null; +}; + +export type CreateDataDictinaryDetailInput = { + id?: string; + code?: (string) | null; + displayText?: (string) | null; + description?: (string) | null; + order?: number; +}; + +export type CreateDataDictinaryInput = { + code?: (string) | null; + displayText?: (string) | null; + description?: (string) | null; +}; + +export type CreateLanguageInput = { + cultureName?: (string) | null; + uiCultureName?: (string) | null; + displayName?: (string) | null; + flagIcon?: (string) | null; + isEnabled?: boolean; +}; + +export type CreateLanguageTextInput = { + resourceName?: (string) | null; + cultureName?: (string) | null; + name?: (string) | null; + value?: (string) | null; +}; + +export type CreateOrganizationUnitInput = { + displayName?: (string) | null; + parentId?: (string) | null; +}; + +export type CurrentCultureDto = { + displayName?: (string) | null; + englishName?: (string) | null; + threeLetterIsoLanguageName?: (string) | null; + twoLetterIsoLanguageName?: (string) | null; + isRightToLeft?: boolean; + cultureName?: (string) | null; + name?: (string) | null; + nativeName?: (string) | null; + dateTimeFormat?: DateTimeFormatDto; +}; + +export type CurrentTenantDto = { + id?: (string) | null; + name?: (string) | null; + isAvailable?: boolean; +}; + +export type CurrentUserDto = { + isAuthenticated?: boolean; + id?: (string) | null; + tenantId?: (string) | null; + impersonatorUserId?: (string) | null; + impersonatorTenantId?: (string) | null; + impersonatorUserName?: (string) | null; + impersonatorTenantName?: (string) | null; + userName?: (string) | null; + name?: (string) | null; + surName?: (string) | null; + email?: (string) | null; + emailVerified?: boolean; + phoneNumber?: (string) | null; + phoneNumberVerified?: boolean; + roles?: Array<(string)> | null; + sessionId?: (string) | null; +}; + +export type DateTimeFormatDto = { + calendarAlgorithmType?: (string) | null; + dateTimeFormatLong?: (string) | null; + shortDatePattern?: (string) | null; + fullDateTimePattern?: (string) | null; + dateSeparator?: (string) | null; + shortTimePattern?: (string) | null; + longTimePattern?: (string) | null; +}; + +export type DeleteConnectionStringInput = { + name?: (string) | null; + tenantId?: string; +}; + +export type DeleteDataDictionaryDetailInput = { + dataDictionaryId?: string; + dataDictionayDetailId?: string; +}; + +export type DeleteFeatureInput = { + providerName?: (string) | null; + providerKey?: (string) | null; +}; + +export type DeleteLanguageInput = { + id?: string; +}; + +export type EntityChangeType = 0 | 1 | 2; + +export type EntityExtensionDto = { + properties?: { + [key: string]: ExtensionPropertyDto; + } | null; + configuration?: { + [key: string]: unknown; + } | null; +}; + +export type ExtensionEnumDto = { + fields?: Array | null; + localizationResource?: (string) | null; +}; + +export type ExtensionEnumFieldDto = { + name?: (string) | null; + value?: unknown; +}; + +export type ExtensionPropertyApiCreateDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyApiDto = { + onGet?: ExtensionPropertyApiGetDto; + onCreate?: ExtensionPropertyApiCreateDto; + onUpdate?: ExtensionPropertyApiUpdateDto; +}; + +export type ExtensionPropertyApiGetDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyApiUpdateDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyAttributeDto = { + typeSimple?: (string) | null; + config?: { + [key: string]: unknown; + } | null; +}; + +export type ExtensionPropertyDto = { + type?: (string) | null; + typeSimple?: (string) | null; + displayName?: LocalizableStringDto; + api?: ExtensionPropertyApiDto; + ui?: ExtensionPropertyUiDto; + policy?: ExtensionPropertyPolicyDto; + attributes?: Array | null; + configuration?: { + [key: string]: unknown; + } | null; + defaultValue?: unknown; +}; + +export type ExtensionPropertyFeaturePolicyDto = { + features?: Array<(string)> | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyGlobalFeaturePolicyDto = { + features?: Array<(string)> | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyPermissionPolicyDto = { + permissionNames?: Array<(string)> | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyPolicyDto = { + globalFeatures?: ExtensionPropertyGlobalFeaturePolicyDto; + features?: ExtensionPropertyFeaturePolicyDto; + permissions?: ExtensionPropertyPermissionPolicyDto; +}; + +export type ExtensionPropertyUiDto = { + onTable?: ExtensionPropertyUiTableDto; + onCreateForm?: ExtensionPropertyUiFormDto; + onEditForm?: ExtensionPropertyUiFormDto; + lookup?: ExtensionPropertyUiLookupDto; +}; + +export type ExtensionPropertyUiFormDto = { + isVisible?: boolean; +}; + +export type ExtensionPropertyUiLookupDto = { + url?: (string) | null; + resultListPropertyName?: (string) | null; + displayPropertyName?: (string) | null; + valuePropertyName?: (string) | null; + filterParamName?: (string) | null; +}; + +export type ExtensionPropertyUiTableDto = { + isVisible?: boolean; +}; + +export type FeatureDto = { + name?: (string) | null; + displayName?: (string) | null; + value?: (string) | null; + provider?: FeatureProviderDto; + description?: (string) | null; + valueType?: IStringValueType; + depth?: number; + parentName?: (string) | null; +}; + +export type FeatureGroupDto = { + name?: (string) | null; + displayName?: (string) | null; + features?: Array | null; +}; + +export type FeatureProviderDto = { + name?: (string) | null; + key?: (string) | null; +}; + +export type FileAggregateRoute = { + routeKeys?: Array<(string)> | null; + routeKeysConfig?: Array | null; + upstreamPathTemplate?: (string) | null; + upstreamHost?: (string) | null; + routeIsCaseSensitive?: boolean; + aggregator?: (string) | null; + readonly upstreamHttpMethod?: Array<(string)> | null; + priority?: number; +}; + +export type FileAuthenticationOptions = { + authenticationProviderKey?: (string) | null; + allowedScopes?: Array<(string)> | null; +}; + +export type FileCacheOptions = { + ttlSeconds?: number; + region?: (string) | null; +}; + +export type FileConfiguration = { + routes?: Array | null; + dynamicRoutes?: Array | null; + aggregates?: Array | null; + globalConfiguration?: FileGlobalConfiguration; +}; + +export type FileDynamicRoute = { + serviceName?: (string) | null; + rateLimitRule?: FileRateLimitRule; + downstreamHttpVersion?: (string) | null; +}; + +export type FileGlobalConfiguration = { + requestIdKey?: (string) | null; + serviceDiscoveryProvider?: FileServiceDiscoveryProvider; + rateLimitOptions?: FileRateLimitOptions; + qoSOptions?: FileQoSOptions; + baseUrl?: (string) | null; + loadBalancerOptions?: FileLoadBalancerOptions; + downstreamScheme?: (string) | null; + httpHandlerOptions?: FileHttpHandlerOptions; + downstreamHttpVersion?: (string) | null; +}; + +export type FileHostAndPort = { + host?: (string) | null; + port?: number; +}; + +export type FileHttpHandlerOptions = { + allowAutoRedirect?: boolean; + useCookieContainer?: boolean; + useTracing?: boolean; + useProxy?: boolean; + maxConnectionsPerServer?: number; +}; + +export type FileLoadBalancerOptions = { + type?: (string) | null; + key?: (string) | null; + expiry?: number; +}; + +export type FileQoSOptions = { + exceptionsAllowedBeforeBreaking?: number; + durationOfBreak?: number; + timeoutValue?: number; +}; + +export type FileRateLimitOptions = { + clientIdHeader?: (string) | null; + quotaExceededMessage?: (string) | null; + rateLimitCounterPrefix?: (string) | null; + disableRateLimitHeaders?: boolean; + httpStatusCode?: number; +}; + +export type FileRateLimitRule = { + clientWhitelist?: Array<(string)> | null; + enableRateLimiting?: boolean; + period?: (string) | null; + periodTimespan?: number; + limit?: number; +}; + +export type FileRoute = { + downstreamPathTemplate?: (string) | null; + upstreamPathTemplate?: (string) | null; + upstreamHttpMethod?: Array<(string)> | null; + downstreamHttpMethod?: (string) | null; + addHeadersToRequest?: { + [key: string]: ((string) | null); + } | null; + upstreamHeaderTransform?: { + [key: string]: ((string) | null); + } | null; + downstreamHeaderTransform?: { + [key: string]: ((string) | null); + } | null; + addClaimsToRequest?: { + [key: string]: ((string) | null); + } | null; + routeClaimsRequirement?: { + [key: string]: ((string) | null); + } | null; + addQueriesToRequest?: { + [key: string]: ((string) | null); + } | null; + changeDownstreamPathTemplate?: { + [key: string]: ((string) | null); + } | null; + requestIdKey?: (string) | null; + fileCacheOptions?: FileCacheOptions; + routeIsCaseSensitive?: boolean; + serviceName?: (string) | null; + serviceNamespace?: (string) | null; + downstreamScheme?: (string) | null; + qoSOptions?: FileQoSOptions; + loadBalancerOptions?: FileLoadBalancerOptions; + rateLimitOptions?: FileRateLimitRule; + authenticationOptions?: FileAuthenticationOptions; + httpHandlerOptions?: FileHttpHandlerOptions; + downstreamHostAndPorts?: Array | null; + upstreamHost?: (string) | null; + key?: (string) | null; + delegatingHandlers?: Array<(string)> | null; + priority?: number; + timeout?: number; + dangerousAcceptAnyServerCertificateValidator?: boolean; + securityOptions?: FileSecurityOptions; + downstreamHttpVersion?: (string) | null; +}; + +export type FileSecurityOptions = { + ipAllowedList?: Array<(string)> | null; + ipBlockedList?: Array<(string)> | null; +}; + +export type FileServiceDiscoveryProvider = { + scheme?: (string) | null; + host?: (string) | null; + port?: number; + type?: (string) | null; + token?: (string) | null; + configurationKey?: (string) | null; + pollingInterval?: number; + namespace?: (string) | null; +}; + +export type FindByUserNameInput = { + userName?: (string) | null; +}; + +export type FindTenantByNameInput = { + name?: (string) | null; +}; + +export type FindTenantResultDto = { + success?: boolean; + tenantId?: (string) | null; + name?: (string) | null; + normalizedName?: (string) | null; + isActive?: boolean; +}; + +export type GetFeatureListResultDto = { + groups?: Array | null; +}; + +export type GetFeatureListResultInput = { + providerName?: (string) | null; + providerKey?: (string) | null; +}; + +export type GetOrganizationUnitRoleInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + organizationUnitId?: string; +}; + +export type GetOrganizationUnitRoleOutput = { + id?: string; + name?: (string) | null; +}; + +export type GetOrganizationUnitRoleOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetOrganizationUnitUserInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + organizationUnitId?: string; + filter?: (string) | null; +}; + +export type GetOrganizationUnitUserOutput = { + id?: string; + userName?: (string) | null; + email?: (string) | null; +}; + +export type GetOrganizationUnitUserOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetPermissionInput = { + providerName?: (string) | null; + providerKey?: (string) | null; +}; + +export type GetUnAddRoleInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + organizationUnitId?: string; + filter?: (string) | null; +}; + +export type GetUnAddRoleOutput = { + id?: string; + name?: (string) | null; +}; + +export type GetUnAddRoleOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetUnAddUserInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + organizationUnitId?: string; + filter?: (string) | null; +}; + +export type GetUnAddUserOutput = { + id?: string; + userName?: (string) | null; + email?: (string) | null; +}; + +export type GetUnAddUserOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type HttpStatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 421 | 422 | 423 | 424 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511; + +export type IanaTimeZone = { + timeZoneName?: (string) | null; +}; + +export type IdentityRoleCreateDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + name: string; + isDefault?: boolean; + isPublic?: boolean; +}; + +export type IdentityRoleDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + id?: string; + name?: (string) | null; + isDefault?: boolean; + isStatic?: boolean; + isPublic?: boolean; + concurrencyStamp?: (string) | null; +}; + +export type IdentityRoleDtoListResultDto = { + items?: Array | null; +}; + +export type IdentityRoleDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type IdentityRoleUpdateDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + name: string; + isDefault?: boolean; + isPublic?: boolean; + concurrencyStamp?: (string) | null; +}; + +export type IdentityUserCreateDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + userName: string; + name?: (string) | null; + surname?: (string) | null; + email: string; + phoneNumber?: (string) | null; + isActive?: boolean; + lockoutEnabled?: boolean; + roleNames?: Array<(string)> | null; + password: string; +}; + +export type IdentityUserDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + id?: string; + creationTime?: string; + creatorId?: (string) | null; + lastModificationTime?: (string) | null; + lastModifierId?: (string) | null; + isDeleted?: boolean; + deleterId?: (string) | null; + deletionTime?: (string) | null; + tenantId?: (string) | null; + userName?: (string) | null; + name?: (string) | null; + surname?: (string) | null; + email?: (string) | null; + emailConfirmed?: boolean; + phoneNumber?: (string) | null; + phoneNumberConfirmed?: boolean; + isActive?: boolean; + lockoutEnabled?: boolean; + accessFailedCount?: number; + lockoutEnd?: (string) | null; + concurrencyStamp?: (string) | null; + entityVersion?: number; + lastPasswordChangeTime?: (string) | null; +}; + +export type IdentityUserUpdateDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + userName: string; + name?: (string) | null; + surname?: (string) | null; + email: string; + phoneNumber?: (string) | null; + isActive?: boolean; + lockoutEnabled?: boolean; + roleNames?: Array<(string)> | null; + password?: (string) | null; + concurrencyStamp?: (string) | null; +}; + +export type IdInput = { + id?: string; +}; + +export type InterfaceMethodApiDescriptionModel = { + name?: (string) | null; + parametersOnMethod?: Array | null; + returnValue?: ReturnValueApiDescriptionModel; +}; + +export type IStringValueType = { + readonly name?: (string) | null; + readonly properties?: { + [key: string]: unknown; + } | null; + validator?: IValueValidator; +}; + +export type IValueValidator = { + readonly name?: (string) | null; + readonly properties?: { + [key: string]: unknown; + } | null; +}; + +export type LanguageInfo = { + cultureName?: (string) | null; + uiCultureName?: (string) | null; + displayName?: (string) | null; + readonly twoLetterISOLanguageName?: (string) | null; +}; + +export type LocalizableStringDto = { + name?: (string) | null; + resource?: (string) | null; +}; + +export type LockUserInput = { + userId?: string; + locked?: boolean; +}; + +export type LoginInput = { + name?: (string) | null; + password?: (string) | null; +}; + +export type LoginOutput = { + id?: string; + name?: (string) | null; + userName?: (string) | null; + token?: (string) | null; + roles?: Array<(string)> | null; +}; + +export type LoginResultType = 1 | 2 | 3 | 4 | 5; + +export type MessageLevel = 10 | 20 | 30; + +export type MessageType = 10 | 20; + +export type MethodParameterApiDescriptionModel = { + name?: (string) | null; + typeAsString?: (string) | null; + type?: (string) | null; + typeSimple?: (string) | null; + isOptional?: boolean; + defaultValue?: unknown; +}; + +export type ModuleApiDescriptionModel = { + rootPath?: (string) | null; + remoteServiceName?: (string) | null; + controllers?: { + [key: string]: ControllerApiDescriptionModel; + } | null; +}; + +export type ModuleExtensionDto = { + entities?: { + [key: string]: EntityExtensionDto; + } | null; + configuration?: { + [key: string]: unknown; + } | null; +}; + +export type MultiTenancyInfoDto = { + isEnabled?: boolean; +}; + +export type MyProfileOutput = { + tenantId?: (string) | null; + userName?: (string) | null; + name?: (string) | null; + surname?: (string) | null; + email?: (string) | null; + phoneNumber?: (string) | null; + isActive?: boolean; + twoFactorEnabled?: boolean; +}; + +export type NameValue = { + name?: (string) | null; + value?: (string) | null; +}; + +export type ObjectExtensionsDto = { + modules?: { + [key: string]: ModuleExtensionDto; + } | null; + enums?: { + [key: string]: ExtensionEnumDto; + } | null; +}; + +export type PageIdentityUserOutput = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + id?: string; + creationTime?: string; + creatorId?: (string) | null; + lastModificationTime?: (string) | null; + lastModifierId?: (string) | null; + isDeleted?: boolean; + deleterId?: (string) | null; + deletionTime?: (string) | null; + tenantId?: (string) | null; + userName?: (string) | null; + name?: (string) | null; + surname?: (string) | null; + email?: (string) | null; + emailConfirmed?: boolean; + phoneNumber?: (string) | null; + phoneNumberConfirmed?: boolean; + isActive?: boolean; + lockoutEnabled?: boolean; + accessFailedCount?: number; + lockoutEnd?: (string) | null; + concurrencyStamp?: (string) | null; + entityVersion?: number; + lastPasswordChangeTime?: (string) | null; + twoFactorEnabled?: boolean; +}; + +export type PageIdentityUserOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageLanguageInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + filter?: (string) | null; +}; + +export type PageLanguageOutput = { + id?: string; + cultureName?: (string) | null; + uiCultureName?: (string) | null; + displayName?: (string) | null; + flagIcon?: (string) | null; + isEnabled?: boolean; + creationTime?: string; + isDefault?: boolean; +}; + +export type PageLanguageOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageLanguageTextInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + cultureName?: (string) | null; + resourceName?: (string) | null; + filter?: (string) | null; +}; + +export type PageLanguageTextOutput = { + resourceName?: (string) | null; + name?: (string) | null; + value?: (string) | null; +}; + +export type PageLanguageTextOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageTenantConnectionStringInput = { + id?: string; + name?: (string) | null; + value?: (string) | null; +}; + +export type PageTenantConnectionStringOutput = { + tenantId?: string; + name?: (string) | null; + value?: (string) | null; +}; + +export type PageTenantConnectionStringOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingAuditLogActionOutput = { + id?: string; + tenantId?: (string) | null; + auditLogId?: string; + serviceName?: (string) | null; + methodName?: (string) | null; + parameters?: (string) | null; + executionTime?: (string) | null; + executionDuration?: number; + extraProperties?: { + [key: string]: unknown; + } | null; +}; + +export type PagingAuditLogInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + sorting?: (string) | null; + startTime?: (string) | null; + endTime?: (string) | null; + httpMethod?: (string) | null; + url?: (string) | null; + userId?: (string) | null; + userName?: (string) | null; + applicationName?: (string) | null; + correlationId?: (string) | null; + maxExecutionDuration?: (number) | null; + minExecutionDuration?: (number) | null; + hasException?: (boolean) | null; + httpStatusCode?: HttpStatusCode; + clientIpAddress?: (string) | null; +}; + +export type PagingAuditLogOutput = { + applicationName?: (string) | null; + userId?: (string) | null; + userName?: (string) | null; + tenantId?: (string) | null; + tenantName?: (string) | null; + impersonatorUserId?: (string) | null; + impersonatorTenantId?: (string) | null; + executionTime?: (string) | null; + executionDuration?: number; + clientIpAddress?: (string) | null; + clientName?: (string) | null; + clientId?: (string) | null; + correlationId?: (string) | null; + browserInfo?: (string) | null; + httpMethod?: (string) | null; + url?: (string) | null; + exceptions?: (string) | null; + comments?: (string) | null; + httpStatusCode?: (number) | null; + entityChanges?: Array | null; + actions?: Array | null; +}; + +export type PagingAuditLogOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingDataDictionaryDetailInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + dataDictionaryId?: string; + filter?: (string) | null; +}; + +export type PagingDataDictionaryDetailOutput = { + id?: string; + dataDictionaryId?: string; + code?: (string) | null; + order?: number; + displayText?: (string) | null; + description?: (string) | null; + isEnabled?: boolean; +}; + +export type PagingDataDictionaryDetailOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingDataDictionaryInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + filter?: (string) | null; +}; + +export type PagingDataDictionaryOutput = { + id?: string; + code?: (string) | null; + displayText?: (string) | null; + description?: (string) | null; +}; + +export type PagingDataDictionaryOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingEntityChangeOutput = { + id?: string; + auditLogId?: string; + tenantId?: (string) | null; + changeTime?: (string) | null; + changeType?: EntityChangeType; + changeTypeDescription?: (string) | null; + entityTenantId?: (string) | null; + entityId?: (string) | null; + entityTypeFullName?: (string) | null; + propertyChanges?: Array | null; + extraProperties?: { + [key: string]: unknown; + } | null; +}; + +export type PagingEntityPropertyChangeOutput = { + id?: string; + tenantId?: (string) | null; + entityChangeId?: string; + newValue?: (string) | null; + originalValue?: (string) | null; + propertyName?: (string) | null; + propertyTypeFullName?: (string) | null; +}; + +export type PagingIdentitySecurityLogInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + sorting?: (string) | null; + startTime?: (string) | null; + endTime?: (string) | null; + identity?: (string) | null; + action?: (string) | null; + userId?: (string) | null; + userName?: (string) | null; + applicationName?: (string) | null; + correlationId?: (string) | null; + clientId?: (string) | null; +}; + +export type PagingIdentitySecurityLogOutput = { + id?: string; + tenantId?: (string) | null; + applicationName?: (string) | null; + identity?: (string) | null; + action?: (string) | null; + userId?: (string) | null; + userName?: (string) | null; + tenantName?: (string) | null; + clientId?: (string) | null; + correlationId?: (string) | null; + clientIpAddress?: (string) | null; + browserInfo?: (string) | null; + creationTime?: string; +}; + +export type PagingIdentitySecurityLogOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingNotificationInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + title?: (string) | null; + content?: (string) | null; + senderUserId?: (string) | null; + senderUserName?: (string) | null; + receiverUserId?: (string) | null; + receiverUserName?: (string) | null; + read?: (boolean) | null; + startReadTime?: (string) | null; + endReadTime?: (string) | null; + messageType?: MessageType; + messageLevel?: MessageLevel; +}; + +export type PagingNotificationOutput = { + id?: string; + tenantId?: (string) | null; + title?: (string) | null; + content?: (string) | null; + messageType?: MessageType; + readonly messageTypeName?: (string) | null; + messageLevel?: MessageLevel; + readonly messageLevelName?: (string) | null; + senderUserId?: string; + senderUserName?: (string) | null; + receiveUserId?: (string) | null; + receiveUserName?: (string) | null; + read?: boolean; + readTime?: (string) | null; + creationTime?: string; +}; + +export type PagingNotificationOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingNotificationSubscriptionInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + notificationId?: string; + receiverUserId?: (string) | null; + receiverUserName?: (string) | null; + read?: (boolean) | null; + startReadTime?: (string) | null; + endReadTime?: (string) | null; +}; + +export type PagingNotificationSubscriptionOutput = { + id?: string; + tenantId?: (string) | null; + notificationId?: string; + receiveUserId?: string; + receiveUserName?: (string) | null; + read?: boolean; + readTime?: string; + title?: (string) | null; + content?: (string) | null; + messageType?: MessageType; + readonly messageTypeName?: (string) | null; + messageLevel?: MessageLevel; + readonly messageLevelName?: (string) | null; + senderUserId?: string; + senderUserName?: (string) | null; +}; + +export type PagingNotificationSubscriptionOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingRoleListInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + filter?: (string) | null; +}; + +export type PagingTenantInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + filter?: (string) | null; +}; + +export type PagingUserListInput = { + pageIndex?: number; + pageSize?: number; + readonly skipCount?: number; + filter?: (string) | null; +}; + +export type ParameterApiDescriptionModel = { + nameOnMethod?: (string) | null; + name?: (string) | null; + jsonName?: (string) | null; + type?: (string) | null; + typeSimple?: (string) | null; + isOptional?: boolean; + defaultValue?: unknown; + constraintTypes?: Array<(string)> | null; + bindingSourceId?: (string) | null; + descriptorName?: (string) | null; +}; + +export type PermissionOutput = { + grants?: Array<(string)> | null; + allGrants?: Array<(string)> | null; + permissions?: Array | null; +}; + +export type PermissionTreeDto = { + title?: (string) | null; + key?: (string) | null; + children?: Array | null; +}; + +export type PropertyApiDescriptionModel = { + name?: (string) | null; + jsonName?: (string) | null; + type?: (string) | null; + typeSimple?: (string) | null; + isRequired?: boolean; + minLength?: (number) | null; + maxLength?: (number) | null; + minimum?: (string) | null; + maximum?: (string) | null; + regex?: (string) | null; +}; + +export type RemoteServiceErrorInfo = { + code?: (string) | null; + message?: (string) | null; + details?: (string) | null; + data?: { + [key: string]: unknown; + } | null; + validationErrors?: Array | null; +}; + +export type RemoteServiceErrorResponse = { + error?: RemoteServiceErrorInfo; +}; + +export type RemoteServiceValidationErrorInfo = { + message?: (string) | null; + members?: Array<(string)> | null; +}; + +export type RemoveRoleToOrganizationUnitInput = { + roleId?: string; + organizationUnitId?: string; +}; + +export type RemoveUserToOrganizationUnitInput = { + userId?: string; + organizationUnitId?: string; +}; + +export type ReturnValueApiDescriptionModel = { + type?: (string) | null; + typeSimple?: (string) | null; +}; + +export type SendBroadCastMessageInput = { + title?: (string) | null; + content?: (string) | null; +}; + +export type SendCommonMessageInput = { + title?: (string) | null; + content?: (string) | null; + receiveUserId?: string; + receiveUserName?: (string) | null; +}; + +export type SetBatchReadInput = { + ids?: Array<(string)> | null; +}; + +export type SetDataDictinaryDetailInput = { + dataDictionaryId?: string; + dataDictionayDetailId?: string; + isEnabled: boolean; +}; + +export type SetReadInput = { + id?: string; +}; + +export type SettingItemOutput = { + name?: (string) | null; + displayName?: (string) | null; + description?: (string) | null; + value?: (string) | null; + type?: (string) | null; +}; + +export type SettingOutput = { + group?: (string) | null; + groupDisplayName?: (string) | null; + settingItemOutput?: Array | null; +}; + +export type StringStringFromSelector = { + readonly value?: (string) | null; + readonly label?: (string) | null; +}; + +export type TenantCreateDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + name: string; + adminEmailAddress: string; + adminPassword: string; +}; + +export type TenantDto = { + readonly extraProperties?: { + [key: string]: unknown; + } | null; + id?: string; + name?: (string) | null; + concurrencyStamp?: (string) | null; +}; + +export type TenantDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type TimeZone = { + iana?: IanaTimeZone; + windows?: WindowsTimeZone; +}; + +export type TimingDto = { + timeZone?: TimeZone; +}; + +export type TreeOutput = { + title?: (string) | null; + key?: string; + children?: Array | null; +}; + +export type TypeApiDescriptionModel = { + baseType?: (string) | null; + isEnum?: boolean; + enumNames?: Array<(string)> | null; + enumValues?: Array | null; + genericArguments?: Array<(string)> | null; + properties?: Array | null; +}; + +export type UpdateDataDictinaryInput = { + id?: string; + code?: (string) | null; + displayText?: (string) | null; + description?: (string) | null; +}; + +export type UpdateDetailInput = { + dataDictionaryId?: string; + id?: string; + displayText?: (string) | null; + description?: (string) | null; + order?: number; +}; + +export type UpdateFeatureDto = { + name?: (string) | null; + value?: (string) | null; +}; + +export type UpdateFeatureInput = { + providerName?: (string) | null; + providerKey?: (string) | null; + updateFeaturesDto?: UpdateFeaturesDto; +}; + +export type UpdateFeaturesDto = { + features?: Array | null; +}; + +export type UpdateLanguageInput = { + id?: string; + cultureName?: (string) | null; + uiCultureName?: (string) | null; + displayName?: (string) | null; + flagIcon?: (string) | null; + isEnabled?: boolean; +}; + +export type UpdateLanguageTextInput = { + resourceName: string; + cultureName: string; + name: string; + value: string; +}; + +export type UpdateOrganizationUnitInput = { + displayName?: (string) | null; + id?: string; +}; + +export type UpdatePermissionDto = { + name?: (string) | null; + isGranted?: boolean; +}; + +export type UpdatePermissionsDto = { + permissions?: Array | null; +}; + +export type UpdateRoleInput = { + roleId?: string; + roleInfo?: IdentityRoleUpdateDto; +}; + +export type UpdateRolePermissionsInput = { + providerName?: (string) | null; + providerKey?: (string) | null; + updatePermissionsDto?: UpdatePermissionsDto; +}; + +export type UpdateSettingInput = { + values?: { + [key: string]: ((string) | null); + } | null; +}; + +export type UpdateTenantInput = { + id?: string; + name?: (string) | null; +}; + +export type UpdateUserInput = { + userId?: string; + userInfo?: IdentityUserUpdateDto; +}; + +export type UserLoginInfo = { + userNameOrEmailAddress: string; + password: string; + rememberMe?: boolean; +}; + +export type WindowsTimeZone = { + timeZoneId?: (string) | null; +}; + +export type GetApiAbpApiDefinitionData = { + query?: { + IncludeTypes?: boolean; + }; +}; + +export type GetApiAbpApiDefinitionResponse = (ApplicationApiDescriptionModel); + +export type GetApiAbpApiDefinitionError = (RemoteServiceErrorResponse); + +export type GetApiAbpApplicationConfigurationData = { + query?: { + IncludeLocalizationResources?: boolean; + }; +}; + +export type GetApiAbpApplicationConfigurationResponse = (ApplicationConfigurationDto); + +export type GetApiAbpApplicationConfigurationError = (RemoteServiceErrorResponse); + +export type GetApiAbpApplicationLocalizationData = { + query: { + CultureName: string; + OnlyDynamics?: boolean; + }; +}; + +export type GetApiAbpApplicationLocalizationResponse = (ApplicationLocalizationDto); + +export type GetApiAbpApplicationLocalizationError = (RemoteServiceErrorResponse); + +export type PostApiAppAccountLoginData = { + body?: LoginInput; +}; + +export type PostApiAppAccountLoginResponse = (LoginOutput); + +export type PostApiAppAccountLoginError = (RemoteServiceErrorResponse); + +export type PostAuditLogsPageData = { + body?: PagingAuditLogInput; +}; + +export type PostAuditLogsPageResponse = (PagingAuditLogOutputPagedResultDto); + +export type PostAuditLogsPageError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryPageData = { + body?: PagingDataDictionaryInput; +}; + +export type PostDataDictionaryPageResponse = (PagingDataDictionaryOutputPagedResultDto); + +export type PostDataDictionaryPageError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryPageDetailData = { + body?: PagingDataDictionaryDetailInput; +}; + +export type PostDataDictionaryPageDetailResponse = (PagingDataDictionaryDetailOutputPagedResultDto); + +export type PostDataDictionaryPageDetailError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryCreateData = { + body?: CreateDataDictinaryInput; +}; + +export type PostDataDictionaryCreateResponse = (unknown); + +export type PostDataDictionaryCreateError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryCreateDetailData = { + body?: CreateDataDictinaryDetailInput; +}; + +export type PostDataDictionaryCreateDetailResponse = (unknown); + +export type PostDataDictionaryCreateDetailError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryStatusData = { + body?: SetDataDictinaryDetailInput; +}; + +export type PostDataDictionaryStatusResponse = (unknown); + +export type PostDataDictionaryStatusError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryUpdateDetailData = { + body?: UpdateDetailInput; +}; + +export type PostDataDictionaryUpdateDetailResponse = (unknown); + +export type PostDataDictionaryUpdateDetailError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryDeleteData = { + body?: DeleteDataDictionaryDetailInput; +}; + +export type PostDataDictionaryDeleteResponse = (unknown); + +export type PostDataDictionaryDeleteError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryDeleteDataDictionaryTypeData = { + body?: IdInput; +}; + +export type PostDataDictionaryDeleteDataDictionaryTypeResponse = (unknown); + +export type PostDataDictionaryDeleteDataDictionaryTypeError = (RemoteServiceErrorResponse); + +export type PostDataDictionaryUpdateData = { + body?: UpdateDataDictinaryInput; +}; + +export type PostDataDictionaryUpdateResponse = (unknown); + +export type PostDataDictionaryUpdateError = (RemoteServiceErrorResponse); + +export type PostFeaturesListData = { + body?: GetFeatureListResultInput; +}; + +export type PostFeaturesListResponse = (GetFeatureListResultDto); + +export type PostFeaturesListError = (RemoteServiceErrorResponse); + +export type PostFeaturesUpdateData = { + body?: UpdateFeatureInput; +}; + +export type PostFeaturesUpdateResponse = (unknown); + +export type PostFeaturesUpdateError = (RemoteServiceErrorResponse); + +export type PostFeaturesDeleteData = { + body?: DeleteFeatureInput; +}; + +export type PostFeaturesDeleteResponse = (unknown); + +export type PostFeaturesDeleteError = (RemoteServiceErrorResponse); + +export type PostIdentitySecurityLogsPageData = { + body?: PagingIdentitySecurityLogInput; +}; + +export type PostIdentitySecurityLogsPageResponse = (PagingIdentitySecurityLogOutputPagedResultDto); + +export type PostIdentitySecurityLogsPageError = (RemoteServiceErrorResponse); + +export type PostLanguagesAllResponse = (Array); + +export type PostLanguagesAllError = (RemoteServiceErrorResponse); + +export type PostLanguagesPageData = { + body?: PageLanguageInput; +}; + +export type PostLanguagesPageResponse = (PageLanguageOutputPagedResultDto); + +export type PostLanguagesPageError = (RemoteServiceErrorResponse); + +export type PostLanguagesCreateData = { + body?: CreateLanguageInput; +}; + +export type PostLanguagesCreateResponse = (unknown); + +export type PostLanguagesCreateError = (RemoteServiceErrorResponse); + +export type PostLanguagesUpdateData = { + body?: UpdateLanguageInput; +}; + +export type PostLanguagesUpdateResponse = (unknown); + +export type PostLanguagesUpdateError = (RemoteServiceErrorResponse); + +export type PostLanguagesDeleteData = { + body?: DeleteLanguageInput; +}; + +export type PostLanguagesDeleteResponse = (unknown); + +export type PostLanguagesDeleteError = (RemoteServiceErrorResponse); + +export type PostLanguagesSetDefaultData = { + body?: IdInput; +}; + +export type PostLanguagesSetDefaultResponse = (unknown); + +export type PostLanguagesSetDefaultError = (RemoteServiceErrorResponse); + +export type PostLanguageTextsAllResourceResponse = (Array); + +export type PostLanguageTextsAllResourceError = (RemoteServiceErrorResponse); + +export type PostLanguageTextsPageData = { + body?: PageLanguageTextInput; +}; + +export type PostLanguageTextsPageResponse = (PageLanguageTextOutputPagedResultDto); + +export type PostLanguageTextsPageError = (RemoteServiceErrorResponse); + +export type PostLanguageTextsCreateData = { + body?: CreateLanguageTextInput; +}; + +export type PostLanguageTextsCreateResponse = (unknown); + +export type PostLanguageTextsCreateError = (RemoteServiceErrorResponse); + +export type PostLanguageTextsUpdateData = { + body?: UpdateLanguageTextInput; +}; + +export type PostLanguageTextsUpdateResponse = (unknown); + +export type PostLanguageTextsUpdateError = (RemoteServiceErrorResponse); + +export type PostNotificationNotificationPageData = { + body?: PagingNotificationInput; +}; + +export type PostNotificationNotificationPageResponse = (PagingNotificationOutputPagedResultDto); + +export type PostNotificationNotificationPageError = (RemoteServiceErrorResponse); + +export type PostNotificationNotificationSubscriptionPageData = { + body?: PagingNotificationSubscriptionInput; +}; + +export type PostNotificationNotificationSubscriptionPageResponse = (PagingNotificationSubscriptionOutputPagedResultDto); + +export type PostNotificationNotificationSubscriptionPageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendCommonWarningMessageData = { + body?: SendCommonMessageInput; +}; + +export type PostNotificationSendCommonWarningMessageResponse = (unknown); + +export type PostNotificationSendCommonWarningMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendCommonInformationMessageData = { + body?: SendCommonMessageInput; +}; + +export type PostNotificationSendCommonInformationMessageResponse = (unknown); + +export type PostNotificationSendCommonInformationMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendCommonErrorMessageData = { + body?: SendCommonMessageInput; +}; + +export type PostNotificationSendCommonErrorMessageResponse = (unknown); + +export type PostNotificationSendCommonErrorMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendBroadCastWarningMessageData = { + body?: SendBroadCastMessageInput; +}; + +export type PostNotificationSendBroadCastWarningMessageResponse = (unknown); + +export type PostNotificationSendBroadCastWarningMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendBroadCastInformationMessageData = { + body?: SendBroadCastMessageInput; +}; + +export type PostNotificationSendBroadCastInformationMessageResponse = (unknown); + +export type PostNotificationSendBroadCastInformationMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationSendBroadCastErrorMessageData = { + body?: SendBroadCastMessageInput; +}; + +export type PostNotificationSendBroadCastErrorMessageResponse = (unknown); + +export type PostNotificationSendBroadCastErrorMessageError = (RemoteServiceErrorResponse); + +export type PostNotificationReadData = { + body?: SetReadInput; +}; + +export type PostNotificationReadResponse = (unknown); + +export type PostNotificationReadError = (RemoteServiceErrorResponse); + +export type PostNotificationBatchReadData = { + body?: SetBatchReadInput; +}; + +export type PostNotificationBatchReadResponse = (unknown); + +export type PostNotificationBatchReadError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsTreeResponse = (Array); + +export type PostOrganizationUnitsTreeError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsCreateData = { + body?: CreateOrganizationUnitInput; +}; + +export type PostOrganizationUnitsCreateResponse = (unknown); + +export type PostOrganizationUnitsCreateError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsDeleteData = { + body?: IdInput; +}; + +export type PostOrganizationUnitsDeleteResponse = (unknown); + +export type PostOrganizationUnitsDeleteError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsUpdateData = { + body?: UpdateOrganizationUnitInput; +}; + +export type PostOrganizationUnitsUpdateResponse = (unknown); + +export type PostOrganizationUnitsUpdateError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsAddRoleToOrganizationUnitAsyncData = { + body?: AddRoleToOrganizationUnitInput; +}; + +export type PostOrganizationUnitsAddRoleToOrganizationUnitAsyncResponse = (unknown); + +export type PostOrganizationUnitsAddRoleToOrganizationUnitAsyncError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncData = { + body?: RemoveRoleToOrganizationUnitInput; +}; + +export type PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncResponse = (unknown); + +export type PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsAddUserToOrganizationUnitData = { + body?: AddUserToOrganizationUnitInput; +}; + +export type PostOrganizationUnitsAddUserToOrganizationUnitResponse = (unknown); + +export type PostOrganizationUnitsAddUserToOrganizationUnitError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsRemoveUserFromOrganizationUnitData = { + body?: RemoveUserToOrganizationUnitInput; +}; + +export type PostOrganizationUnitsRemoveUserFromOrganizationUnitResponse = (unknown); + +export type PostOrganizationUnitsRemoveUserFromOrganizationUnitError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsGetUsersData = { + body?: GetOrganizationUnitUserInput; +}; + +export type PostOrganizationUnitsGetUsersResponse = (GetOrganizationUnitUserOutputPagedResultDto); + +export type PostOrganizationUnitsGetUsersError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsGetRolesData = { + body?: GetOrganizationUnitRoleInput; +}; + +export type PostOrganizationUnitsGetRolesResponse = (GetOrganizationUnitRoleOutputPagedResultDto); + +export type PostOrganizationUnitsGetRolesError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsGetUnAddUsersData = { + body?: GetUnAddUserInput; +}; + +export type PostOrganizationUnitsGetUnAddUsersResponse = (GetUnAddUserOutputPagedResultDto); + +export type PostOrganizationUnitsGetUnAddUsersError = (RemoteServiceErrorResponse); + +export type PostOrganizationUnitsGetUnAddRolesData = { + body?: GetUnAddRoleInput; +}; + +export type PostOrganizationUnitsGetUnAddRolesResponse = (GetUnAddRoleOutputPagedResultDto); + +export type PostOrganizationUnitsGetUnAddRolesError = (RemoteServiceErrorResponse); + +export type PostPermissionsTreeData = { + body?: GetPermissionInput; +}; + +export type PostPermissionsTreeResponse = (PermissionOutput); + +export type PostPermissionsTreeError = (RemoteServiceErrorResponse); + +export type PostPermissionsUpdateData = { + body?: UpdateRolePermissionsInput; +}; + +export type PostPermissionsUpdateResponse = (unknown); + +export type PostPermissionsUpdateError = (RemoteServiceErrorResponse); + +export type PostRolesAllResponse = (IdentityRoleDtoListResultDto); + +export type PostRolesAllError = (RemoteServiceErrorResponse); + +export type PostRolesPageData = { + body?: PagingRoleListInput; +}; + +export type PostRolesPageResponse = (IdentityRoleDtoPagedResultDto); + +export type PostRolesPageError = (RemoteServiceErrorResponse); + +export type PostRolesCreateData = { + body?: IdentityRoleCreateDto; +}; + +export type PostRolesCreateResponse = (IdentityRoleDto); + +export type PostRolesCreateError = (RemoteServiceErrorResponse); + +export type PostRolesUpdateData = { + body?: UpdateRoleInput; +}; + +export type PostRolesUpdateResponse = (IdentityRoleDto); + +export type PostRolesUpdateError = (RemoteServiceErrorResponse); + +export type PostRolesDeleteData = { + body?: IdInput; +}; + +export type PostRolesDeleteResponse = (unknown); + +export type PostRolesDeleteError = (RemoteServiceErrorResponse); + +export type PostSettingsAllResponse = (Array); + +export type PostSettingsAllError = (RemoteServiceErrorResponse); + +export type PostSettingsUpdateData = { + body?: UpdateSettingInput; +}; + +export type PostSettingsUpdateResponse = (unknown); + +export type PostSettingsUpdateError = (RemoteServiceErrorResponse); + +export type PostTenantsFindData = { + body?: FindTenantByNameInput; +}; + +export type PostTenantsFindResponse = (FindTenantResultDto); + +export type PostTenantsFindError = (RemoteServiceErrorResponse); + +export type PostTenantsPageData = { + body?: PagingTenantInput; +}; + +export type PostTenantsPageResponse = (TenantDtoPagedResultDto); + +export type PostTenantsPageError = (RemoteServiceErrorResponse); + +export type PostTenantsCreateData = { + body?: TenantCreateDto; +}; + +export type PostTenantsCreateResponse = (TenantDto); + +export type PostTenantsCreateError = (RemoteServiceErrorResponse); + +export type PostTenantsUpdateData = { + body?: UpdateTenantInput; +}; + +export type PostTenantsUpdateResponse = (TenantDto); + +export type PostTenantsUpdateError = (RemoteServiceErrorResponse); + +export type PostTenantsDeleteData = { + body?: IdInput; +}; + +export type PostTenantsDeleteResponse = (unknown); + +export type PostTenantsDeleteError = (RemoteServiceErrorResponse); + +export type PostTenantsPageConnectionStringData = { + body?: PageTenantConnectionStringInput; +}; + +export type PostTenantsPageConnectionStringResponse = (PageTenantConnectionStringOutputPagedResultDto); + +export type PostTenantsPageConnectionStringError = (RemoteServiceErrorResponse); + +export type PostTenantsAddOrUpdateConnectionStringData = { + body?: AddOrUpdateConnectionStringInput; +}; + +export type PostTenantsAddOrUpdateConnectionStringResponse = (unknown); + +export type PostTenantsAddOrUpdateConnectionStringError = (RemoteServiceErrorResponse); + +export type PostTenantsDeleteConnectionStringData = { + body?: DeleteConnectionStringInput; +}; + +export type PostTenantsDeleteConnectionStringResponse = (unknown); + +export type PostTenantsDeleteConnectionStringError = (RemoteServiceErrorResponse); + +export type PostUsersPageData = { + body?: PagingUserListInput; +}; + +export type PostUsersPageResponse = (PageIdentityUserOutputPagedResultDto); + +export type PostUsersPageError = (RemoteServiceErrorResponse); + +export type PostUsersListData = { + body?: PagingUserListInput; +}; + +export type PostUsersListResponse = (Array); + +export type PostUsersListError = (RemoteServiceErrorResponse); + +export type PostUsersExportData = { + body?: PagingUserListInput; +}; + +export type PostUsersExportResponse = ((Blob | File)); + +export type PostUsersExportError = (RemoteServiceErrorResponse); + +export type PostUsersCreateData = { + body?: IdentityUserCreateDto; +}; + +export type PostUsersCreateResponse = (IdentityUserDto); + +export type PostUsersCreateError = (RemoteServiceErrorResponse); + +export type PostUsersUpdateData = { + body?: UpdateUserInput; +}; + +export type PostUsersUpdateResponse = (IdentityUserDto); + +export type PostUsersUpdateError = (RemoteServiceErrorResponse); + +export type PostUsersDeleteData = { + body?: IdInput; +}; + +export type PostUsersDeleteResponse = (unknown); + +export type PostUsersDeleteError = (RemoteServiceErrorResponse); + +export type PostUsersRoleData = { + body?: IdInput; +}; + +export type PostUsersRoleResponse = (IdentityRoleDtoListResultDto); + +export type PostUsersRoleError = (RemoteServiceErrorResponse); + +export type PostUsersChangePasswordData = { + body?: ChangePasswordInput; +}; + +export type PostUsersChangePasswordResponse = (boolean); + +export type PostUsersChangePasswordError = (RemoteServiceErrorResponse); + +export type PostUsersLockData = { + body?: LockUserInput; +}; + +export type PostUsersLockResponse = (unknown); + +export type PostUsersLockError = (RemoteServiceErrorResponse); + +export type PostUsersFindByUserNameData = { + body?: FindByUserNameInput; +}; + +export type PostUsersFindByUserNameResponse = (IdentityUserDto); + +export type PostUsersFindByUserNameError = (RemoteServiceErrorResponse); + +export type PostUsersMyProfileResponse = (MyProfileOutput); + +export type PostUsersMyProfileError = (RemoteServiceErrorResponse); \ No newline at end of file diff --git a/apps/web-antd/src/api/core/auth.ts b/apps/web-antd/src/api/core/auth.ts new file mode 100644 index 0000000..71d9f99 --- /dev/null +++ b/apps/web-antd/src/api/core/auth.ts @@ -0,0 +1,51 @@ +import { baseRequestClient, requestClient } from '#/api/request'; + +export namespace AuthApi { + /** 登录接口参数 */ + export interface LoginParams { + password?: string; + username?: string; + } + + /** 登录接口返回值 */ + export interface LoginResult { + accessToken: string; + } + + export interface RefreshTokenResult { + data: string; + status: number; + } +} + +/** + * 登录 + */ +export async function loginApi(data: AuthApi.LoginParams) { + return requestClient.post('/auth/login', data); +} + +/** + * 刷新accessToken + */ +export async function refreshTokenApi() { + return baseRequestClient.post('/auth/refresh', { + withCredentials: true, + }); +} + +/** + * 退出登录 + */ +export async function logoutApi() { + return baseRequestClient.post('/auth/logout', { + withCredentials: true, + }); +} + +/** + * 获取用户权限码 + */ +export async function getAccessCodesApi() { + return requestClient.get('/auth/codes'); +} diff --git a/apps/web-antd/src/api/core/index.ts b/apps/web-antd/src/api/core/index.ts new file mode 100644 index 0000000..28a5aef --- /dev/null +++ b/apps/web-antd/src/api/core/index.ts @@ -0,0 +1,3 @@ +export * from './auth'; +export * from './menu'; +export * from './user'; diff --git a/apps/web-antd/src/api/core/menu.ts b/apps/web-antd/src/api/core/menu.ts new file mode 100644 index 0000000..9ef60b1 --- /dev/null +++ b/apps/web-antd/src/api/core/menu.ts @@ -0,0 +1,10 @@ +import type { RouteRecordStringComponent } from '@vben/types'; + +import { requestClient } from '#/api/request'; + +/** + * 获取用户所有菜单 + */ +export async function getAllMenusApi() { + return requestClient.get('/menu/all'); +} diff --git a/apps/web-antd/src/api/core/user.ts b/apps/web-antd/src/api/core/user.ts new file mode 100644 index 0000000..7e28ea8 --- /dev/null +++ b/apps/web-antd/src/api/core/user.ts @@ -0,0 +1,10 @@ +import type { UserInfo } from '@vben/types'; + +import { requestClient } from '#/api/request'; + +/** + * 获取用户信息 + */ +export async function getUserInfoApi() { + return requestClient.get('/user/info'); +} diff --git a/apps/web-antd/src/api/index.ts b/apps/web-antd/src/api/index.ts new file mode 100644 index 0000000..4b0e041 --- /dev/null +++ b/apps/web-antd/src/api/index.ts @@ -0,0 +1 @@ +export * from './core'; diff --git a/apps/web-antd/src/api/request.ts b/apps/web-antd/src/api/request.ts new file mode 100644 index 0000000..288dddd --- /dev/null +++ b/apps/web-antd/src/api/request.ts @@ -0,0 +1,113 @@ +/** + * 该文件可自行根据业务逻辑进行调整 + */ +import type { RequestClientOptions } from '@vben/request'; + +import { useAppConfig } from '@vben/hooks'; +import { preferences } from '@vben/preferences'; +import { + authenticateResponseInterceptor, + defaultResponseInterceptor, + errorMessageResponseInterceptor, + RequestClient, +} from '@vben/request'; +import { useAccessStore } from '@vben/stores'; + +import { message } from 'ant-design-vue'; + +import { useAuthStore } from '#/store'; + +import { refreshTokenApi } from './core'; + +const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); + +function createRequestClient(baseURL: string, options?: RequestClientOptions) { + const client = new RequestClient({ + ...options, + baseURL, + }); + + /** + * 重新认证逻辑 + */ + async function doReAuthenticate() { + console.warn('Access token or refresh token is invalid or expired. '); + const accessStore = useAccessStore(); + const authStore = useAuthStore(); + accessStore.setAccessToken(null); + if ( + preferences.app.loginExpiredMode === 'modal' && + accessStore.isAccessChecked + ) { + accessStore.setLoginExpired(true); + } else { + await authStore.logout(); + } + } + + /** + * 刷新token逻辑 + */ + async function doRefreshToken() { + const accessStore = useAccessStore(); + const resp = await refreshTokenApi(); + const newToken = resp.data; + accessStore.setAccessToken(newToken); + return newToken; + } + + function formatToken(token: null | string) { + return token ? `Bearer ${token}` : null; + } + + // 请求头处理 + client.addRequestInterceptor({ + fulfilled: async (config) => { + const accessStore = useAccessStore(); + + config.headers.Authorization = formatToken(accessStore.accessToken); + config.headers['Accept-Language'] = preferences.app.locale; + return config; + }, + }); + + // 处理返回的响应数据格式 + client.addResponseInterceptor( + defaultResponseInterceptor({ + codeField: 'code', + dataField: 'data', + successCode: 0, + }), + ); + + // token过期的处理 + client.addResponseInterceptor( + authenticateResponseInterceptor({ + client, + doReAuthenticate, + doRefreshToken, + enableRefreshToken: preferences.app.enableRefreshToken, + formatToken, + }), + ); + + // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 + client.addResponseInterceptor( + errorMessageResponseInterceptor((msg: string, error) => { + // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg + // 当前mock接口返回的错误字段是 error 或者 message + const responseData = error?.response?.data ?? {}; + const errorMessage = responseData?.error ?? responseData?.message ?? ''; + // 如果没有错误信息,则会根据状态码进行提示 + message.error(errorMessage || msg); + }), + ); + + return client; +} + +export const requestClient = createRequestClient(apiURL, { + responseReturn: 'data', +}); + +export const baseRequestClient = new RequestClient({ baseURL: apiURL }); diff --git a/apps/web-antd/src/app.vue b/apps/web-antd/src/app.vue new file mode 100644 index 0000000..bbaccce --- /dev/null +++ b/apps/web-antd/src/app.vue @@ -0,0 +1,39 @@ + + + diff --git a/apps/web-antd/src/bootstrap.ts b/apps/web-antd/src/bootstrap.ts new file mode 100644 index 0000000..39dd9b4 --- /dev/null +++ b/apps/web-antd/src/bootstrap.ts @@ -0,0 +1,68 @@ +import { createApp, watchEffect } from 'vue'; + +import { registerAccessDirective } from '@vben/access'; +import { initTippy } from '@vben/common-ui'; +import { preferences } from '@vben/preferences'; +import { initStores } from '@vben/stores'; +import '@vben/styles'; +import '@vben/styles/antd'; + +import { useTitle } from '@vueuse/core'; +// https://github.com/rennzhang/codemirror-editor-vue3 +import { InstallCodeMirror } from 'codemirror-editor-vue3'; +import JsonViewer from 'vue3-json-viewer'; + +import { $t, setupI18n } from '#/locales'; + +import { initComponentAdapter } from './adapter/component'; +import App from './app.vue'; +import { router } from './router'; + +import 'vue3-json-viewer/dist/index.css'; + +async function bootstrap(namespace: string) { + // 初始化组件适配器 + await initComponentAdapter(); + + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // zIndex: 1020, + // }); + + const app = createApp(App); + + // 国际化 i18n 配置 + await setupI18n(app); + + // 配置 pinia-tore + await initStores(app, { namespace }); + + // 安装权限指令 + registerAccessDirective(app); + + // 初始化 tippy + initTippy(app); + + // 配置路由及路由守卫 + app.use(router); + // 配置 json-viewer + app.use(JsonViewer); + + // 动态更新标题 + watchEffect(() => { + if (preferences.app.dynamicTitle) { + const routeTitle = router.currentRoute.value.meta?.title; + const pageTitle = + (routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name; + useTitle(pageTitle); + } + }); + app.use(InstallCodeMirror); + app.mount('#app'); +} + +export { bootstrap }; diff --git a/apps/web-antd/src/components/Loading/index.ts b/apps/web-antd/src/components/Loading/index.ts new file mode 100644 index 0000000..18bb3e9 --- /dev/null +++ b/apps/web-antd/src/components/Loading/index.ts @@ -0,0 +1,4 @@ +export { createLoading } from './src/createLoading'; +export { default as Loading } from './src/Loading.vue'; + +export { useLoading } from './src/useLoading'; diff --git a/apps/web-antd/src/components/Loading/src/Loading.vue b/apps/web-antd/src/components/Loading/src/Loading.vue new file mode 100644 index 0000000..c3ad8c6 --- /dev/null +++ b/apps/web-antd/src/components/Loading/src/Loading.vue @@ -0,0 +1,78 @@ + + + diff --git a/apps/web-antd/src/components/Loading/src/createLoading.ts b/apps/web-antd/src/components/Loading/src/createLoading.ts new file mode 100644 index 0000000..0133f9a --- /dev/null +++ b/apps/web-antd/src/components/Loading/src/createLoading.ts @@ -0,0 +1,84 @@ +import type { LoadingProps } from './typing'; + +import { createVNode, defineComponent, h, reactive, render } from 'vue'; + +import Loading from './Loading.vue'; + +// 创建一个加载组件的函数 +export function createLoading( + props?: Partial, + target?: HTMLElement, + wait = false, +) { + let vm: any = null; + const data = reactive({ + tip: '', + loading: true, + ...props, + }); + + // 定义加载组件的包装 + const LoadingWrap = defineComponent({ + render() { + return h(Loading, { ...data }); + }, + }); + + vm = createVNode(LoadingWrap); + + let container: any = null; + // 根据wait参数决定何时渲染Loading组件 + if (wait) { + setTimeout(() => { + render(vm, (container = document.createElement('div'))); + }, 0); + } else { + render(vm, (container = document.createElement('div'))); + } + + // 关闭加载组件的函数 + function close() { + if (vm?.el && vm.el.parentNode) { + vm.el.remove(); + } + } + + // 打开加载组件并将其附加到目标元素上的函数 + function open(target: HTMLElement = document.body) { + if (!vm || !vm.el) { + return; + } + target.append(vm.el as HTMLElement); + } + + // 销毁加载组件的函数 + function destroy() { + container && render(null, container); + container = vm = null; + } + + // 如果提供了目标元素,则打开加载组件 + if (target) { + open(target); + } + + // 返回加载组件的实例及控制方法 + return { + vm, + close, + open, + destroy, + setTip: (tip: string) => { + data.tip = tip; + }, + setLoading: (loading: boolean) => { + data.loading = loading; + }, + get loading() { + return data.loading; + }, + get $el() { + return vm?.el as HTMLElement; + }, + }; +} diff --git a/apps/web-antd/src/components/Loading/src/typing.ts b/apps/web-antd/src/components/Loading/src/typing.ts new file mode 100644 index 0000000..8805acd --- /dev/null +++ b/apps/web-antd/src/components/Loading/src/typing.ts @@ -0,0 +1,14 @@ +export enum SizeEnum { + DEFAULT = 'default', + LARGE = 'large', + SMALL = 'small', +} + +export interface LoadingProps { + tip: string; + size: SizeEnum; + absolute: boolean; + loading: boolean; + background: string; + theme: 'dark' | 'light'; +} diff --git a/apps/web-antd/src/components/Loading/src/useLoading.ts b/apps/web-antd/src/components/Loading/src/useLoading.ts new file mode 100644 index 0000000..fe2b9fb --- /dev/null +++ b/apps/web-antd/src/components/Loading/src/useLoading.ts @@ -0,0 +1,61 @@ +import type { LoadingProps } from './typing'; + +import type { Ref } from 'vue'; +import { unref } from 'vue'; + +import { tryOnUnmounted } from '@vueuse/core'; + +import { createLoading } from './createLoading'; + +export interface UseLoadingOptions { + target?: any; + props?: Partial; +} + +interface Fn { + (): void; +} + +export function useLoading( + props: Partial, +): [Fn, Fn, (arg0: string) => void]; +export function useLoading( + opt: Partial, +): [Fn, Fn, (arg0: string) => void]; + +export function useLoading( + opt: Partial | Partial, +): [Fn, Fn, (arg0: string) => void] { + let props: Partial; + let target: HTMLElement | Ref = document.body; + + if (Reflect.has(opt, 'target') || Reflect.has(opt, 'props')) { + const options = opt as Partial; + props = options.props || {}; + target = options.target || document.body; + } else { + props = opt as Partial; + } + + const instance = createLoading(props, undefined, false); + + const open = (): void => { + const t = unref(target as Ref); + if (!t) return; + instance.open(t); + }; + + const close = (): void => { + instance.close(); + }; + + const setTip = (tip: string) => { + instance.setTip(tip); + }; + + tryOnUnmounted(() => { + instance.destroy(); + }); + + return [open, close, setTip]; +} diff --git a/apps/web-antd/src/components/icon/icon.vue b/apps/web-antd/src/components/icon/icon.vue new file mode 100644 index 0000000..e5c0c31 --- /dev/null +++ b/apps/web-antd/src/components/icon/icon.vue @@ -0,0 +1,51 @@ + + + + diff --git a/apps/web-antd/src/components/icon/index.ts b/apps/web-antd/src/components/icon/index.ts new file mode 100644 index 0000000..fc98972 --- /dev/null +++ b/apps/web-antd/src/components/icon/index.ts @@ -0,0 +1 @@ +export { default as Icon } from './icon.vue'; diff --git a/apps/web-antd/src/components/table-action/index.ts b/apps/web-antd/src/components/table-action/index.ts new file mode 100644 index 0000000..00b7e6b --- /dev/null +++ b/apps/web-antd/src/components/table-action/index.ts @@ -0,0 +1,2 @@ +export { default as TableAction } from './table-action.vue'; +export type * from './types.d.ts'; diff --git a/apps/web-antd/src/components/table-action/table-action.vue b/apps/web-antd/src/components/table-action/table-action.vue new file mode 100644 index 0000000..2ce2af6 --- /dev/null +++ b/apps/web-antd/src/components/table-action/table-action.vue @@ -0,0 +1,225 @@ + + + + diff --git a/apps/web-antd/src/components/table-action/types.d.ts b/apps/web-antd/src/components/table-action/types.d.ts new file mode 100644 index 0000000..29e7d4d --- /dev/null +++ b/apps/web-antd/src/components/table-action/types.d.ts @@ -0,0 +1,26 @@ +import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; +import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip'; + +export interface PopConfirm { + title: string; + okText?: string; + cancelText?: string; + confirm: Fn; + cancel?: Fn; + icon?: string; + disabled?: boolean; +} +export interface ActionItem extends ButtonProps { + onClick?: Fn; + label?: string; + color?: 'error' | 'success' | 'warning'; + icon?: string; + popConfirm?: PopConfirm; + disabled?: boolean; + divider?: boolean; + // 权限编码控制是否显示 + auth?: string[]; + // 业务控制是否显示 + ifShow?: ((action: ActionItem) => boolean) | boolean; + tooltip?: string | TooltipProps; +} diff --git a/apps/web-antd/src/hooks/useSignalR.ts b/apps/web-antd/src/hooks/useSignalR.ts new file mode 100644 index 0000000..494d6aa --- /dev/null +++ b/apps/web-antd/src/hooks/useSignalR.ts @@ -0,0 +1,125 @@ +import { useEventbus } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import * as signalR from '@microsoft/signalr'; +import { notification } from 'ant-design-vue'; + +const eventbus = useEventbus(); +let connection: signalR.HubConnection; +export function useSignalR() { + /** + * 开始连接SignalR + */ + async function startConnect() { + try { + connectionsignalR(); + await connection.start(); + } catch (error) { + console.error(error); + setTimeout(() => startConnect(), 5000); + } + } + + /** + * 关闭SignalR连接 + */ + function closeConnect(): void { + 8; + if (connection) { + connection.stop(); + } + } + + async function connectionsignalR() { + const userStore = useUserStore(); + const token = userStore.userInfo?.token; + connection = new signalR.HubConnectionBuilder() + .withUrl(import.meta.env.VITE_WEBSOCKET_URL, { + accessTokenFactory: () => token, + skipNegotiation: true, + transport: signalR.HttpTransportType.WebSockets, + }) + .withAutomaticReconnect({ + nextRetryDelayInMilliseconds: (retryContext) => { + // 重连规则:重连次数<300:间隔1s;重试次数<3000:间隔3s;重试次数>3000:间隔30s + const count = retryContext.previousRetryCount / 300; + if (count < 1) { + // 重试次数<300,间隔1s + return 1000; + } else if (count < 10) { + // 重试次数>300:间隔5s + return 1000 * 5; + } // 重试次数>3000:间隔30s + else { + return 1000 * 30; + } + }, + }) + .configureLogging(signalR.LogLevel.Debug) + .build(); + + // 接收普通文本消息 + connection.on('ReceiveTextMessageAsync', ReceiveTextMessageHandlerAsync); + // 接收广播消息 + connection.on( + 'ReceiveBroadCastMessageAsync', + ReceiveBroadCastMessageHandlerAsync, + ); + } + + /** + * 接收文本消息 + * @param message 消息体 + */ + function ReceiveTextMessageHandlerAsync(message: any) { + // 发布事件 + eventbus.publish('ReceiveTextMessageHandlerAsync', message); + if (message.messageLevel === 10) { + notification.warn({ + description: message.content, + message: message.title, + }); + } + if (message.messageLevel === 20) { + notification.info({ + message: message.title, + description: message.content, + }); + } + if (message.messageLevel === 30) { + notification.error({ + message: message.title, + description: message.content, + }); + } + } + + /** + * 接收广播消息 + * @param message 消息体 + */ + function ReceiveBroadCastMessageHandlerAsync(message: any) { + // 发布事件 + eventbus.publish('ReceiveTextMessageHandlerAsync', message); + if (message.messageLevel === 10) { + notification.warn({ + message: message.title, + description: message.content, + }); + } + if (message.messageLevel === 20) { + notification.info({ + message: message.title, + description: message.content, + }); + } + if (message.messageLevel === 30) { + notification.error({ + message: message.title, + description: message.content, + }); + } + } + + return { startConnect, closeConnect }; +} diff --git a/apps/web-antd/src/layouts/NotifyItem.vue b/apps/web-antd/src/layouts/NotifyItem.vue new file mode 100644 index 0000000..5d6943a --- /dev/null +++ b/apps/web-antd/src/layouts/NotifyItem.vue @@ -0,0 +1,207 @@ + + + + + diff --git a/apps/web-antd/src/layouts/auth.vue b/apps/web-antd/src/layouts/auth.vue new file mode 100644 index 0000000..18d415b --- /dev/null +++ b/apps/web-antd/src/layouts/auth.vue @@ -0,0 +1,23 @@ + + + diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue new file mode 100644 index 0000000..6298049 --- /dev/null +++ b/apps/web-antd/src/layouts/basic.vue @@ -0,0 +1,256 @@ + + + diff --git a/apps/web-antd/src/layouts/index.ts b/apps/web-antd/src/layouts/index.ts new file mode 100644 index 0000000..a432078 --- /dev/null +++ b/apps/web-antd/src/layouts/index.ts @@ -0,0 +1,6 @@ +const BasicLayout = () => import('./basic.vue'); +const AuthPageLayout = () => import('./auth.vue'); + +const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView); + +export { AuthPageLayout, BasicLayout, IFrameView }; diff --git a/apps/web-antd/src/layouts/my-profile.vue b/apps/web-antd/src/layouts/my-profile.vue new file mode 100644 index 0000000..61a185b --- /dev/null +++ b/apps/web-antd/src/layouts/my-profile.vue @@ -0,0 +1,216 @@ + + + diff --git a/apps/web-antd/src/locales/README.md b/apps/web-antd/src/locales/README.md new file mode 100644 index 0000000..7b45103 --- /dev/null +++ b/apps/web-antd/src/locales/README.md @@ -0,0 +1,3 @@ +# locale + +每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。 diff --git a/apps/web-antd/src/locales/index.ts b/apps/web-antd/src/locales/index.ts new file mode 100644 index 0000000..7f32bd1 --- /dev/null +++ b/apps/web-antd/src/locales/index.ts @@ -0,0 +1,102 @@ +import type { Locale } from 'ant-design-vue/es/locale'; + +import type { App } from 'vue'; + +import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; + +import { ref } from 'vue'; + +import { + $t, + setupI18n as coreSetup, + loadLocalesMapFromDir, +} from '@vben/locales'; +import { preferences } from '@vben/preferences'; + +import antdEnLocale from 'ant-design-vue/es/locale/en_US'; +import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN'; +import dayjs from 'dayjs'; + +const antdLocale = ref(antdDefaultLocale); + +const modules = import.meta.glob('./langs/**/*.json'); + +const localesMap = loadLocalesMapFromDir( + /\.\/langs\/([^/]+)\/(.*)\.json$/, + modules, +); +/** + * 加载应用特有的语言包 + * 这里也可以改造为从服务端获取翻译数据 + * @param lang + */ +async function loadMessages(lang: SupportedLanguagesType) { + const [appLocaleMessages] = await Promise.all([ + localesMap[lang]?.(), + loadThirdPartyMessage(lang), + ]); + return appLocaleMessages?.default; +} + +/** + * 加载第三方组件库的语言包 + * @param lang + */ +async function loadThirdPartyMessage(lang: SupportedLanguagesType) { + await Promise.all([loadAntdLocale(lang), loadDayjsLocale(lang)]); +} + +/** + * 加载dayjs的语言包 + * @param lang + */ +async function loadDayjsLocale(lang: SupportedLanguagesType) { + let locale; + switch (lang) { + case 'en-US': { + locale = await import('dayjs/locale/en'); + break; + } + case 'zh-CN': { + locale = await import('dayjs/locale/zh-cn'); + break; + } + // 默认使用英语 + default: { + locale = await import('dayjs/locale/en'); + } + } + if (locale) { + dayjs.locale(locale); + } else { + console.error(`Failed to load dayjs locale for ${lang}`); + } +} + +/** + * 加载antd的语言包 + * @param lang + */ +async function loadAntdLocale(lang: SupportedLanguagesType) { + switch (lang) { + case 'en-US': { + antdLocale.value = antdEnLocale; + break; + } + case 'zh-CN': { + antdLocale.value = antdDefaultLocale; + break; + } + } +} + +async function setupI18n(app: App, options: LocaleSetupOptions = {}) { + await coreSetup(app, { + defaultLocale: preferences.app.locale, + loadMessages, + missingWarn: !import.meta.env.PROD, + ...options, + }); +} + +export { $t, antdLocale, setupI18n }; diff --git a/apps/web-antd/src/locales/langs/en-US/abp.json b/apps/web-antd/src/locales/langs/en-US/abp.json new file mode 100644 index 0000000..1649a3e --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/abp.json @@ -0,0 +1,131 @@ +{ + "login": { + "selectTenant": "Please select Tenant and ignore the non-tenant mode", + "oidcTip": "Login......" + }, + "menu": { + "system": "SystemManagement", + "user": "UserManagement", + "role": "RoleManagement", + "tenant": "TenantManagement", + "tenantList": "TenantList", + "language": "LanguageManagement", + "auditLog": "AuditLog", + "loginLog": "LoginLog", + "feature": "FeatureManagement", + "setting": "SettingsManagement", + "organizationUnit": "OrganizationUnitManagement", + "languageText": "LanguageTextManagement", + "dataDictionary": "DataDictionaryManagement", + "notification": "NotificationManagement", + "message": "MessageManagement", + "code": "CodeManagement", + "code-project": "ProjectList", + "code-template": "TemplateList", + "code-genarate": "CodeGenarate", + "code-entity": "Entity", + "code-template-detail": "TemplateDetail", + "code-Preview": "Preview" + }, + "user": { + "user": "User", + "userName": "UserName", + "name": "Name", + "surname": "Surname", + "email": "Email", + "phone": "Phone", + "password": "Password", + "currentPassword": "CurrentPassword", + "newPassword": "NewPassword", + "confirmNewPassword": "ConfirmNewPassword", + "changePassword": "ChangePassword", + "status": "Status", + "comfirmPassword": "ComfirmPassword", + "comfirmDeleteUser": "Are you sure you want to delete the user", + "newPasswordAndConfirmPasswordNotMatch": "New password and confirm password not match", + "newPasswordAndCurrentPasswordNotAlike": "The old and new passwords cannot be the same", + "myProfile": "MyProfile", + "myAccount": "MyAccount", + "twoFactor": "TwoFactor", + "verifyAuthenticator": "Verify the Authenticator", + "twoFactorDesc": "Your two-factor authentication app will generate a code. Please enter the code and confirm it.", + "code": "TwoFactor Code", + "twoFactorEnabled": "Two-factor authentication for your account has been successfully enabled. You will be required to enter the code generated by the application when logging in.", + "twoFactorDisabled": "Two-factor authentication for your account has been turned off. You will no longer be required to enter the code generated by the application when logging in.", + "twoFactorEnabledDesc": "Two-factor authentication has been enabled for your account. If you need to turn it off, please enter the two-factor authentication code and then disable it.", + "resetTwoFactor": "ResetTwoFactor" + }, + "role": { + "role": "Role", + "roleName": "RoleName", + "isDefault": "IsDefault", + "permissions": "Permissions" + }, + "log": { + "loginTime": "LoginTime", + "userName": "UserName", + "tenant": "Tenant", + "executionTime": "ExecutionTime", + "responseTime": "ResponseTime(ms)", + "clientIp": "ClientIp", + "exception": "Exception", + "applicationName": "ApplicationName", + "loginMode": "LoginMode", + "loginUrl": "LoginUrl", + "detail": "Detail" + }, + "message": { + "title": "Title", + "content": "Content", + "type": "Type", + "level": "Level", + "sender": "Sender", + "receiver": "Receiver", + "isRead": "IsRead", + "sendMessage": "SendMessage", + "sendNotification": "SendNotification", + "setRead": "SetRead", + "confirmRead": "Are you sure you want to set the message as read?", + "read": "Read", + "unread": "UnRead" + }, + "language": { + "language": "LanguageName", + "showLanguage": "ShowLanguageName", + "icon": "Icon", + "resourceName": "ResourceName", + "value": "Value", + "name": "Name" + }, + "dataDictionary": { + "codeName": "Code|Name", + "code": "Code", + "name": "Name", + "order": "Order", + "status": "Status", + "description": "Description", + "type": "Type" + }, + "organizationunit": { + "organizationunit": "Organizationunit", + "add": "Add", + "member": "Member", + "role": "Role", + "userName": "UserName", + "email": "Email", + "name": "Name", + "selectNode": "Select a node to operate on" + }, + "tenant": { + "tenant": "Tenant", + "notExist": "Tenant Does not exist", + "name": "Tenant Name", + "adminEmail": "Admin Email", + "adminPassword": "Admin Password", + "mangeConnectionString": "MangeConnectionString", + "addorEdit": "AddorEdit", + "featureManagement": "FeatureManagement", + "connectionStringName": "ConnectionStringName", + "connectionString": "ConnectionString" + } +} diff --git a/apps/web-antd/src/locales/langs/en-US/code.json b/apps/web-antd/src/locales/langs/en-US/code.json new file mode 100644 index 0000000..4dab556 --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/code.json @@ -0,0 +1,37 @@ +{ + "companyName": "CompanyName", + "projectName": "ProjectName", + "projectEnglishName": "ProjectEnglishName", + "namespace": "Namespace", + "remark": "Remark", + "templateName": "TemplateName", + "model": "Model", + "property": "Property", + "enum": "Enum", + "isRequired": "IsRequired", + "maxLength": "MaxLength", + "minLength": "MinLength", + "decimalPrecision18": "Accuracy (18,6) of 18", + "decimalPrecision6": "Accuracy (18,6) of 6", + "pleaseSelectEntity": "Please select entity", + "pleaseSelectEnum": "Please select enum", + "detail": "Detail", + "copy": "Copy", + "addFolder": "AddFolder", + "addFile": "AddFile", + "desc": "Description", + "name": "Name", + "templateType": "TemplateType", + "supportTenant": "Support Multi-Tenant", + "project": "Project", + "template": "Template", + "preview": "Preview", + "download": "Download", + "description": "Please select the target and project to generate", + "autoGenerate": "Auto Generate Code", + "code": "Code", + "type": "Type", + "value": "Value", + "relational": "Relational", + "dataType": "DataType" +} diff --git a/apps/web-antd/src/locales/langs/en-US/common.json b/apps/web-antd/src/locales/langs/en-US/common.json new file mode 100644 index 0000000..54bc64e --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/common.json @@ -0,0 +1,39 @@ +{ + "add": "Add", + "edit": "Edit", + "delete": "Delete", + "search": "Search", + "export": "Export", + "save": "save", + "seq": "Seq", + "isEnable": "IsEnable", + "enabled": "Enabled", + "disabled": "Disabled", + "action": "Action", + "createTime": "CreationTime", + "pleaseInput": "Please input", + "addSuccess": "Add Success", + "editSuccess": "Edit Success", + "deleteSuccess": "Delete Success", + "yes": "yes", + "no": "no", + "confirmDelete": "Confirm to delete", + "askConfirmDelete": "Confirm to delete?", + "warning": "warning", + "info": "info", + "error": "error", + "success": "Success", + "keyword": "Keyword", + "mesage403": "You don't have permission to access this page or function!", + "mesage401": "You are not logged in or the login has timed out. Please log in again!", + "mesage500": "Internal server error!", + "mesage404": "The page you are trying to access does not exist!", + "mesage400": "Request error!", + "mesage405": "Incorrect request method!", + "timeOut": "Request timed out!", + "expandAll": "EexpandAll", + "collapseAll": "CollapseAll", + "description": "description", + "comfirm": "Comfirm", + "valid": "Valid" +} diff --git a/apps/web-antd/src/locales/langs/en-US/page.json b/apps/web-antd/src/locales/langs/en-US/page.json new file mode 100644 index 0000000..7975ddf --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/page.json @@ -0,0 +1,15 @@ +{ + "auth": { + "login": "Login", + "register": "Register", + "codeLogin": "Code Login", + "qrcodeLogin": "Qr Code Login", + "forgetPassword": "Forget Password", + "thirdPartyLogin": "Third Party Login" + }, + "dashboard": { + "title": "Dashboard", + "analytics": "Analytics", + "workspace": "Workspace" + } +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/abp.json b/apps/web-antd/src/locales/langs/zh-CN/abp.json new file mode 100644 index 0000000..b9d5d3b --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/abp.json @@ -0,0 +1,131 @@ +{ + "login": { + "selectTenant": "请选择租户,非租户模式请忽略", + "oidcTip": "登陆中......" + }, + "menu": { + "system": "系统管理", + "user": "用户管理", + "role": "角色管理", + "tenant": "租户管理", + "tenantList": "租户列表", + "language": "语言管理", + "auditLog": "审计日志", + "loginLog": "登录日志", + "feature": "功能管理", + "setting": "设置管理", + "organizationUnit": "组织机构管理", + "languageText": "语言文本管理", + "dataDictionary": "数据字典管理", + "notification": "通告管理", + "message": "消息管理", + "code": "代码管理", + "code-project": "项目列表", + "code-template": "模板列表", + "code-genarate": "代码生成", + "code-entity": "实体", + "code-template-detail": "模板详情", + "code-Preview": "预览" + }, + "user": { + "user": "用户", + "userName": "用户名", + "name": "名称", + "surname": "姓氏", + "email": "邮箱", + "phone": "手机号", + "password": "密码", + "currentPassword": "当前密码", + "newPassword": "新密码", + "confirmNewPassword": "确认新密码", + "changePassword": "修改密码", + "status": "状态", + "comfirmPassword": "确认密码", + "comfirmDeleteUser": "确认删除用户", + "newPasswordAndConfirmPasswordNotMatch": "新密码与确认密码不匹配", + "newPasswordAndCurrentPasswordNotAlike": "新旧密码不能一样", + "myProfile": "个人信息", + "myAccount": "我的账户", + "twoFactor": "双因素验证", + "verifyAuthenticator": "验证身份验证器", + "twoFactorDesc": "您的双因素身份验证应用程序将生成一个代码,请输入该代码并确认.", + "code": "双因素验证码", + "twoFactorEnabled": "您的账户已经成功开启双因素验证,登录时要求输入应用程序生成的代码.", + "twoFactorDisabled": "您的账户已经关闭双因素验证,登录时不在要求输入应用程序生成的代码.", + "twoFactorEnabledDesc": "您的账户已经开启双因素验证,如果需要关闭,请输入双因素验证码,然后在禁用.如果忘记验证码,请联系管理员.", + "resetTwoFactor": "重置双因素验证" + }, + "role": { + "role": "角色", + "roleName": "角色名称", + "isDefault": "是否默认", + "permissions": "授权" + }, + "log": { + "loginTime": "登录时间", + "userName": "用户名", + "tenant": "租户", + "executionTime": "执行时间", + "responseTime": "响应时间(毫秒)", + "clientIp": "客户端Ip", + "exception": "异常", + "applicationName": "应用名称", + "loginMode": "登录方式", + "loginUrl": "登录地址", + "detail": "详情" + }, + "message": { + "title": "标题", + "content": "内容", + "type": "类型", + "level": "级别", + "sender": "发送人", + "receiver": "接收人", + "isRead": "是否已读", + "sendMessage": "发送消息", + "sendNotification": "发送通告", + "setRead": "设置已读", + "confirmRead": "确认设置已读?", + "read": "已读", + "unread": "未读" + }, + "language": { + "language": "语言名称", + "showLanguage": "显示名称", + "icon": "图标", + "resourceName": "资源名称", + "value": "值", + "name": "名称" + }, + "dataDictionary": { + "codeName": "编码|名称", + "code": "编码", + "name": "名称", + "order": "排序", + "status": "状态", + "description": "描述", + "type": "字典类型" + }, + "organizationunit": { + "organizationunit": "组织机构", + "add": "新增根机构", + "member": "成员", + "role": "角色", + "userName": "用户名", + "email": "邮箱", + "name": "名称", + "selectNode": "请先选择一个节点再进行操作" + }, + "tenant": { + "tenant": "租户", + "notExist": "租户不存在", + "name": "租户名称", + "adminEmail": "管理员邮箱", + "adminPassword": "管理员密码", + "mangeConnectionString": "管理链接字符串", + "addorEdit": "新增或编辑", + "featureManagement": "功能管理", + "connectionStringName": "连接名称", + "connectionString": "连接字符串" + } +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/code.json b/apps/web-antd/src/locales/langs/zh-CN/code.json new file mode 100644 index 0000000..1032454 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/code.json @@ -0,0 +1,37 @@ +{ + "companyName": "公司名称", + "projectName": "项目名称", + "projectEnglishName": "项目英文名称", + "namespace": "命名空间", + "remark": "备注", + "templateName": "模板名称", + "model": "模型", + "property": "属性", + "enum": "枚举", + "isRequired": "是否必填", + "maxLength": "最大长度", + "minLength": "最小长度", + "decimalPrecision18": "精度(18,6)中的18", + "decimalPrecision6": "精度(18,6)中的6", + "pleaseSelectEntity": "请选择实体", + "pleaseSelectEnum": "请选择枚举", + "detail": "详情", + "copy": "复制", + "addFolder": "新增文件夹", + "addFile": "新增文件", + "desc": "描述", + "name": "名称", + "templateType": "模板类型", + "supportTenant": "支持多租户", + "project": "项目", + "template": "模板", + "preview": "预览", + "download": "下载", + "description": "请选择要生成的目标和项目", + "autoGenerate": "自动生成代码", + "code": "编码", + "type": "类型", + "value": "值", + "relational": "关系", + "dataType": "数据类型" +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/common.json b/apps/web-antd/src/locales/langs/zh-CN/common.json new file mode 100644 index 0000000..fa46172 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/common.json @@ -0,0 +1,39 @@ +{ + "add": "新增", + "edit": "编辑", + "delete": "删除", + "search": "搜索", + "save": "保存", + "export": "导出", + "isEnable": "是否启用", + "enabled": "启用", + "disabled": "禁用", + "seq": "序号", + "action": "操作", + "createTime": "创建时间", + "pleaseInput": "请输入", + "addSuccess": "新增成功!", + "editSuccess": "编辑成功!", + "deleteSuccess": "删除成功!", + "yes": "是", + "no": "否", + "confirmDelete": "确认删除", + "askConfirmDelete": "确认删除吗?", + "warning": "警告", + "info": "正常", + "error": "错误", + "success": "成功", + "keyword": "关键字", + "mesage403": "您没有权限访问此页面或功能!", + "mesage401": "未登录或登录已超时,请重新登录!", + "mesage500": "服务器内部错误!", + "mesage404": "您访问的页面不存在!", + "mesage400": "请求错误!", + "mesage405": "请求方法错误!", + "timeOut": "请求超时!", + "expandAll": "展开全部", + "collapseAll": "折叠全部", + "description": "描述", + "comfirm": "确认", + "valid": "验证" +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/page.json b/apps/web-antd/src/locales/langs/zh-CN/page.json new file mode 100644 index 0000000..39a4f45 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/page.json @@ -0,0 +1,15 @@ +{ + "auth": { + "login": "登录", + "register": "注册", + "codeLogin": "验证码登录", + "qrcodeLogin": "二维码登录", + "forgetPassword": "忘记密码", + "thirdPartyLogin": "第三方登录" + }, + "dashboard": { + "title": "概览", + "analytics": "分析页", + "workspace": "工作台" + } +} diff --git a/apps/web-antd/src/main.ts b/apps/web-antd/src/main.ts new file mode 100644 index 0000000..18a0409 --- /dev/null +++ b/apps/web-antd/src/main.ts @@ -0,0 +1,35 @@ +import { initPreferences } from '@vben/preferences'; +import { unmountGlobalLoading } from '@vben/utils'; + +import { overridesPreferences } from './preferences'; +// eslint-disable-next-line unused-imports/no-unused-imports +import client from '#/api-client-config/index'; +// eslint-disable-next-line unused-imports/no-unused-imports +import clientblob from '#/api-client-config/index-blob'; + +/** + * 应用初始化完成之后再进行页面加载渲染 + */ +async function initApplication() { + // name用于指定项目唯一标识 + // 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据 + const env = import.meta.env.PROD ? 'prod' : 'dev'; + const appVersion = import.meta.env.VITE_APP_VERSION; + const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`; + + // app偏好设置初始化 + await initPreferences({ + namespace, + overrides: overridesPreferences, + }); + + // 启动应用并挂载 + // vue应用主要逻辑及视图 + const { bootstrap } = await import('./bootstrap'); + await bootstrap(namespace); + + // 移除并销毁loading + unmountGlobalLoading(); +} + +initApplication(); diff --git a/apps/web-antd/src/preferences.ts b/apps/web-antd/src/preferences.ts new file mode 100644 index 0000000..0f10284 --- /dev/null +++ b/apps/web-antd/src/preferences.ts @@ -0,0 +1,23 @@ +import { defineOverridesPreferences } from '@vben/preferences'; + +/** + * @description 项目配置文件 + * 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置 + * !!! 更改配置后请清空缓存,否则可能不生效 + */ +export const overridesPreferences = defineOverridesPreferences({ + // overrides + app: { + name: import.meta.env.VITE_APP_TITLE, + // 是否开启检查更新 + enableCheckUpdates: false, + // 检查更新的时间间隔,单位为分钟 + checkUpdatesInterval: 1, + }, + theme: { + mode: 'light', + }, + copyright: { + companyName: '集社', + }, +}); diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts new file mode 100644 index 0000000..3a48be2 --- /dev/null +++ b/apps/web-antd/src/router/access.ts @@ -0,0 +1,42 @@ +import type { + ComponentRecordType, + GenerateMenuAndRoutesOptions, +} from '@vben/types'; + +import { generateAccessible } from '@vben/access'; +import { preferences } from '@vben/preferences'; + +import { message } from 'ant-design-vue'; + +import { getAllMenusApi } from '#/api'; +import { BasicLayout, IFrameView } from '#/layouts'; +import { $t } from '#/locales'; + +const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue'); + +async function generateAccess(options: GenerateMenuAndRoutesOptions) { + const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue'); + + const layoutMap: ComponentRecordType = { + BasicLayout, + IFrameView, + }; + + return await generateAccessible(preferences.app.accessMode, { + ...options, + fetchMenuListAsync: async () => { + message.loading({ + content: `${$t('common.loadingMenu')}...`, + duration: 1.5, + }); + return await getAllMenusApi(); + }, + // 可以指定没有权限跳转403页面 + forbiddenComponent, + // 如果 route.meta.menuVisibleWithForbidden = true + layoutMap, + pageMap, + }); +} + +export { generateAccess }; diff --git a/apps/web-antd/src/router/guard.ts b/apps/web-antd/src/router/guard.ts new file mode 100644 index 0000000..503621d --- /dev/null +++ b/apps/web-antd/src/router/guard.ts @@ -0,0 +1,138 @@ +import type { Router } from 'vue-router'; + +import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; +import { preferences } from '@vben/preferences'; +import { useAccessStore, useUserStore } from '@vben/stores'; +import { startProgress, stopProgress } from '@vben/utils'; + +import { accessRoutes, coreRouteNames } from '#/router/routes'; +import { useAuthStore } from '#/store'; + +import { generateAccess } from './access'; + +/** + * 通用守卫配置 + * @param router + */ +function setupCommonGuard(router: Router) { + // 记录已经加载的页面 + const loadedPaths = new Set(); + + router.beforeEach(async (to) => { + to.meta.loaded = loadedPaths.has(to.path); + + // 页面加载进度条 + if (!to.meta.loaded && preferences.transition.progress) { + startProgress(); + } + return true; + }); + + router.afterEach((to) => { + // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行 + + loadedPaths.add(to.path); + + // 关闭页面加载进度条 + if (preferences.transition.progress) { + stopProgress(); + } + }); +} + +/** + * 权限访问守卫配置 + * @param router + */ +function setupAccessGuard(router: Router) { + router.beforeEach(async (to, from) => { + const accessStore = useAccessStore(); + const userStore = useUserStore(); + const authStore = useAuthStore(); + + // 基本路由,这些路由不需要进入权限拦截 + if (coreRouteNames.includes(to.name as string)) { + if (to.path === LOGIN_PATH && accessStore.accessToken) { + return decodeURIComponent( + (to.query?.redirect as string) || + userStore.userInfo?.homePath || + DEFAULT_HOME_PATH, + ); + } + return true; + } + + // accessToken 检查 + if (!accessStore.accessToken) { + // 明确声明忽略权限访问权限,则可以访问 + if (to.meta.ignoreAccess) { + return true; + } + + // 没有访问权限,跳转登录页面 + if (to.fullPath !== LOGIN_PATH) { + return { + path: LOGIN_PATH, + // 如不需要,直接删除 query + query: + to.fullPath === DEFAULT_HOME_PATH + ? {} + : { redirect: encodeURIComponent(to.fullPath) }, + // 携带当前跳转的页面,登录后重新跳转该页面 + replace: true, + }; + } + return to; + } + + // 是否已经生成过动态路由 + if (accessStore.isAccessChecked) { + return true; + } + // 生成路由表 + // 当前登录用户拥有的角色标识列表 + // const userInfo = userStore.userInfo || (await authStore.fetchUserInfo()); + // const userRoles = userInfo.roles ?? []; + const refreshCount = userStore?.applicationInfo?.refreshCount ?? -1; + if (import.meta.env.VITE_REFRESH_ROLE && refreshCount > 0) { + await authStore.getApplicationConfiguration(); + } + + const userRoles = accessStore.accessCodes ?? []; + + // 生成菜单和路由 + const { accessibleMenus, accessibleRoutes } = await generateAccess({ + roles: userRoles, + router, + // 则会在菜单中显示,但是访问会被重定向到403 + routes: accessRoutes, + }); + + // 保存菜单信息和路由信息 + accessStore.setAccessMenus(accessibleMenus); + accessStore.setAccessRoutes(accessibleRoutes); + accessStore.setIsAccessChecked(true); + const redirectPath = (from.query.redirect ?? + (to.path === DEFAULT_HOME_PATH + ? DEFAULT_HOME_PATH + : to.fullPath)) as string; + + return { + ...router.resolve(decodeURIComponent(redirectPath)), + replace: true, + }; + }); +} + +/** + * 项目守卫配置 + * @param router + */ +function createRouterGuard(router: Router) { + /** 通用 */ + setupCommonGuard(router); + /** 权限访问 */ + setupAccessGuard(router); +} + +export { createRouterGuard }; diff --git a/apps/web-antd/src/router/index.ts b/apps/web-antd/src/router/index.ts new file mode 100644 index 0000000..4840230 --- /dev/null +++ b/apps/web-antd/src/router/index.ts @@ -0,0 +1,37 @@ +import { + createRouter, + createWebHashHistory, + createWebHistory, +} from 'vue-router'; + +import { resetStaticRoutes } from '@vben/utils'; + +import { createRouterGuard } from './guard'; +import { routes } from './routes'; + +/** + * @zh_CN 创建vue-router实例 + */ +const router = createRouter({ + history: + import.meta.env.VITE_ROUTER_HISTORY === 'hash' + ? createWebHashHistory(import.meta.env.VITE_BASE) + : createWebHistory(import.meta.env.VITE_BASE), + // 应该添加到路由的初始路由列表。 + routes, + scrollBehavior: (to, _from, savedPosition) => { + if (savedPosition) { + return savedPosition; + } + return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 }; + }, + // 是否应该禁止尾部斜杠。 + // strict: true, +}); + +const resetRoutes = () => resetStaticRoutes(router, routes); + +// 创建路由守卫 +createRouterGuard(router); + +export { resetRoutes, router }; diff --git a/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts new file mode 100644 index 0000000..7218da2 --- /dev/null +++ b/apps/web-antd/src/router/routes/core.ts @@ -0,0 +1,96 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; + +import { AuthPageLayout, BasicLayout } from '#/layouts'; +import { $t } from '#/locales'; +import Login from '#/views/_core/authentication/login.vue'; + +/** 全局404页面 */ +const fallbackNotFoundRoute: RouteRecordRaw = { + component: () => import('#/views/_core/fallback/not-found.vue'), + meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, + title: '404', + }, + name: 'FallbackNotFound', + path: '/:path(.*)*', +}; + +/** 基本路由,这些路由是必须存在的 */ +const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ + { + component: BasicLayout, + meta: { + hideInBreadcrumb: true, + title: 'Root', + }, + name: 'Root', + path: '/', + redirect: DEFAULT_HOME_PATH, + children: [], + }, + { + component: AuthPageLayout, + meta: { + hideInTab: true, + title: 'Authentication', + }, + name: 'Authentication', + path: '/auth', + redirect: LOGIN_PATH, + children: [ + { + name: 'Login', + path: 'login', + component: Login, + meta: { + title: $t('page.auth.login'), + }, + }, + { + name: 'CodeLogin', + path: 'code-login', + component: () => import('#/views/_core/authentication/code-login.vue'), + meta: { + title: $t('page.auth.codeLogin'), + }, + }, + { + name: 'QrCodeLogin', + path: 'qrcode-login', + component: () => + import('#/views/_core/authentication/qrcode-login.vue'), + meta: { + title: $t('page.auth.qrcodeLogin'), + }, + }, + { + name: 'ForgetPassword', + path: 'forget-password', + component: () => + import('#/views/_core/authentication/forget-password.vue'), + meta: { + title: $t('page.auth.forgetPassword'), + }, + }, + { + name: 'Register', + path: 'register', + component: () => import('#/views/_core/authentication/register.vue'), + meta: { + title: $t('page.auth.register'), + }, + }, + ], + }, +]; + +export { coreRoutes, fallbackNotFoundRoute }; diff --git a/apps/web-antd/src/router/routes/index.ts b/apps/web-antd/src/router/routes/index.ts new file mode 100644 index 0000000..e6fb144 --- /dev/null +++ b/apps/web-antd/src/router/routes/index.ts @@ -0,0 +1,37 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { mergeRouteModules, traverseTreeValues } from '@vben/utils'; + +import { coreRoutes, fallbackNotFoundRoute } from './core'; + +const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', { + eager: true, +}); + +// 有需要可以自行打开注释,并创建文件夹 +// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true }); +// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true }); + +/** 动态路由 */ +const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles); + +/** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统(不会显示在菜单中) */ +// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles); +// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles); +const staticRoutes: RouteRecordRaw[] = []; +const externalRoutes: RouteRecordRaw[] = []; + +/** 路由列表,由基本路由、外部路由和404兜底路由组成 + * 无需走权限验证(会一直显示在菜单中) */ +const routes: RouteRecordRaw[] = [ + ...coreRoutes, + ...externalRoutes, + fallbackNotFoundRoute, +]; + +/** 基本路由列表,这些路由不需要进入权限拦截 */ +const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name); + +/** 有权限校验的路由列表,包含动态路由和静态路由 */ +const accessRoutes = [...dynamicRoutes, ...staticRoutes]; +export { accessRoutes, coreRouteNames, routes }; diff --git a/apps/web-antd/src/router/routes/modules/dashboard.ts b/apps/web-antd/src/router/routes/modules/dashboard.ts new file mode 100644 index 0000000..5254dc6 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/dashboard.ts @@ -0,0 +1,38 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + meta: { + icon: 'lucide:layout-dashboard', + order: -1, + title: $t('page.dashboard.title'), + }, + name: 'Dashboard', + path: '/dashboard', + children: [ + { + name: 'Analytics', + path: '/analytics', + component: () => import('#/views/dashboard/analytics/index.vue'), + meta: { + affixTab: true, + icon: 'lucide:area-chart', + title: $t('page.dashboard.analytics'), + }, + }, + { + name: 'Workspace', + path: '/workspace', + component: () => import('#/views/dashboard/workspace/index.vue'), + meta: { + icon: 'carbon:workspace', + title: $t('page.dashboard.workspace'), + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/modules/system.ts b/apps/web-antd/src/router/routes/modules/system.ts new file mode 100644 index 0000000..b30e603 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/system.ts @@ -0,0 +1,144 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { BasicLayout } from '#/layouts'; +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'lucide:layout-dashboard', + order: 1, + title: $t('abp.menu.system'), + authority: ['AbpIdentity'], + }, + name: 'system', + path: '/system', + children: [ + { + name: 'abpUser', + path: 'user', + component: () => import('#/views/system/abpuser/index.vue'), + meta: { + // affixTab: true, + icon: 'ph:user', + title: $t('abp.menu.user'), + authority: ['AbpIdentity.Users'], + }, + }, + { + name: 'abpRole', + path: 'role', + component: () => import('#/views/system/abprole/index.vue'), + meta: { + icon: 'oui:app-users-roles', + title: $t('abp.menu.role'), + authority: ['AbpIdentity.Roles'], + }, + }, + { + name: 'OrganizationUnit', + path: 'organizationUnit', + component: () => import('#/views/system/abporganizationunit/index.vue'), + meta: { + title: $t('abp.menu.organizationUnit'), + authority: ['AbpIdentity.OrganizationUnitManagement'], + icon: 'ant-design:team-outlined', + }, + }, + { + name: 'abpSetting', + path: 'setting', + component: () => import('#/views/system/abpsetting/index.vue'), + meta: { + icon: 'uil:setting', + title: $t('abp.menu.setting'), + authority: ['AbpIdentity.Setting'], + }, + }, + { + name: 'abpfeature', + path: 'Feature', + component: () => import('#/views/system/abpfeature/index.vue'), + meta: { + icon: 'ant-design:tool-outlined', + title: $t('abp.menu.feature'), + authority: ['AbpIdentity.FeatureManagement'], + }, + }, + { + name: 'AbpAuditLog', + path: 'auditlog', + component: () => import('#/views/system/abplog/audit.vue'), + meta: { + title: $t('abp.menu.auditLog'), + authority: ['AbpIdentity.AuditLog'], + icon: 'ant-design:snippets-twotone', + }, + }, + { + name: 'AbpLoginLog', + path: 'loginlog', + component: () => import('#/views/system/abplog/login.vue'), + meta: { + title: $t('abp.menu.loginLog'), + authority: ['AbpIdentity.IdentitySecurityLogs'], + icon: 'ant-design:file-protect-outlined', + }, + }, + { + name: 'AboLanguage', + path: 'language', + component: () => import('#/views/system/abplanguage/language.vue'), + meta: { + title: $t('abp.menu.language'), + authority: ['AbpIdentity.Languages'], + icon: 'ant-design:read-outlined', + }, + }, + { + name: 'AboLanguageText', + path: 'languagetext', + component: () => import('#/views/system/abplanguage/languagetext.vue'), + meta: { + title: $t('abp.menu.languageText'), + authority: ['AbpIdentity.LanguageTexts'], + icon: 'ant-design:font-size-outlined', + }, + }, + { + name: 'DataDictionary', + path: 'data-dictionary', + component: () => import('#/views/system/abpdatadictionary/index.vue'), + meta: { + title: $t('abp.menu.dataDictionary'), + authority: ['AbpIdentity.DataDictionaryManagement'], + icon: 'ant-design:table-outlined', + }, + }, + { + name: 'AbpNotification', + path: 'notification', + component: () => + import('#/views/system/abpnotification/notification.vue'), + meta: { + title: $t('abp.menu.notification'), + authority: ['AbpIdentity.NotificationSubscriptionManagement'], + icon: 'ant-design:comment-outlined', + }, + }, + { + name: 'AbpMessage', + path: 'message', + component: () => import('#/views/system/abpnotification/message.vue'), + meta: { + title: $t('abp.menu.message'), + authority: ['AbpIdentity.NotificationManagement'], + icon: 'ant-design:customer-service-twotone', + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/modules/tenant.ts b/apps/web-antd/src/router/routes/modules/tenant.ts new file mode 100644 index 0000000..1555f18 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/tenant.ts @@ -0,0 +1,32 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { BasicLayout } from '#/layouts'; +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'ant-design:switcher-filled', + order: 2, + title: $t('abp.menu.tenant'), + authority: ['AbpTenantManagement'], + }, + name: 'tenant', + path: '/tenant', + children: [ + { + name: 'abpTenant', + path: 'page', + component: () => import('#/views/system/abptenant/index.vue'), + meta: { + icon: 'ph:user', + title: $t('abp.menu.tenantList'), + authority: ['AbpTenantManagement.Tenants'], + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/store/auth.ts b/apps/web-antd/src/store/auth.ts new file mode 100644 index 0000000..6216976 --- /dev/null +++ b/apps/web-antd/src/store/auth.ts @@ -0,0 +1,152 @@ +import type { Recordable, UserInfo } from '@vben/types'; + +import { ref } from 'vue'; +import { useRouter } from 'vue-router'; + +import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; +import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; + +import { message as Message, notification } from 'ant-design-vue'; +import { defineStore } from 'pinia'; + +import { + type ApplicationAuthConfigurationDto, + type ApplicationConfigurationDto, + getApiAbpApplicationConfiguration, + postApiAppAccountLogin, + postTenantsFind, +} from '#/api-client'; +import { useSignalR } from '#/hooks/useSignalR'; +import { $t } from '#/locales'; + +export const useAuthStore = defineStore('auth', () => { + const accessStore = useAccessStore(); + const userStore = useUserStore(); + const router = useRouter(); + + const loginLoading = ref(false); + + /** + * 异步处理登录操作 + * Asynchronously handle the login process + * @param params 登录表单数据 + */ + async function authLogin( + params: Recordable, + onSuccess?: () => Promise | void, + ) { + // 异步处理用户登录操作并获取 accessToken + let userInfo: null | UserInfo = null; + + try { + loginLoading.value = true; + // 判断是否租户登录 + if (params.tenant) { + const tenantResult = await postTenantsFind({ + body: { + name: params.tenant, + }, + }); + + if (tenantResult.data?.success) { + userStore.setTenantInfo(tenantResult.data as any); + } else { + Message.error(`${params.tenant}$t('abp.tenant.notExist')`); + userStore.setTenantInfo(null); + delete params.tenant; + return; + } + } + + const { data = {} } = await postApiAppAccountLogin({ + body: { + ...params, + }, + }); + // 如果成功获取到 accessToken + if (data.token) { + accessStore.setAccessToken(data.token); + userInfo = data as any; + userStore.setUserInfo(userInfo as any); + await getApplicationConfiguration(); + if (accessStore.loginExpired) { + accessStore.setLoginExpired(false); + } else { + onSuccess + ? await onSuccess?.() + : await router.push(DEFAULT_HOME_PATH); + } + + if (userInfo?.userName) { + notification.success({ + description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.userName}`, + duration: 3, + message: $t('authentication.loginSuccess'), + }); + } + } + } catch { + userStore.setTenantInfo(null); + userStore.setUserInfo(null); + } finally { + loginLoading.value = false; + } + + return { + userInfo, + }; + } + + async function logout(redirect: boolean = true) { + try { + // await logoutApi(); + const { closeConnect } = useSignalR(); + closeConnect(); + } catch { + // 不做任何处理 + } + resetAllStores(); + accessStore.setLoginExpired(false); + + // 回登录页带上当前路由地址 + await router.replace({ + path: LOGIN_PATH, + query: redirect + ? { + redirect: encodeURIComponent(router.currentRoute.value.fullPath), + } + : {}, + }); + } + + async function fetchUserInfo() { + const userInfo: null | UserInfo = null; + // userInfo = await getUserInfoApi(); + // userStore.setUserInfo(userInfo); + return userInfo; + } + + function $reset() { + loginLoading.value = false; + } + + async function getApplicationConfiguration() { + const { data: authData } = await getApiAbpApplicationConfiguration({ + query: { IncludeLocalizationResources: false }, + }); + const { auth } = authData as ApplicationConfigurationDto; + const accessCodes = Object.keys( + (auth as ApplicationAuthConfigurationDto) + .grantedPolicies as unknown as Record, + ); + accessStore.setAccessCodes(accessCodes); + } + return { + $reset, + authLogin, + fetchUserInfo, + loginLoading, + logout, + getApplicationConfiguration, + }; +}); diff --git a/apps/web-antd/src/store/index.ts b/apps/web-antd/src/store/index.ts new file mode 100644 index 0000000..269586e --- /dev/null +++ b/apps/web-antd/src/store/index.ts @@ -0,0 +1 @@ +export * from './auth'; diff --git a/apps/web-antd/src/views/_core/README.md b/apps/web-antd/src/views/_core/README.md new file mode 100644 index 0000000..8248afe --- /dev/null +++ b/apps/web-antd/src/views/_core/README.md @@ -0,0 +1,3 @@ +# \_core + +此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。 diff --git a/apps/web-antd/src/views/_core/about/index.vue b/apps/web-antd/src/views/_core/about/index.vue new file mode 100644 index 0000000..0ee5243 --- /dev/null +++ b/apps/web-antd/src/views/_core/about/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/code-login.vue b/apps/web-antd/src/views/_core/authentication/code-login.vue new file mode 100644 index 0000000..acfd1fd --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/code-login.vue @@ -0,0 +1,69 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/forget-password.vue b/apps/web-antd/src/views/_core/authentication/forget-password.vue new file mode 100644 index 0000000..fef0d42 --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/forget-password.vue @@ -0,0 +1,43 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/login.vue b/apps/web-antd/src/views/_core/authentication/login.vue new file mode 100644 index 0000000..2e228ef --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/login.vue @@ -0,0 +1,76 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/qrcode-login.vue b/apps/web-antd/src/views/_core/authentication/qrcode-login.vue new file mode 100644 index 0000000..23f5f2d --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/qrcode-login.vue @@ -0,0 +1,10 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/register.vue b/apps/web-antd/src/views/_core/authentication/register.vue new file mode 100644 index 0000000..b1a5de7 --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/register.vue @@ -0,0 +1,96 @@ + + + diff --git a/apps/web-antd/src/views/_core/fallback/coming-soon.vue b/apps/web-antd/src/views/_core/fallback/coming-soon.vue new file mode 100644 index 0000000..f394930 --- /dev/null +++ b/apps/web-antd/src/views/_core/fallback/coming-soon.vue @@ -0,0 +1,7 @@ + + + diff --git a/apps/web-antd/src/views/_core/fallback/forbidden.vue b/apps/web-antd/src/views/_core/fallback/forbidden.vue new file mode 100644 index 0000000..8ea65fe --- /dev/null +++ b/apps/web-antd/src/views/_core/fallback/forbidden.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/_core/fallback/internal-error.vue b/apps/web-antd/src/views/_core/fallback/internal-error.vue new file mode 100644 index 0000000..819a47d --- /dev/null +++ b/apps/web-antd/src/views/_core/fallback/internal-error.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/_core/fallback/not-found.vue b/apps/web-antd/src/views/_core/fallback/not-found.vue new file mode 100644 index 0000000..4d178e9 --- /dev/null +++ b/apps/web-antd/src/views/_core/fallback/not-found.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/_core/fallback/offline.vue b/apps/web-antd/src/views/_core/fallback/offline.vue new file mode 100644 index 0000000..5de4a88 --- /dev/null +++ b/apps/web-antd/src/views/_core/fallback/offline.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue new file mode 100644 index 0000000..f1f0b23 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue @@ -0,0 +1,98 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue new file mode 100644 index 0000000..190fb41 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue new file mode 100644 index 0000000..02f5091 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue new file mode 100644 index 0000000..0915c7a --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue new file mode 100644 index 0000000..7e0f101 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue @@ -0,0 +1,55 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/analytics/index.vue b/apps/web-antd/src/views/dashboard/analytics/index.vue new file mode 100644 index 0000000..5e3d6d2 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/analytics/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/apps/web-antd/src/views/dashboard/workspace/index.vue b/apps/web-antd/src/views/dashboard/workspace/index.vue new file mode 100644 index 0000000..b95d613 --- /dev/null +++ b/apps/web-antd/src/views/dashboard/workspace/index.vue @@ -0,0 +1,266 @@ + + + diff --git a/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryDetailModal.vue b/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryDetailModal.vue new file mode 100644 index 0000000..1c9b055 --- /dev/null +++ b/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryDetailModal.vue @@ -0,0 +1,125 @@ + + diff --git a/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryModal.vue b/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryModal.vue new file mode 100644 index 0000000..5bc54f2 --- /dev/null +++ b/apps/web-antd/src/views/system/abpdatadictionary/DataDictionaryModal.vue @@ -0,0 +1,100 @@ + + diff --git a/apps/web-antd/src/views/system/abpdatadictionary/index.vue b/apps/web-antd/src/views/system/abpdatadictionary/index.vue new file mode 100644 index 0000000..5e73562 --- /dev/null +++ b/apps/web-antd/src/views/system/abpdatadictionary/index.vue @@ -0,0 +1,355 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abpfeature/index.vue b/apps/web-antd/src/views/system/abpfeature/index.vue new file mode 100644 index 0000000..feb74ba --- /dev/null +++ b/apps/web-antd/src/views/system/abpfeature/index.vue @@ -0,0 +1,134 @@ + + + diff --git a/apps/web-antd/src/views/system/abplanguage/AddLanguageTextModal.vue b/apps/web-antd/src/views/system/abplanguage/AddLanguageTextModal.vue new file mode 100644 index 0000000..98e47b4 --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/AddLanguageTextModal.vue @@ -0,0 +1,72 @@ + + diff --git a/apps/web-antd/src/views/system/abplanguage/EditLanguageTextModal.vue b/apps/web-antd/src/views/system/abplanguage/EditLanguageTextModal.vue new file mode 100644 index 0000000..047a55c --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/EditLanguageTextModal.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-antd/src/views/system/abplanguage/language.vue b/apps/web-antd/src/views/system/abplanguage/language.vue new file mode 100644 index 0000000..0da91c7 --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/language.vue @@ -0,0 +1,72 @@ + + + + diff --git a/apps/web-antd/src/views/system/abplanguage/languagetext.vue b/apps/web-antd/src/views/system/abplanguage/languagetext.vue new file mode 100644 index 0000000..6321861 --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/languagetext.vue @@ -0,0 +1,147 @@ + + + + diff --git a/apps/web-antd/src/views/system/abplanguage/schema.ts b/apps/web-antd/src/views/system/abplanguage/schema.ts new file mode 100644 index 0000000..58b6a3b --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/schema.ts @@ -0,0 +1,163 @@ +import { $t } from '@vben/locales'; + +export const languageQuerySchema: any = [ + { + component: 'Input', + fieldName: 'filter', + label: $t('common.keyword'), + }, +]; + +export const languageTableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'cultureName', title: $t('abp.language.language'), minWidth: '150' }, + { + field: 'displayName', + title: $t('abp.language.showLanguage'), + minWidth: '150', + }, + // { field: 'flagIcon', title: '图标', minWidth: '150' }, + { + field: 'isEnabled', + title: $t('common.isEnable'), + minWidth: '150', + slots: { default: 'isEnabled' }, + }, +]; + +export const languageTextQuerySchema: any = [ + { + component: 'VbenSelect', + fieldName: 'cultureName', + label: $t('abp.language.language'), + defaultValue: 'zh-Hans', + componentProps: { + options: [ + { + label: '简体中文', + value: 'zh-Hans', + }, + { + label: 'en', + value: 'en', + }, + ], + }, + }, + { + component: 'VbenSelect', + fieldName: 'resourceName', + label: $t('abp.language.resourceName'), + componentProps: { + options: [], + }, + }, + { + component: 'Input', + fieldName: 'filter', + label: $t('common.keyword'), + }, +]; + +export const languageTextTableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'name', title: $t('abp.language.name'), minWidth: '150' }, + { field: 'value', title: $t('abp.language.value'), minWidth: '150' }, + { + field: 'resourceName', + title: $t('abp.language.resourceName'), + minWidth: '150', + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '150', + slots: { default: 'action' }, + }, +]; + +export const addFormSchema: any = [ + { + component: 'VbenSelect', + fieldName: 'cultureName', + label: $t('abp.language.language'), + defaultValue: 'zh-Hans', + componentProps: { + options: [ + { + label: '简体中文', + value: 'zh-Hans', + }, + { + label: 'en', + value: 'en', + }, + ], + }, + }, + { + component: 'VbenSelect', + fieldName: 'resourceName', + label: $t('abp.language.resourceName'), + componentProps: { + options: [], + }, + }, + { + fieldName: 'name', + label: $t('abp.language.name'), + component: 'Input', + componentProps: {}, + }, + { + fieldName: 'value', + label: $t('abp.language.value'), + component: 'Input', + componentProps: {}, + }, +]; + +export const editFormSchema: any = [ + { + component: 'VbenSelect', + fieldName: 'cultureName', + label: $t('abp.language.language'), + defaultValue: 'zh-Hans', + componentProps: { + disabled: true, + options: [ + { + label: '简体中文', + value: 'zh-Hans', + }, + { + label: 'en', + value: 'en', + }, + ], + }, + }, + { + component: 'Input', + fieldName: 'resourceName', + label: $t('abp.language.resourceName'), + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'name', + label: $t('abp.language.name'), + component: 'Input', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'value', + label: $t('abp.language.value'), + component: 'Input', + componentProps: {}, + }, +]; diff --git a/apps/web-antd/src/views/system/abplog/audit.vue b/apps/web-antd/src/views/system/abplog/audit.vue new file mode 100644 index 0000000..ac2e8b9 --- /dev/null +++ b/apps/web-antd/src/views/system/abplog/audit.vue @@ -0,0 +1,82 @@ + + + + diff --git a/apps/web-antd/src/views/system/abplog/login.vue b/apps/web-antd/src/views/system/abplog/login.vue new file mode 100644 index 0000000..ce98ff8 --- /dev/null +++ b/apps/web-antd/src/views/system/abplog/login.vue @@ -0,0 +1,62 @@ + + + diff --git a/apps/web-antd/src/views/system/abplog/schema.ts b/apps/web-antd/src/views/system/abplog/schema.ts new file mode 100644 index 0000000..68ed2e6 --- /dev/null +++ b/apps/web-antd/src/views/system/abplog/schema.ts @@ -0,0 +1,114 @@ +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const logQuerySchema: any = [ + { + component: 'RangePicker', + fieldName: 'time', + label: $t('abp.log.loginTime'), + componentProps: { + 'value-format': 'YYYY-MM-DD', + }, + defaultValue: [ + dayjs().subtract(0, 'day').format('YYYY-MM-DD'), + dayjs().format('YYYY-MM-DD'), + ], + }, + { + component: 'Input', + fieldName: 'userName', + label: $t('abp.log.userName'), + }, + { + component: 'Input', + fieldName: 'correlationId', + label: 'CorrelationId', + }, +]; + +export const logTableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { + field: 'applicationName', + title: $t('abp.log.applicationName'), + minWidth: '150', + }, + { field: 'identity', title: $t('abp.log.loginMode'), minWidth: '150' }, + { field: 'action', title: $t('abp.log.loginUrl'), minWidth: '150' }, + { field: 'userName', title: $t('abp.log.userName'), minWidth: '150' }, + { field: 'correlationId', title: 'CorrelationId', minWidth: '150' }, + { field: 'clientIpAddress', title: $t('abp.log.clientIp'), minWidth: '150' }, + { + field: 'creationTime', + title: $t('common.createTime'), + minWidth: '150', + formatter: ({ cellValue }) => { + return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); + }, + }, +]; + +export const auditLogQuerySchema: any = [ + { + component: 'RangePicker', + fieldName: 'time', + label: $t('abp.log.executionTime'), + componentProps: { + 'value-format': 'YYYY-MM-DD', + }, + defaultValue: [ + dayjs().subtract(0, 'day').format('YYYY-MM-DD'), + dayjs().format('YYYY-MM-DD'), + ], + }, + { + component: 'Input', + fieldName: 'userName', + label: $t('abp.log.userName'), + }, + { + component: 'Input', + fieldName: 'correlationId', + label: 'CorrelationId', + }, + { + component: 'Input', + fieldName: 'url', + label: 'Url', + }, +]; + +export const auditLogTableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'url', title: 'Url', minWidth: '150' }, + { field: 'tenantName', title: $t('abp.log.tenant'), minWidth: '150' }, + { field: 'userName', title: $t('abp.log.userName'), minWidth: '150' }, + { + field: 'executionTime', + title: $t('abp.log.executionTime'), + minWidth: '150', + formatter: ({ cellValue }) => { + return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); + }, + }, + { + field: 'executionDuration', + title: $t('abp.log.responseTime'), + minWidth: '150', + }, + { + field: 'clientIpAddress', + title: $t('abp.log.clientIp'), + minWidth: '150', + }, + { field: 'correlationId', title: 'CorrelationId', minWidth: '150' }, + { field: 'exceptions', title: $t('abp.log.exception'), minWidth: '150' }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + width: 120, + }, +]; diff --git a/apps/web-antd/src/views/system/abpnotification/message.vue b/apps/web-antd/src/views/system/abpnotification/message.vue new file mode 100644 index 0000000..95df5c2 --- /dev/null +++ b/apps/web-antd/src/views/system/abpnotification/message.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abpnotification/notification.vue b/apps/web-antd/src/views/system/abpnotification/notification.vue new file mode 100644 index 0000000..698e08e --- /dev/null +++ b/apps/web-antd/src/views/system/abpnotification/notification.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abpnotification/schema.ts b/apps/web-antd/src/views/system/abpnotification/schema.ts new file mode 100644 index 0000000..0597680 --- /dev/null +++ b/apps/web-antd/src/views/system/abpnotification/schema.ts @@ -0,0 +1,284 @@ +import { z } from '@vben/common-ui'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const querySchema: any = [ + { + component: 'Input', + fieldName: 'messageType', + label: 'messageType', + defaultValue: 10, + dependencies: { + show: () => false, + triggerFields: ['messageType'], + }, + }, + { + component: 'Input', + fieldName: 'title', + label: $t('abp.message.title'), + }, + { + component: 'Input', + fieldName: 'content', + label: $t('abp.message.content'), + }, + { + component: 'Select', + fieldName: 'messageLevel', + label: $t('abp.message.level'), + width: 120, + componentProps: { + options: [ + { + label: $t('common.warning'), + value: 10, + }, + { + label: $t('common.info'), + value: 20, + }, + { + label: $t('common.error'), + value: 30, + }, + ], + }, + }, +]; +export const tableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'title', title: $t('abp.message.title'), minWidth: '150' }, + { field: 'content', title: $t('abp.message.content'), minWidth: '150' }, + { + field: 'messageLevelName', + title: $t('abp.message.level'), + minWidth: '150', + slots: { default: 'messageLevel' }, + }, + { field: 'senderUserName', title: $t('abp.message.sender'), minWidth: '150' }, + { + field: 'creationTime', + title: $t('common.createTime'), + width: '150', + formatter: ({ cellValue }) => { + return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); + }, + }, +]; + +export const addFormSchema: any = [ + { + component: 'Input', + componentProps: {}, + fieldName: 'title', + label: $t('abp.message.title'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.message.title') }), + }, + { + component: 'Textarea', + componentProps: {}, + fieldName: 'content', + label: $t('abp.message.content'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('abp.message.content'), + }), + }, + { + component: 'Select', + fieldName: 'messageLevel', + label: $t('abp.message.level'), + required: true, + defaultValue: 20, + componentProps: { + options: [ + { + label: $t('common.warning'), + value: 10, + }, + { + label: $t('common.info'), + value: 20, + }, + { + label: $t('common.error'), + value: 30, + }, + ], + }, + }, +]; + +export const addMessageFormSchema: any = [ + { + component: 'Input', + componentProps: {}, + fieldName: 'userName', + label: $t('abp.message.sender'), + rules: z.string().min(1, { message: '请输入接收人username' }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'title', + label: $t('abp.message.title'), + rules: z.string().min(1, { message: '请输入标题' }), + }, + { + component: 'Textarea', + componentProps: {}, + fieldName: 'content', + label: $t('abp.message.content'), + rules: z.string().min(1, { message: '请输入内容' }), + }, + { + component: 'Select', + fieldName: 'messageLevel', + label: $t('abp.message.level'), + required: true, + defaultValue: 20, + componentProps: { + options: [ + { + label: $t('common.warning'), + value: 10, + }, + { + label: $t('common.info'), + value: 20, + }, + { + label: $t('common.error'), + value: 30, + }, + ], + }, + }, +]; + +export const tableMessageSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'title', title: $t('abp.message.title'), minWidth: '150' }, + { field: 'content', title: $t('abp.message.content'), minWidth: '150' }, + // { field: 'messageTypeName', title: '类型', minWidth: '150' }, + { + field: 'messageLevelName', + title: $t('abp.message.level'), + minWidth: '150', + slots: { default: 'messageLevel' }, + }, + { + field: 'senderUserName', + title: $t('abp.message.receiver'), + minWidth: '150', + }, + { + field: 'receiveUserName', + title: $t('abp.message.sender'), + minWidth: '150', + }, + { + field: 'read', + title: $t('abp.message.isRead'), + minWidth: '150', + slots: { default: 'read' }, + }, + { + field: 'creationTime', + title: $t('common.createTime'), + minWidth: '150', + formatter: ({ cellValue }) => { + return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); + }, + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '150', + slots: { default: 'action' }, + }, +]; +export const queryMessageSchema: any = [ + { + component: 'Input', + fieldName: 'messageType', + label: 'messageType', + defaultValue: 20, + dependencies: { + show: () => false, + triggerFields: ['messageType'], + }, + }, + { + component: 'Input', + fieldName: 'title', + label: $t('abp.message.title'), + }, + { + component: 'Input', + fieldName: 'content', + label: $t('abp.message.content'), + }, + { + component: 'Select', + fieldName: 'messageLevel', + label: $t('abp.message.level'), + width: 120, + componentProps: { + options: [ + { + label: $t('common.warning'), + value: 10, + }, + { + label: $t('common.info'), + value: 20, + }, + { + label: $t('common.error'), + value: 30, + }, + ], + }, + }, + // { + // component: 'Select', + // fieldName: 'messageType', + // label: '类型', + // width: 120, + // componentProps: { + // options: [ + // { + // label: '广播消息', + // value: 10, + // }, + // { + // label: '普通文本消息', + // value: 20, + // }, + // ], + // }, + // }, + { + component: 'Select', + fieldName: 'read', + label: $t('abp.message.isRead'), + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, +]; diff --git a/apps/web-antd/src/views/system/abporganizationunit/ContextMenu.vue b/apps/web-antd/src/views/system/abporganizationunit/ContextMenu.vue new file mode 100644 index 0000000..e9b2c26 --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/ContextMenu.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abporganizationunit/OrgTreeAddModal.vue b/apps/web-antd/src/views/system/abporganizationunit/OrgTreeAddModal.vue new file mode 100644 index 0000000..44ee456 --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/OrgTreeAddModal.vue @@ -0,0 +1,83 @@ + + diff --git a/apps/web-antd/src/views/system/abporganizationunit/OrgTreeEditModal.vue b/apps/web-antd/src/views/system/abporganizationunit/OrgTreeEditModal.vue new file mode 100644 index 0000000..edc55fe --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/OrgTreeEditModal.vue @@ -0,0 +1,71 @@ + + diff --git a/apps/web-antd/src/views/system/abporganizationunit/index.vue b/apps/web-antd/src/views/system/abporganizationunit/index.vue new file mode 100644 index 0000000..4d82262 --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/index.vue @@ -0,0 +1,693 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abprole/index.vue b/apps/web-antd/src/views/system/abprole/index.vue new file mode 100644 index 0000000..24adc83 --- /dev/null +++ b/apps/web-antd/src/views/system/abprole/index.vue @@ -0,0 +1,337 @@ + + + + diff --git a/apps/web-antd/src/views/system/abprole/schema.ts b/apps/web-antd/src/views/system/abprole/schema.ts new file mode 100644 index 0000000..3468f5f --- /dev/null +++ b/apps/web-antd/src/views/system/abprole/schema.ts @@ -0,0 +1,62 @@ +import { z } from '@vben/common-ui'; + +import { $t } from '#/locales'; + +export const querySchema: any = [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.role.roleName'), + }, +]; + +export const tableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'name', title: $t('abp.role.roleName'), minWidth: '150' }, + { + field: 'isDefault', + title: $t('abp.role.isDefault'), + minWidth: '75', + slots: { default: 'isDefault' }, + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '200', + slots: { default: 'action' }, + }, +]; + +export const addRoleFormSchema: any = [ + { + component: 'Input', + componentProps: { + placeholder: $t('common.pleaseInput') + $t('abp.role.roleName'), + }, + fieldName: 'name', + label: $t('abp.role.roleName'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.role.roleName') }), + }, + { + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: 1, + }, + { + label: $t('common.no'), + value: 0, + }, + ], + }, + defaultValue: 0, + fieldName: 'isDefault', + label: $t('abp.role.isDefault'), + rules: 'required', + }, +]; diff --git a/apps/web-antd/src/views/system/abpsetting/index.vue b/apps/web-antd/src/views/system/abpsetting/index.vue new file mode 100644 index 0000000..5ec38b8 --- /dev/null +++ b/apps/web-antd/src/views/system/abpsetting/index.vue @@ -0,0 +1,138 @@ + + + diff --git a/apps/web-antd/src/views/system/abptenant/AddEditModal.vue b/apps/web-antd/src/views/system/abptenant/AddEditModal.vue new file mode 100644 index 0000000..d5fe9b3 --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/AddEditModal.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-antd/src/views/system/abptenant/ConnectionStringModal.vue b/apps/web-antd/src/views/system/abptenant/ConnectionStringModal.vue new file mode 100644 index 0000000..ec4b048 --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/ConnectionStringModal.vue @@ -0,0 +1,136 @@ + + diff --git a/apps/web-antd/src/views/system/abptenant/FeatureManageModal.vue b/apps/web-antd/src/views/system/abptenant/FeatureManageModal.vue new file mode 100644 index 0000000..c4d1423 --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/FeatureManageModal.vue @@ -0,0 +1,132 @@ + + diff --git a/apps/web-antd/src/views/system/abptenant/index.vue b/apps/web-antd/src/views/system/abptenant/index.vue new file mode 100644 index 0000000..0db681c --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/index.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abptenant/schema.ts b/apps/web-antd/src/views/system/abptenant/schema.ts new file mode 100644 index 0000000..a03ad85 --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/schema.ts @@ -0,0 +1,74 @@ +import { z } from '@vben/common-ui'; + +import { $t } from '#/locales'; + +export const querySchema: any = [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.tenant.name'), + }, +]; + +export const tableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'name', title: $t('abp.tenant.name'), minWidth: '150' }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '500', + slots: { default: 'action' }, + }, +]; + +export const addTenantFormSchema: any = [ + { + component: 'Input', + componentProps: {}, + fieldName: 'name', + label: $t('abp.tenant.name'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.tenant.name') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'adminEmailAddress', + label: $t('abp.tenant.adminEmail'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('abp.tenant.adminEmail'), + }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'adminPassword', + label: $t('abp.tenant.adminPassword'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('abp.tenant.adminPassword'), + }), + }, +]; + +export const editTenantFormSchemaEdit: any = [ + { + component: 'Input', + fieldName: 'id', + label: 'id', + dependencies: { + show: () => false, + triggerFields: ['id'], + }, + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'name', + label: $t('abp.tenant.name'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.tenant.name') }), + }, +]; diff --git a/apps/web-antd/src/views/system/abpuser/index.vue b/apps/web-antd/src/views/system/abpuser/index.vue new file mode 100644 index 0000000..1053c16 --- /dev/null +++ b/apps/web-antd/src/views/system/abpuser/index.vue @@ -0,0 +1,331 @@ + + + + + diff --git a/apps/web-antd/src/views/system/abpuser/schema.ts b/apps/web-antd/src/views/system/abpuser/schema.ts new file mode 100644 index 0000000..4d635c2 --- /dev/null +++ b/apps/web-antd/src/views/system/abpuser/schema.ts @@ -0,0 +1,166 @@ +import { z } from '@vben/common-ui'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const querySchema = [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.user.userName'), + }, +]; + +export const tableSchema: any = [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'userName', title: $t('abp.user.userName'), minWidth: '150' }, + { field: 'name', title: $t('abp.user.name'), minWidth: '150' }, + { field: 'email', title: $t('abp.user.email'), minWidth: '150' }, + { + field: 'isActive', + title: $t('abp.user.status'), + minWidth: '150', + slots: { default: 'isActive' }, + }, + { + field: 'twoFactorEnabled', + title: $t('abp.user.twoFactor'), + minWidth: '150', + slots: { default: 'twoFactorEnabled' }, + }, + { field: 'phoneNumber', title: $t('abp.user.phone'), minWidth: '150' }, + { + field: 'creationTime', + title: $t('common.createTime'), + minWidth: '150', + formatter: ({ cellValue }) => { + return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); + }, + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '150', + slots: { default: 'action' }, + }, +]; + +export const addUserFormSchema: any = [ + { + component: 'Input', + componentProps: {}, + fieldName: 'userName', + label: $t('abp.user.userName'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.userName') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'name', + label: $t('abp.user.name'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.name') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'email', + label: $t('abp.user.email'), + rules: z.string().email($t('common.pleaseInput') + $t('abp.user.email')), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'phoneNumber', + label: $t('abp.user.phone'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.phone') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'password', + label: $t('abp.user.password'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.password') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'confirmPassword', + label: $t('abp.user.comfirmPassword'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('abp.user.comfirmPassword'), + }), + }, +]; + +export const editUserFormSchemaEdit: any = [ + { + component: 'Input', + fieldName: 'isActive', + label: 'isActive', + dependencies: { + show: () => false, + triggerFields: ['isActive'], + }, + }, + { + component: 'Input', + componentProps: {}, + disabled: true, + fieldName: 'userName', + label: $t('abp.user.userName'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.userName') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'name', + label: $t('abp.user.name'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.name') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'email', + label: $t('abp.user.email'), + rules: z.string().email($t('common.pleaseInput') + $t('abp.user.email')), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'phoneNumber', + label: $t('abp.user.phone'), + rules: z + .string() + .min(1, { message: $t('common.pleaseInput') + $t('abp.user.phone') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'password', + label: $t('abp.user.password'), + // rules: z.string().min(1, { message: $t('common.pleaseInput') + $t('abp.user.password') }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'confirmPassword', + label: $t('abp.user.comfirmPassword'), + // rules: z + // .string() + // .min(1, { message: $t('common.pleaseInput') + $t('abp.user.comfirmPassword') }), + }, +]; diff --git a/apps/web-antd/tailwind.config.mjs b/apps/web-antd/tailwind.config.mjs new file mode 100644 index 0000000..f17f556 --- /dev/null +++ b/apps/web-antd/tailwind.config.mjs @@ -0,0 +1 @@ +export { default } from '@vben/tailwind-config'; diff --git a/apps/web-antd/tsconfig.json b/apps/web-antd/tsconfig.json new file mode 100644 index 0000000..02c287f --- /dev/null +++ b/apps/web-antd/tsconfig.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web-app.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "#/*": ["./src/*"] + } + }, + "references": [{ "path": "./tsconfig.node.json" }], + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/apps/web-antd/tsconfig.node.json b/apps/web-antd/tsconfig.node.json new file mode 100644 index 0000000..c2f0d86 --- /dev/null +++ b/apps/web-antd/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "noEmit": false + }, + "include": ["vite.config.mts"] +} diff --git a/apps/web-antd/vite.config.mts b/apps/web-antd/vite.config.mts new file mode 100644 index 0000000..7b9fe83 --- /dev/null +++ b/apps/web-antd/vite.config.mts @@ -0,0 +1,32 @@ +import { defineConfig } from '@vben/vite-config'; + +import { loadEnv } from 'vite'; + +export default defineConfig(async (config) => { + const { command, mode } = config as { command: string; mode: string }; + const env = loadEnv(mode, process.cwd()); + console.log(env, '-----------env', command); + return { + application: {}, + vite: { + server: { + proxy: { + '/proxy': { + changeOrigin: true, + rewrite: (path) => path.replace(/^\/proxy/, ''), + // mock代理目标地址 + target: env.VITE_APP_API_ADDRESS, + ws: true, + }, + // '/api': { + // changeOrigin: true, + // rewrite: (path) => path.replace(/^\/api/, ''), + // // mock代理目标地址 + // target: 'http://localhost:5320/api', + // ws: true, + // }, + }, + }, + }, + }; +}); diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..89545b4 --- /dev/null +++ b/cspell.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", + "version": "0.2", + "language": "en,en-US", + "allowCompoundWords": true, + "words": [ + "acmr", + "antd", + "antdv", + "astro", + "brotli", + "clsx", + "defu", + "demi", + "echarts", + "ependencies", + "esno", + "etag", + "execa", + "iconify", + "iconoir", + "intlify", + "lockb", + "lucide", + "minh", + "minw", + "mkdist", + "mockjs", + "naiveui", + "nocheck", + "noopener", + "noreferrer", + "nprogress", + "nuxt", + "pinia", + "prefixs", + "publint", + "qrcode", + "shadcn", + "sonner", + "sortablejs", + "styl", + "taze", + "ui-kit", + "uicons", + "unplugin", + "unref", + "vben", + "vbenjs", + "vite", + "vitejs", + "vitepress", + "vnode", + "vueuse", + "yxxx" + ], + "ignorePaths": [ + "**/node_modules/**", + "**/dist/**", + "**/*-dist/**", + "**/icons/**", + "pnpm-lock.yaml", + "**/*.log", + "**/*.test.ts", + "**/*.spec.ts", + "**/__tests__/**" + ] +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..b29b567 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,5 @@ +// @ts-check + +import { defineConfig } from '@vben/eslint-config'; + +export default defineConfig(); diff --git a/internal/lint-configs/commitlint-config/index.mjs b/internal/lint-configs/commitlint-config/index.mjs new file mode 100644 index 0000000..3d85439 --- /dev/null +++ b/internal/lint-configs/commitlint-config/index.mjs @@ -0,0 +1,153 @@ +import { execSync } from 'node:child_process'; + +import { getPackagesSync } from '@vben/node-utils'; + +const { packages } = getPackagesSync(); + +const allowedScopes = [ + ...packages.map((pkg) => pkg.packageJson.name), + 'project', + 'style', + 'lint', + 'ci', + 'dev', + 'deploy', + 'other', +]; + +// precomputed scope +const scopeComplete = execSync('git status --porcelain || true') + .toString() + .trim() + .split('\n') + .find((r) => ~r.indexOf('M src')) + ?.replace(/(\/)/g, '%%') + ?.match(/src%%((\w|-)*)/)?.[1] + ?.replace(/s$/, ''); + +/** + * @type {import('cz-git').UserConfig} + */ +const userConfig = { + extends: ['@commitlint/config-conventional'], + plugins: ['commitlint-plugin-function-rules'], + prompt: { + /** @use `pnpm commit :f` */ + alias: { + b: 'build: bump dependencies', + c: 'chore: update config', + f: 'docs: fix typos', + r: 'docs: update README', + s: 'style: update code format', + }, + allowCustomIssuePrefixs: false, + // scopes: [...scopes, 'mock'], + allowEmptyIssuePrefixs: false, + customScopesAlign: scopeComplete ? 'bottom' : 'top', + defaultScope: scopeComplete, + // English + typesAppend: [ + { name: 'workflow: workflow improvements', value: 'workflow' }, + { name: 'types: type definition file changes', value: 'types' }, + ], + + // 中英文对照版 + // messages: { + // type: '选择你要提交的类型 :', + // scope: '选择一个提交范围 (可选):', + // customScope: '请输入自定义的提交范围 :', + // subject: '填写简短精炼的变更描述 :\n', + // body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n', + // breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n', + // footerPrefixsSelect: '选择关联issue前缀 (可选):', + // customFooterPrefixs: '输入自定义issue前缀 :', + // footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', + // confirmCommit: '是否提交或修改commit ?', + // }, + // types: [ + // { value: 'feat', name: 'feat: 新增功能' }, + // { value: 'fix', name: 'fix: 修复缺陷' }, + // { value: 'docs', name: 'docs: 文档变更' }, + // { value: 'style', name: 'style: 代码格式' }, + // { value: 'refactor', name: 'refactor: 代码重构' }, + // { value: 'perf', name: 'perf: 性能优化' }, + // { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' }, + // { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' }, + // { value: 'ci', name: 'ci: 修改 CI 配置、脚本' }, + // { value: 'revert', name: 'revert: 回滚 commit' }, + // { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' }, + // { value: 'wip', name: 'wip: 正在开发中' }, + // { value: 'workflow', name: 'workflow: 工作流程改进' }, + // { value: 'types', name: 'types: 类型定义文件修改' }, + // ], + // emptyScopesAlias: 'empty: 不填写', + // customScopesAlias: 'custom: 自定义', + }, + rules: { + /** + * type[scope]: [function] description + * + * ^^^^^^^^^^^^^^ empty line. + * - Something here + */ + 'body-leading-blank': [2, 'always'], + /** + * type[scope]: [function] description + * + * - something here + * + * ^^^^^^^^^^^^^^ + */ + 'footer-leading-blank': [1, 'always'], + /** + * type[scope]: [function] description + * ^^^^^ + */ + 'function-rules/scope-enum': [ + 2, // level: error + 'always', + (parsed) => { + if (!parsed.scope || allowedScopes.includes(parsed.scope)) { + return [true]; + } + + return [false, `scope must be one of ${allowedScopes.join(', ')}`]; + }, + ], + /** + * type[scope]: [function] description [No more than 108 characters] + * ^^^^^ + */ + 'header-max-length': [2, 'always', 108], + + 'scope-enum': [0], + 'subject-case': [0], + 'subject-empty': [2, 'never'], + 'type-empty': [2, 'never'], + /** + * type[scope]: [function] description + * ^^^^ + */ + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'perf', + 'style', + 'docs', + 'test', + 'refactor', + 'build', + 'ci', + 'chore', + 'revert', + 'types', + 'release', + ], + ], + }, +}; + +export default userConfig; diff --git a/internal/lint-configs/commitlint-config/package.json b/internal/lint-configs/commitlint-config/package.json new file mode 100644 index 0000000..a1645bb --- /dev/null +++ b/internal/lint-configs/commitlint-config/package.json @@ -0,0 +1,33 @@ +{ + "name": "@vben/commitlint-config", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/lint-configs/commitlint-config" + }, + "license": "MIT", + "type": "module", + "files": [ + "dist" + ], + "main": "./index.mjs", + "module": "./index.mjs", + "exports": { + ".": { + "import": "./index.mjs", + "default": "./index.mjs" + } + }, + "dependencies": { + "@commitlint/cli": "catalog:", + "@commitlint/config-conventional": "catalog:", + "@vben/node-utils": "workspace:*", + "commitlint-plugin-function-rules": "catalog:", + "cz-git": "catalog:", + "czg": "catalog:" + } +} diff --git a/internal/lint-configs/eslint-config/build.config.ts b/internal/lint-configs/eslint-config/build.config.ts new file mode 100644 index 0000000..97e572c --- /dev/null +++ b/internal/lint-configs/eslint-config/build.config.ts @@ -0,0 +1,7 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index'], +}); diff --git a/internal/lint-configs/eslint-config/package.json b/internal/lint-configs/eslint-config/package.json new file mode 100644 index 0000000..12556ec --- /dev/null +++ b/internal/lint-configs/eslint-config/package.json @@ -0,0 +1,56 @@ +{ + "name": "@vben/eslint-config", + "version": "5.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/lint-configs/eslint-config" + }, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild --stub" + }, + "files": [ + "dist" + ], + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs" + } + }, + "dependencies": { + "eslint-config-turbo": "catalog:", + "eslint-plugin-command": "catalog:", + "eslint-plugin-import-x": "catalog:" + }, + "devDependencies": { + "@eslint/js": "catalog:", + "@types/eslint": "catalog:", + "@typescript-eslint/eslint-plugin": "catalog:", + "@typescript-eslint/parser": "catalog:", + "eslint": "catalog:", + "eslint-plugin-eslint-comments": "catalog:", + "eslint-plugin-jsdoc": "catalog:", + "eslint-plugin-jsonc": "catalog:", + "eslint-plugin-n": "catalog:", + "eslint-plugin-no-only-tests": "catalog:", + "eslint-plugin-perfectionist": "catalog:", + "eslint-plugin-prettier": "catalog:", + "eslint-plugin-regexp": "catalog:", + "eslint-plugin-unicorn": "catalog:", + "eslint-plugin-unused-imports": "catalog:", + "eslint-plugin-vitest": "catalog:", + "eslint-plugin-vue": "catalog:", + "globals": "catalog:", + "jsonc-eslint-parser": "catalog:", + "vue-eslint-parser": "catalog:" + } +} diff --git a/internal/lint-configs/eslint-config/src/configs/command.ts b/internal/lint-configs/eslint-config/src/configs/command.ts new file mode 100644 index 0000000..67651b2 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/command.ts @@ -0,0 +1,10 @@ +import createCommand from 'eslint-plugin-command/config'; + +export async function command() { + return [ + { + // @ts-expect-error - no types + ...createCommand(), + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/comments.ts b/internal/lint-configs/eslint-config/src/configs/comments.ts new file mode 100644 index 0000000..77ccd5d --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/comments.ts @@ -0,0 +1,24 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function comments(): Promise { + const [pluginComments] = await Promise.all([ + // @ts-expect-error - no types + interopDefault(import('eslint-plugin-eslint-comments')), + ] as const); + + return [ + { + plugins: { + 'eslint-comments': pluginComments, + }, + rules: { + 'eslint-comments/no-aggregating-enable': 'error', + 'eslint-comments/no-duplicate-disable': 'error', + 'eslint-comments/no-unlimited-disable': 'error', + 'eslint-comments/no-unused-enable': 'error', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/disableds.ts b/internal/lint-configs/eslint-config/src/configs/disableds.ts new file mode 100644 index 0000000..152b84c --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/disableds.ts @@ -0,0 +1,28 @@ +import type { Linter } from 'eslint'; + +export async function disableds(): Promise { + return [ + { + files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'], + name: 'disables/test', + rules: { + '@typescript-eslint/ban-ts-comment': 'off', + 'no-console': 'off', + }, + }, + { + files: ['**/*.d.ts'], + name: 'disables/dts', + rules: { + '@typescript-eslint/triple-slash-reference': 'off', + }, + }, + { + files: ['**/*.js', '**/*.mjs', '**/*.cjs'], + name: 'disables/js', + rules: { + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/ignores.ts b/internal/lint-configs/eslint-config/src/configs/ignores.ts new file mode 100644 index 0000000..136c956 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/ignores.ts @@ -0,0 +1,52 @@ +import type { Linter } from 'eslint'; + +export async function ignores(): Promise { + return [ + { + ignores: [ + '**/node_modules', + '**/dist', + '**/dist-*', + '**/*-dist', + '**/.husky', + '**/.nitro', + '**/.output', + '**/Dockerfile', + '**/package-lock.json', + '**/yarn.lock', + '**/pnpm-lock.yaml', + '**/bun.lockb', + '**/output', + '**/coverage', + '**/temp', + '**/.temp', + '**/tmp', + '**/.tmp', + '**/.history', + '**/.turbo', + '**/.nuxt', + '**/.next', + '**/.vercel', + '**/.changeset', + '**/.idea', + '**/.cache', + '**/.output', + '**/.vite-inspect', + + '**/CHANGELOG*.md', + '**/*.min.*', + '**/LICENSE*', + '**/__snapshots__', + '**/*.snap', + '**/fixtures/**', + '**/.vitepress/cache/**', + '**/auto-import?(s).d.ts', + '**/components.d.ts', + '**/vite.config.mts.*', + '**/*.sh', + '**/*.ttf', + '**/*.woff', + ], + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/import.ts b/internal/lint-configs/eslint-config/src/configs/import.ts new file mode 100644 index 0000000..ce6cf65 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/import.ts @@ -0,0 +1,25 @@ +import type { Linter } from 'eslint'; + +import * as pluginImport from 'eslint-plugin-import-x'; + +export async function importPluginConfig(): Promise { + return [ + { + plugins: { + // @ts-expect-error - This is a dynamic import + import: pluginImport, + }, + rules: { + 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], + 'import/first': 'error', + 'import/newline-after-import': 'error', + 'import/no-duplicates': 'error', + 'import/no-mutable-exports': 'error', + 'import/no-named-default': 'error', + 'import/no-self-import': 'error', + 'import/no-unresolved': 'off', + 'import/no-webpack-loader-syntax': 'error', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/index.ts b/internal/lint-configs/eslint-config/src/configs/index.ts new file mode 100644 index 0000000..c0284ef --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/index.ts @@ -0,0 +1,17 @@ +export * from './command'; +export * from './comments'; +export * from './disableds'; +export * from './ignores'; +export * from './import'; +export * from './javascript'; +export * from './jsdoc'; +export * from './jsonc'; +export * from './node'; +export * from './perfectionist'; +export * from './prettier'; +export * from './regexp'; +export * from './test'; +export * from './turbo'; +export * from './typescript'; +export * from './unicorn'; +export * from './vue'; diff --git a/internal/lint-configs/eslint-config/src/configs/javascript.ts b/internal/lint-configs/eslint-config/src/configs/javascript.ts new file mode 100644 index 0000000..f6b767f --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/javascript.ts @@ -0,0 +1,241 @@ +import type { Linter } from 'eslint'; + +import js from '@eslint/js'; +import pluginUnusedImports from 'eslint-plugin-unused-imports'; +import globals from 'globals'; + +export async function javascript(): Promise { + return [ + { + languageOptions: { + ecmaVersion: 'latest', + globals: { + ...globals.browser, + ...globals.es2021, + ...globals.node, + document: 'readonly', + navigator: 'readonly', + window: 'readonly', + }, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 'latest', + sourceType: 'module', + }, + sourceType: 'module', + }, + linterOptions: { + reportUnusedDisableDirectives: true, + }, + plugins: { + 'unused-imports': pluginUnusedImports, + }, + rules: { + ...js.configs.recommended.rules, + 'accessor-pairs': [ + 'error', + { enforceForClassMembers: true, setWithoutGet: true }, + ], + 'array-callback-return': 'error', + 'block-scoped-var': 'error', + 'constructor-super': 'error', + 'default-case-last': 'error', + 'dot-notation': ['error', { allowKeywords: true }], + eqeqeq: ['error', 'always'], + 'keyword-spacing': 'off', + + 'new-cap': [ + 'error', + { capIsNew: false, newIsCap: true, properties: true }, + ], + 'no-alert': 'error', + 'no-array-constructor': 'error', + 'no-async-promise-executor': 'error', + 'no-caller': 'error', + 'no-case-declarations': 'error', + 'no-class-assign': 'error', + 'no-compare-neg-zero': 'error', + 'no-cond-assign': ['error', 'always'], + 'no-console': ['error', { allow: ['warn', 'error'] }], + 'no-const-assign': 'error', + 'no-control-regex': 'error', + 'no-debugger': 'error', + 'no-delete-var': 'error', + 'no-dupe-args': 'error', + 'no-dupe-class-members': 'error', + 'no-dupe-keys': 'error', + 'no-duplicate-case': 'error', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-empty-character-class': 'error', + 'no-empty-function': 'off', + 'no-empty-pattern': 'error', + 'no-eval': 'error', + 'no-ex-assign': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-extra-boolean-cast': 'error', + 'no-fallthrough': 'error', + 'no-func-assign': 'error', + 'no-global-assign': 'error', + 'no-implied-eval': 'error', + 'no-import-assign': 'error', + 'no-invalid-regexp': 'error', + 'no-irregular-whitespace': 'error', + 'no-iterator': 'error', + 'no-labels': ['error', { allowLoop: false, allowSwitch: false }], + 'no-lone-blocks': 'error', + 'no-loss-of-precision': 'error', + 'no-misleading-character-class': 'error', + 'no-multi-str': 'error', + 'no-new': 'error', + 'no-new-func': 'error', + 'no-new-object': 'error', + 'no-new-symbol': 'error', + 'no-new-wrappers': 'error', + 'no-obj-calls': 'error', + 'no-octal': 'error', + 'no-octal-escape': 'error', + 'no-proto': 'error', + 'no-prototype-builtins': 'error', + 'no-redeclare': ['error', { builtinGlobals: false }], + 'no-regex-spaces': 'error', + 'no-restricted-globals': [ + 'error', + { message: 'Use `globalThis` instead.', name: 'global' }, + { message: 'Use `globalThis` instead.', name: 'self' }, + ], + 'no-restricted-properties': [ + 'error', + { + message: + 'Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.', + property: '__proto__', + }, + { + message: 'Use `Object.defineProperty` instead.', + property: '__defineGetter__', + }, + { + message: 'Use `Object.defineProperty` instead.', + property: '__defineSetter__', + }, + { + message: 'Use `Object.getOwnPropertyDescriptor` instead.', + property: '__lookupGetter__', + }, + { + message: 'Use `Object.getOwnPropertyDescriptor` instead.', + property: '__lookupSetter__', + }, + ], + 'no-restricted-syntax': [ + 'error', + 'DebuggerStatement', + 'LabeledStatement', + 'WithStatement', + 'TSEnumDeclaration[const=true]', + 'TSExportAssignment', + ], + 'no-self-assign': ['error', { props: true }], + 'no-self-compare': 'error', + 'no-sequences': 'error', + 'no-shadow-restricted-names': 'error', + 'no-sparse-arrays': 'error', + 'no-template-curly-in-string': 'error', + 'no-this-before-super': 'error', + 'no-throw-literal': 'error', + 'no-undef': 'off', + 'no-undef-init': 'error', + 'no-unexpected-multiline': 'error', + 'no-unmodified-loop-condition': 'error', + 'no-unneeded-ternary': ['error', { defaultAssignment: false }], + 'no-unreachable': 'error', + 'no-unreachable-loop': 'error', + 'no-unsafe-finally': 'error', + 'no-unsafe-negation': 'error', + 'no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTaggedTemplates: true, + allowTernary: true, + }, + ], + 'no-unused-vars': [ + 'error', + { + args: 'none', + caughtErrors: 'none', + ignoreRestSiblings: true, + vars: 'all', + }, + ], + 'no-use-before-define': [ + 'error', + { classes: false, functions: false, variables: true }, + ], + 'no-useless-backreference': 'error', + 'no-useless-call': 'error', + 'no-useless-catch': 'error', + 'no-useless-computed-key': 'error', + 'no-useless-constructor': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + 'no-with': 'error', + 'object-shorthand': [ + 'error', + 'always', + { avoidQuotes: true, ignoreConstructors: false }, + ], + 'one-var': ['error', { initialized: 'never' }], + 'prefer-arrow-callback': [ + 'error', + { + allowNamedFunctions: false, + allowUnboundThis: true, + }, + ], + 'prefer-const': [ + 'error', + { + destructuring: 'all', + ignoreReadBeforeAssign: true, + }, + ], + 'prefer-exponentiation-operator': 'error', + + 'prefer-promise-reject-errors': 'error', + 'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }], + 'prefer-rest-params': 'error', + 'prefer-spread': 'error', + 'prefer-template': 'error', + 'space-before-function-paren': 'off', + 'spaced-comment': 'error', + 'symbol-description': 'error', + 'unicode-bom': ['error', 'never'], + + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': [ + 'error', + { + args: 'after-used', + argsIgnorePattern: '^_', + vars: 'all', + varsIgnorePattern: '^_', + }, + ], + 'use-isnan': [ + 'error', + { enforceForIndexOf: true, enforceForSwitchCase: true }, + ], + 'valid-typeof': ['error', { requireStringLiterals: true }], + + 'vars-on-top': 'error', + yoda: ['error', 'never'], + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/jsdoc.ts b/internal/lint-configs/eslint-config/src/configs/jsdoc.ts new file mode 100644 index 0000000..1368197 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/jsdoc.ts @@ -0,0 +1,34 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function jsdoc(): Promise { + const [pluginJsdoc] = await Promise.all([ + interopDefault(import('eslint-plugin-jsdoc')), + ] as const); + + return [ + { + plugins: { + jsdoc: pluginJsdoc, + }, + rules: { + 'jsdoc/check-access': 'warn', + 'jsdoc/check-param-names': 'warn', + 'jsdoc/check-property-names': 'warn', + 'jsdoc/check-types': 'warn', + 'jsdoc/empty-tags': 'warn', + 'jsdoc/implements-on-classes': 'warn', + 'jsdoc/no-defaults': 'warn', + 'jsdoc/no-multi-asterisks': 'warn', + 'jsdoc/require-param-name': 'warn', + 'jsdoc/require-property': 'warn', + 'jsdoc/require-property-description': 'warn', + 'jsdoc/require-property-name': 'warn', + 'jsdoc/require-returns-check': 'warn', + 'jsdoc/require-returns-description': 'warn', + 'jsdoc/require-yields-check': 'warn', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/jsonc.ts b/internal/lint-configs/eslint-config/src/configs/jsonc.ts new file mode 100644 index 0000000..4072e4c --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/jsonc.ts @@ -0,0 +1,258 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function jsonc(): Promise { + const [pluginJsonc, parserJsonc] = await Promise.all([ + interopDefault(import('eslint-plugin-jsonc')), + interopDefault(import('jsonc-eslint-parser')), + ] as const); + + return [ + { + files: ['**/*.json', '**/*.json5', '**/*.jsonc', '*.code-workspace'], + languageOptions: { + parser: parserJsonc as any, + }, + plugins: { + jsonc: pluginJsonc as any, + }, + rules: { + 'jsonc/no-bigint-literals': 'error', + 'jsonc/no-binary-expression': 'error', + 'jsonc/no-binary-numeric-literals': 'error', + 'jsonc/no-dupe-keys': 'error', + 'jsonc/no-escape-sequence-in-identifier': 'error', + 'jsonc/no-floating-decimal': 'error', + 'jsonc/no-hexadecimal-numeric-literals': 'error', + 'jsonc/no-infinity': 'error', + 'jsonc/no-multi-str': 'error', + 'jsonc/no-nan': 'error', + 'jsonc/no-number-props': 'error', + 'jsonc/no-numeric-separators': 'error', + 'jsonc/no-octal': 'error', + 'jsonc/no-octal-escape': 'error', + 'jsonc/no-octal-numeric-literals': 'error', + 'jsonc/no-parenthesized': 'error', + 'jsonc/no-plus-sign': 'error', + 'jsonc/no-regexp-literals': 'error', + 'jsonc/no-sparse-arrays': 'error', + 'jsonc/no-template-literals': 'error', + 'jsonc/no-undefined-value': 'error', + 'jsonc/no-unicode-codepoint-escapes': 'error', + 'jsonc/no-useless-escape': 'error', + 'jsonc/space-unary-ops': 'error', + 'jsonc/valid-json-number': 'error', + 'jsonc/vue-custom-block/no-parsing-error': 'error', + }, + }, + sortTsconfig(), + sortPackageJson(), + ]; +} + +function sortPackageJson(): Linter.Config { + return { + files: ['**/package.json'], + rules: { + 'jsonc/sort-array-values': [ + 'error', + { + order: { type: 'asc' }, + pathPattern: '^files$|^pnpm.neverBuiltDependencies$', + }, + ], + 'jsonc/sort-keys': [ + 'error', + { + order: [ + 'name', + 'version', + 'description', + 'private', + 'keywords', + 'homepage', + 'bugs', + 'repository', + 'license', + 'author', + 'contributors', + 'categories', + 'funding', + 'type', + 'scripts', + 'files', + 'sideEffects', + 'bin', + 'main', + 'module', + 'unpkg', + 'jsdelivr', + 'types', + 'typesVersions', + 'imports', + 'exports', + 'publishConfig', + 'icon', + 'activationEvents', + 'contributes', + 'peerDependencies', + 'peerDependenciesMeta', + 'dependencies', + 'optionalDependencies', + 'devDependencies', + 'engines', + 'packageManager', + 'pnpm', + 'overrides', + 'resolutions', + 'husky', + 'simple-git-hooks', + 'lint-staged', + 'eslintConfig', + ], + pathPattern: '^$', + }, + { + order: { type: 'asc' }, + pathPattern: '^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$', + }, + { + order: { type: 'asc' }, + pathPattern: '^(?:resolutions|overrides|pnpm.overrides)$', + }, + { + order: ['types', 'import', 'require', 'default'], + pathPattern: '^exports.*$', + }, + ], + }, + }; +} + +function sortTsconfig(): Linter.Config { + return { + files: [ + '**/tsconfig.json', + '**/tsconfig.*.json', + 'internal/tsconfig/*.json', + ], + rules: { + 'jsonc/sort-keys': [ + 'error', + { + order: [ + 'extends', + 'compilerOptions', + 'references', + 'files', + 'include', + 'exclude', + ], + pathPattern: '^$', + }, + { + order: [ + /* Projects */ + 'incremental', + 'composite', + 'tsBuildInfoFile', + 'disableSourceOfProjectReferenceRedirect', + 'disableSolutionSearching', + 'disableReferencedProjectLoad', + /* Language and Environment */ + 'target', + 'jsx', + 'jsxFactory', + 'jsxFragmentFactory', + 'jsxImportSource', + 'lib', + 'moduleDetection', + 'noLib', + 'reactNamespace', + 'useDefineForClassFields', + 'emitDecoratorMetadata', + 'experimentalDecorators', + /* Modules */ + 'baseUrl', + 'rootDir', + 'rootDirs', + 'customConditions', + 'module', + 'moduleResolution', + 'moduleSuffixes', + 'noResolve', + 'paths', + 'resolveJsonModule', + 'resolvePackageJsonExports', + 'resolvePackageJsonImports', + 'typeRoots', + 'types', + 'allowArbitraryExtensions', + 'allowImportingTsExtensions', + 'allowUmdGlobalAccess', + /* JavaScript Support */ + 'allowJs', + 'checkJs', + 'maxNodeModuleJsDepth', + /* Type Checking */ + 'strict', + 'strictBindCallApply', + 'strictFunctionTypes', + 'strictNullChecks', + 'strictPropertyInitialization', + 'allowUnreachableCode', + 'allowUnusedLabels', + 'alwaysStrict', + 'exactOptionalPropertyTypes', + 'noFallthroughCasesInSwitch', + 'noImplicitAny', + 'noImplicitOverride', + 'noImplicitReturns', + 'noImplicitThis', + 'noPropertyAccessFromIndexSignature', + 'noUncheckedIndexedAccess', + 'noUnusedLocals', + 'noUnusedParameters', + 'useUnknownInCatchVariables', + /* Emit */ + 'declaration', + 'declarationDir', + 'declarationMap', + 'downlevelIteration', + 'emitBOM', + 'emitDeclarationOnly', + 'importHelpers', + 'importsNotUsedAsValues', + 'inlineSourceMap', + 'inlineSources', + 'mapRoot', + 'newLine', + 'noEmit', + 'noEmitHelpers', + 'noEmitOnError', + 'outDir', + 'outFile', + 'preserveConstEnums', + 'preserveValueImports', + 'removeComments', + 'sourceMap', + 'sourceRoot', + 'stripInternal', + /* Interop Constraints */ + 'allowSyntheticDefaultImports', + 'esModuleInterop', + 'forceConsistentCasingInFileNames', + 'isolatedModules', + 'preserveSymlinks', + 'verbatimModuleSyntax', + /* Completeness */ + 'skipDefaultLibCheck', + 'skipLibCheck', + ], + pathPattern: '^compilerOptions$', + }, + ], + }, + }; +} diff --git a/internal/lint-configs/eslint-config/src/configs/node.ts b/internal/lint-configs/eslint-config/src/configs/node.ts new file mode 100644 index 0000000..fa960d8 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/node.ts @@ -0,0 +1,57 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function node(): Promise { + const pluginNode = await interopDefault(import('eslint-plugin-n')); + + return [ + { + plugins: { + n: pluginNode, + }, + rules: { + 'n/handle-callback-err': ['error', '^(err|error)$'], + 'n/no-deprecated-api': 'error', + 'n/no-exports-assign': 'error', + 'n/no-extraneous-import': [ + 'error', + { + allowModules: [ + 'unbuild', + '@vben/vite-config', + 'vitest', + 'vite', + '@vue/test-utils', + '@vben/tailwind-config', + '@playwright/test', + ], + }, + ], + 'n/no-new-require': 'error', + 'n/no-path-concat': 'error', + // 'n/no-unpublished-import': 'off', + 'n/no-unsupported-features/es-syntax': [ + 'error', + { + ignores: [], + version: '>=18.0.0', + }, + ], + 'n/prefer-global/buffer': ['error', 'never'], + // 'n/no-missing-import': 'off', + 'n/prefer-global/process': ['error', 'never'], + 'n/process-exit-as-throw': 'error', + }, + }, + { + files: [ + 'scripts/**/*.?([cm])[jt]s?(x)', + 'internal/**/*.?([cm])[jt]s?(x)', + ], + rules: { + 'n/prefer-global/process': 'off', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/perfectionist.ts b/internal/lint-configs/eslint-config/src/configs/perfectionist.ts new file mode 100644 index 0000000..d4fd0bb --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/perfectionist.ts @@ -0,0 +1,89 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function perfectionist(): Promise { + const perfectionistPlugin = await interopDefault( + // @ts-expect-error - no types + import('eslint-plugin-perfectionist'), + ); + + return [ + perfectionistPlugin.configs['recommended-natural'], + { + rules: { + 'perfectionist/sort-exports': [ + 'error', + { + order: 'asc', + type: 'natural', + }, + ], + 'perfectionist/sort-imports': [ + 'error', + { + customGroups: { + type: { + 'vben-core-type': ['^@vben-core/.+'], + 'vben-type': ['^@vben/.+'], + 'vue-type': ['^vue$', '^vue-.+', '^@vue/.+'], + }, + value: { + vben: ['^@vben/.+'], + 'vben-core': ['^@vben-core/.+'], + vue: ['^vue$', '^vue-.+', '^@vue/.+'], + }, + }, + environment: 'node', + groups: [ + ['external-type', 'builtin-type', 'type'], + 'vue-type', + 'vben-type', + 'vben-core-type', + ['parent-type', 'sibling-type', 'index-type'], + ['internal-type'], + 'builtin', + 'vue', + 'vben', + 'vben-core', + 'external', + 'internal', + ['parent', 'sibling', 'index'], + 'side-effect', + 'side-effect-style', + 'style', + 'object', + 'unknown', + ], + internalPattern: ['^#/.+'], + newlinesBetween: 'always', + order: 'asc', + type: 'natural', + }, + ], + 'perfectionist/sort-modules': 'off', + 'perfectionist/sort-named-exports': [ + 'error', + { + order: 'asc', + type: 'natural', + }, + ], + 'perfectionist/sort-objects': [ + 'error', + { + customGroups: { + items: 'items', + list: 'list', + children: 'children', + }, + groups: ['unknown', 'items', 'list', 'children'], + ignorePattern: ['children'], + order: 'asc', + type: 'natural', + }, + ], + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/prettier.ts b/internal/lint-configs/eslint-config/src/configs/prettier.ts new file mode 100644 index 0000000..3cd7af4 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/prettier.ts @@ -0,0 +1,19 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function prettier(): Promise { + const [pluginPrettier] = await Promise.all([ + interopDefault(import('eslint-plugin-prettier')), + ] as const); + return [ + { + plugins: { + prettier: pluginPrettier, + }, + rules: { + 'prettier/prettier': 'error', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/regexp.ts b/internal/lint-configs/eslint-config/src/configs/regexp.ts new file mode 100644 index 0000000..c0f4c9f --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/regexp.ts @@ -0,0 +1,20 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function regexp(): Promise { + const [pluginRegexp] = await Promise.all([ + interopDefault(import('eslint-plugin-regexp')), + ] as const); + + return [ + { + plugins: { + regexp: pluginRegexp, + }, + rules: { + ...pluginRegexp.configs.recommended.rules, + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/test.ts b/internal/lint-configs/eslint-config/src/configs/test.ts new file mode 100644 index 0000000..ddfde2b --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/test.ts @@ -0,0 +1,45 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function test(): Promise { + const [pluginTest, pluginNoOnlyTests] = await Promise.all([ + interopDefault(import('eslint-plugin-vitest')), + // @ts-expect-error - no types + interopDefault(import('eslint-plugin-no-only-tests')), + ] as const); + + return [ + { + files: [ + `**/__tests__/**/*.?([cm])[jt]s?(x)`, + `**/*.spec.?([cm])[jt]s?(x)`, + `**/*.test.?([cm])[jt]s?(x)`, + `**/*.bench.?([cm])[jt]s?(x)`, + `**/*.benchmark.?([cm])[jt]s?(x)`, + ], + plugins: { + test: { + ...pluginTest, + rules: { + ...pluginTest.rules, + ...pluginNoOnlyTests.rules, + }, + }, + }, + rules: { + 'no-console': 'off', + 'node/prefer-global/process': 'off', + 'test/consistent-test-it': [ + 'error', + { fn: 'it', withinDescribe: 'it' }, + ], + 'test/no-identical-title': 'error', + 'test/no-import-node-test': 'error', + 'test/no-only-tests': 'error', + 'test/prefer-hooks-in-order': 'error', + 'test/prefer-lowercase-title': 'error', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/turbo.ts b/internal/lint-configs/eslint-config/src/configs/turbo.ts new file mode 100644 index 0000000..9f6bf75 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/turbo.ts @@ -0,0 +1,18 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function turbo(): Promise { + const [pluginTurbo] = await Promise.all([ + // @ts-expect-error - no types + interopDefault(import('eslint-config-turbo')), + ] as const); + + return [ + { + plugins: { + turbo: pluginTurbo, + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/typescript.ts b/internal/lint-configs/eslint-config/src/configs/typescript.ts new file mode 100644 index 0000000..cff9aa4 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/typescript.ts @@ -0,0 +1,72 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function typescript(): Promise { + const [pluginTs, parserTs] = await Promise.all([ + interopDefault(import('@typescript-eslint/eslint-plugin')), + // @ts-expect-error missing types + interopDefault(import('@typescript-eslint/parser')), + ] as const); + + return [ + { + files: ['**/*.?([cm])[jt]s?(x)'], + languageOptions: { + parser: parserTs, + parserOptions: { + createDefaultProgram: false, + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 'latest', + extraFileExtensions: ['.vue'], + jsxPragma: 'React', + project: './tsconfig.*.json', + sourceType: 'module', + }, + }, + plugins: { + '@typescript-eslint': pluginTs, + }, + rules: { + ...pluginTs.configs['eslint-recommended'].overrides?.[0].rules, + ...pluginTs.configs.strict.rules, + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-check': false, + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': 'allow-with-description', + 'ts-nocheck': 'allow-with-description', + }, + ], + + // '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-empty-function': [ + 'error', + { + allow: ['arrowFunctions', 'functions', 'methods'], + }, + ], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-var-requires': 'error', + 'unused-imports/no-unused-vars': 'off', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/unicorn.ts b/internal/lint-configs/eslint-config/src/configs/unicorn.ts new file mode 100644 index 0000000..21b1902 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/unicorn.ts @@ -0,0 +1,45 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function unicorn(): Promise { + const [pluginUnicorn] = await Promise.all([ + interopDefault(import('eslint-plugin-unicorn')), + ] as const); + + return [ + { + plugins: { + unicorn: pluginUnicorn, + }, + rules: { + ...pluginUnicorn.configs.recommended.rules, + + 'unicorn/better-regex': 'off', + 'unicorn/consistent-destructuring': 'off', + 'unicorn/consistent-function-scoping': 'off', + 'unicorn/expiring-todo-comments': 'off', + 'unicorn/filename-case': 'off', + 'unicorn/import-style': 'off', + 'unicorn/no-array-for-each': 'off', + 'unicorn/no-null': 'off', + 'unicorn/no-useless-undefined': 'off', + 'unicorn/prefer-at': 'off', + 'unicorn/prefer-dom-node-text-content': 'off', + 'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }], + 'unicorn/prefer-global-this': 'off', + 'unicorn/prefer-top-level-await': 'off', + 'unicorn/prevent-abbreviations': 'off', + }, + }, + { + files: [ + 'scripts/**/*.?([cm])[jt]s?(x)', + 'internal/**/*.?([cm])[jt]s?(x)', + ], + rules: { + 'unicorn/no-process-exit': 'off', + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/configs/vue.ts b/internal/lint-configs/eslint-config/src/configs/vue.ts new file mode 100644 index 0000000..d1c6521 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/vue.ts @@ -0,0 +1,149 @@ +import type { Linter } from 'eslint'; + +import { interopDefault } from '../util'; + +export async function vue(): Promise { + const [pluginVue, parserVue, parserTs] = await Promise.all([ + interopDefault(import('eslint-plugin-vue')), + interopDefault(import('vue-eslint-parser')), + // @ts-expect-error missing types + interopDefault(import('@typescript-eslint/parser')), + ] as const); + + return [ + { + files: ['**/*.vue'], + languageOptions: { + // globals: { + // computed: 'readonly', + // defineEmits: 'readonly', + // defineExpose: 'readonly', + // defineProps: 'readonly', + // onMounted: 'readonly', + // onUnmounted: 'readonly', + // reactive: 'readonly', + // ref: 'readonly', + // shallowReactive: 'readonly', + // shallowRef: 'readonly', + // toRef: 'readonly', + // toRefs: 'readonly', + // watch: 'readonly', + // watchEffect: 'readonly', + // }, + parser: parserVue, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + extraFileExtensions: ['.vue'], + parser: parserTs, + sourceType: 'module', + }, + }, + plugins: { + vue: pluginVue, + }, + processor: pluginVue.processors['.vue'], + rules: { + ...pluginVue.configs.base.rules, + ...pluginVue.configs['vue3-essential'].rules, + ...pluginVue.configs['vue3-strongly-recommended'].rules, + ...pluginVue.configs['vue3-recommended'].rules, + + 'vue/attribute-hyphenation': [ + 'error', + 'always', + { + ignore: [], + }, + ], + 'vue/attributes-order': 'off', + 'vue/block-order': [ + 'error', + { + order: ['script', 'template', 'style'], + }, + ], + 'vue/component-name-in-template-casing': ['error', 'PascalCase'], + 'vue/component-options-name-casing': ['error', 'PascalCase'], + 'vue/custom-event-name-casing': ['error', 'camelCase'], + 'vue/define-macros-order': [ + 'error', + { + order: [ + 'defineOptions', + 'defineProps', + 'defineEmits', + 'defineSlots', + ], + }, + ], + 'vue/dot-location': ['error', 'property'], + 'vue/dot-notation': ['error', { allowKeywords: true }], + 'vue/eqeqeq': ['error', 'smart'], + 'vue/html-closing-bracket-newline': 'error', + 'vue/html-indent': 'off', + // 'vue/html-indent': ['error', 2], + 'vue/html-quotes': ['error', 'double'], + 'vue/html-self-closing': [ + 'error', + { + html: { + component: 'always', + normal: 'never', + void: 'always', + }, + math: 'always', + svg: 'always', + }, + ], + 'vue/max-attributes-per-line': 'off', + 'vue/multi-word-component-names': 'off', + 'vue/multiline-html-element-content-newline': 'error', + 'vue/no-empty-pattern': 'error', + 'vue/no-extra-parens': ['error', 'functions'], + 'vue/no-irregular-whitespace': 'error', + 'vue/no-loss-of-precision': 'error', + 'vue/no-reserved-component-names': 'off', + 'vue/no-restricted-syntax': [ + 'error', + 'DebuggerStatement', + 'LabeledStatement', + 'WithStatement', + ], + 'vue/no-restricted-v-bind': ['error', '/^v-/'], + 'vue/no-sparse-arrays': 'error', + 'vue/no-unused-refs': 'error', + 'vue/no-useless-v-bind': 'error', + 'vue/object-shorthand': [ + 'error', + 'always', + { + avoidQuotes: true, + ignoreConstructors: false, + }, + ], + 'vue/one-component-per-file': 'error', + 'vue/prefer-import-from-vue': 'error', + 'vue/prefer-separate-static-class': 'error', + 'vue/prefer-template': 'error', + 'vue/prop-name-casing': ['error', 'camelCase'], + 'vue/require-default-prop': 'error', + 'vue/require-explicit-emits': 'error', + 'vue/require-prop-types': 'off', + 'vue/script-setup-uses-vars': 'error', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/space-infix-ops': 'error', + 'vue/space-unary-ops': ['error', { nonwords: false, words: true }], + 'vue/v-on-event-hyphenation': [ + 'error', + 'always', + { + autofix: true, + ignore: [], + }, + ], + }, + }, + ]; +} diff --git a/internal/lint-configs/eslint-config/src/custom-config.ts b/internal/lint-configs/eslint-config/src/custom-config.ts new file mode 100644 index 0000000..973df92 --- /dev/null +++ b/internal/lint-configs/eslint-config/src/custom-config.ts @@ -0,0 +1,161 @@ +import type { Linter } from 'eslint'; + +const restrictedImportIgnores = [ + '**/vite.config.mts', + '**/tailwind.config.mjs', + '**/postcss.config.mjs', +]; + +const customConfig: Linter.Config[] = [ + // shadcn-ui 内部组件是自动生成的,不做太多限制 + { + files: ['packages/@core/ui-kit/shadcn-ui/**/**'], + rules: { + 'vue/require-default-prop': 'off', + }, + }, + { + files: [ + 'apps/**/**', + 'packages/effects/**/**', + 'packages/utils/**/**', + 'packages/types/**/**', + 'packages/locales/**/**', + ], + ignores: restrictedImportIgnores, + rules: { + 'perfectionist/sort-interfaces': 'off', + 'perfectionist/sort-objects': 'off', + }, + }, + { + // apps内部的一些基础规则 + files: ['apps/**/**'], + ignores: restrictedImportIgnores, + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['#/api/*'], + message: + 'The #/api package cannot be imported, please use the @core package itself', + }, + { + group: ['#/layouts/*'], + message: + 'The #/layouts package cannot be imported, please use the @core package itself', + }, + { + group: ['#/locales/*'], + message: + 'The #/locales package cannot be imported, please use the @core package itself', + }, + { + group: ['#/stores/*'], + message: + 'The #/stores package cannot be imported, please use the @core package itself', + }, + ], + }, + ], + 'perfectionist/sort-interfaces': 'off', + }, + }, + { + // @core内部组件,不能引入@vben/* 里面的包 + files: ['packages/@core/**/**'], + ignores: restrictedImportIgnores, + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['@vben/*'], + message: + 'The @core package cannot import the @vben package, please use the @core package itself', + }, + ], + }, + ], + }, + }, + { + // @core/shared内部组件,不能引入@vben/* 或者 @vben-core/* 里面的包 + files: ['packages/@core/base/**/**'], + ignores: restrictedImportIgnores, + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['@vben/*', '@vben-core/*'], + message: + 'The @vben-core/shared package cannot import the @vben package, please use the @core/shared package itself', + }, + ], + }, + ], + }, + }, + + { + // 不能引入@vben/*里面的包 + files: [ + 'packages/types/**/**', + 'packages/utils/**/**', + 'packages/icons/**/**', + 'packages/constants/**/**', + 'packages/styles/**/**', + 'packages/stores/**/**', + 'packages/preferences/**/**', + 'packages/locales/**/**', + ], + ignores: restrictedImportIgnores, + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['@vben/*'], + message: + 'The @vben package cannot be imported, please use the @core package itself', + }, + ], + }, + ], + }, + }, + // 后端模拟代码,不需要太多规则 + { + files: ['apps/backend-mock/**/**', 'docs/**/**'], + rules: { + '@typescript-eslint/no-extraneous-class': 'off', + 'n/no-extraneous-import': 'off', + 'n/prefer-global/buffer': 'off', + 'n/prefer-global/process': 'off', + 'no-console': 'off', + 'unicorn/prefer-module': 'off', + }, + }, + { + files: ['**/**/playwright.config.ts'], + rules: { + 'n/prefer-global/buffer': 'off', + 'n/prefer-global/process': 'off', + 'no-console': 'off', + }, + }, + { + files: ['internal/**/**', 'scripts/**/**'], + rules: { + 'no-console': 'off', + }, + }, +]; + +export { customConfig }; diff --git a/internal/lint-configs/eslint-config/src/index.ts b/internal/lint-configs/eslint-config/src/index.ts new file mode 100644 index 0000000..c9f08bd --- /dev/null +++ b/internal/lint-configs/eslint-config/src/index.ts @@ -0,0 +1,60 @@ +import type { Linter } from 'eslint'; + +import { + command, + comments, + disableds, + ignores, + importPluginConfig, + javascript, + jsdoc, + jsonc, + node, + perfectionist, + prettier, + regexp, + test, + turbo, + typescript, + unicorn, + vue, +} from './configs'; +import { customConfig } from './custom-config'; + +type FlatConfig = Linter.Config; + +type FlatConfigPromise = + | FlatConfig + | FlatConfig[] + | Promise + | Promise; + +async function defineConfig(config: FlatConfig[] = []) { + const configs: FlatConfigPromise[] = [ + vue(), + javascript(), + ignores(), + prettier(), + typescript(), + jsonc(), + disableds(), + importPluginConfig(), + node(), + perfectionist(), + comments(), + jsdoc(), + unicorn(), + test(), + regexp(), + command(), + turbo(), + ...customConfig, + ...config, + ]; + + const resolved = await Promise.all(configs); + + return resolved.flat(); +} + +export { defineConfig }; diff --git a/internal/lint-configs/eslint-config/src/util.ts b/internal/lint-configs/eslint-config/src/util.ts new file mode 100644 index 0000000..d1a10ad --- /dev/null +++ b/internal/lint-configs/eslint-config/src/util.ts @@ -0,0 +1,8 @@ +export type Awaitable = Promise | T; + +export async function interopDefault( + m: Awaitable, +): Promise { + const resolved = await m; + return (resolved as any).default || resolved; +} diff --git a/internal/lint-configs/eslint-config/tsconfig.json b/internal/lint-configs/eslint-config/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/internal/lint-configs/eslint-config/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/internal/lint-configs/prettier-config/index.mjs b/internal/lint-configs/prettier-config/index.mjs new file mode 100644 index 0000000..f6a20c8 --- /dev/null +++ b/internal/lint-configs/prettier-config/index.mjs @@ -0,0 +1,18 @@ +export default { + endOfLine: 'auto', + overrides: [ + { + files: ['*.json5'], + options: { + quoteProps: 'preserve', + singleQuote: false, + }, + }, + ], + plugins: ['prettier-plugin-tailwindcss'], + printWidth: 80, + proseWrap: 'never', + semi: true, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/internal/lint-configs/prettier-config/package.json b/internal/lint-configs/prettier-config/package.json new file mode 100644 index 0000000..65e8b8f --- /dev/null +++ b/internal/lint-configs/prettier-config/package.json @@ -0,0 +1,28 @@ +{ + "name": "@vben/prettier-config", + "version": "5.0.0", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/lint-configs/prettier-config" + }, + "license": "MIT", + "type": "module", + "files": [ + "dist" + ], + "main": "./index.mjs", + "module": "./index.mjs", + "exports": { + ".": { + "default": "./index.mjs" + } + }, + "dependencies": { + "prettier": "catalog:", + "prettier-plugin-tailwindcss": "catalog:" + } +} diff --git a/internal/lint-configs/stylelint-config/index.mjs b/internal/lint-configs/stylelint-config/index.mjs new file mode 100644 index 0000000..7ef175c --- /dev/null +++ b/internal/lint-configs/stylelint-config/index.mjs @@ -0,0 +1,140 @@ +export default { + extends: ['stylelint-config-standard', 'stylelint-config-recess-order'], + ignoreFiles: [ + '**/*.js', + '**/*.jsx', + '**/*.tsx', + '**/*.ts', + '**/*.json', + '**/*.md', + ], + overrides: [ + { + customSyntax: 'postcss-html', + files: ['*.(html|vue)', '**/*.(html|vue)'], + rules: { + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global', 'deep'], + }, + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'], + }, + ], + }, + }, + { + customSyntax: 'postcss-scss', + extends: [ + 'stylelint-config-recommended-scss', + 'stylelint-config-recommended-vue/scss', + ], + files: ['*.scss', '**/*.scss'], + }, + ], + plugins: [ + 'stylelint-order', + '@stylistic/stylelint-plugin', + 'stylelint-prettier', + 'stylelint-scss', + ], + rules: { + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'extends', + 'ignores', + 'include', + 'mixin', + 'if', + 'else', + 'media', + 'for', + 'at-root', + 'tailwind', + 'apply', + 'variants', + 'responsive', + 'screen', + 'function', + 'each', + 'use', + 'forward', + 'return', + ], + }, + ], + 'font-family-no-missing-generic-family-keyword': null, + 'function-no-unknown': null, + 'import-notation': null, + 'media-feature-range-notation': null, + 'named-grid-areas-no-invalid': null, + 'no-descending-specificity': null, + 'no-empty-source': null, + 'order/order': [ + [ + 'dollar-variables', + 'custom-properties', + 'at-rules', + 'declarations', + { + name: 'supports', + type: 'at-rule', + }, + { + name: 'media', + type: 'at-rule', + }, + { + name: 'include', + type: 'at-rule', + }, + 'rules', + ], + { severity: 'error' }, + ], + 'prettier/prettier': true, + 'rule-empty-line-before': [ + 'always', + { + ignore: ['after-comment', 'first-nested'], + }, + ], + 'scss/at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'extends', + 'ignores', + 'include', + 'mixin', + 'if', + 'else', + 'media', + 'for', + 'at-root', + 'tailwind', + 'apply', + 'variants', + 'responsive', + 'screen', + 'function', + 'each', + 'use', + 'forward', + 'return', + ], + }, + ], + 'scss/operator-no-newline-after': null, + 'selector-class-pattern': + '^(?:(?:o|c|u|t|s|is|has|_|js|qa)-)?[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*(?:__[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:--[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:[.+])?$', + + 'selector-not-notation': null, + }, +}; diff --git a/internal/lint-configs/stylelint-config/package.json b/internal/lint-configs/stylelint-config/package.json new file mode 100644 index 0000000..da7f4e8 --- /dev/null +++ b/internal/lint-configs/stylelint-config/package.json @@ -0,0 +1,43 @@ +{ + "name": "@vben/stylelint-config", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/lint-configs/stylelint-config" + }, + "license": "MIT", + "type": "module", + "files": [ + "dist" + ], + "main": "./index.mjs", + "module": "./index.mjs", + "exports": { + ".": { + "import": "./index.mjs", + "default": "./index.mjs" + } + }, + "dependencies": { + "@stylistic/stylelint-plugin": "catalog:", + "stylelint-config-recess-order": "catalog:", + "stylelint-scss": "catalog:" + }, + "devDependencies": { + "postcss": "catalog:", + "postcss-html": "catalog:", + "postcss-scss": "catalog:", + "prettier": "catalog:", + "stylelint": "catalog:", + "stylelint-config-recommended": "catalog:", + "stylelint-config-recommended-scss": "catalog:", + "stylelint-config-recommended-vue": "catalog:", + "stylelint-config-standard": "catalog:", + "stylelint-order": "catalog:", + "stylelint-prettier": "catalog:" + } +} diff --git a/internal/node-utils/build.config.ts b/internal/node-utils/build.config.ts new file mode 100644 index 0000000..97e572c --- /dev/null +++ b/internal/node-utils/build.config.ts @@ -0,0 +1,7 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index'], +}); diff --git a/internal/node-utils/package.json b/internal/node-utils/package.json new file mode 100644 index 0000000..2ad9577 --- /dev/null +++ b/internal/node-utils/package.json @@ -0,0 +1,43 @@ +{ + "name": "@vben/node-utils", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/node-utils" + }, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild --stub" + }, + "files": [ + "dist" + ], + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "import": "./dist/index.mjs", + "default": "./dist/index.mjs" + } + }, + "dependencies": { + "@changesets/git": "catalog:", + "@manypkg/get-packages": "catalog:", + "chalk": "catalog:", + "consola": "catalog:", + "dayjs": "catalog:", + "execa": "catalog:", + "find-up": "catalog:", + "ora": "catalog:", + "pkg-types": "catalog:", + "prettier": "catalog:", + "rimraf": "catalog:" + } +} diff --git a/internal/node-utils/src/__tests__/hash.test.ts b/internal/node-utils/src/__tests__/hash.test.ts new file mode 100644 index 0000000..3851306 --- /dev/null +++ b/internal/node-utils/src/__tests__/hash.test.ts @@ -0,0 +1,52 @@ +import { createHash } from 'node:crypto'; + +import { describe, expect, it } from 'vitest'; + +import { generatorContentHash } from '../hash'; + +describe('generatorContentHash', () => { + it('should generate an MD5 hash for the content', () => { + const content = 'example content'; + const expectedHash = createHash('md5') + .update(content, 'utf8') + .digest('hex'); + const actualHash = generatorContentHash(content); + expect(actualHash).toBe(expectedHash); + }); + + it('should generate an MD5 hash with specified length', () => { + const content = 'example content'; + const hashLength = 10; + const generatedHash = generatorContentHash(content, hashLength); + expect(generatedHash).toHaveLength(hashLength); + }); + + it('should correctly generate the hash with specified length', () => { + const content = 'example content'; + const hashLength = 8; + const expectedHash = createHash('md5') + .update(content, 'utf8') + .digest('hex') + .slice(0, hashLength); + const generatedHash = generatorContentHash(content, hashLength); + expect(generatedHash).toBe(expectedHash); + }); + + it('should return full hash if hash length parameter is not provided', () => { + const content = 'example content'; + const expectedHash = createHash('md5') + .update(content, 'utf8') + .digest('hex'); + const actualHash = generatorContentHash(content); + expect(actualHash).toBe(expectedHash); + }); + + it('should handle empty content', () => { + const content = ''; + const expectedHash = createHash('md5') + .update(content, 'utf8') + .digest('hex'); + const actualHash = generatorContentHash(content); + expect(actualHash).toBe(expectedHash); + }); +}); diff --git a/internal/node-utils/src/__tests__/path.test.ts b/internal/node-utils/src/__tests__/path.test.ts new file mode 100644 index 0000000..3bab5a1 --- /dev/null +++ b/internal/node-utils/src/__tests__/path.test.ts @@ -0,0 +1,67 @@ +// pathUtils.test.ts + +import { describe, expect, it } from 'vitest'; + +import { toPosixPath } from '../path'; + +describe('toPosixPath', () => { + // 测试 Windows 风格路径到 POSIX 风格路径的转换 + it('converts Windows-style paths to POSIX paths', () => { + const windowsPath = String.raw`C:\Users\Example\file.txt`; + const expectedPosixPath = 'C:/Users/Example/file.txt'; + expect(toPosixPath(windowsPath)).toBe(expectedPosixPath); + }); + + // 确认 POSIX 风格路径不会被改变 + it('leaves POSIX-style paths unchanged', () => { + const posixPath = '/home/user/file.txt'; + expect(toPosixPath(posixPath)).toBe(posixPath); + }); + + // 测试带有多个分隔符的路径 + it('converts paths with mixed separators', () => { + const mixedPath = String.raw`C:/Users\Example\file.txt`; + const expectedPosixPath = 'C:/Users/Example/file.txt'; + expect(toPosixPath(mixedPath)).toBe(expectedPosixPath); + }); + + // 测试空字符串 + it('handles empty strings', () => { + const emptyPath = ''; + expect(toPosixPath(emptyPath)).toBe(''); + }); + + // 测试仅包含分隔符的路径 + it('handles path with only separators', () => { + const separatorsPath = '\\\\\\'; + const expectedPosixPath = '///'; + expect(toPosixPath(separatorsPath)).toBe(expectedPosixPath); + }); + + // 测试不包含任何分隔符的路径 + it('handles path without separators', () => { + const noSeparatorPath = 'file.txt'; + expect(toPosixPath(noSeparatorPath)).toBe('file.txt'); + }); + + // 测试以分隔符结尾的路径 + it('handles path ending with a separator', () => { + const endingSeparatorPath = 'C:\\Users\\Example\\'; + const expectedPosixPath = 'C:/Users/Example/'; + expect(toPosixPath(endingSeparatorPath)).toBe(expectedPosixPath); + }); + + // 测试以分隔符开头的路径 + it('handles path starting with a separator', () => { + const startingSeparatorPath = String.raw`\Users\Example`; + const expectedPosixPath = '/Users/Example'; + expect(toPosixPath(startingSeparatorPath)).toBe(expectedPosixPath); + }); + + // 测试包含非法字符的路径 + it('handles path with invalid characters', () => { + const invalidCharsPath = String.raw`C:\Us*?ers\Ex|file.txt`; + const expectedPosixPath = 'C:/Us*?ers/Ex|file.txt'; + expect(toPosixPath(invalidCharsPath)).toBe(expectedPosixPath); + }); +}); diff --git a/internal/node-utils/src/constants.ts b/internal/node-utils/src/constants.ts new file mode 100644 index 0000000..71d8a6c --- /dev/null +++ b/internal/node-utils/src/constants.ts @@ -0,0 +1,6 @@ +enum UNICODE { + FAILURE = '\u2716', // ✖ + SUCCESS = '\u2714', // ✔ +} + +export { UNICODE }; diff --git a/internal/node-utils/src/date.ts b/internal/node-utils/src/date.ts new file mode 100644 index 0000000..d36572d --- /dev/null +++ b/internal/node-utils/src/date.ts @@ -0,0 +1,12 @@ +import dayjs from 'dayjs'; +import timezone from 'dayjs/plugin/timezone'; +import utc from 'dayjs/plugin/utc'; + +dayjs.extend(utc); +dayjs.extend(timezone); + +dayjs.tz.setDefault('Asia/Shanghai'); + +const dateUtil = dayjs; + +export { dateUtil }; diff --git a/internal/node-utils/src/fs.ts b/internal/node-utils/src/fs.ts new file mode 100644 index 0000000..8eec357 --- /dev/null +++ b/internal/node-utils/src/fs.ts @@ -0,0 +1,39 @@ +import { promises as fs } from 'node:fs'; +import { dirname } from 'node:path'; + +export async function outputJSON( + filePath: string, + data: any, + spaces: number = 2, +) { + try { + const dir = dirname(filePath); + await fs.mkdir(dir, { recursive: true }); + const jsonData = JSON.stringify(data, null, spaces); + await fs.writeFile(filePath, jsonData, 'utf8'); + } catch (error) { + console.error('Error writing JSON file:', error); + throw error; + } +} + +export async function ensureFile(filePath: string) { + try { + const dir = dirname(filePath); + await fs.mkdir(dir, { recursive: true }); + await fs.writeFile(filePath, '', { flag: 'a' }); + } catch (error) { + console.error('Error ensuring file:', error); + throw error; + } +} + +export async function readJSON(filePath: string) { + try { + const data = await fs.readFile(filePath, 'utf8'); + return JSON.parse(data); + } catch (error) { + console.error('Error reading JSON file:', error); + throw error; + } +} diff --git a/internal/node-utils/src/git.ts b/internal/node-utils/src/git.ts new file mode 100644 index 0000000..88f159c --- /dev/null +++ b/internal/node-utils/src/git.ts @@ -0,0 +1,34 @@ +import path from 'node:path'; + +import { execa } from 'execa'; + +export * from '@changesets/git'; + +/** + * 获取暂存区文件 + */ +async function getStagedFiles(): Promise { + try { + const { stdout } = await execa('git', [ + '-c', + 'submodule.recurse=false', + 'diff', + '--staged', + '--diff-filter=ACMR', + '--name-only', + '--ignore-submodules', + '-z', + ]); + + let changedList = stdout ? stdout.replace(/\0$/, '').split('\0') : []; + changedList = changedList.map((item) => path.resolve(process.cwd(), item)); + const changedSet = new Set(changedList); + changedSet.delete(''); + return [...changedSet]; + } catch (error) { + console.error('Failed to get staged files:', error); + return []; + } +} + +export { getStagedFiles }; diff --git a/internal/node-utils/src/hash.ts b/internal/node-utils/src/hash.ts new file mode 100644 index 0000000..81f6b05 --- /dev/null +++ b/internal/node-utils/src/hash.ts @@ -0,0 +1,18 @@ +import { createHash } from 'node:crypto'; + +/** + * 生产基于内容的 hash,可自定义长度 + * @param content + * @param hashLSize + */ +function generatorContentHash(content: string, hashLSize?: number) { + const hash = createHash('md5').update(content, 'utf8').digest('hex'); + + if (hashLSize) { + return hash.slice(0, hashLSize); + } + + return hash; +} + +export { generatorContentHash }; diff --git a/internal/node-utils/src/index.ts b/internal/node-utils/src/index.ts new file mode 100644 index 0000000..963cb87 --- /dev/null +++ b/internal/node-utils/src/index.ts @@ -0,0 +1,19 @@ +export * from './constants'; +export * from './date'; +export * from './fs'; +export * from './git'; +export { getStagedFiles, add as gitAdd } from './git'; +export { generatorContentHash } from './hash'; +export * from './monorepo'; +export { toPosixPath } from './path'; +export { prettierFormat } from './prettier'; +export * from './spinner'; +export type { Package } from '@manypkg/get-packages'; +export { default as colors } from 'chalk'; +export { consola } from 'consola'; +export * from 'execa'; + +export { default as fs } from 'node:fs/promises'; + +export { type PackageJson, readPackageJSON } from 'pkg-types'; +export { rimraf } from 'rimraf'; diff --git a/internal/node-utils/src/monorepo.ts b/internal/node-utils/src/monorepo.ts new file mode 100644 index 0000000..b6373e7 --- /dev/null +++ b/internal/node-utils/src/monorepo.ts @@ -0,0 +1,46 @@ +import { dirname } from 'node:path'; + +import { + getPackages as getPackagesFunc, + getPackagesSync as getPackagesSyncFunc, +} from '@manypkg/get-packages'; +import { findUpSync } from 'find-up'; + +/** + * 查找大仓的根目录 + * @param cwd + */ +function findMonorepoRoot(cwd: string = process.cwd()) { + const lockFile = findUpSync('pnpm-lock.yaml', { + cwd, + type: 'file', + }); + return dirname(lockFile || ''); +} + +/** + * 获取大仓的所有包 + */ +function getPackagesSync() { + const root = findMonorepoRoot(); + return getPackagesSyncFunc(root); +} + +/** + * 获取大仓的所有包 + */ +async function getPackages() { + const root = findMonorepoRoot(); + + return await getPackagesFunc(root); +} + +/** + * 获取大仓指定的包 + */ +async function getPackage(pkgName: string) { + const { packages } = await getPackages(); + return packages.find((pkg) => pkg.packageJson.name === pkgName); +} + +export { findMonorepoRoot, getPackage, getPackages, getPackagesSync }; diff --git a/internal/node-utils/src/path.ts b/internal/node-utils/src/path.ts new file mode 100644 index 0000000..e625fd2 --- /dev/null +++ b/internal/node-utils/src/path.ts @@ -0,0 +1,11 @@ +import { posix } from 'node:path'; + +/** + * 将给定的文件路径转换为 POSIX 风格。 + * @param {string} pathname - 原始文件路径。 + */ +function toPosixPath(pathname: string) { + return pathname.split(`\\`).join(posix.sep); +} + +export { toPosixPath }; diff --git a/internal/node-utils/src/prettier.ts b/internal/node-utils/src/prettier.ts new file mode 100644 index 0000000..1e1525d --- /dev/null +++ b/internal/node-utils/src/prettier.ts @@ -0,0 +1,21 @@ +import fs from 'node:fs/promises'; + +import { format, getFileInfo, resolveConfig } from 'prettier'; + +async function prettierFormat(filepath: string) { + const prettierOptions = await resolveConfig(filepath, {}); + + const fileInfo = await getFileInfo(filepath); + + const input = await fs.readFile(filepath, 'utf8'); + const output = await format(input, { + ...prettierOptions, + parser: fileInfo.inferredParser as any, + }); + if (output !== input) { + await fs.writeFile(filepath, output, 'utf8'); + } + return output; +} + +export { prettierFormat }; diff --git a/internal/node-utils/src/spinner.ts b/internal/node-utils/src/spinner.ts new file mode 100644 index 0000000..13ad6a4 --- /dev/null +++ b/internal/node-utils/src/spinner.ts @@ -0,0 +1,26 @@ +import type { Ora } from 'ora'; + +import ora from 'ora'; + +interface SpinnerOptions { + failedText?: string; + successText?: string; + title: string; +} +export async function spinner( + { failedText, successText, title }: SpinnerOptions, + callback: () => Promise, +): Promise { + const loading: Ora = ora(title).start(); + + try { + const result = await callback(); + loading.succeed(successText || 'Success!'); + return result; + } catch (error) { + loading.fail(failedText || 'Failed!'); + throw error; + } finally { + loading.stop(); + } +} diff --git a/internal/node-utils/tsconfig.json b/internal/node-utils/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/internal/node-utils/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/internal/tailwind-config/build.config.ts b/internal/tailwind-config/build.config.ts new file mode 100644 index 0000000..1f3c3c2 --- /dev/null +++ b/internal/tailwind-config/build.config.ts @@ -0,0 +1,10 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index', './src/postcss.config'], + rollup: { + emitCJS: true, + }, +}); diff --git a/internal/tailwind-config/package.json b/internal/tailwind-config/package.json new file mode 100644 index 0000000..9737ab3 --- /dev/null +++ b/internal/tailwind-config/package.json @@ -0,0 +1,66 @@ +{ + "name": "@vben/tailwind-config", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/tailwind-config" + }, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild" + }, + "files": [ + "dist" + ], + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "./dist/*", + "./*" + ] + } + }, + "exports": { + ".": { + "types": "./src/index.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./postcss": { + "types": "./src/postcss.config.ts", + "import": "./dist/postcss.config.mjs", + "require": "./dist/postcss.config.cjs", + "default": "./dist/postcss.config.mjs" + }, + "./*": "./*" + }, + "peerDependencies": { + "tailwindcss": "^3.4.3" + }, + "dependencies": { + "@iconify/json": "catalog:", + "@iconify/tailwind": "catalog:", + "@manypkg/get-packages": "catalog:", + "@tailwindcss/nesting": "catalog:", + "@tailwindcss/typography": "catalog:", + "autoprefixer": "catalog:", + "cssnano": "catalog:", + "postcss": "catalog:", + "postcss-antd-fixes": "catalog:", + "postcss-import": "catalog:", + "postcss-preset-env": "catalog:", + "tailwindcss": "catalog:", + "tailwindcss-animate": "catalog:" + }, + "devDependencies": { + "@types/postcss-import": "catalog:" + } +} diff --git a/internal/tailwind-config/src/index.ts b/internal/tailwind-config/src/index.ts new file mode 100644 index 0000000..93332a3 --- /dev/null +++ b/internal/tailwind-config/src/index.ts @@ -0,0 +1,266 @@ +import type { Config } from 'tailwindcss'; + +import path from 'node:path'; + +import { addDynamicIconSelectors } from '@iconify/tailwind'; +import { getPackagesSync } from '@manypkg/get-packages'; +import typographyPlugin from '@tailwindcss/typography'; +import animate from 'tailwindcss-animate'; + +import { enterAnimationPlugin } from './plugins/entry'; + +// import defaultTheme from 'tailwindcss/defaultTheme'; + +const { packages } = getPackagesSync(process.cwd()); + +const tailwindPackages: string[] = []; + +packages.forEach((pkg) => { + // apps目录下和 @vben-core/tailwind-ui 包需要使用到 tailwindcss ui + // if (fs.existsSync(path.join(pkg.dir, 'tailwind.config.mjs'))) { + tailwindPackages.push(pkg.dir); + // } +}); + +const shadcnUiColors = { + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', + hover: 'hsl(var(--accent-hover))', + lighter: 'has(val(--accent-lighter))', + }, + background: { + deep: 'hsl(var(--background-deep))', + DEFAULT: 'hsl(var(--background))', + }, + border: { + DEFAULT: 'hsl(var(--border))', + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', + }, + destructive: { + ...createColorsPalette('destructive'), + DEFAULT: 'hsl(var(--destructive))', + }, + + foreground: { + DEFAULT: 'hsl(var(--foreground))', + }, + + input: { + background: 'hsl(var(--input-background))', + DEFAULT: 'hsl(var(--input))', + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', + }, + primary: { + ...createColorsPalette('primary'), + DEFAULT: 'hsl(var(--primary))', + }, + + ring: 'hsl(var(--ring))', + secondary: { + DEFAULT: 'hsl(var(--secondary))', + desc: 'hsl(var(--secondary-desc))', + foreground: 'hsl(var(--secondary-foreground))', + }, +}; + +const customColors = { + green: { + ...createColorsPalette('green'), + foreground: 'hsl(var(--success-foreground))', + }, + header: { + DEFAULT: 'hsl(var(--header))', + }, + heavy: { + DEFAULT: 'hsl(var(--heavy))', + foreground: 'hsl(var(--heavy-foreground))', + }, + main: { + DEFAULT: 'hsl(var(--main))', + }, + overlay: { + content: 'hsl(var(--overlay-content))', + DEFAULT: 'hsl(var(--overlay))', + }, + red: { + ...createColorsPalette('red'), + foreground: 'hsl(var(--destructive-foreground))', + }, + sidebar: { + deep: 'hsl(var(--sidebar-deep))', + DEFAULT: 'hsl(var(--sidebar))', + }, + success: { + ...createColorsPalette('success'), + DEFAULT: 'hsl(var(--success))', + }, + warning: { + ...createColorsPalette('warning'), + DEFAULT: 'hsl(var(--warning))', + }, + yellow: { + ...createColorsPalette('yellow'), + foreground: 'hsl(var(--warning-foreground))', + }, +}; + +export default { + content: [ + './index.html', + ...tailwindPackages.map((item) => + path.join(item, 'src/**/*.{vue,js,ts,jsx,tsx,svelte,astro,html}'), + ), + ], + darkMode: 'selector', + plugins: [ + animate, + typographyPlugin, + addDynamicIconSelectors(), + enterAnimationPlugin, + ], + prefix: '', + theme: { + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px', + }, + }, + extend: { + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', + 'collapsible-down': 'collapsible-down 0.2s ease-in-out', + 'collapsible-up': 'collapsible-up 0.2s ease-in-out', + float: 'float 5s linear 0ms infinite', + }, + + animationDuration: { + '2000': '2000ms', + '3000': '3000ms', + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + xl: 'calc(var(--radius) + 4px)', + }, + boxShadow: { + float: `0 6px 16px 0 rgb(0 0 0 / 8%), + 0 3px 6px -4px rgb(0 0 0 / 12%), + 0 9px 28px 8px rgb(0 0 0 / 5%)`, + }, + colors: { + ...customColors, + ...shadcnUiColors, + }, + fontFamily: { + sans: [ + 'var(--font-family)', + // ...defaultTheme.fontFamily.sans + ], + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' }, + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' }, + }, + 'collapsible-down': { + from: { height: '0' }, + to: { height: 'var(--radix-collapsible-content-height)' }, + }, + 'collapsible-up': { + from: { height: 'var(--radix-collapsible-content-height)' }, + to: { height: '0' }, + }, + float: { + '0%': { transform: 'translateY(0)' }, + '50%': { transform: 'translateY(-20px)' }, + '100%': { transform: 'translateY(0)' }, + }, + }, + zIndex: { + '100': '100', + '1000': '1000', + }, + }, + }, + safelist: ['dark'], +} as Config; + +function createColorsPalette(name: string) { + // backgroundLightest: '#EFF6FF', // Tailwind CSS 默认的 `blue-50` + // backgroundLighter: '#DBEAFE', // Tailwind CSS 默认的 `blue-100` + // backgroundLight: '#BFDBFE', // Tailwind CSS 默认的 `blue-200` + // borderLight: '#93C5FD', // Tailwind CSS 默认的 `blue-300` + // border: '#60A5FA', // Tailwind CSS 默认的 `blue-400` + // main: '#3B82F6', // Tailwind CSS 默认的 `blue-500` + // hover: '#2563EB', // Tailwind CSS 默认的 `blue-600` + // active: '#1D4ED8', // Tailwind CSS 默认的 `blue-700` + // backgroundDark: '#1E40AF', // Tailwind CSS 默认的 `blue-800` + // backgroundDarker: '#1E3A8A', // Tailwind CSS 默认的 `blue-900` + // backgroundDarkest: '#172554', // Tailwind CSS 默认的 `blue-950` + + // • backgroundLightest (#EFF6FF): 适用于最浅的背景色,可能用于非常轻微的阴影或卡片的背景。 + // • backgroundLighter (#DBEAFE): 适用于略浅的背景色,通常用于次要背景或略浅的区域。 + // • backgroundLight (#BFDBFE): 适用于浅色背景,可能用于输入框或表单区域的背景。 + // • borderLight (#93C5FD): 适用于浅色边框,可能用于输入框或卡片的边框。 + // • border (#60A5FA): 适用于普通边框,可能用于按钮或卡片的边框。 + // • main (#3B82F6): 适用于主要的主题色,通常用于按钮、链接或主要的强调色。 + // • hover (#2563EB): 适用于鼠标悬停状态下的颜色,例如按钮悬停时的背景色或边框色。 + // • active (#1D4ED8): 适用于激活状态下的颜色,例如按钮按下时的背景色或边框色。 + // • backgroundDark (#1E40AF): 适用于深色背景,可能用于主要按钮或深色卡片背景。 + // • backgroundDarker (#1E3A8A): 适用于更深的背景,通常用于头部导航栏或页脚。 + // • backgroundDarkest (#172554): 适用于最深的背景,可能用于非常深色的区域或极端对比色。 + + return { + 50: `hsl(var(--${name}-50))`, + 100: `hsl(var(--${name}-100))`, + 200: `hsl(var(--${name}-200))`, + 300: `hsl(var(--${name}-300))`, + 400: `hsl(var(--${name}-400))`, + 500: `hsl(var(--${name}-500))`, + 600: `hsl(var(--${name}-600))`, + 700: `hsl(var(--${name}-700))`, + // 800: `hsl(var(--${name}-800))`, + // 900: `hsl(var(--${name}-900))`, + // 950: `hsl(var(--${name}-950))`, + // 激活状态下的颜色,适用于按钮按下时的背景色或边框色。 + active: `hsl(var(--${name}-700))`, + // 浅色背景,适用于输入框或表单区域的背景。 + 'background-light': `hsl(var(--${name}-200))`, + // 适用于略浅的背景色,通常用于次要背景或略浅的区域。 + 'background-lighter': `hsl(var(--${name}-100))`, + // 最浅的背景色,适用于非常轻微的阴影或卡片的背景。 + 'background-lightest': `hsl(var(--${name}-50))`, + // 适用于普通边框,可能用于按钮或卡片的边框。 + border: `hsl(var(--${name}-400))`, + // 浅色边框,适用于输入框或卡片的边框。 + 'border-light': `hsl(var(--${name}-300))`, + foreground: `hsl(var(--${name}-foreground))`, + // 鼠标悬停状态下的颜色,适用于按钮悬停时的背景色或边框色。 + hover: `hsl(var(--${name}-600))`, + // 主色文本 + text: `hsl(var(--${name}-500))`, + // 主色文本激活态 + 'text-active': `hsl(var(--${name}-700))`, + // 主色文本悬浮态 + 'text-hover': `hsl(var(--${name}-600))`, + }; +} diff --git a/internal/tailwind-config/src/module.d.ts b/internal/tailwind-config/src/module.d.ts new file mode 100644 index 0000000..a399653 --- /dev/null +++ b/internal/tailwind-config/src/module.d.ts @@ -0,0 +1,3 @@ +declare module '@tailwindcss/nesting' { + export default any; +} diff --git a/internal/tailwind-config/src/plugins/entry.ts b/internal/tailwind-config/src/plugins/entry.ts new file mode 100644 index 0000000..0d8e8ec --- /dev/null +++ b/internal/tailwind-config/src/plugins/entry.ts @@ -0,0 +1,53 @@ +import plugin from 'tailwindcss/plugin.js'; + +const enterAnimationPlugin = plugin(({ addUtilities }) => { + const maxChild = 5; + const utilities: Record = {}; + for (let i = 1; i <= maxChild; i++) { + const baseDelay = 0.1; + const delay = `${baseDelay * i}s`; + + utilities[`.enter-x:nth-child(${i})`] = { + animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateX(50px)`, + }; + + utilities[`.enter-y:nth-child(${i})`] = { + animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateY(50px)`, + }; + + utilities[`.-enter-x:nth-child(${i})`] = { + animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateX(-50px)`, + }; + + utilities[`.-enter-y:nth-child(${i})`] = { + animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateY(-50px)`, + }; + } + + // 添加动画关键帧 + addUtilities(utilities); + addUtilities({ + '@keyframes enter-x-animation': { + to: { + opacity: '1', + transform: 'translateX(0)', + }, + }, + '@keyframes enter-y-animation': { + to: { + opacity: '1', + transform: 'translateY(0)', + }, + }, + }); +}); + +export { enterAnimationPlugin }; diff --git a/internal/tailwind-config/src/postcss.config.ts b/internal/tailwind-config/src/postcss.config.ts new file mode 100644 index 0000000..43b30b3 --- /dev/null +++ b/internal/tailwind-config/src/postcss.config.ts @@ -0,0 +1,15 @@ +import config from '.'; + +export default { + plugins: { + ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), + // Specifying the config is not necessary in most cases, but it is included + autoprefixer: {}, + // 修复 element-plus 和 ant-design-vue 的样式和tailwindcss冲突问题 + 'postcss-antd-fixes': { prefixes: ['ant', 'el'] }, + 'postcss-import': {}, + 'postcss-preset-env': {}, + tailwindcss: { config }, + 'tailwindcss/nesting': {}, + }, +}; diff --git a/internal/tailwind-config/tsconfig.json b/internal/tailwind-config/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/internal/tailwind-config/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/internal/tsconfig/base.json b/internal/tsconfig/base.json new file mode 100644 index 0000000..1e45a78 --- /dev/null +++ b/internal/tsconfig/base.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Base", + "compilerOptions": { + "composite": false, + "target": "ESNext", + + "moduleDetection": "force", + "experimentalDecorators": true, + + "baseUrl": ".", + "module": "ESNext", + + "moduleResolution": "node", + "resolveJsonModule": true, + + "strict": true, + "strictNullChecks": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitThis": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "inlineSources": false, + "noEmit": true, + "removeComments": true, + "sourceMap": false, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "preserveWatchOutput": true + }, + "exclude": ["**/node_modules/**", "**/dist/**", "**/.turbo/**"] +} diff --git a/internal/tsconfig/library.json b/internal/tsconfig/library.json new file mode 100644 index 0000000..7a976f0 --- /dev/null +++ b/internal/tsconfig/library.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Web Application", + "extends": "./base.json", + "compilerOptions": { + "jsx": "preserve", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "moduleResolution": "bundler", + "declaration": true, + "noEmit": false + } +} diff --git a/internal/tsconfig/node.json b/internal/tsconfig/node.json new file mode 100644 index 0000000..31ce8f1 --- /dev/null +++ b/internal/tsconfig/node.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node Config", + "extends": "./base.json", + "compilerOptions": { + "composite": false, + "lib": ["ESNext"], + "baseUrl": "./", + "types": ["node"], + "noImplicitAny": true + } +} diff --git a/internal/tsconfig/package.json b/internal/tsconfig/package.json new file mode 100644 index 0000000..efeef61 --- /dev/null +++ b/internal/tsconfig/package.json @@ -0,0 +1,25 @@ +{ + "name": "@vben/tsconfig", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/tsconfig" + }, + "license": "MIT", + "type": "module", + "files": [ + "base.json", + "library.json", + "node.json", + "web-app.json", + "web.json" + ], + "dependencies": { + "@vben/types": "workspace:*", + "vite": "catalog:" + } +} diff --git a/internal/tsconfig/web-app.json b/internal/tsconfig/web-app.json new file mode 100644 index 0000000..00479cb --- /dev/null +++ b/internal/tsconfig/web-app.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Web Application", + "extends": "./web.json", + "compilerOptions": { + "types": ["vite/client", "@vben/types/global"] + } +} diff --git a/internal/tsconfig/web.json b/internal/tsconfig/web.json new file mode 100644 index 0000000..a4b60ce --- /dev/null +++ b/internal/tsconfig/web.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Web Package", + "extends": "./base.json", + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "vue", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "moduleResolution": "bundler", + "types": ["vite/client"], + "declaration": false + } +} diff --git a/internal/vite-config/build.config.ts b/internal/vite-config/build.config.ts new file mode 100644 index 0000000..97e572c --- /dev/null +++ b/internal/vite-config/build.config.ts @@ -0,0 +1,7 @@ +import { defineBuildConfig } from 'unbuild'; + +export default defineBuildConfig({ + clean: true, + declaration: true, + entries: ['src/index'], +}); diff --git a/internal/vite-config/package.json b/internal/vite-config/package.json new file mode 100644 index 0000000..708d519 --- /dev/null +++ b/internal/vite-config/package.json @@ -0,0 +1,59 @@ +{ + "name": "@vben/vite-config", + "version": "5.5.3", + "private": true, + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "internal/vite-config" + }, + "license": "MIT", + "type": "module", + "scripts": { + "stub": "pnpm unbuild --stub" + }, + "files": [ + "dist" + ], + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./dist/index.mjs" + } + }, + "dependencies": { + "@intlify/unplugin-vue-i18n": "catalog:", + "@jspm/generator": "catalog:", + "archiver": "catalog:", + "cheerio": "catalog:", + "get-port": "catalog:", + "html-minifier-terser": "catalog:", + "nitropack": "catalog:", + "resolve.exports": "catalog:", + "vite-plugin-pwa": "catalog:", + "vite-plugin-vue-devtools": "catalog:" + }, + "devDependencies": { + "@pnpm/workspace.read-manifest": "catalog:", + "@types/archiver": "catalog:", + "@types/html-minifier-terser": "catalog:", + "@vben/node-utils": "workspace:*", + "@vitejs/plugin-vue": "catalog:", + "@vitejs/plugin-vue-jsx": "catalog:", + "dayjs": "catalog:", + "dotenv": "catalog:", + "rollup": "catalog:", + "rollup-plugin-visualizer": "catalog:", + "sass": "catalog:", + "vite": "catalog:", + "vite-plugin-compression": "catalog:", + "vite-plugin-dts": "catalog:", + "vite-plugin-html": "catalog:", + "vite-plugin-lazy-import": "catalog:" + } +} diff --git a/internal/vite-config/src/config/application.ts b/internal/vite-config/src/config/application.ts new file mode 100644 index 0000000..0b56103 --- /dev/null +++ b/internal/vite-config/src/config/application.ts @@ -0,0 +1,125 @@ +import type { CSSOptions, UserConfig } from 'vite'; + +import type { DefineApplicationOptions } from '../typing'; + +import path, { relative } from 'node:path'; + +import { findMonorepoRoot } from '@vben/node-utils'; + +import { NodePackageImporter } from 'sass'; +import { defineConfig, loadEnv, mergeConfig } from 'vite'; + +import { defaultImportmapOptions, getDefaultPwaOptions } from '../options'; +import { loadApplicationPlugins } from '../plugins'; +import { loadAndConvertEnv } from '../utils/env'; +import { getCommonConfig } from './common'; + +function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) { + return defineConfig(async (config) => { + const options = await userConfigPromise?.(config); + const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv(); + const { command, mode } = config; + const { application = {}, vite = {} } = options || {}; + const root = process.cwd(); + const isBuild = command === 'build'; + const env = loadEnv(mode, root); + + const plugins = await loadApplicationPlugins({ + archiver: true, + archiverPluginOptions: {}, + compress: false, + compressTypes: ['brotli', 'gzip'], + devtools: true, + env, + extraAppConfig: true, + html: true, + i18n: true, + importmapOptions: defaultImportmapOptions, + injectAppLoading: true, + injectMetadata: true, + isBuild, + license: true, + mode, + nitroMock: !isBuild, + nitroMockOptions: {}, + print: !isBuild, + // printInfoMap: { + // 'Vben Admin Docs': 'https://doc.cncore.club/', + // }, + pwa: true, + pwaOptions: getDefaultPwaOptions(appTitle), + vxeTableLazyImport: true, + ...envConfig, + ...application, + }); + + const { injectGlobalScss = true } = application; + + const applicationConfig: UserConfig = { + base, + build: { + rollupOptions: { + output: { + assetFileNames: '[ext]/[name]-[hash].[ext]', + chunkFileNames: 'js/[name]-[hash].js', + entryFileNames: 'jse/index-[name]-[hash].js', + }, + }, + target: 'es2015', + }, + css: createCssOptions(injectGlobalScss), + esbuild: { + drop: isBuild + ? [ + // 'console', + 'debugger', + ] + : [], + legalComments: 'none', + }, + plugins, + server: { + host: true, + port, + warmup: { + // 预热文件 + clientFiles: [ + './index.html', + './src/bootstrap.ts', + './src/{views,layouts,router,store,api,adapter}/*', + ], + }, + }, + }; + + const mergedCommonConfig = mergeConfig( + await getCommonConfig(), + applicationConfig, + ); + return mergeConfig(mergedCommonConfig, vite); + }); +} + +function createCssOptions(injectGlobalScss = true): CSSOptions { + const root = findMonorepoRoot(); + return { + preprocessorOptions: injectGlobalScss + ? { + scss: { + additionalData: (content: string, filepath: string) => { + const relativePath = relative(root, filepath); + // apps下的包注入全局样式 + if (relativePath.startsWith(`apps${path.sep}`)) { + return `@use "@vben/styles/global" as *;\n${content}`; + } + return content; + }, + api: 'modern', + importers: [new NodePackageImporter()], + }, + } + : {}, + }; +} + +export { defineApplicationConfig }; diff --git a/internal/vite-config/src/config/common.ts b/internal/vite-config/src/config/common.ts new file mode 100644 index 0000000..653f210 --- /dev/null +++ b/internal/vite-config/src/config/common.ts @@ -0,0 +1,13 @@ +import type { UserConfig } from 'vite'; + +async function getCommonConfig(): Promise { + return { + build: { + chunkSizeWarningLimit: 2000, + reportCompressedSize: false, + sourcemap: false, + }, + }; +} + +export { getCommonConfig }; diff --git a/internal/vite-config/src/config/index.ts b/internal/vite-config/src/config/index.ts new file mode 100644 index 0000000..d04a84a --- /dev/null +++ b/internal/vite-config/src/config/index.ts @@ -0,0 +1,37 @@ +import type { DefineConfig } from '../typing'; + +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; + +import { defineApplicationConfig } from './application'; +import { defineLibraryConfig } from './library'; + +export * from './application'; +export * from './library'; + +function defineConfig( + userConfigPromise?: DefineConfig, + type: 'application' | 'auto' | 'library' = 'auto', +) { + let projectType = type; + + // 根据包是否存在 index.html,自动判断类型 + if (projectType === 'auto') { + const htmlPath = join(process.cwd(), 'index.html'); + projectType = existsSync(htmlPath) ? 'application' : 'library'; + } + + switch (projectType) { + case 'application': { + return defineApplicationConfig(userConfigPromise); + } + case 'library': { + return defineLibraryConfig(userConfigPromise); + } + default: { + throw new Error(`Unsupported project type: ${projectType}`); + } + } +} + +export { defineConfig }; diff --git a/internal/vite-config/src/config/library.ts b/internal/vite-config/src/config/library.ts new file mode 100644 index 0000000..08b8135 --- /dev/null +++ b/internal/vite-config/src/config/library.ts @@ -0,0 +1,59 @@ +import type { ConfigEnv, UserConfig } from 'vite'; + +import type { DefineLibraryOptions } from '../typing'; + +import { readPackageJSON } from '@vben/node-utils'; + +import { defineConfig, mergeConfig } from 'vite'; + +import { loadLibraryPlugins } from '../plugins'; +import { getCommonConfig } from './common'; + +function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) { + return defineConfig(async (config: ConfigEnv) => { + const options = await userConfigPromise?.(config); + const { command, mode } = config; + const { library = {}, vite = {} } = options || {}; + const root = process.cwd(); + const isBuild = command === 'build'; + + const plugins = await loadLibraryPlugins({ + dts: false, + injectMetadata: true, + isBuild, + mode, + ...library, + }); + + const { dependencies = {}, peerDependencies = {} } = + await readPackageJSON(root); + + const externalPackages = [ + ...Object.keys(dependencies), + ...Object.keys(peerDependencies), + ]; + + const packageConfig: UserConfig = { + build: { + lib: { + entry: 'src/index.ts', + fileName: () => 'index.mjs', + formats: ['es'], + }, + rollupOptions: { + external: (id) => { + return externalPackages.some( + (pkg) => id === pkg || id.startsWith(`${pkg}/`), + ); + }, + }, + }, + plugins, + }; + const commonConfig = await getCommonConfig(); + const mergedConmonConfig = mergeConfig(commonConfig, packageConfig); + return mergeConfig(mergedConmonConfig, vite); + }); +} + +export { defineLibraryConfig }; diff --git a/internal/vite-config/src/index.ts b/internal/vite-config/src/index.ts new file mode 100644 index 0000000..352a323 --- /dev/null +++ b/internal/vite-config/src/index.ts @@ -0,0 +1,4 @@ +export * from './config'; +export * from './options'; +export * from './plugins'; +export { loadAndConvertEnv } from './utils/env'; diff --git a/internal/vite-config/src/options.ts b/internal/vite-config/src/options.ts new file mode 100644 index 0000000..f1e2401 --- /dev/null +++ b/internal/vite-config/src/options.ts @@ -0,0 +1,45 @@ +import type { Options as PwaPluginOptions } from 'vite-plugin-pwa'; + +import type { ImportmapPluginOptions } from './typing'; + +const isDevelopment = process.env.NODE_ENV === 'development'; + +const getDefaultPwaOptions = (name: string): Partial => ({ + manifest: { + description: + 'Vben Admin is a modern admin dashboard template based on Vue 3. ', + icons: [ + { + sizes: '192x192', + src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-192.png', + type: 'image/png', + }, + { + sizes: '512x512', + src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-512.png', + type: 'image/png', + }, + ], + name: `${name}${isDevelopment ? ' dev' : ''}`, + short_name: `${name}${isDevelopment ? ' dev' : ''}`, + }, +}); + +/** + * importmap CDN 暂时不开启,因为有些包不支持,且网络不稳定 + */ +const defaultImportmapOptions: ImportmapPluginOptions = { + // 通过 Importmap CDN 方式引入, + // 目前只有esm.sh源兼容性好一点,jspm.io对于 esm 入口要求高 + defaultProvider: 'esm.sh', + importmap: [ + { name: 'vue' }, + { name: 'pinia' }, + { name: 'vue-router' }, + // { name: 'vue-i18n' }, + { name: 'dayjs' }, + { name: 'vue-demi' }, + ], +}; + +export { defaultImportmapOptions, getDefaultPwaOptions }; diff --git a/internal/vite-config/src/plugins/archiver.ts b/internal/vite-config/src/plugins/archiver.ts new file mode 100644 index 0000000..8eec8a0 --- /dev/null +++ b/internal/vite-config/src/plugins/archiver.ts @@ -0,0 +1,75 @@ +import type { PluginOption } from 'vite'; + +import type { ArchiverPluginOptions } from '../typing'; + +import fs from 'node:fs'; +import fsp from 'node:fs/promises'; +import { join } from 'node:path'; + +import archiver from 'archiver'; + +export const viteArchiverPlugin = ( + options: ArchiverPluginOptions = {}, +): PluginOption => { + return { + apply: 'build', + closeBundle: { + handler() { + const { name = 'dist', outputDir = '.' } = options; + + setTimeout(async () => { + const folderToZip = 'dist'; + + const zipOutputDir = join(process.cwd(), outputDir); + const zipOutputPath = join(zipOutputDir, `${name}.zip`); + try { + await fsp.mkdir(zipOutputDir, { recursive: true }); + } catch { + // ignore + } + + try { + await zipFolder(folderToZip, zipOutputPath); + console.log(`Folder has been zipped to: ${zipOutputPath}`); + } catch (error) { + console.error('Error zipping folder:', error); + } + }, 0); + }, + order: 'post', + }, + enforce: 'post', + name: 'vite:archiver', + }; +}; + +async function zipFolder( + folderPath: string, + outputPath: string, +): Promise { + return new Promise((resolve, reject) => { + const output = fs.createWriteStream(outputPath); + const archive = archiver('zip', { + zlib: { level: 9 }, // 设置压缩级别为 9 以实现最高压缩率 + }); + + output.on('close', () => { + console.log( + `ZIP file created: ${outputPath} (${archive.pointer()} total bytes)`, + ); + resolve(); + }); + + archive.on('error', (err) => { + reject(err); + }); + + archive.pipe(output); + + // 使用 directory 方法以流的方式压缩文件夹,减少内存消耗 + archive.directory(folderPath, false); + + // 流式处理完成 + archive.finalize(); + }); +} diff --git a/internal/vite-config/src/plugins/extra-app-config.ts b/internal/vite-config/src/plugins/extra-app-config.ts new file mode 100644 index 0000000..813819b --- /dev/null +++ b/internal/vite-config/src/plugins/extra-app-config.ts @@ -0,0 +1,92 @@ +import type { PluginOption } from 'vite'; + +import { + colors, + generatorContentHash, + readPackageJSON, +} from '@vben/node-utils'; + +import { loadEnv } from '../utils/env'; + +interface PluginOptions { + isBuild: boolean; + root: string; +} + +const GLOBAL_CONFIG_FILE_NAME = '_app.config.js'; +const VBEN_ADMIN_PRO_APP_CONF = '_VBEN_ADMIN_PRO_APP_CONF_'; + +/** + * 用于将配置文件抽离出来并注入到项目中 + * @returns + */ + +async function viteExtraAppConfigPlugin({ + isBuild, + root, +}: PluginOptions): Promise { + let publicPath: string; + let source: string; + + if (!isBuild) { + return; + } + + const { version = '' } = await readPackageJSON(root); + + return { + async configResolved(config) { + publicPath = ensureTrailingSlash(config.base); + source = await getConfigSource(); + }, + async generateBundle() { + try { + this.emitFile({ + fileName: GLOBAL_CONFIG_FILE_NAME, + source, + type: 'asset', + }); + + console.log(colors.cyan(`✨configuration file is build successfully!`)); + } catch (error) { + console.log( + colors.red( + `configuration file configuration file failed to package:\n${error}`, + ), + ); + } + }, + name: 'vite:extra-app-config', + async transformIndexHtml(html) { + const hash = `v=${version}-${generatorContentHash(source, 8)}`; + + const appConfigSrc = `${publicPath}${GLOBAL_CONFIG_FILE_NAME}?${hash}`; + + return { + html, + tags: [{ attrs: { src: appConfigSrc }, tag: 'script' }], + }; + }, + }; +} + +async function getConfigSource() { + const config = await loadEnv(); + const windowVariable = `window.${VBEN_ADMIN_PRO_APP_CONF}`; + // 确保变量不会被修改 + let source = `${windowVariable}=${JSON.stringify(config)};`; + source += ` + Object.freeze(${windowVariable}); + Object.defineProperty(window, "${VBEN_ADMIN_PRO_APP_CONF}", { + configurable: false, + writable: false, + }); + `.replaceAll(/\s/g, ''); + return source; +} + +function ensureTrailingSlash(path: string) { + return path.endsWith('/') ? path : `${path}/`; +} + +export { viteExtraAppConfigPlugin }; diff --git a/internal/vite-config/src/plugins/importmap.ts b/internal/vite-config/src/plugins/importmap.ts new file mode 100644 index 0000000..0ccda99 --- /dev/null +++ b/internal/vite-config/src/plugins/importmap.ts @@ -0,0 +1,245 @@ +/** + * 参考 https://github.com/jspm/vite-plugin-jspm,调整为需要的功能 + */ +import type { GeneratorOptions } from '@jspm/generator'; +import type { Plugin } from 'vite'; + +import { Generator } from '@jspm/generator'; +import { load } from 'cheerio'; +import { minify } from 'html-minifier-terser'; + +const DEFAULT_PROVIDER = 'jspm.io'; + +type pluginOptions = GeneratorOptions & { + debug?: boolean; + defaultProvider?: 'esm.sh' | 'jsdelivr' | 'jspm.io'; + importmap?: Array<{ name: string; range?: string }>; +}; + +// async function getLatestVersionOfShims() { +// const result = await fetch('https://ga.jspm.io/npm:es-module-shims'); +// const version = result.text(); +// return version; +// } + +async function getShimsUrl(provide: string) { + // const version = await getLatestVersionOfShims(); + const version = '1.10.0'; + + const shimsSubpath = `dist/es-module-shims.js`; + const providerShimsMap: Record = { + 'esm.sh': `https://esm.sh/es-module-shims@${version}/${shimsSubpath}`, + // unpkg: `https://unpkg.com/es-module-shims@${version}/${shimsSubpath}`, + jsdelivr: `https://cdn.jsdelivr.net/npm/es-module-shims@${version}/${shimsSubpath}`, + + // 下面两个CDN不稳定,暂时不用 + 'jspm.io': `https://ga.jspm.io/npm:es-module-shims@${version}/${shimsSubpath}`, + }; + + return providerShimsMap[provide] || providerShimsMap[DEFAULT_PROVIDER]; +} + +let generator: Generator; + +async function viteImportMapPlugin( + pluginOptions?: pluginOptions, +): Promise { + const { importmap } = pluginOptions || {}; + + let isSSR = false; + let isBuild = false; + let installed = false; + let installError: Error | null = null; + + const options: pluginOptions = Object.assign( + {}, + { + debug: false, + defaultProvider: 'jspm.io', + env: ['production', 'browser', 'module'], + importmap: [], + }, + pluginOptions, + ); + + generator = new Generator({ + ...options, + baseUrl: process.cwd(), + }); + + if (options?.debug) { + (async () => { + for await (const { message, type } of generator.logStream()) { + console.log(`${type}: ${message}`); + } + })(); + } + + const imports = options.inputMap?.imports ?? {}; + const scopes = options.inputMap?.scopes ?? {}; + const firstLayerKeys = Object.keys(scopes); + const inputMapScopes: string[] = []; + firstLayerKeys.forEach((key) => { + inputMapScopes.push(...Object.keys(scopes[key] || {})); + }); + const inputMapImports = Object.keys(imports); + + const allDepNames: string[] = [ + ...(importmap?.map((item) => item.name) || []), + ...inputMapImports, + ...inputMapScopes, + ]; + const depNames = new Set(allDepNames); + + const installDeps = importmap?.map((item) => ({ + range: item.range, + target: item.name, + })); + + return [ + { + async config(_, { command, isSsrBuild }) { + isBuild = command === 'build'; + isSSR = !!isSsrBuild; + }, + enforce: 'pre', + name: 'importmap:external', + resolveId(id) { + if (isSSR || !isBuild) { + return null; + } + + if (!depNames.has(id)) { + return null; + } + return { external: true, id }; + }, + }, + { + enforce: 'post', + name: 'importmap:install', + async resolveId() { + if (isSSR || !isBuild || installed) { + return null; + } + try { + installed = true; + await Promise.allSettled( + (installDeps || []).map((dep) => generator.install(dep)), + ); + } catch (error: any) { + installError = error; + installed = false; + } + return null; + }, + }, + { + buildEnd() { + // 未生成importmap时,抛出错误,防止被turbo缓存 + if (!installed && !isSSR) { + installError && console.error(installError); + throw new Error('Importmap installation failed.'); + } + }, + enforce: 'post', + name: 'importmap:html', + transformIndexHtml: { + async handler(html) { + if (isSSR || !isBuild) { + return html; + } + + const importmapJson = generator.getMap(); + + if (!importmapJson) { + return html; + } + + const esModuleShimsSrc = await getShimsUrl( + options.defaultProvider || DEFAULT_PROVIDER, + ); + + const resultHtml = await injectShimsToHtml( + html, + esModuleShimsSrc || '', + ); + html = await minify(resultHtml || html, { + collapseWhitespace: true, + minifyCSS: true, + minifyJS: true, + removeComments: false, + }); + + return { + html, + tags: [ + { + attrs: { + type: 'importmap', + }, + injectTo: 'head-prepend', + tag: 'script', + children: `${JSON.stringify(importmapJson)}`, + }, + ], + }; + }, + order: 'post', + }, + }, + ]; +} + +async function injectShimsToHtml(html: string, esModuleShimUrl: string) { + const $ = load(html); + + const $script = $(`script[type='module']`); + + if (!$script) { + return; + } + + const entry = $script.attr('src'); + + $script.removeAttr('type'); + $script.removeAttr('crossorigin'); + $script.removeAttr('src'); + $script.html(` +if (!HTMLScriptElement.supports || !HTMLScriptElement.supports('importmap')) { + self.importShim = function () { + const promise = new Promise((resolve, reject) => { + document.head.appendChild( + Object.assign(document.createElement('script'), { + src: '${esModuleShimUrl}', + crossorigin: 'anonymous', + async: true, + onload() { + if (!importShim.$proxy) { + resolve(importShim); + } else { + reject(new Error('No globalThis.importShim found:' + esModuleShimUrl)); + } + }, + onerror(error) { + reject(error); + }, + }), + ); + }); + importShim.$proxy = true; + return promise.then((importShim) => importShim(...arguments)); + }; +} + +var modules = ['${entry}']; +typeof importShim === 'function' + ? modules.forEach((moduleName) => importShim(moduleName)) + : modules.forEach((moduleName) => import(moduleName)); + `); + $('body').after($script); + $('head').remove(`script[type='module']`); + return $.html(); +} + +export { viteImportMapPlugin }; diff --git a/internal/vite-config/src/plugins/index.ts b/internal/vite-config/src/plugins/index.ts new file mode 100644 index 0000000..da08db4 --- /dev/null +++ b/internal/vite-config/src/plugins/index.ts @@ -0,0 +1,247 @@ +import type { PluginOption } from 'vite'; + +import type { + ApplicationPluginOptions, + CommonPluginOptions, + ConditionPlugin, + LibraryPluginOptions, +} from '../typing'; + +import viteVueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; +import viteVue from '@vitejs/plugin-vue'; +import viteVueJsx from '@vitejs/plugin-vue-jsx'; +import { visualizer as viteVisualizerPlugin } from 'rollup-plugin-visualizer'; +import viteCompressPlugin from 'vite-plugin-compression'; +import viteDtsPlugin from 'vite-plugin-dts'; +import { createHtmlPlugin as viteHtmlPlugin } from 'vite-plugin-html'; +import { VitePWA } from 'vite-plugin-pwa'; +import viteVueDevTools from 'vite-plugin-vue-devtools'; + +import { viteArchiverPlugin } from './archiver'; +import { viteExtraAppConfigPlugin } from './extra-app-config'; +import { viteImportMapPlugin } from './importmap'; +import { viteInjectAppLoadingPlugin } from './inject-app-loading'; +import { viteMetadataPlugin } from './inject-metadata'; +import { viteLicensePlugin } from './license'; +import { viteNitroMockPlugin } from './nitro-mock'; +import { vitePrintPlugin } from './print'; +import { viteVxeTableImportsPlugin } from './vxe-table'; + +/** + * 获取条件成立的 vite 插件 + * @param conditionPlugins + */ +async function loadConditionPlugins(conditionPlugins: ConditionPlugin[]) { + const plugins: PluginOption[] = []; + for (const conditionPlugin of conditionPlugins) { + if (conditionPlugin.condition) { + const realPlugins = await conditionPlugin.plugins(); + plugins.push(...realPlugins); + } + } + return plugins.flat(); +} + +/** + * 根据条件获取通用的vite插件 + */ +async function loadCommonPlugins( + options: CommonPluginOptions, +): Promise { + const { devtools, injectMetadata, isBuild, visualizer } = options; + return [ + { + condition: true, + plugins: () => [ + viteVue({ + script: { + defineModel: true, + // propsDestructure: true, + }, + }), + viteVueJsx(), + ], + }, + + { + condition: !isBuild && devtools, + plugins: () => [viteVueDevTools()], + }, + { + condition: injectMetadata, + plugins: async () => [await viteMetadataPlugin()], + }, + { + condition: isBuild && !!visualizer, + plugins: () => [viteVisualizerPlugin({ + filename: './node_modules/.cache/visualizer/stats.html', + gzipSize: true, + open: true, + })], + }, + ]; +} + +/** + * 根据条件获取应用类型的vite插件 + */ +async function loadApplicationPlugins( + options: ApplicationPluginOptions, +): Promise { + // 单独取,否则commonOptions拿不到 + const isBuild = options.isBuild; + const env = options.env; + + const { + archiver, + archiverPluginOptions, + compress, + compressTypes, + extraAppConfig, + html, + i18n, + importmap, + importmapOptions, + injectAppLoading, + license, + nitroMock, + nitroMockOptions, + print, + printInfoMap, + pwa, + pwaOptions, + vxeTableLazyImport, + ...commonOptions + } = options; + + const commonPlugins = await loadCommonPlugins(commonOptions); + + return await loadConditionPlugins([ + ...commonPlugins, + { + condition: i18n, + plugins: async () => { + return [ + viteVueI18nPlugin({ + compositionOnly: true, + fullInstall: true, + runtimeOnly: true, + }), + ]; + }, + }, + { + condition: print, + plugins: async () => { + return [await vitePrintPlugin({ infoMap: printInfoMap })]; + }, + }, + { + condition: vxeTableLazyImport, + plugins: async () => { + return [await viteVxeTableImportsPlugin()]; + }, + }, + { + condition: nitroMock, + plugins: async () => { + return [await viteNitroMockPlugin(nitroMockOptions)]; + }, + }, + + { + condition: injectAppLoading, + plugins: async () => [await viteInjectAppLoadingPlugin(!!isBuild, env)], + }, + { + condition: license, + plugins: async () => [await viteLicensePlugin()], + }, + { + condition: pwa, + plugins: () => + VitePWA({ + injectRegister: false, + workbox: { + globPatterns: [], + }, + ...pwaOptions, + manifest: { + display: 'standalone', + start_url: '/', + theme_color: '#ffffff', + ...pwaOptions?.manifest, + }, + }), + }, + { + condition: isBuild && !!compress, + plugins: () => { + const compressPlugins: PluginOption[] = []; + if (compressTypes?.includes('brotli')) { + compressPlugins.push( + viteCompressPlugin({ deleteOriginFile: false, ext: '.br' }), + ); + } + if (compressTypes?.includes('gzip')) { + compressPlugins.push( + viteCompressPlugin({ deleteOriginFile: false, ext: '.gz' }), + ); + } + return compressPlugins; + }, + }, + { + condition: !!html, + plugins: () => [viteHtmlPlugin({ minify: true })], + }, + { + condition: isBuild && importmap, + plugins: () => { + return [viteImportMapPlugin(importmapOptions)]; + }, + }, + { + condition: isBuild && extraAppConfig, + plugins: async () => [ + await viteExtraAppConfigPlugin({ isBuild: true, root: process.cwd() }), + ], + }, + { + condition: archiver, + plugins: async () => { + return [await viteArchiverPlugin(archiverPluginOptions)]; + }, + }, + ]); +} + +/** + * 根据条件获取库类型的vite插件 + */ +async function loadLibraryPlugins( + options: LibraryPluginOptions, +): Promise { + // 单独取,否则commonOptions拿不到 + const isBuild = options.isBuild; + const { dts, ...commonOptions } = options; + const commonPlugins = await loadCommonPlugins(commonOptions); + return await loadConditionPlugins([ + ...commonPlugins, + { + condition: isBuild && !!dts, + plugins: () => [viteDtsPlugin({ logLevel: 'error' })], + }, + ]); +} + +export { + loadApplicationPlugins, + loadLibraryPlugins, + viteArchiverPlugin, + viteCompressPlugin, + viteDtsPlugin, + viteHtmlPlugin, + viteVisualizerPlugin, + viteVxeTableImportsPlugin, +}; diff --git a/internal/vite-config/src/plugins/inject-app-loading/README.md b/internal/vite-config/src/plugins/inject-app-loading/README.md new file mode 100644 index 0000000..8d2358f --- /dev/null +++ b/internal/vite-config/src/plugins/inject-app-loading/README.md @@ -0,0 +1,3 @@ +# inject-app-loading + +用于在应用加载时显示加载动画的插件,可自行选择加载动画的样式。 diff --git a/internal/vite-config/src/plugins/inject-app-loading/default-loading-antd.html b/internal/vite-config/src/plugins/inject-app-loading/default-loading-antd.html new file mode 100644 index 0000000..20a21fb --- /dev/null +++ b/internal/vite-config/src/plugins/inject-app-loading/default-loading-antd.html @@ -0,0 +1,107 @@ + +
+ +
<%= VITE_APP_TITLE %>
+
diff --git a/internal/vite-config/src/plugins/inject-app-loading/default-loading.html b/internal/vite-config/src/plugins/inject-app-loading/default-loading.html new file mode 100644 index 0000000..2895705 --- /dev/null +++ b/internal/vite-config/src/plugins/inject-app-loading/default-loading.html @@ -0,0 +1,113 @@ + +
+
+
<%= VITE_APP_TITLE %>
+
diff --git a/internal/vite-config/src/plugins/inject-app-loading/index.ts b/internal/vite-config/src/plugins/inject-app-loading/index.ts new file mode 100644 index 0000000..c6a7983 --- /dev/null +++ b/internal/vite-config/src/plugins/inject-app-loading/index.ts @@ -0,0 +1,66 @@ +import type { PluginOption } from 'vite'; + +import fs from 'node:fs'; +import fsp from 'node:fs/promises'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { readPackageJSON } from '@vben/node-utils'; + +/** + * 用于生成将loading样式注入到项目中 + * 为多app提供loading样式,无需在每个 app -> index.html单独引入 + */ +async function viteInjectAppLoadingPlugin( + isBuild: boolean, + env: Record = {}, + loadingTemplate = 'loading.html', +): Promise { + const loadingHtml = await getLoadingRawByHtmlTemplate(loadingTemplate); + const { version } = await readPackageJSON(process.cwd()); + const envRaw = isBuild ? 'prod' : 'dev'; + const cacheName = `'${env.VITE_APP_NAMESPACE}-${version}-${envRaw}-preferences-theme'`; + + // 获取缓存的主题 + // 保证黑暗主题下,刷新页面时,loading也是黑暗主题 + const injectScript = ` + +`; + + if (!loadingHtml) { + return; + } + + return { + enforce: 'pre', + name: 'vite:inject-app-loading', + transformIndexHtml: { + handler(html) { + const re = //; + html = html.replace(re, `${injectScript}${loadingHtml}`); + return html; + }, + order: 'pre', + }, + }; +} + +/** + * 用于获取loading的html模板 + */ +async function getLoadingRawByHtmlTemplate(loadingTemplate: string) { + // 支持在app内自定义loading模板,模版参考default-loading.html即可 + let appLoadingPath = join(process.cwd(), loadingTemplate); + + if (!fs.existsSync(appLoadingPath)) { + const __dirname = fileURLToPath(new URL('.', import.meta.url)); + appLoadingPath = join(__dirname, './default-loading.html'); + } + + return await fsp.readFile(appLoadingPath, 'utf8'); +} + +export { viteInjectAppLoadingPlugin }; diff --git a/internal/vite-config/src/plugins/inject-metadata.ts b/internal/vite-config/src/plugins/inject-metadata.ts new file mode 100644 index 0000000..41c4db4 --- /dev/null +++ b/internal/vite-config/src/plugins/inject-metadata.ts @@ -0,0 +1,111 @@ +import type { PluginOption } from 'vite'; + +import { + dateUtil, + findMonorepoRoot, + getPackages, + readPackageJSON, +} from '@vben/node-utils'; + +import { readWorkspaceManifest } from '@pnpm/workspace.read-manifest'; + +function resolvePackageVersion( + pkgsMeta: Record, + name: string, + value: string, + catalog: Record, +) { + if (value.includes('catalog:')) { + return catalog[name]; + } + + if (value.includes('workspace')) { + return pkgsMeta[name]; + } + + return value; +} + +async function resolveMonorepoDependencies() { + const { packages } = await getPackages(); + const manifest = await readWorkspaceManifest(findMonorepoRoot()); + const catalog = manifest?.catalog || {}; + + const resultDevDependencies: Record = {}; + const resultDependencies: Record = {}; + const pkgsMeta: Record = {}; + + for (const { packageJson } of packages) { + pkgsMeta[packageJson.name] = packageJson.version; + } + + for (const { packageJson } of packages) { + const { dependencies = {}, devDependencies = {} } = packageJson; + for (const [key, value] of Object.entries(dependencies)) { + resultDependencies[key] = resolvePackageVersion( + pkgsMeta, + key, + value, + catalog, + ); + } + for (const [key, value] of Object.entries(devDependencies)) { + resultDevDependencies[key] = resolvePackageVersion( + pkgsMeta, + key, + value, + catalog, + ); + } + } + return { + dependencies: resultDependencies, + devDependencies: resultDevDependencies, + }; +} + +/** + * 用于注入项目信息 + */ +async function viteMetadataPlugin( + root = process.cwd(), +): Promise { + const { author, description, homepage, license, version } = + await readPackageJSON(root); + + const buildTime = dateUtil().format('YYYY-MM-DD HH:mm:ss'); + + return { + async config() { + const { dependencies, devDependencies } = + await resolveMonorepoDependencies(); + + const isAuthorObject = typeof author === 'object'; + const authorName = isAuthorObject ? author.name : author; + const authorEmail = isAuthorObject ? author.email : null; + const authorUrl = isAuthorObject ? author.url : null; + + return { + define: { + __VBEN_ADMIN_METADATA__: JSON.stringify({ + authorEmail, + authorName, + authorUrl, + buildTime, + dependencies, + description, + devDependencies, + homepage, + license, + version, + }), + 'import.meta.env.VITE_APP_VERSION': JSON.stringify(version), + }, + }; + }, + enforce: 'post', + name: 'vite:inject-metadata', + }; +} + +export { viteMetadataPlugin }; diff --git a/internal/vite-config/src/plugins/license.ts b/internal/vite-config/src/plugins/license.ts new file mode 100644 index 0000000..81fc4ff --- /dev/null +++ b/internal/vite-config/src/plugins/license.ts @@ -0,0 +1,63 @@ +import type { + NormalizedOutputOptions, + OutputBundle, + OutputChunk, +} from 'rollup'; +import type { PluginOption } from 'vite'; + +import { EOL } from 'node:os'; + +import { dateUtil, readPackageJSON } from '@vben/node-utils'; + +/** + * 用于注入版权信息 + * @returns + */ + +async function viteLicensePlugin( + root = process.cwd(), +): Promise { + const { + description = '', + homepage = '', + version = '', + } = await readPackageJSON(root); + + return { + apply: 'build', + enforce: 'post', + generateBundle: { + handler: (_options: NormalizedOutputOptions, bundle: OutputBundle) => { + const date = dateUtil().format('YYYY-MM-DD '); + const copyrightText = `/*! + * Vben Admin + * Version: ${version} + * Author: vben + * Copyright (C) 2024 Vben + * License: MIT License + * Description: ${description} + * Date Created: ${date} + * Homepage: ${homepage} + * Contact: ann.vben@gmail.com +*/ + `.trim(); + + for (const [, fileContent] of Object.entries(bundle)) { + if (fileContent.type === 'chunk' && fileContent.isEntry) { + const chunkContent = fileContent as OutputChunk; + // 插入版权信息 + const content = chunkContent.code; + const updatedContent = `${copyrightText}${EOL}${content}`; + + // 更新bundle + (fileContent as OutputChunk).code = updatedContent; + } + } + }, + order: 'post', + }, + name: 'vite:license', + }; +} + +export { viteLicensePlugin }; diff --git a/internal/vite-config/src/plugins/nitro-mock.ts b/internal/vite-config/src/plugins/nitro-mock.ts new file mode 100644 index 0000000..60d7327 --- /dev/null +++ b/internal/vite-config/src/plugins/nitro-mock.ts @@ -0,0 +1,98 @@ +import type { PluginOption } from 'vite'; + +import type { NitroMockPluginOptions } from '../typing'; + +import { colors, consola, getPackage } from '@vben/node-utils'; + +import getPort from 'get-port'; +import { build, createDevServer, createNitro, prepare } from 'nitropack'; + +const hmrKeyRe = /^runtimeConfig\.|routeRules\./; + +export const viteNitroMockPlugin = ({ + mockServerPackage = '@vben/backend-mock', + port = 5320, + verbose = true, +}: NitroMockPluginOptions = {}): PluginOption => { + return { + async configureServer(server) { + const availablePort = await getPort({ port }); + if (availablePort !== port) { + return; + } + + const pkg = await getPackage(mockServerPackage); + if (!pkg) { + consola.log( + `Package ${mockServerPackage} not found. Skip mock server.`, + ); + return; + } + + runNitroServer(pkg.dir, port, verbose); + + const _printUrls = server.printUrls; + server.printUrls = () => { + _printUrls(); + + consola.log( + ` ${colors.green('➜')} ${colors.bold('Nitro Mock Server')}: ${colors.cyan(`http://localhost:${port}/api`)}`, + ); + }; + }, + enforce: 'pre', + name: 'vite:mock-server', + }; +}; + +async function runNitroServer(rootDir: string, port: number, verbose: boolean) { + let nitro: any; + const reload = async () => { + if (nitro) { + consola.info('Restarting dev server...'); + if ('unwatch' in nitro.options._c12) { + await nitro.options._c12.unwatch(); + } + await nitro.close(); + } + nitro = await createNitro( + { + dev: true, + preset: 'nitro-dev', + rootDir, + }, + { + c12: { + async onUpdate({ getDiff, newConfig }) { + const diff = getDiff(); + if (diff.length === 0) { + return; + } + verbose && + consola.info( + `Nitro config updated:\n${diff + .map((entry) => ` ${entry.toString()}`) + .join('\n')}`, + ); + await (diff.every((e) => hmrKeyRe.test(e.key)) + ? nitro.updateConfig(newConfig.config) + : reload()); + }, + }, + watch: true, + }, + ); + nitro.hooks.hookOnce('restart', reload); + + const server = createDevServer(nitro); + await server.listen(port, { showURL: false }); + await prepare(nitro); + await build(nitro); + + if (verbose) { + console.log(''); + consola.success(colors.bold(colors.green('Nitro Mock Server started.'))); + } + }; + return await reload(); +} diff --git a/internal/vite-config/src/plugins/print.ts b/internal/vite-config/src/plugins/print.ts new file mode 100644 index 0000000..0146b8a --- /dev/null +++ b/internal/vite-config/src/plugins/print.ts @@ -0,0 +1,28 @@ +import type { PluginOption } from 'vite'; + +import type { PrintPluginOptions } from '../typing'; + +import { colors } from '@vben/node-utils'; + +export const vitePrintPlugin = ( + options: PrintPluginOptions = {}, +): PluginOption => { + const { infoMap = {} } = options; + + return { + configureServer(server) { + const _printUrls = server.printUrls; + server.printUrls = () => { + _printUrls(); + + for (const [key, value] of Object.entries(infoMap)) { + console.log( + ` ${colors.green('➜')} ${colors.bold(key)}: ${colors.cyan(value)}`, + ); + } + }; + }, + enforce: 'pre', + name: 'vite:print-info', + }; +}; diff --git a/internal/vite-config/src/plugins/vxe-table.ts b/internal/vite-config/src/plugins/vxe-table.ts new file mode 100644 index 0000000..3c107a7 --- /dev/null +++ b/internal/vite-config/src/plugins/vxe-table.ts @@ -0,0 +1,20 @@ +import type { PluginOption } from 'vite'; + +import { lazyImport, VxeResolver } from 'vite-plugin-lazy-import'; + +async function viteVxeTableImportsPlugin(): Promise { + return [ + lazyImport({ + resolvers: [ + VxeResolver({ + libraryName: 'vxe-table', + }), + VxeResolver({ + libraryName: 'vxe-pc-ui', + }), + ], + }), + ]; +} + +export { viteVxeTableImportsPlugin }; diff --git a/internal/vite-config/src/typing.ts b/internal/vite-config/src/typing.ts new file mode 100644 index 0000000..31683cc --- /dev/null +++ b/internal/vite-config/src/typing.ts @@ -0,0 +1,164 @@ +import type { PluginVisualizerOptions } from 'rollup-plugin-visualizer'; +import type { ConfigEnv, PluginOption, UserConfig } from 'vite'; +import type { PluginOptions } from 'vite-plugin-dts'; +import type { Options as PwaPluginOptions } from 'vite-plugin-pwa'; + +interface IImportMap { + imports?: Record; + scopes?: { + [scope: string]: Record; + }; +} +interface PrintPluginOptions { + /** + * 打印的数据 + */ + infoMap?: Record; +} + +interface NitroMockPluginOptions { + /** + * mock server 包名 + */ + mockServerPackage?: string; + + /** + * mock 服务端口 + */ + port?: number; + + /** + * mock 日志是否打印 + */ + verbose?: boolean; +} + +interface ArchiverPluginOptions { + /** + * 输出文件名 + * @default dist + */ + name?: string; + /** + * 输出目录 + * @default . + */ + outputDir?: string; +} + +/** + * importmap 插件配置 + */ +interface ImportmapPluginOptions { + /** + * CDN 供应商 + * @default jspm.io + */ + defaultProvider?: 'esm.sh' | 'jspm.io'; + /** importmap 配置 */ + importmap?: Array<{ name: string; range?: string }>; + /** 手动配置importmap */ + inputMap?: IImportMap; +} + +/** + * 用于判断是否需要加载插件 + */ +interface ConditionPlugin { + // 判断条件 + condition?: boolean; + // 插件对象 + plugins: () => PluginOption[] | PromiseLike; +} + +interface CommonPluginOptions { + /** 是否开启devtools */ + devtools?: boolean; + /** 环境变量 */ + env?: Record; + /** 是否注入metadata */ + injectMetadata?: boolean; + /** 是否构建模式 */ + isBuild?: boolean; + /** 构建模式 */ + mode?: string; + /** 开启依赖分析 */ + visualizer?: boolean | PluginVisualizerOptions; +} + +interface ApplicationPluginOptions extends CommonPluginOptions { + /** 开启后,会在打包dist同级生成dist.zip */ + archiver?: boolean; + /** 压缩归档插件配置 */ + archiverPluginOptions?: ArchiverPluginOptions; + /** 开启 gzip|brotli 压缩 */ + compress?: boolean; + /** 压缩类型 */ + compressTypes?: ('brotli' | 'gzip')[]; + /** 在构建的时候抽离配置文件 */ + extraAppConfig?: boolean; + /** 是否开启html插件 */ + html?: boolean; + /** 是否开启i18n */ + i18n?: boolean; + /** 是否开启 importmap CDN */ + importmap?: boolean; + /** importmap 插件配置 */ + importmapOptions?: ImportmapPluginOptions; + /** 是否注入app loading */ + injectAppLoading?: boolean; + /** 是否注入全局scss */ + injectGlobalScss?: boolean; + /** 是否注入版权信息 */ + license?: boolean; + /** 是否开启nitro mock */ + nitroMock?: boolean; + /** nitro mock 插件配置 */ + nitroMockOptions?: NitroMockPluginOptions; + /** 开启控制台自定义打印 */ + print?: boolean; + /** 打印插件配置 */ + printInfoMap?: PrintPluginOptions['infoMap']; + /** 是否开启pwa */ + pwa?: boolean; + /** pwa 插件配置 */ + pwaOptions?: Partial; + /** 是否开启vxe-table懒加载 */ + vxeTableLazyImport?: boolean; +} + +interface LibraryPluginOptions extends CommonPluginOptions { + /** 开启 dts 输出 */ + dts?: boolean | PluginOptions; +} + +type ApplicationOptions = ApplicationPluginOptions; + +type LibraryOptions = LibraryPluginOptions; + +type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{ + application?: ApplicationOptions; + vite?: UserConfig; +}>; + +type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{ + library?: LibraryOptions; + vite?: UserConfig; +}>; + +type DefineConfig = DefineApplicationOptions | DefineLibraryOptions; + +export type { + ApplicationPluginOptions, + ArchiverPluginOptions, + CommonPluginOptions, + ConditionPlugin, + DefineApplicationOptions, + DefineConfig, + DefineLibraryOptions, + IImportMap, + ImportmapPluginOptions, + LibraryPluginOptions, + NitroMockPluginOptions, + PrintPluginOptions, +}; diff --git a/internal/vite-config/src/utils/env.ts b/internal/vite-config/src/utils/env.ts new file mode 100644 index 0000000..f342216 --- /dev/null +++ b/internal/vite-config/src/utils/env.ts @@ -0,0 +1,110 @@ +import type { ApplicationPluginOptions } from '../typing'; + +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; + +import { fs } from '@vben/node-utils'; + +import dotenv from 'dotenv'; + +const getBoolean = (value: string | undefined) => value === 'true'; + +const getString = (value: string | undefined, fallback: string) => + value ?? fallback; + +const getNumber = (value: string | undefined, fallback: number) => + Number(value) || fallback; + +/** + * 获取当前环境下生效的配置文件名 + */ +function getConfFiles() { + const script = process.env.npm_lifecycle_script as string; + const reg = /--mode ([\d_a-z]+)/; + const result = reg.exec(script); + let mode = 'production'; + if (result) { + mode = result[1] as string; + } + return ['.env', '.env.local', `.env.${mode}`, `.env.${mode}.local`]; +} + +/** + * Get the environment variables starting with the specified prefix + * @param match prefix + * @param confFiles ext + */ +async function loadEnv>( + match = 'VITE_GLOB_', + confFiles = getConfFiles(), +) { + let envConfig = {}; + + for (const confFile of confFiles) { + try { + const confFilePath = join(process.cwd(), confFile); + if (existsSync(confFilePath)) { + const envPath = await fs.readFile(confFilePath, { + encoding: 'utf8', + }); + const env = dotenv.parse(envPath); + envConfig = { ...envConfig, ...env }; + } + } catch (error) { + console.error(`Error while parsing ${confFile}`, error); + } + } + const reg = new RegExp(`^(${match})`); + Object.keys(envConfig).forEach((key) => { + if (!reg.test(key)) { + Reflect.deleteProperty(envConfig, key); + } + }); + return envConfig as T; +} + +async function loadAndConvertEnv( + match = 'VITE_', + confFiles = getConfFiles(), +): Promise< + Partial & { + appTitle: string; + base: string; + port: number; + } +> { + const envConfig = await loadEnv(match, confFiles); + + const { + VITE_APP_TITLE, + VITE_ARCHIVER, + VITE_BASE, + VITE_COMPRESS, + VITE_DEVTOOLS, + VITE_INJECT_APP_LOADING, + VITE_NITRO_MOCK, + VITE_PORT, + VITE_PWA, + VITE_VISUALIZER, + } = envConfig; + + const compressTypes = (VITE_COMPRESS ?? '') + .split(',') + .filter((item) => item === 'brotli' || item === 'gzip'); + + return { + appTitle: getString(VITE_APP_TITLE, 'Vben Admin'), + archiver: getBoolean(VITE_ARCHIVER), + base: getString(VITE_BASE, '/'), + compress: compressTypes.length > 0, + compressTypes, + devtools: getBoolean(VITE_DEVTOOLS), + injectAppLoading: getBoolean(VITE_INJECT_APP_LOADING), + nitroMock: getBoolean(VITE_NITRO_MOCK), + port: getNumber(VITE_PORT, 5173), + pwa: getBoolean(VITE_PWA), + visualizer: getBoolean(VITE_VISUALIZER), + }; +} + +export { loadAndConvertEnv, loadEnv }; diff --git a/internal/vite-config/tsconfig.json b/internal/vite-config/tsconfig.json new file mode 100644 index 0000000..b2ec3b6 --- /dev/null +++ b/internal/vite-config/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1228fb0 --- /dev/null +++ b/package.json @@ -0,0 +1,118 @@ +{ + "name": "vben-admin-monorepo", + "version": "5.5.3", + "private": true, + "keywords": [ + "monorepo", + "turbo", + "vben", + "vben admin", + "vben pro", + "vue", + "vue admin", + "vue vben admin", + "vue vben admin pro", + "vue3" + ], + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": "vbenjs/vue-vben-admin.git", + "license": "MIT", + "author": { + "name": "vben", + "email": "ann.vben@gmail.com", + "url": "https://github.com/anncwb" + }, + "type": "module", + "scripts": { + "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build", + "build:analyze": "turbo build:analyze", + "build:antd": "pnpm run build --filter=@vben/web-antd", + "build:docker": "./scripts/deploy/build-local-docker-image.sh", + "build:docs": "pnpm run build --filter=@vben/docs", + "build:play": "pnpm run build --filter=@vben/playground", + "changeset": "pnpm exec changeset", + "check": "pnpm run check:circular && pnpm run check:dep && pnpm run check:type && pnpm check:cspell", + "check:circular": "vsh check-circular", + "check:cspell": "cspell lint **/*.ts **/README.md .changeset/*.md --no-progress", + "check:dep": "vsh check-dep", + "check:type": "turbo run typecheck", + "clean": "node ./scripts/clean.mjs", + "commit": "czg", + "dev": "turbo-run dev", + "dev:antd": "pnpm -F @vben/web-antd run dev", + "dev:docs": "pnpm -F @vben/docs run dev", + "dev:play": "pnpm -F @vben/playground run dev", + "format": "vsh lint --format", + "lint": "vsh lint", + "postinstall": "pnpm -r run stub --if-present", + "preinstall": "npx only-allow pnpm", + "prepare": "is-ci || husky", + "preview": "turbo-run preview", + "publint": "vsh publint", + "reinstall": "pnpm clean --del-lock && pnpm install", + "test:unit": "vitest run --dom", + "test:e2e": "turbo run test:e2e", + "update:deps": "npx taze -r -w", + "version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile" + }, + "devDependencies": { + "@changesets/changelog-github": "catalog:", + "@changesets/cli": "catalog:", + "@playwright/test": "catalog:", + "@types/node": "catalog:", + "@vben/commitlint-config": "workspace:*", + "@vben/eslint-config": "workspace:*", + "@vben/prettier-config": "workspace:*", + "@vben/stylelint-config": "workspace:*", + "@vben/tailwind-config": "workspace:*", + "@vben/tsconfig": "workspace:*", + "@vben/turbo-run": "workspace:*", + "@vben/vite-config": "workspace:*", + "@vben/vsh": "workspace:*", + "@vitejs/plugin-vue": "catalog:", + "@vitejs/plugin-vue-jsx": "catalog:", + "@vue/test-utils": "catalog:", + "autoprefixer": "catalog:", + "cross-env": "catalog:", + "cspell": "catalog:", + "happy-dom": "catalog:", + "husky": "catalog:", + "is-ci": "catalog:", + "lint-staged": "catalog:", + "playwright": "catalog:", + "rimraf": "catalog:", + "tailwindcss": "catalog:", + "turbo": "catalog:", + "typescript": "catalog:", + "unbuild": "catalog:", + "vite": "catalog:", + "vitest": "catalog:", + "vue": "catalog:", + "vue-tsc": "catalog:" + }, + "engines": { + "node": ">=20.10.0", + "pnpm": ">=9.12.0" + }, + "packageManager": "pnpm@9.15.3", + "pnpm": { + "peerDependencyRules": { + "allowedVersions": { + "eslint": "*" + } + }, + "overrides": { + "@ast-grep/napi": "catalog:", + "@ctrl/tinycolor": "catalog:", + "clsx": "catalog:", + "esbuild": "0.24.0", + "pinia": "catalog:", + "vue": "catalog:" + }, + "neverBuiltDependencies": [ + "canvas", + "node-gyp" + ] + } +} diff --git a/packages/@core/README.md b/packages/@core/README.md new file mode 100644 index 0000000..8eb201d --- /dev/null +++ b/packages/@core/README.md @@ -0,0 +1,3 @@ +# @vben-core + +系统一些比较基础的SDK和UI组件库,该目录后续完善后,可能会迁移出去或者发布到npm,请勿将任何业务逻辑和业务包放在该目录。 diff --git a/packages/@core/base/README.md b/packages/@core/base/README.md new file mode 100644 index 0000000..cc745b4 --- /dev/null +++ b/packages/@core/base/README.md @@ -0,0 +1,5 @@ +# base + +基础共享包,请勿引入 workspace 依赖 + +- diff --git a/packages/@core/base/design/package.json b/packages/@core/base/design/package.json new file mode 100644 index 0000000..ee19681 --- /dev/null +++ b/packages/@core/base/design/package.json @@ -0,0 +1,41 @@ +{ + "name": "@vben-core/design", + "version": "5.5.3", + "homepage": "https://github.com/vbenjs/vue-vben-admin", + "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "directory": "packages/@vben-core/base/design" + }, + "license": "MIT", + "type": "module", + "scripts": { + "build": "pnpm vite build", + "prepublishOnly": "npm run build" + }, + "files": [ + "dist", + "src" + ], + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "exports": { + "./bem": { + "development": "./src/scss-bem/bem.scss", + "default": "./dist/bem.scss" + }, + ".": { + "types": "./src/index.ts", + "development": "./src/index.ts", + "default": "./dist/design.css" + } + }, + "publishConfig": { + "exports": { + ".": { + "default": "./dist/index.mjs" + } + } + } +} diff --git a/packages/@core/base/design/src/css/global.css b/packages/@core/base/design/src/css/global.css new file mode 100644 index 0000000..d199909 --- /dev/null +++ b/packages/@core/base/design/src/css/global.css @@ -0,0 +1,160 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + *, + ::after, + ::before { + @apply border-border; + + box-sizing: border-box; + border-style: solid; + border-width: 0; + } + + html { + @apply text-foreground bg-background font-sans text-[100%]; + + font-variation-settings: normal; + line-height: 1.15; + text-size-adjust: 100%; + font-synthesis-weight: none; + scroll-behavior: smooth; + text-rendering: optimizelegibility; + -webkit-tap-highlight-color: transparent; + + /* -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; */ + } + + #app, + body, + html { + @apply size-full; + + /* scrollbar-gutter: stable; */ + } + + body { + min-height: 100vh; + + /* pointer-events: auto !important; */ + + /* overflow: overlay; */ + + /* -webkit-font-smoothing: antialiased; */ + + /* -moz-osx-font-smoothing: grayscale; */ + } + + a, + a:active, + a:hover, + a:link, + a:visited { + @apply no-underline; + } + + ::view-transition-new(root), + ::view-transition-old(root) { + @apply animate-none mix-blend-normal; + } + + ::view-transition-old(root) { + @apply z-[1]; + } + + ::view-transition-new(root) { + @apply z-[2147483646]; + } + + html.dark::view-transition-old(root) { + @apply z-[2147483646]; + } + + html.dark::view-transition-new(root) { + @apply z-[1]; + } + + input::placeholder, + textarea::placeholder { + @apply opacity-100; + } + + /* input:-webkit-autofill { + @apply border-none; + + box-shadow: 0 0 0 1000px transparent inset; + } */ + + input[type='number']::-webkit-inner-spin-button, + input[type='number']::-webkit-outer-spin-button { + @apply m-0 appearance-none; + } + + /* 只有非mac下才进行调整,mac下使用默认滚动条 */ + html:not([data-platform='macOs']) { + ::-webkit-scrollbar { + @apply h-[10px] w-[10px]; + } + + ::-webkit-scrollbar-thumb { + @apply bg-border rounded-sm border-none; + } + + ::-webkit-scrollbar-track { + @apply rounded-sm border-none bg-transparent shadow-none; + } + + ::-webkit-scrollbar-button { + @apply hidden; + } + } +} + +@layer components { + .flex-center { + @apply flex items-center justify-center; + } + + .flex-col-center { + @apply flex flex-col items-center justify-center; + } + + .outline-box { + @apply outline-border relative cursor-pointer rounded-md p-1 outline outline-1; + } + + .outline-box::after { + @apply absolute left-1/2 top-1/2 z-20 h-0 w-[1px] rounded-sm opacity-0 outline outline-2 outline-transparent transition-all duration-300 content-[""]; + } + + .outline-box.outline-box-active { + @apply outline-primary outline outline-2; + } + + .outline-box.outline-box-active::after { + display: none; + } + + .outline-box:not(.outline-box-active):hover::after { + @apply outline-primary left-0 top-0 h-full w-full p-1 opacity-100; + } + + .vben-link { + @apply text-primary hover:text-primary-hover active:text-primary-active cursor-pointer; + } + + .card-box { + @apply bg-card text-card-foreground border-border rounded-xl border; + } +} + +html.invert-mode { + @apply invert; +} + +html.grayscale-mode { + @apply grayscale; +} diff --git a/packages/@core/base/design/src/css/nprogress.css b/packages/@core/base/design/src/css/nprogress.css new file mode 100644 index 0000000..3503dab --- /dev/null +++ b/packages/@core/base/design/src/css/nprogress.css @@ -0,0 +1,59 @@ +/* Make clicks pass-through */ +#nprogress { + @apply pointer-events-none; +} + +#nprogress .bar { + @apply bg-primary fixed left-0 top-0 z-[1031] h-[2px] w-full; +} + +/* Fancy blur effect */ +#nprogress .peg { + @apply absolute right-0 block h-full w-[100px]; + + box-shadow: + 0 0 10px hsl(var(--primary)), + 0 0 5px hsl(var(--primary)); + opacity: 1; + transform: rotate(3deg) translate(0, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + @apply fixed right-4 top-4 z-[1031] block; +} + +#nprogress .spinner-icon { + @apply border-t-primary border-l-primary size-4 rounded-full border-[2px] border-solid border-transparent; + + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + @apply relative overflow-hidden; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + @apply absolute; +} + +@keyframes nprogress-spinner { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +@keyframes nprogress-spinner { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/packages/@core/base/design/src/css/transition.css b/packages/@core/base/design/src/css/transition.css new file mode 100644 index 0000000..c1cb0e4 --- /dev/null +++ b/packages/@core/base/design/src/css/transition.css @@ -0,0 +1,236 @@ +.slide-up-enter-active, +.slide-up-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-up-move { + transition: transform 0.3s; +} + +.slide-up-enter-from, +.slide-up-leave-to { + opacity: 0; + transform: translateY(-15px); +} + +.slide-down-enter-active, +.slide-down-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-down-move { + transition: transform 0.3s; +} + +.slide-down-enter-from, +.slide-down-leave-to { + opacity: 0; + transform: translateY(15px); +} + +.slide-left-enter-active, +.slide-left-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-left-move { + transition: transform 0.3s; +} + +.slide-left-enter-from, +.slide-left-leave-to { + opacity: 0; + transform: translate(-15px); +} + +.slide-right-enter-active, +.slide-right-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-right-move { + transition: transform 0.3s; +} + +.slide-right-enter-from, +.slide-right-leave-to { + opacity: 0; + transform: translate(15px); +} + +.fade-transition-enter-active, +.fade-transition-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-transition-enter-from, +.fade-transition-leave-to { + opacity: 0; +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + opacity: 0; + transform: translate(-30px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translate(30px); +} + +.fade-down-enter-active, +.fade-down-leave-active { + transition: + opacity 0.25s, + transform 0.3s; +} + +.fade-down-enter-from { + opacity: 0; + transform: translateY(-10%); +} + +.fade-down-leave-to { + opacity: 0; + transform: translateY(10%); +} + +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} + +.fade-scale-enter-from { + opacity: 0; + transform: scale(1.2); +} + +.fade-scale-leave-to { + opacity: 0; + transform: scale(0.8); +} + +.fade-up-enter-active, +.fade-up-leave-active { + transition: + opacity 0.2s, + transform 0.25s; +} + +.fade-up-enter-from { + opacity: 0; + transform: translateY(10%); +} + +.fade-up-leave-to { + opacity: 0; + transform: translateY(-10%); +} + +@keyframes fade-slide { + 0% { + opacity: 0; + transform: translate(-30px); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translate(30px); + } +} + +@keyframes fade { + 0% { + opacity: 0; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fade-up { + 0% { + opacity: 0; + transform: translateY(10%); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translateY(-10%); + } +} + +@keyframes fade-down { + 0% { + opacity: 0; + transform: translateY(-10%); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translateY(10%); + } +} + +.fade-slow { + animation: fade 3s infinite; +} + +.fade-slide-slow { + animation: fade-slide 3s infinite; +} + +.fade-up-slow { + animation: fade-up 3s infinite; +} + +.fade-down-slow { + animation: fade-down 3s infinite; +} + +.collapse-transition { + transition: + 0.2s height ease-in-out, + 0.2s padding-top ease-in-out, + 0.2s padding-bottom ease-in-out; +} + +.collapse-transition-leave-active, +.collapse-transition-enter-active { + transition: + 0.2s max-height ease-in-out, + 0.2s padding-top ease-in-out, + 0.2s margin-top ease-in-out; +} diff --git a/packages/@core/base/design/src/css/ui.css b/packages/@core/base/design/src/css/ui.css new file mode 100644 index 0000000..f7119c8 --- /dev/null +++ b/packages/@core/base/design/src/css/ui.css @@ -0,0 +1,87 @@ +.side-content { + animation-duration: 0.2s; + animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +.side-content[data-side='top'] { + animation-name: slide-up; +} + +.side-content[data-side='bottom'] { + animation-name: slide-down; +} + +.side-content[data-side='left'] { + animation-name: slide-left; +} + +.side-content[data-side='right'] { + animation-name: slide-right; +} + +.breadcrumb-transition-enter-active { + transition: + transform 0.4s cubic-bezier(0.76, 0, 0.24, 1), + opacity 0.4s cubic-bezier(0.76, 0, 0.24, 1); +} + +.breadcrumb-transition-leave-active { + display: none; +} + +.breadcrumb-transition-enter-from { + opacity: 0; + transform: translateX(30px) skewX(-30deg); +} + +@keyframes slide-down { + from { + opacity: 0; + transform: translateY(-10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slide-left { + from { + opacity: 0; + transform: translateX(-10px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slide-right { + from { + opacity: 0; + transform: translateX(-10px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slide-up { + from { + opacity: 0; + transform: translateY(10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.z-popup { + z-index: var(--popup-z-index); +} diff --git a/packages/@core/base/design/src/design-tokens/dark.css b/packages/@core/base/design/src/design-tokens/dark.css new file mode 100644 index 0000000..d34541e --- /dev/null +++ b/packages/@core/base/design/src/design-tokens/dark.css @@ -0,0 +1,446 @@ +.dark, +.dark[data-theme='custom'], +.dark[data-theme='default'] { + /* Default background color of ...etc */ + --background: 222.34deg 10.43% 12.27%; + + /* 主体区域背景色 */ + --background-deep: 220deg 13.06% 9%; + --foreground: 0 0% 95%; + + /* Background color for */ + --card: 222.34deg 10.43% 12.27%; + + /* --card: 222.2 84% 4.9%; */ + --card-foreground: 210 40% 98%; + + /* Background color for popovers such as , , */ + + /* --popover: 222.82deg 8.43% 12.27%; */ + + /* 弹出层的背景色与主题区域背景色太过接近 */ + --popover: 0 0 14.2%; + --popover-foreground: 210 40% 98%; + + /* Muted backgrounds such as , and */ + + /* --muted: 220deg 6.82% 17.25%; */ + + /* --muted-foreground: 215 20.2% 65.1%; */ + + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + + /* 主题颜色 */ + + /* --primary: 245 82% 67%; */ + --primary-foreground: 0 0% 98%; + + /* Used for destructive actions such as