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..5fda2cf --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: + - port: 5555 + onOpen: open-preview +tasks: + - init: npm i -g corepack && pnpm install + command: pnpm run dev:play diff --git a/.husky/_/commit-msg b/.husky/_/commit-msg new file mode 100644 index 0000000..2defe5f --- /dev/null +++ b/.husky/_/commit-msg @@ -0,0 +1,69 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook.exe -h >/dev/null 2>&1 + then + lefthook.exe "$@" + elif lefthook.bat -h >/dev/null 2>&1 + then + lefthook.bat "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif go tool lefthook -h >/dev/null 2>&1 + then + go tool lefthook "$@" + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package lefthook >/dev/null 2>&1 + then + swift package --build-path .build/lefthook --disable-sandbox lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif uv run lefthook -h >/dev/null 2>&1 + then + uv run lefthook "$@" + elif mise exec -- lefthook -h >/dev/null 2>&1 + then + mise exec -- lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "commit-msg" "$@" diff --git a/.husky/_/post-merge b/.husky/_/post-merge new file mode 100644 index 0000000..f8913fc --- /dev/null +++ b/.husky/_/post-merge @@ -0,0 +1,69 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook.exe -h >/dev/null 2>&1 + then + lefthook.exe "$@" + elif lefthook.bat -h >/dev/null 2>&1 + then + lefthook.bat "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif go tool lefthook -h >/dev/null 2>&1 + then + go tool lefthook "$@" + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package lefthook >/dev/null 2>&1 + then + swift package --build-path .build/lefthook --disable-sandbox lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif uv run lefthook -h >/dev/null 2>&1 + then + uv run lefthook "$@" + elif mise exec -- lefthook -h >/dev/null 2>&1 + then + mise exec -- lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "post-merge" "$@" diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit new file mode 100644 index 0000000..53ee229 --- /dev/null +++ b/.husky/_/pre-commit @@ -0,0 +1,69 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook.exe -h >/dev/null 2>&1 + then + lefthook.exe "$@" + elif lefthook.bat -h >/dev/null 2>&1 + then + lefthook.bat "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif go tool lefthook -h >/dev/null 2>&1 + then + go tool lefthook "$@" + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package lefthook >/dev/null 2>&1 + then + swift package --build-path .build/lefthook --disable-sandbox lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif uv run lefthook -h >/dev/null 2>&1 + then + uv run lefthook "$@" + elif mise exec -- lefthook -h >/dev/null 2>&1 + then + mise exec -- lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "pre-commit" "$@" diff --git a/.husky/_/prepare-commit-msg b/.husky/_/prepare-commit-msg new file mode 100644 index 0000000..0415d12 --- /dev/null +++ b/.husky/_/prepare-commit-msg @@ -0,0 +1,69 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook.exe -h >/dev/null 2>&1 + then + lefthook.exe "$@" + elif lefthook.bat -h >/dev/null 2>&1 + then + lefthook.bat "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook.exe" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook.exe" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif go tool lefthook -h >/dev/null 2>&1 + then + go tool lefthook "$@" + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package lefthook >/dev/null 2>&1 + then + swift package --build-path .build/lefthook --disable-sandbox lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif uv run lefthook -h >/dev/null 2>&1 + then + uv run lefthook "$@" + elif mise exec -- lefthook -h >/dev/null 2>&1 + then + mise exec -- lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "prepare-commit-msg" "$@" diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..ee5c244 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +22.1.0 diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..21147af --- /dev/null +++ b/.npmrc @@ -0,0 +1,13 @@ +registry = "https://registry.npmmirror.com" +public-hoist-pattern[]=lefthook +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..1cfc017 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,241 @@ +{ + "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": true, + "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, + "**/.vitepress": 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 + }, + + "typescript.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"], + + // 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,lefthook.yml", + "tailwind.config.mjs": "postcss.*" + }, + "commentTranslate.hover.enabled": false, + "commentTranslate.multiLineMerge": true, + "vue.server.hybridMode": true, + "typescript.tsdk": "node_modules/typescript/lib", + "oxc.enable": false, + "cSpell.words": [ + "archiver", + "axios", + "dotenv", + "isequal", + "jspm", + "napi", + "nolebase", + "rollup", + "vitest" + ] +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..82fd821 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +FROM node:20-slim 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/_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..1005666 --- /dev/null +++ b/apps/web-antd/.env @@ -0,0 +1,8 @@ +# 应用标题 +VITE_APP_TITLE=采集端综合管理 + +# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 +VITE_APP_NAMESPACE=abp-vnext-pro-vben5-antd + +# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 +VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key 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..650c1ed --- /dev/null +++ b/apps/web-antd/.env.development @@ -0,0 +1,37 @@ +# 端口号 +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://182.43.18.151:44317 + +# # websocket地址 +# VITE_WEBSOCKET_URL=http://182.43.18.151:44317/signalr/notification + +# 后端接口地址 +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..dc56f3d --- /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://182.43.18.151:44317 + +# websocket地址 +VITE_WEBSOCKET_URL=http://182.43.18.151:44317/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..8efbd69 --- /dev/null +++ b/apps/web-antd/package.json @@ -0,0 +1,62 @@ +{ + "name": "@vben/web-antd", + "version": "5.5.6", + "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": { + "@iconify/json": "^2.2.282", + "@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/avatar-v1.webp b/apps/web-antd/public/avatar-v1.webp new file mode 100644 index 0000000..9f6ba9a Binary files /dev/null and b/apps/web-antd/public/avatar-v1.webp differ diff --git a/apps/web-antd/public/favicon.ico b/apps/web-antd/public/favicon.ico new file mode 100644 index 0000000..fcf9818 Binary files /dev/null and b/apps/web-antd/public/favicon.ico differ diff --git a/apps/web-antd/public/logo-v1.webp b/apps/web-antd/public/logo-v1.webp new file mode 100644 index 0000000..25a6f39 Binary files /dev/null and b/apps/web-antd/public/logo-v1.webp differ diff --git a/apps/web-antd/src/adapter/component/index.ts b/apps/web-antd/src/adapter/component/index.ts new file mode 100644 index 0000000..d452d52 --- /dev/null +++ b/apps/web-antd/src/adapter/component/index.ts @@ -0,0 +1,218 @@ +/** + * 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用 + * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, + */ + +import type { Component } from 'vue'; + +import type { BaseFormComponentType } from '@vben/common-ui'; +import type { Recordable } from '@vben/types'; + +import { + defineAsyncComponent, + defineComponent, + getCurrentInstance, + h, + ref, +} from 'vue'; + +import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; +import { $t } from '@vben/locales'; + +import { notification } from 'ant-design-vue'; + +const AutoComplete = defineAsyncComponent( + () => import('ant-design-vue/es/auto-complete'), +); +const Button = defineAsyncComponent(() => import('ant-design-vue/es/button')); +const Checkbox = defineAsyncComponent( + () => import('ant-design-vue/es/checkbox'), +); +const CheckboxGroup = defineAsyncComponent(() => + import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup), +); +const DatePicker = defineAsyncComponent( + () => import('ant-design-vue/es/date-picker'), +); +const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider')); +const Input = defineAsyncComponent(() => import('ant-design-vue/es/input')); +const InputNumber = defineAsyncComponent( + () => import('ant-design-vue/es/input-number'), +); +const InputPassword = defineAsyncComponent(() => + import('ant-design-vue/es/input').then((res) => res.InputPassword), +); +const Mentions = defineAsyncComponent( + () => import('ant-design-vue/es/mentions'), +); +const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio')); +const RadioGroup = defineAsyncComponent(() => + import('ant-design-vue/es/radio').then((res) => res.RadioGroup), +); +const RangePicker = defineAsyncComponent(() => + import('ant-design-vue/es/date-picker').then((res) => res.RangePicker), +); +const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate')); +const Select = defineAsyncComponent(() => import('ant-design-vue/es/select')); +const Space = defineAsyncComponent(() => import('ant-design-vue/es/space')); +const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch')); +const Textarea = defineAsyncComponent(() => + import('ant-design-vue/es/input').then((res) => res.Textarea), +); +const TimePicker = defineAsyncComponent( + () => import('ant-design-vue/es/time-picker'), +); +const TreeSelect = defineAsyncComponent( + () => import('ant-design-vue/es/tree-select'), +); +const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload')); + +const withDefaultPlaceholder = ( + component: T, + type: 'input' | 'select', + componentProps: Recordable = {}, +) => { + return defineComponent({ + name: component.name, + inheritAttrs: false, + setup: (props: any, { attrs, expose, slots }) => { + const placeholder = + props?.placeholder || + attrs?.placeholder || + $t(`ui.placeholder.${type}`); + // 透传组件暴露的方法 + const innerRef = ref(); + const publicApi: Recordable = {}; + expose(publicApi); + const instance = getCurrentInstance(); + instance?.proxy?.$nextTick(() => { + for (const key in innerRef.value) { + if (typeof innerRef.value[key] === 'function') { + publicApi[key] = innerRef.value[key]; + } + } + }); + return () => + h( + component, + { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef }, + 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: withDefaultPlaceholder( + { + ...ApiComponent, + name: 'ApiSelect', + }, + 'select', + { + component: Select, + loadingSlot: 'suffixIcon', + visibleEvent: 'onDropdownVisibleChange', + modelPropName: 'value', + }, + ), + ApiTreeSelect: withDefaultPlaceholder( + { + ...ApiComponent, + name: 'ApiTreeSelect', + }, + 'select', + { + component: TreeSelect, + fieldNames: { label: 'label', value: 'value', children: 'children' }, + loadingSlot: 'suffixIcon', + modelPropName: 'value', + optionsPropName: 'treeData', + visibleEvent: 'onVisibleChange', + }, + ), + AutoComplete, + Checkbox, + CheckboxGroup, + DatePicker, + // 自定义默认按钮 + DefaultButton: (props, { attrs, slots }) => { + return h(Button, { ...props, attrs, type: 'default' }, slots); + }, + Divider, + IconPicker: withDefaultPlaceholder(IconPicker, 'select', { + iconSlot: 'addonAfter', + inputComponent: Input, + modelValueProp: 'value', + }), + 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..90081e2 --- /dev/null +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -0,0 +1,72 @@ +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, + }, + sortConfig: { + remote: true, + }, + proxyConfig: { + sort: true, // 启用排序请求代理 + autoLoad: true, + response: { + result: 'items', + total: 'totalCount', + list: 'items', + }, + showActiveMsg: true, + showResponseMsg: false, + }, + round: true, + showOverflow: true, + stripe: 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..d562e98 --- /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/AbpPro/swagger.json', + output: 'src/api-client', +}); 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..97d6367 --- /dev/null +++ b/apps/web-antd/src/api-client-config/index.ts @@ -0,0 +1,143 @@ +import { useAccessStore, useUserStore } from '@vben/stores'; + +import { message as Message } from 'ant-design-vue'; + +import { postApiAppAccountRefreshToken } from '#/api-client'; +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, +}); +// 是否正在刷新token +let isRefreshing = false; +// 刷新token队列 +let refreshTokenQueue: ((token: string) => void)[] = []; +client.instance.interceptors.request.use((request) => { + // 全局拦截请求发送前提交的参数 + const userStore = useUserStore(); + const accessStore = useAccessStore(); + const token = accessStore.getAccessToken(); + // 设置请求头 + 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 (request.headers) { + request.headers.Authorization = `Bearer ${token}`; + } + + return request; +}); + +client.instance.interceptors.response.use( + (response) => { + return Promise.resolve(response); + }, + async (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'); + const { config } = error; + const originalRequest = config; + if (isRefreshing) { + return new Promise((resolve) => { + refreshTokenQueue.push((token) => { + originalRequest.headers.Authorization = `Bearer ${token}`; + resolve(client.request(originalRequest)); + }); + }); + } else { + isRefreshing = true; + try { + const newToken = await refreshTokenAsync(); + // 处理队列中的请求 + refreshTokenQueue.forEach((callback) => callback(newToken)); + // 清空队列 + refreshTokenQueue = []; + return client.request(originalRequest); + } catch (refreshError) { + // 如果刷新 token 失败,处理错误(如强制登出或跳转登录页面) + message = $t('common.mesage401'); + refreshTokenQueue = []; + const authStore = useAuthStore(); + authStore.logout(); + console.error(refreshError); + } finally { + isRefreshing = false; + } + } + 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); + throw error; + }, +); + +async function refreshTokenAsync(): Promise { + try { + const userStore = useUserStore(); + const accessStore = useAccessStore(); + const refreshToken = accessStore.getRefreshToken(); + if (!refreshToken) return ''; + const res = await postApiAppAccountRefreshToken({ + body: { + userId: userStore.userInfo?.id, + refreshToken, + }, + }); + if (res?.data?.success) { + accessStore.setAccessToken(res.data.token as string); + accessStore.setRefreshToken(res.data.refreshToken as string); + return res.data.token as string; + } else { + throw new Error('get refreshToken error'); + } + } catch { + throw new Error($t('common.mesage401')); + } +} +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..002afc3 --- /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'; 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..6bdde7c --- /dev/null +++ b/apps/web-antd/src/api-client/schemas.gen.ts @@ -0,0 +1,8221 @@ +// 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 AbpProApplicationConfigurationDtoSchema = { + type: 'object', + properties: { + oidcConfiguration: { + $ref: '#/components/schemas/ApplicationOidcConfigurationDto', + }, + multiTenancy: { + $ref: '#/components/schemas/MultiTenancyInfoDto', + }, + }, + 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', + description: 'id', + format: 'uuid', + }, + name: { + type: 'string', + description: '连接字符串名称', + nullable: true, + }, + value: { + type: 'string', + description: '连接字符串地址', + 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 ApplicationOidcConfigurationDtoSchema = { + type: 'object', + properties: { + enabled: { + type: 'boolean', + description: '是否启用', + }, + oidcConfiguration: { + type: 'array', + items: { + $ref: '#/components/schemas/OidcConfiguration', + }, + 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 ControlTypeSchema = { + enum: [10, 20, 30, 40], + type: 'integer', + description: '控制策略', + format: 'int32', + 'x-enumNames': ['Aggregate', 'Entity', 'Enum', 'Global'], + 'x-enum-varnames': ['Aggregate', 'Entity', 'Enum', 'Global'], +} 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 CopyTemplateInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const CreateAggregateInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + projectId: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + }, + 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 CreateEntityModelInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + relationalType: { + $ref: '#/components/schemas/RelationalType', + }, + }, + additionalProperties: false, +} as const; + +export const CreateEntityModelPropertyInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + isRequired: { + type: 'boolean', + description: '必填', + }, + maxLength: { + type: 'integer', + description: '字符串最大长度', + format: 'int32', + nullable: true, + }, + minLength: { + type: 'integer', + description: '字符串最小长度', + format: 'int32', + nullable: true, + }, + decimalPrecision: { + type: 'integer', + description: '当类型为decimal时的小数位数 (18,4) 中的18', + format: 'int32', + nullable: true, + }, + decimalScale: { + type: 'integer', + description: '当类型为decimal时的字段长度 (18,4) 中的4', + format: 'int32', + nullable: true, + }, + enumTypeId: { + type: 'string', + description: '枚举类型Id', + format: 'uuid', + nullable: true, + }, + dataTypeId: { + type: 'string', + description: '数据类型Id', + format: 'uuid', + nullable: true, + }, + allowSearch: { + type: 'boolean', + description: '允许作为查询条件', + }, + allowAdd: { + type: 'boolean', + description: '允许添加', + }, + allowEdit: { + type: 'boolean', + description: '允许编辑', + }, + }, + additionalProperties: false, +} as const; + +export const CreateEnumTypeInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + entityModelId: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + projectId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const CreateEnumTypePropertyInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + enumTypeId: { + type: 'string', + description: 'Id', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + value: { + type: 'integer', + description: '枚举值', + format: 'int32', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + }, + additionalProperties: false, +} as const; + +export const CreateLanguageInputSchema = { + type: 'object', + properties: { + cultureName: { + type: 'string', + description: '语言名称', + nullable: true, + }, + uiCultureName: { + type: 'string', + description: 'Ui语言名称', + nullable: true, + }, + displayName: { + type: 'string', + description: '显示名称', + nullable: true, + }, + flagIcon: { + type: 'string', + description: '图标', + nullable: true, + }, + isEnabled: { + type: 'boolean', + description: '是否启用', + }, + }, + additionalProperties: false, + description: '创建语言', +} as const; + +export const CreateLanguageTextInputSchema = { + type: 'object', + properties: { + resourceName: { + type: 'string', + description: '资源名称', + nullable: true, + }, + cultureName: { + type: 'string', + description: '语言名称', + nullable: true, + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + value: { + type: 'string', + description: '值', + nullable: true, + }, + }, + additionalProperties: false, + description: '创建语言文本', +} as const; + +export const CreateMenuInputSchema = { + required: ['hideInMenu', 'keepAlive', 'name', 'order', 'path', 'title'], + type: 'object', + properties: { + parentId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + name: { + minLength: 1, + type: 'string', + description: '唯一编码', + }, + title: { + minLength: 1, + type: 'string', + description: '标题', + }, + displayTitle: { + type: 'string', + description: '标题', + nullable: true, + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + keepAlive: { + type: 'boolean', + description: '是否缓存', + }, + hideInMenu: { + type: 'boolean', + description: '是否显示', + }, + order: { + type: 'integer', + description: '排序', + format: 'int32', + }, + path: { + minLength: 1, + type: 'string', + description: '路由地址', + }, + menuType: { + $ref: '#/components/schemas/MenuType', + }, + openType: { + $ref: '#/components/schemas/OpenType', + }, + url: { + type: 'string', + description: '内外链地址', + nullable: true, + }, + component: { + type: 'string', + description: '组件地址', + nullable: true, + }, + enabled: { + type: 'boolean', + description: '是否启用', + }, + policy: { + type: 'string', + description: '权限', + nullable: true, + }, + }, + additionalProperties: false, + description: '创建菜单', +} 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 CreateProjectInputSchema = { + type: 'object', + properties: { + owner: { + type: 'string', + description: '负责人', + nullable: true, + }, + companyName: { + type: 'string', + description: '公司名称', + nullable: true, + }, + projectName: { + type: 'string', + description: '项目名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + supportTenant: { + type: 'boolean', + description: '是否支持多租户', + }, + }, + additionalProperties: false, +} as const; + +export const CreateTemplateDetailInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + parentId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + templateType: { + $ref: '#/components/schemas/TemplateType', + }, + controlType: { + $ref: '#/components/schemas/ControlType', + }, + name: { + type: 'string', + description: '模板类型', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const CreateTemplateInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + description: '名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const CreateTextTemplateInputSchema = { + required: ['code', 'content', 'cultureName', 'name'], + type: 'object', + properties: { + name: { + minLength: 1, + type: 'string', + description: '名称', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + content: { + minLength: 1, + type: 'string', + description: '内容', + }, + cultureName: { + minLength: 1, + type: 'string', + description: '语言', + }, + }, + additionalProperties: false, + description: '创建模板', +} 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 DataTypeDtoSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '编码', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + isEnum: { + type: 'boolean', + description: '是否是枚举', + }, + }, + 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 DeleteAggregateInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteConnectionStringInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + description: '连接字符串名称', + nullable: true, + }, + tenantId: { + type: 'string', + description: '租户id', + 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 DeleteEntityModelInputSchema = { + type: 'object', + properties: { + aggregateId: { + type: 'string', + format: 'uuid', + }, + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteEntityModelPropertyInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + propertyId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteEnumTypeInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: 'Id', + format: 'uuid', + }, + entityModelId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteEnumTypePropertyInputSchema = { + type: 'object', + properties: { + enumTypeId: { + type: 'string', + description: 'Id', + format: 'uuid', + }, + id: { + type: 'string', + description: 'Id', + 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 DeleteFileObjectInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '文件Id', + format: 'uuid', + }, + }, + additionalProperties: false, + description: '删除文件', +} as const; + +export const DeleteLanguageInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '语言Id', + format: 'uuid', + }, + }, + additionalProperties: false, + description: '删除语言', +} as const; + +export const DeleteMenuInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '菜单Id', + format: 'uuid', + }, + }, + additionalProperties: false, + description: '删除菜单', +} as const; + +export const DeleteMessageInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + receiverUserId: { + type: 'string', + description: '接受者Id', + format: 'uuid', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const DeleteProjectInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteTemplateDetailInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + format: 'uuid', + }, + templateDetailId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteTemplateInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const DeleteTextTemplateInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '模板Id', + format: 'uuid', + }, + }, + additionalProperties: false, + description: '删除模板', +} as const; + +export const DisabledTwoFactorInputSchema = { + required: ['code'], + type: 'object', + properties: { + code: { + minLength: 1, + type: 'string', + description: '验证码', + }, + }, + additionalProperties: false, +} as const; + +export const DownCodeInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + format: 'uuid', + }, + projectId: { + type: 'string', + format: 'uuid', + }, + entityId: { + type: 'array', + items: { + type: 'string', + format: 'uuid', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const DownloadFileObjectInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '文件Id', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const EnabledTwoFactorInputSchema = { + required: ['code', 'secret'], + type: 'object', + properties: { + code: { + minLength: 1, + type: 'string', + description: '验证码', + }, + secret: { + minLength: 1, + type: 'string', + description: '密钥', + }, + }, + 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 EntityOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '编码', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + codeCamelCase: { + type: 'string', + description: '首字母小写', + nullable: true, + readOnly: true, + }, + codePluralized: { + type: 'string', + description: '复数形式', + nullable: true, + readOnly: 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 GetDataTypeInputSchema = { + type: 'object', + properties: { + entityModelId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetDataTypeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '枚举编码', + nullable: true, + }, + description: { + type: 'string', + description: '枚举描述', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetEntityModelInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetEntityModelOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '编码', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + relationalType: { + $ref: '#/components/schemas/RelationalType', + }, + entityModelProperties: { + type: 'array', + items: { + $ref: '#/components/schemas/GetEntityModelPropertyOutput', + }, + description: '实体模型属性集合', + nullable: true, + }, + entityModelOutputs: { + type: 'array', + items: { + $ref: '#/components/schemas/GetEntityModelOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetEntityModelPropertyOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + isRequired: { + type: 'boolean', + description: '必填', + }, + maxLength: { + type: 'integer', + description: '字符串最大长度', + format: 'int32', + nullable: true, + }, + minLength: { + type: 'integer', + description: '字符串最小长度', + format: 'int32', + nullable: true, + }, + decimalPrecision: { + type: 'integer', + description: '当类型为decimal时的小数位数 (18,4) 中的18', + format: 'int32', + nullable: true, + }, + decimalScale: { + type: 'integer', + description: '当类型为decimal时的字段长度 (18,4) 中的4', + format: 'int32', + nullable: true, + }, + enumTypeId: { + type: 'string', + description: '枚举类型Id', + format: 'uuid', + nullable: true, + }, + isEnum: { + type: 'boolean', + }, + enumTypeOutput: { + $ref: '#/components/schemas/GetEnumTypeOutput', + }, + dataTypeId: { + type: 'string', + description: '数据类型Id', + format: 'uuid', + nullable: true, + }, + dataTypeOutput: { + $ref: '#/components/schemas/GetDataTypeOutput', + }, + entityModelId: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetEntityModelTreeInputSchema = { + type: 'object', + properties: { + projectId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetEntityModelTreeOutputSchema = { + type: 'object', + properties: { + key: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + code: { + type: 'string', + description: '描述', + nullable: true, + }, + title: { + type: 'string', + description: '描述', + nullable: true, + }, + parentId: { + type: 'string', + description: '父类Id', + format: 'uuid', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + relationalType: { + $ref: '#/components/schemas/RelationalType', + }, + children: { + type: 'array', + items: { + $ref: '#/components/schemas/GetEntityModelTreeOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetEnumTypeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '枚举编码', + nullable: true, + }, + description: { + type: 'string', + description: '枚举描述', + nullable: true, + }, + }, + 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 GetMenuTreeMetaOutputSchema = { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true, + }, + displayTitle: { + type: 'string', + nullable: true, + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + order: { + type: 'integer', + description: '排序', + format: 'int32', + }, + keepAlive: { + type: 'boolean', + description: '是否缓存', + }, + hideInMenu: { + type: 'boolean', + description: '是否显示', + }, + link: { + type: 'string', + description: '外链地址', + nullable: true, + }, + iframeSrc: { + type: 'string', + description: '内链地址', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetMenuTreeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + parentId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + path: { + type: 'string', + nullable: true, + }, + component: { + type: 'string', + nullable: true, + }, + enabled: { + type: 'boolean', + }, + meta: { + $ref: '#/components/schemas/GetMenuTreeMetaOutput', + }, + children: { + type: 'array', + items: { + $ref: '#/components/schemas/GetMenuTreeOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetOrganizationUnitRoleInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: 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 GetProjectAndEntityInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetProjectAndEntityOutputSchema = { + type: 'object', + properties: { + project: { + $ref: '#/components/schemas/ProjectOutput', + }, + entities: { + type: 'array', + items: { + $ref: '#/components/schemas/EntityOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetQRCodeOutputSchema = { + type: 'object', + properties: { + qrCode: { + type: 'string', + description: 'base64 二维码', + format: 'byte', + nullable: true, + }, + secret: { + type: 'string', + description: '密钥', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetTemplateTreeOutputSchema = { + type: 'object', + properties: { + key: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + templateType: { + $ref: '#/components/schemas/TemplateType', + }, + controlType: { + $ref: '#/components/schemas/ControlType', + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + name: { + type: 'string', + description: '模板名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + title: { + type: 'string', + description: '描述', + nullable: true, + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + children: { + type: 'array', + items: { + $ref: '#/components/schemas/GetTemplateTreeOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const GetTemplteTreeInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + format: 'uuid', + }, + }, + additionalProperties: false, +} as const; + +export const GetUnAddRoleInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: 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, + }, + creationTime: { + type: 'string', + format: 'date-time', + }, + }, + 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 Login2FAInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + description: '用户名或者邮箱', + nullable: true, + }, + password: { + type: 'string', + description: '密码', + nullable: true, + }, + code: { + type: 'string', + description: '双因素验证码', + nullable: true, + }, + }, + additionalProperties: false, + description: '登录', +} as const; + +export const LoginInputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + description: '用户名或者邮箱', + nullable: true, + }, + password: { + type: 'string', + description: '密码', + nullable: true, + }, + }, + additionalProperties: false, + description: '登录', +} as const; + +export const LoginOidcInputSchema = { + required: ['code', 'state'], + type: 'object', + properties: { + code: { + minLength: 1, + type: 'string', + description: 'code', + }, + state: { + minLength: 1, + type: 'string', + description: 'Provider', + }, + }, + additionalProperties: false, + description: '登录', +} 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, + }, + refreshToken: { + 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 MenuTypeSchema = { + enum: [10, 20], + type: 'integer', + description: '菜单类型', + format: 'int32', + 'x-enumNames': ['Folder', 'Menu'], + 'x-enum-varnames': ['Folder', 'Menu'], +} as const; + +export const MessageLevelSchema = { + enum: [10, 20, 30], + type: 'integer', + description: '消息等级', + format: 'int32', + 'x-enumNames': ['Warning', 'Information', 'Error'], + 'x-enum-varnames': ['Warning', 'Information', 'Error'], +} as const; + +export const MessageTypeSchema = { + enum: [10, 20], + type: 'integer', + description: '消息类型', + 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 NeedChangePasswordOutputSchema = { + type: 'object', + properties: { + needChangePassword: { + type: 'boolean', + }, + message: { + 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 OidcConfigurationSchema = { + type: 'object', + properties: { + enabled: { + type: 'boolean', + description: '是否启用', + }, + type: { + type: 'string', + description: '类型', + nullable: true, + }, + clientId: { + type: 'string', + description: 'client_id', + nullable: true, + }, + clientName: { + type: 'string', + description: '应用名称', + nullable: true, + }, + icon: { + type: 'string', + description: '应用图标', + nullable: true, + }, + authUri: { + type: 'string', + description: '认证地址', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const OpenTypeSchema = { + enum: [10, 20, 30, 40], + type: 'integer', + description: '打开类型', + format: 'int32', + 'x-enumNames': ['Default', 'Component', 'InternalLink', 'ExternalLink'], + 'x-enum-varnames': ['Default', 'Component', 'InternalLink', 'ExternalLink'], +} as const; + +export const PageEntityModelInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + id: { + type: 'string', + format: 'uuid', + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageEntityModelPropertyOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + nullable: true, + }, + entityModelId: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + code: { + type: 'string', + description: '名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + isRequired: { + type: 'boolean', + description: '必填', + }, + maxLength: { + type: 'integer', + description: '字符串最大长度', + format: 'int32', + nullable: true, + }, + minLength: { + type: 'integer', + description: '字符串最小长度', + format: 'int32', + nullable: true, + }, + decimalPrecision: { + type: 'integer', + description: '当类型为decimal时的小数位数 (18,4) 中的18', + format: 'int32', + nullable: true, + }, + decimalScale: { + type: 'integer', + description: '当类型为decimal时的字段长度 (18,4) 中的4', + format: 'int32', + nullable: true, + }, + dataTypeId: { + type: 'string', + format: 'uuid', + }, + isEnum: { + type: 'boolean', + }, + dataTypeCode: { + type: 'string', + nullable: true, + }, + dataTypeDescription: { + type: 'string', + nullable: true, + }, + allowSearch: { + type: 'boolean', + description: '允许作为查询条件', + }, + allowAdd: { + type: 'boolean', + description: '允许添加', + }, + allowEdit: { + type: 'boolean', + description: '允许编辑', + }, + }, + additionalProperties: false, +} as const; + +export const PageEntityModelPropertyOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageEntityModelPropertyOutput', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypeInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + id: { + type: 'string', + format: 'uuid', + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypeOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + nullable: true, + }, + entityModelId: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + code: { + type: 'string', + description: '名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + creationTime: { + type: 'string', + format: 'date-time', + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypeOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageEnumTypeOutput', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypePropertyInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + id: { + type: 'string', + format: 'uuid', + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypePropertyOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + nullable: true, + }, + code: { + type: 'string', + description: '名称', + nullable: true, + }, + value: { + type: 'integer', + description: '名称', + format: 'int32', + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + creationTime: { + type: 'string', + format: 'date-time', + }, + }, + additionalProperties: false, +} as const; + +export const PageEnumTypePropertyOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageEnumTypePropertyOutput', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const PageFileObjectInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + startCreationTime: { + type: 'string', + description: '开始创建时间', + format: 'date-time', + nullable: true, + }, + endCreationTime: { + type: 'string', + description: '结束创建时间', + format: 'date-time', + nullable: true, + }, + fileName: { + type: 'string', + description: '文件名称', + nullable: true, + }, + }, + additionalProperties: false, + description: '分页查询文件', +} as const; + +export const PageFileObjectOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '文件Id', + format: 'uuid', + }, + fileSize: { + type: 'integer', + description: '文件大小', + format: 'int64', + }, + beautifySize: { + type: 'string', + nullable: true, + readOnly: true, + }, + contentType: { + type: 'string', + description: '文件名称', + nullable: true, + }, + fileName: { + type: 'string', + description: '文件名称', + nullable: true, + }, + creationTime: { + type: 'string', + description: '创建时间', + format: 'date-time', + }, + }, + additionalProperties: false, + description: '分页查询文件', +} as const; + +export const PageFileObjectOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageFileObjectOutput', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + 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', + description: '是否开启双因素验证码', + }, + }, + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, + description: '创建语言', +} as const; + +export const PageLanguageOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '语言Id', + format: 'uuid', + }, + cultureName: { + type: 'string', + description: '语言名称', + nullable: true, + }, + uiCultureName: { + type: 'string', + description: 'Ui语言名称', + nullable: true, + }, + displayName: { + type: 'string', + description: '显示名称', + nullable: true, + }, + flagIcon: { + type: 'string', + description: '图标', + nullable: true, + }, + isEnabled: { + type: 'boolean', + description: '是否启用', + }, + creationTime: { + type: 'string', + description: '创建时间', + format: 'date-time', + }, + isDefault: { + type: 'boolean', + description: '是否是默认语言', + }, + }, + additionalProperties: false, + description: '创建语言', +} 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + cultureName: { + type: 'string', + description: '语言', + nullable: true, + }, + resourceName: { + type: 'string', + description: '资源', + nullable: true, + }, + filter: { + type: 'string', + description: '查询条件 name or value', + nullable: true, + }, + }, + additionalProperties: false, + description: '创建语言文本', +} as const; + +export const PageLanguageTextOutputSchema = { + type: 'object', + properties: { + resourceName: { + type: 'string', + description: '资源名称', + nullable: true, + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + value: { + type: 'string', + description: '值', + nullable: true, + }, + }, + additionalProperties: false, + description: '创建语言文本', +} 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 PageMenuInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + startCreationTime: { + type: 'string', + description: '开始创建时间', + format: 'date-time', + nullable: true, + }, + endCreationTime: { + type: 'string', + description: '结束创建时间', + format: 'date-time', + nullable: true, + }, + }, + additionalProperties: false, + description: '分页查询菜单', +} as const; + +export const PageMenuOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '菜单Id', + format: 'uuid', + }, + parentId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + name: { + type: 'string', + description: '唯一编码', + nullable: true, + }, + localizationTitle: { + type: 'string', + description: '标题', + nullable: true, + }, + displayTitle: { + type: 'string', + description: '标题', + nullable: true, + }, + title: { + type: 'string', + description: '标题', + nullable: true, + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + keepAlive: { + type: 'boolean', + description: '是否缓存', + }, + hideInMenu: { + type: 'boolean', + description: '是否显示', + }, + order: { + type: 'integer', + description: '排序', + format: 'int32', + }, + path: { + type: 'string', + description: '路由/接口地址', + nullable: true, + }, + menuType: { + $ref: '#/components/schemas/MenuType', + }, + menuTypeDescription: { + type: 'string', + nullable: true, + readOnly: true, + }, + openType: { + $ref: '#/components/schemas/OpenType', + }, + openTypeDescription: { + type: 'string', + nullable: true, + readOnly: true, + }, + url: { + type: 'string', + description: '内外链地址', + nullable: true, + }, + component: { + type: 'string', + description: '组件地址', + nullable: true, + }, + creationTime: { + type: 'string', + description: '创建时间', + format: 'date-time', + }, + enabled: { + type: 'boolean', + description: '是否启用', + }, + policy: { + type: 'string', + description: '权限', + nullable: true, + }, + }, + additionalProperties: false, + description: '分页查询菜单', +} as const; + +export const PageMenuOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageMenuOutput', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const PageProjectInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageTemplateInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageTenantConnectionStringInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '租户id', + format: 'uuid', + }, + name: { + type: 'string', + description: '连接字符串名称', + nullable: true, + }, + value: { + type: 'string', + description: '连接字符串地址', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PageTenantConnectionStringOutputSchema = { + type: 'object', + properties: { + tenantId: { + type: 'string', + description: '租户id', + format: 'uuid', + }, + name: { + type: 'string', + description: '连接字符串名称', + nullable: true, + }, + value: { + type: 'string', + description: '连接字符串地址', + 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 PageTextTemplateInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + code: { + type: 'string', + description: '编码', + nullable: true, + }, + content: { + type: 'string', + description: '内容', + nullable: true, + }, + startCreationTime: { + type: 'string', + description: '开始创建时间', + format: 'date-time', + nullable: true, + }, + endCreationTime: { + type: 'string', + description: '结束创建时间', + format: 'date-time', + nullable: true, + }, + }, + additionalProperties: false, + description: '分页查询模板', +} as const; + +export const PageTextTemplateOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + description: '模板Id', + format: 'uuid', + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + code: { + type: 'string', + description: '编码', + nullable: true, + }, + content: { + type: 'string', + description: '内容', + nullable: true, + }, + cultureName: { + type: 'string', + description: '语言', + nullable: true, + }, + creationTime: { + type: 'string', + description: '创建时间', + format: 'date-time', + }, + }, + additionalProperties: false, + description: '分页查询模板', +} as const; + +export const PageTextTemplateOutputPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/PageTextTemplateOutput', + }, + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: '排序', + nullable: true, + }, + startTime: { + type: 'string', + description: '开始时间', + format: 'date-time', + nullable: true, + }, + endTime: { + type: 'string', + description: '结束时间', + format: 'date-time', + nullable: true, + }, + httpMethod: { + type: 'string', + description: '请求方法', + nullable: true, + }, + url: { + type: 'string', + description: '请求地址', + nullable: true, + }, + userId: { + type: 'string', + description: '用户Id', + format: 'uuid', + nullable: true, + }, + userName: { + type: 'string', + description: '用户名', + nullable: true, + }, + applicationName: { + type: 'string', + description: '应用程序名称', + nullable: true, + }, + correlationId: { + type: 'string', + description: 'RequestId', + nullable: true, + }, + maxExecutionDuration: { + type: 'integer', + description: '最大执行时间', + format: 'int32', + nullable: true, + }, + minExecutionDuration: { + type: 'integer', + description: '最小执行时间', + format: 'int32', + nullable: true, + }, + hasException: { + type: 'boolean', + description: '是否有异常', + nullable: true, + }, + httpStatusCode: { + $ref: '#/components/schemas/HttpStatusCode', + }, + clientIpAddress: { + type: 'string', + description: '客户端IP', + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: 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', + description: '所属字典Id', + format: 'uuid', + }, + code: { + type: 'string', + description: '字典明细编码', + nullable: true, + }, + order: { + type: 'integer', + description: '展现列表时排序用', + format: 'int32', + }, + displayText: { + type: 'string', + description: '英文显示名', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + isEnabled: { + type: 'boolean', + description: '启/停用(默认启用)', + }, + }, + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PagingDataDictionaryOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + type: 'string', + description: '字典编码', + nullable: true, + }, + displayText: { + type: 'string', + description: '显示名', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: '排序', + nullable: true, + }, + startTime: { + type: 'string', + description: '开始时间', + format: 'date-time', + nullable: true, + }, + endTime: { + type: 'string', + description: '结束时间', + format: 'date-time', + nullable: true, + }, + identity: { + type: 'string', + nullable: true, + }, + action: { + type: 'string', + description: '请求地址', + nullable: true, + }, + userId: { + type: 'string', + description: '用户Id', + format: 'uuid', + nullable: true, + }, + userName: { + type: 'string', + description: '用户名', + nullable: true, + }, + applicationName: { + type: 'string', + description: '应用程序名称', + nullable: true, + }, + correlationId: { + type: 'string', + description: 'RequestId', + nullable: true, + }, + clientId: { + type: 'string', + description: 'ClientId', + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + title: { + type: 'string', + description: '标题', + nullable: true, + }, + content: { + type: 'string', + description: '内容', + nullable: true, + }, + senderUserId: { + type: 'string', + description: '发送者Id', + format: 'uuid', + nullable: true, + }, + senderUserName: { + type: 'string', + description: '发送者名称', + nullable: true, + }, + receiverUserId: { + type: 'string', + description: '接受者Id', + format: 'uuid', + nullable: true, + }, + receiverUserName: { + type: 'string', + description: '接受者名称', + nullable: true, + }, + read: { + type: 'boolean', + description: '是否已读', + nullable: true, + }, + startReadTime: { + type: 'string', + description: '已读开始时间', + format: 'date-time', + nullable: true, + }, + endReadTime: { + type: 'string', + description: '已读结束时间', + 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', + description: '租户id', + format: 'uuid', + nullable: true, + }, + title: { + type: 'string', + description: '消息标题', + nullable: true, + }, + content: { + type: 'string', + description: '消息内容', + 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', + description: '发送人', + format: 'uuid', + }, + senderUserName: { + type: 'string', + description: '发送人用户名', + nullable: true, + }, + receiveUserId: { + type: 'string', + description: `订阅人 +消息类型是广播消息时,订阅人为空`, + format: 'uuid', + nullable: true, + }, + receiveUserName: { + type: 'string', + description: `接收人用户名 +消息类型是广播消息时,订接收人用户名为空`, + nullable: true, + }, + read: { + type: 'boolean', + description: '是否已读', + }, + readTime: { + type: 'string', + description: '已读时间', + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + notificationId: { + type: 'string', + format: 'uuid', + }, + receiverUserId: { + type: 'string', + description: '接受者Id', + format: 'uuid', + nullable: true, + }, + receiverUserName: { + type: 'string', + description: '接受者名称', + nullable: true, + }, + read: { + type: 'boolean', + description: '是否已读', + nullable: true, + }, + startReadTime: { + type: 'string', + description: '已读开始时间', + format: 'date-time', + nullable: true, + }, + endReadTime: { + type: 'string', + description: '已读结束时间', + format: 'date-time', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PagingNotificationSubscriptionOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + tenantId: { + type: 'string', + description: '租户id', + format: 'uuid', + nullable: true, + }, + notificationId: { + type: 'string', + description: '消息Id', + format: 'uuid', + }, + receiveUserId: { + type: 'string', + description: '接收人id', + format: 'uuid', + }, + receiveUserName: { + type: 'string', + description: '接收人用户名', + nullable: true, + }, + read: { + type: 'boolean', + description: '是否已读', + }, + readTime: { + type: 'string', + description: '已读时间', + format: 'date-time', + }, + title: { + type: 'string', + description: '消息标题', + nullable: true, + }, + content: { + type: 'string', + description: '消息内容', + 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', + description: '发送人', + format: 'uuid', + }, + senderUserName: { + type: 'string', + description: '发送人用户名', + 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', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PagingTenantInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const PagingUserListInputSchema = { + type: 'object', + properties: { + pageIndex: { + type: 'integer', + description: '当前页面.默认从1开始', + format: 'int32', + }, + pageSize: { + type: 'integer', + description: '每页多少条.每页显示多少记录', + format: 'int32', + }, + skipCount: { + type: 'integer', + description: '跳过多少条', + format: 'int32', + readOnly: true, + }, + sorting: { + type: 'string', + description: `排序 + + name desc +`, + nullable: true, + }, + filter: { + type: 'string', + description: '关键字', + 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 PreViewCodeInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + format: 'uuid', + }, + projectId: { + type: 'string', + format: 'uuid', + }, + entityId: { + type: 'array', + items: { + type: 'string', + format: 'uuid', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const ProjectDtoSchema = { + type: 'object', + properties: { + 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, + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + owner: { + type: 'string', + description: '负责人', + nullable: true, + }, + nameSpace: { + type: 'string', + description: '名称空间', + nullable: true, + }, + companyName: { + type: 'string', + description: '公司名称', + nullable: true, + }, + projectName: { + type: 'string', + description: '项目名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + supportTenant: { + type: 'boolean', + description: '是否支持多租户', + }, + }, + additionalProperties: false, +} as const; + +export const ProjectDtoPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/ProjectDto', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const ProjectOutputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + companyName: { + type: 'string', + description: '公司名称', + nullable: true, + }, + projectName: { + type: 'string', + description: '项目名称', + 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 RefreshTokenInputSchema = { + required: ['refreshToken'], + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid', + }, + refreshToken: { + minLength: 1, + type: 'string', + }, + }, + additionalProperties: false, +} as const; + +export const RefreshTokenOutputSchema = { + type: 'object', + properties: { + success: { + type: 'boolean', + }, + message: { + type: 'string', + nullable: true, + }, + token: { + type: 'string', + nullable: true, + }, + refreshToken: { + type: 'string', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const RelationalTypeSchema = { + enum: [10, 20], + type: 'integer', + format: 'int32', + 'x-enumNames': ['OnoToOne', 'OneToMany'], + 'x-enum-varnames': ['OnoToOne', 'OneToMany'], +} 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 RemoteStreamContentSchema = { + type: 'object', + properties: { + fileName: { + type: 'string', + nullable: true, + }, + contentType: { + type: 'string', + nullable: true, + }, + contentLength: { + type: 'integer', + format: 'int64', + nullable: true, + readOnly: 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 ResetPasswordInputSchema = { + required: ['password'], + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid', + }, + password: { + maxLength: 128, + minLength: 0, + type: 'string', + }, + }, + additionalProperties: false, +} as const; + +export const ResetTwoFactorInputSchema = { + type: 'object', + properties: { + userId: { + 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', + description: '消息标题', + nullable: true, + }, + content: { + type: 'string', + description: '消息内容', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const SendCommonMessageInputSchema = { + type: 'object', + properties: { + title: { + type: 'string', + description: '消息标题', + nullable: true, + }, + content: { + type: 'string', + description: '消息内容', + nullable: true, + }, + receiveUserId: { + type: 'string', + description: '发送人', + format: 'uuid', + }, + receiveUserName: { + type: 'string', + description: '发送人名称', + 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', + description: '名称', + nullable: true, + }, + displayName: { + type: 'string', + description: '显示名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + value: { + type: 'string', + description: '值', + nullable: true, + }, + type: { + type: 'string', + description: '前端控件类型', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const SettingOutputSchema = { + type: 'object', + properties: { + group: { + type: 'string', + description: '分组', + nullable: true, + }, + groupDisplayName: { + type: 'string', + description: '分组显示名称', + nullable: true, + }, + settingItemOutput: { + type: 'array', + items: { + $ref: '#/components/schemas/SettingItemOutput', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const StringInt32KeyValuePairSchema = { + type: 'object', + properties: { + key: { + type: 'string', + nullable: true, + }, + value: { + type: 'integer', + format: 'int32', + }, + }, + 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 TemplateDetailDtoSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + templateId: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + templateType: { + $ref: '#/components/schemas/TemplateType', + }, + controlType: { + $ref: '#/components/schemas/ControlType', + }, + parentId: { + type: 'string', + description: '父级id', + format: 'uuid', + nullable: true, + }, + name: { + type: 'string', + description: '模板名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + }, + additionalProperties: false, + description: '模板明细', +} as const; + +export const TemplateDtoSchema = { + type: 'object', + properties: { + 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, + }, + tenantId: { + type: 'string', + format: 'uuid', + nullable: true, + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + templateDetails: { + type: 'array', + items: { + $ref: '#/components/schemas/TemplateDetailDto', + }, + description: '关联属性1:N 模板明细集合', + nullable: true, + }, + }, + additionalProperties: false, + description: '模板', +} as const; + +export const TemplateDtoPagedResultDtoSchema = { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/TemplateDto', + }, + nullable: true, + }, + totalCount: { + type: 'integer', + format: 'int64', + }, + }, + additionalProperties: false, +} as const; + +export const TemplateTreeDtoSchema = { + type: 'object', + properties: { + key: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + templateType: { + $ref: '#/components/schemas/TemplateType', + }, + controlType: { + $ref: '#/components/schemas/ControlType', + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + isFolder: { + type: 'boolean', + description: '是否是文件夹', + }, + name: { + type: 'string', + description: '模板名称', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + title: { + type: 'string', + description: '描述', + nullable: true, + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + children: { + type: 'array', + items: { + $ref: '#/components/schemas/TemplateTreeDto', + }, + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const TemplateTypeSchema = { + enum: [10, 20], + type: 'integer', + format: 'int32', + 'x-enumNames': ['Folder', 'File'], + 'x-enum-varnames': ['Folder', 'File'], +} 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 UpdateAggregateInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + }, + 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 UpdateEntityModelInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + relationalType: { + $ref: '#/components/schemas/RelationalType', + }, + }, + additionalProperties: false, +} as const; + +export const UpdateEntityModelPropertyInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + propertyId: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + isRequired: { + type: 'boolean', + description: '必填', + }, + maxLength: { + type: 'integer', + description: '字符串最大长度', + format: 'int32', + nullable: true, + }, + minLength: { + type: 'integer', + description: '字符串最小长度', + format: 'int32', + nullable: true, + }, + decimalPrecision: { + type: 'integer', + description: '当类型为decimal时的小数位数 (18,4) 中的18', + format: 'int32', + nullable: true, + }, + decimalScale: { + type: 'integer', + description: '当类型为decimal时的字段长度 (18,4) 中的4', + format: 'int32', + nullable: true, + }, + enumTypeId: { + type: 'string', + description: '枚举类型Id', + format: 'uuid', + nullable: true, + }, + dataTypeId: { + type: 'string', + description: '数据类型Id', + format: 'uuid', + nullable: true, + }, + entityModelId: { + type: 'string', + description: '实体模型Id', + format: 'uuid', + }, + allowSearch: { + type: 'boolean', + description: '允许作为查询条件', + }, + allowAdd: { + type: 'boolean', + description: '允许添加', + }, + allowEdit: { + type: 'boolean', + description: '允许编辑', + }, + }, + additionalProperties: false, +} as const; + +export const UpdateEnumTypeInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + }, + additionalProperties: false, +} as const; + +export const UpdateEnumTypePropertyInputSchema = { + required: ['code', 'description'], + type: 'object', + properties: { + enumTypeId: { + type: 'string', + description: 'Id', + format: 'uuid', + }, + id: { + type: 'string', + description: 'Id', + format: 'uuid', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + value: { + type: 'integer', + description: '枚举值', + format: 'int32', + }, + description: { + minLength: 1, + type: 'string', + description: '描述', + }, + }, + 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', + description: '语言Id', + format: 'uuid', + }, + cultureName: { + type: 'string', + description: '语言名称', + nullable: true, + }, + uiCultureName: { + type: 'string', + description: 'Ui语言名称', + nullable: true, + }, + displayName: { + type: 'string', + description: '显示名称', + nullable: true, + }, + flagIcon: { + type: 'string', + description: '图标', + nullable: true, + }, + isEnabled: { + type: 'boolean', + description: '是否启用', + }, + }, + additionalProperties: false, + description: '删除语言', +} as const; + +export const UpdateLanguageTextInputSchema = { + required: ['cultureName', 'name', 'resourceName', 'value'], + type: 'object', + properties: { + resourceName: { + minLength: 1, + type: 'string', + description: '资源名称', + }, + cultureName: { + minLength: 1, + type: 'string', + description: '语言名称', + }, + name: { + minLength: 1, + type: 'string', + description: '名称', + }, + value: { + minLength: 1, + type: 'string', + description: '值', + }, + }, + additionalProperties: false, + description: '删除语言文本', +} as const; + +export const UpdateMenuInputSchema = { + required: ['hideInMenu', 'keepAlive', 'name', 'order', 'path', 'title'], + type: 'object', + properties: { + id: { + type: 'string', + description: '菜单Id', + format: 'uuid', + }, + name: { + minLength: 1, + type: 'string', + description: '唯一编码', + }, + title: { + minLength: 1, + type: 'string', + description: '标题', + }, + icon: { + type: 'string', + description: '图标', + nullable: true, + }, + keepAlive: { + type: 'boolean', + description: '是否缓存', + }, + hideInMenu: { + type: 'boolean', + description: '是否显示', + }, + order: { + type: 'integer', + description: '排序', + format: 'int32', + }, + path: { + minLength: 1, + type: 'string', + description: '路由地址', + }, + menuType: { + $ref: '#/components/schemas/MenuType', + }, + openType: { + $ref: '#/components/schemas/OpenType', + }, + url: { + type: 'string', + description: '内外链地址', + nullable: true, + }, + component: { + type: 'string', + description: '组件地址', + nullable: true, + }, + enabled: { + type: 'boolean', + }, + policy: { + type: 'string', + description: '权限', + nullable: true, + }, + }, + additionalProperties: false, + description: '更新菜单', +} 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 UpdateProjectInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + owner: { + type: 'string', + description: '负责人', + nullable: true, + }, + companyName: { + type: 'string', + description: '公司名称', + nullable: true, + }, + projectName: { + type: 'string', + description: '项目名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + nullable: true, + }, + supportTenant: { + type: 'boolean', + description: '是否支持多租户', + }, + }, + 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 UpdateTemplateDetailContentInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + templateDetailId: { + type: 'string', + format: 'uuid', + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const UpdateTemplateDetailInputSchema = { + type: 'object', + properties: { + templateId: { + type: 'string', + description: '模板id', + format: 'uuid', + }, + templateDetailId: { + type: 'string', + format: 'uuid', + }, + controlType: { + $ref: '#/components/schemas/ControlType', + }, + name: { + type: 'string', + description: '模板类型', + nullable: true, + }, + description: { + type: 'string', + description: '描述', + nullable: true, + }, + content: { + type: 'string', + description: '模板内容', + nullable: true, + }, + }, + additionalProperties: false, +} as const; + +export const UpdateTemplateInputSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + name: { + type: 'string', + description: '名称', + nullable: true, + }, + remark: { + type: 'string', + description: '备注', + 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 UpdateTextTemplateInputSchema = { + required: ['code', 'content', 'cultureName', 'name'], + type: 'object', + properties: { + id: { + type: 'string', + description: '模板Id', + format: 'uuid', + }, + name: { + minLength: 1, + type: 'string', + description: '名称', + }, + code: { + minLength: 1, + type: 'string', + description: '编码', + }, + content: { + minLength: 1, + type: 'string', + description: '内容', + }, + cultureName: { + minLength: 1, + type: 'string', + description: '语言', + }, + }, + additionalProperties: false, + description: '更新模板', +} 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; 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..a53f248 --- /dev/null +++ b/apps/web-antd/src/api-client/services.gen.ts @@ -0,0 +1,2947 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Options } from '@hey-api/client-axios'; + +import type { + GetApiAbpApiDefinitionData, + GetApiAbpApiDefinitionError, + GetApiAbpApiDefinitionResponse, + GetApiAbpApplicationConfigurationData, + GetApiAbpApplicationConfigurationError, + GetApiAbpApplicationConfigurationResponse, + GetApiAbpApplicationLocalizationData, + GetApiAbpApplicationLocalizationError, + GetApiAbpApplicationLocalizationResponse, + GetApiAppAbpProBasicApplicationConfigurationError, + GetApiAppAbpProBasicApplicationConfigurationResponse, + PostApiAppAccountLogin2FaData, + PostApiAppAccountLogin2FaError, + PostApiAppAccountLogin2FaResponse, + PostApiAppAccountLoginData, + PostApiAppAccountLoginError, + PostApiAppAccountLoginOidcData, + PostApiAppAccountLoginOidcError, + PostApiAppAccountLoginOidcResponse, + PostApiAppAccountLoginResponse, + PostApiAppAccountRefreshTokenData, + PostApiAppAccountRefreshTokenError, + PostApiAppAccountRefreshTokenResponse, + PostAuditLogsPageData, + PostAuditLogsPageError, + PostAuditLogsPageResponse, + PostDataDictionaryCreateData, + PostDataDictionaryCreateDetailData, + PostDataDictionaryCreateDetailError, + PostDataDictionaryCreateDetailResponse, + PostDataDictionaryCreateError, + PostDataDictionaryCreateResponse, + PostDataDictionaryDeleteData, + PostDataDictionaryDeleteDataDictionaryTypeData, + PostDataDictionaryDeleteDataDictionaryTypeError, + PostDataDictionaryDeleteDataDictionaryTypeResponse, + PostDataDictionaryDeleteError, + PostDataDictionaryDeleteResponse, + PostDataDictionaryPageData, + PostDataDictionaryPageDetailData, + PostDataDictionaryPageDetailError, + PostDataDictionaryPageDetailResponse, + PostDataDictionaryPageError, + PostDataDictionaryPageResponse, + PostDataDictionaryStatusData, + PostDataDictionaryStatusError, + PostDataDictionaryStatusResponse, + PostDataDictionaryUpdateData, + PostDataDictionaryUpdateDetailData, + PostDataDictionaryUpdateDetailError, + PostDataDictionaryUpdateDetailResponse, + PostDataDictionaryUpdateError, + PostDataDictionaryUpdateResponse, + PostDataTypesListData, + PostDataTypesListError, + PostDataTypesListResponse, + PostEntityModelsCreateAggregateData, + PostEntityModelsCreateAggregateError, + PostEntityModelsCreateAggregateResponse, + PostEntityModelsCreateEntityModelData, + PostEntityModelsCreateEntityModelError, + PostEntityModelsCreateEntityModelPropertyData, + PostEntityModelsCreateEntityModelPropertyError, + PostEntityModelsCreateEntityModelPropertyResponse, + PostEntityModelsCreateEntityModelResponse, + PostEntityModelsDeleteAggregateData, + PostEntityModelsDeleteAggregateError, + PostEntityModelsDeleteAggregateResponse, + PostEntityModelsDeleteEntityModelData, + PostEntityModelsDeleteEntityModelError, + PostEntityModelsDeleteEntityModelPropertyData, + PostEntityModelsDeleteEntityModelPropertyError, + PostEntityModelsDeleteEntityModelPropertyResponse, + PostEntityModelsDeleteEntityModelResponse, + PostEntityModelsGetData, + PostEntityModelsGetError, + PostEntityModelsGetResponse, + PostEntityModelsPagePropertyData, + PostEntityModelsPagePropertyError, + PostEntityModelsPagePropertyResponse, + PostEntityModelsTreeData, + PostEntityModelsTreeError, + PostEntityModelsTreeResponse, + PostEntityModelsUpdateAggregateData, + PostEntityModelsUpdateAggregateError, + PostEntityModelsUpdateAggregateResponse, + PostEntityModelsUpdateEntityModelData, + PostEntityModelsUpdateEntityModelError, + PostEntityModelsUpdateEntityModelPropertyData, + PostEntityModelsUpdateEntityModelPropertyError, + PostEntityModelsUpdateEntityModelPropertyResponse, + PostEntityModelsUpdateEntityModelResponse, + PostEnumTypesCreateEnumTypeData, + PostEnumTypesCreateEnumTypeError, + PostEnumTypesCreateEnumTypePropertyData, + PostEnumTypesCreateEnumTypePropertyError, + PostEnumTypesCreateEnumTypePropertyResponse, + PostEnumTypesCreateEnumTypeResponse, + PostEnumTypesDeleteEnumTypeData, + PostEnumTypesDeleteEnumTypeError, + PostEnumTypesDeleteEnumTypePropertyData, + PostEnumTypesDeleteEnumTypePropertyError, + PostEnumTypesDeleteEnumTypePropertyResponse, + PostEnumTypesDeleteEnumTypeResponse, + PostEnumTypesPageData, + PostEnumTypesPageError, + PostEnumTypesPagePropertyData, + PostEnumTypesPagePropertyError, + PostEnumTypesPagePropertyResponse, + PostEnumTypesPageResponse, + PostEnumTypesUpdateEnumTypeData, + PostEnumTypesUpdateEnumTypeError, + PostEnumTypesUpdateEnumTypePropertyData, + PostEnumTypesUpdateEnumTypePropertyError, + PostEnumTypesUpdateEnumTypePropertyResponse, + PostEnumTypesUpdateEnumTypeResponse, + PostFeaturesDeleteData, + PostFeaturesDeleteError, + PostFeaturesDeleteResponse, + PostFeaturesListData, + PostFeaturesListError, + PostFeaturesListResponse, + PostFeaturesUpdateData, + PostFeaturesUpdateError, + PostFeaturesUpdateResponse, + PostFilesDeleteData, + PostFilesDeleteError, + PostFilesDeleteResponse, + PostFilesDownloadData, + PostFilesDownloadError, + PostFilesDownloadResponse, + PostFilesPageData, + PostFilesPageError, + PostFilesPageResponse, + PostFilesUploadData, + PostFilesUploadError, + PostFilesUploadResponse, + PostGeneratorDownData, + PostGeneratorDownError, + PostGeneratorDownResponse, + PostGeneratorPreViewCodeData, + PostGeneratorPreViewCodeError, + PostGeneratorPreViewCodeResponse, + PostIdentitySecurityLogsPageData, + PostIdentitySecurityLogsPageError, + PostIdentitySecurityLogsPageResponse, + PostLanguagesAllError, + PostLanguagesAllResponse, + PostLanguagesCreateData, + PostLanguagesCreateError, + PostLanguagesCreateResponse, + PostLanguagesDeleteData, + PostLanguagesDeleteError, + PostLanguagesDeleteResponse, + PostLanguagesPageData, + PostLanguagesPageError, + PostLanguagesPageResponse, + PostLanguagesSetDefaultData, + PostLanguagesSetDefaultError, + PostLanguagesSetDefaultResponse, + PostLanguagesUpdateData, + PostLanguagesUpdateError, + PostLanguagesUpdateResponse, + PostLanguageTextsAllResourceError, + PostLanguageTextsAllResourceResponse, + PostLanguageTextsCreateData, + PostLanguageTextsCreateError, + PostLanguageTextsCreateResponse, + PostLanguageTextsPageData, + PostLanguageTextsPageError, + PostLanguageTextsPageResponse, + PostLanguageTextsUpdateData, + PostLanguageTextsUpdateError, + PostLanguageTextsUpdateResponse, + PostMenusCreateData, + PostMenusCreateError, + PostMenusCreateResponse, + PostMenusDeleteData, + PostMenusDeleteError, + PostMenusDeleteResponse, + PostMenusPageData, + PostMenusPageError, + PostMenusPageResponse, + PostMenusTreeError, + PostMenusTreeResponse, + PostMenusUpdateData, + PostMenusUpdateError, + PostMenusUpdateResponse, + PostMenusUserMenuError, + PostMenusUserMenuResponse, + PostNotificationBatchReadData, + PostNotificationBatchReadError, + PostNotificationBatchReadResponse, + PostNotificationDeleteData, + PostNotificationDeleteError, + PostNotificationDeleteResponse, + PostNotificationNotificationPageData, + PostNotificationNotificationPageError, + PostNotificationNotificationPageResponse, + PostNotificationNotificationSubscriptionPageData, + PostNotificationNotificationSubscriptionPageError, + PostNotificationNotificationSubscriptionPageResponse, + PostNotificationReadData, + PostNotificationReadError, + PostNotificationReadResponse, + PostNotificationSendBroadCastErrorMessageData, + PostNotificationSendBroadCastErrorMessageError, + PostNotificationSendBroadCastErrorMessageResponse, + PostNotificationSendBroadCastInformationMessageData, + PostNotificationSendBroadCastInformationMessageError, + PostNotificationSendBroadCastInformationMessageResponse, + PostNotificationSendBroadCastWarningMessageData, + PostNotificationSendBroadCastWarningMessageError, + PostNotificationSendBroadCastWarningMessageResponse, + PostNotificationSendCommonErrorMessageData, + PostNotificationSendCommonErrorMessageError, + PostNotificationSendCommonErrorMessageResponse, + PostNotificationSendCommonInformationMessageData, + PostNotificationSendCommonInformationMessageError, + PostNotificationSendCommonInformationMessageResponse, + PostNotificationSendCommonWarningMessageData, + PostNotificationSendCommonWarningMessageError, + PostNotificationSendCommonWarningMessageResponse, + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncData, + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncError, + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncResponse, + PostOrganizationUnitsAddUserToOrganizationUnitData, + PostOrganizationUnitsAddUserToOrganizationUnitError, + PostOrganizationUnitsAddUserToOrganizationUnitResponse, + PostOrganizationUnitsCreateData, + PostOrganizationUnitsCreateError, + PostOrganizationUnitsCreateResponse, + PostOrganizationUnitsDeleteData, + PostOrganizationUnitsDeleteError, + PostOrganizationUnitsDeleteResponse, + PostOrganizationUnitsGetRolesData, + PostOrganizationUnitsGetRolesError, + PostOrganizationUnitsGetRolesResponse, + PostOrganizationUnitsGetUnAddRolesData, + PostOrganizationUnitsGetUnAddRolesError, + PostOrganizationUnitsGetUnAddRolesResponse, + PostOrganizationUnitsGetUnAddUsersData, + PostOrganizationUnitsGetUnAddUsersError, + PostOrganizationUnitsGetUnAddUsersResponse, + PostOrganizationUnitsGetUsersData, + PostOrganizationUnitsGetUsersError, + PostOrganizationUnitsGetUsersResponse, + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncData, + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncError, + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncResponse, + PostOrganizationUnitsRemoveUserFromOrganizationUnitData, + PostOrganizationUnitsRemoveUserFromOrganizationUnitError, + PostOrganizationUnitsRemoveUserFromOrganizationUnitResponse, + PostOrganizationUnitsTreeError, + PostOrganizationUnitsTreeResponse, + PostOrganizationUnitsUpdateData, + PostOrganizationUnitsUpdateError, + PostOrganizationUnitsUpdateResponse, + PostPermissionsTreeData, + PostPermissionsTreeError, + PostPermissionsTreeResponse, + PostPermissionsUpdateData, + PostPermissionsUpdateError, + PostPermissionsUpdateResponse, + PostProjectsAllError, + PostProjectsAllResponse, + PostProjectsCreateData, + PostProjectsCreateError, + PostProjectsCreateResponse, + PostProjectsDeleteData, + PostProjectsDeleteError, + PostProjectsDeleteResponse, + PostProjectsGetProjectAndEntityData, + PostProjectsGetProjectAndEntityError, + PostProjectsGetProjectAndEntityResponse, + PostProjectsPageData, + PostProjectsPageError, + PostProjectsPageResponse, + PostProjectsUpdateData, + PostProjectsUpdateError, + PostProjectsUpdateResponse, + PostRolesAllError, + PostRolesAllResponse, + PostRolesCreateData, + PostRolesCreateError, + PostRolesCreateResponse, + PostRolesDeleteData, + PostRolesDeleteError, + PostRolesDeleteResponse, + PostRolesPageData, + PostRolesPageError, + PostRolesPageResponse, + PostRolesUpdateData, + PostRolesUpdateError, + PostRolesUpdateResponse, + PostSettingsAllError, + PostSettingsAllResponse, + PostSettingsUpdateData, + PostSettingsUpdateError, + PostSettingsUpdateResponse, + PostTemplatesAllError, + PostTemplatesAllResponse, + PostTemplatesControlTypeError, + PostTemplatesControlTypeResponse, + PostTemplatesCopyData, + PostTemplatesCopyError, + PostTemplatesCopyResponse, + PostTemplatesCreateData, + PostTemplatesCreateDetailData, + PostTemplatesCreateDetailError, + PostTemplatesCreateDetailResponse, + PostTemplatesCreateError, + PostTemplatesCreateResponse, + PostTemplatesDeleteData, + PostTemplatesDeleteDetailData, + PostTemplatesDeleteDetailError, + PostTemplatesDeleteDetailResponse, + PostTemplatesDeleteError, + PostTemplatesDeleteResponse, + PostTemplatesListError, + PostTemplatesListResponse, + PostTemplatesPageData, + PostTemplatesPageError, + PostTemplatesPageResponse, + PostTemplatesTemplateTypeError, + PostTemplatesTemplateTypeResponse, + PostTemplatesTreeData, + PostTemplatesTreeError, + PostTemplatesTreeResponse, + PostTemplatesUpdateData, + PostTemplatesUpdateDetailContentData, + PostTemplatesUpdateDetailContentError, + PostTemplatesUpdateDetailContentResponse, + PostTemplatesUpdateDetailData, + PostTemplatesUpdateDetailError, + PostTemplatesUpdateDetailResponse, + PostTemplatesUpdateError, + PostTemplatesUpdateResponse, + PostTenantsAddOrUpdateConnectionStringData, + PostTenantsAddOrUpdateConnectionStringError, + PostTenantsAddOrUpdateConnectionStringResponse, + PostTenantsCreateData, + PostTenantsCreateError, + PostTenantsCreateResponse, + PostTenantsDeleteConnectionStringData, + PostTenantsDeleteConnectionStringError, + PostTenantsDeleteConnectionStringResponse, + PostTenantsDeleteData, + PostTenantsDeleteError, + PostTenantsDeleteResponse, + PostTenantsFindData, + PostTenantsFindError, + PostTenantsFindResponse, + PostTenantsPageConnectionStringData, + PostTenantsPageConnectionStringError, + PostTenantsPageConnectionStringResponse, + PostTenantsPageData, + PostTenantsPageError, + PostTenantsPageResponse, + PostTenantsUpdateData, + PostTenantsUpdateError, + PostTenantsUpdateResponse, + PostTextTemplatesCreateData, + PostTextTemplatesCreateError, + PostTextTemplatesCreateResponse, + PostTextTemplatesDeleteData, + PostTextTemplatesDeleteError, + PostTextTemplatesDeleteResponse, + PostTextTemplatesExportData, + PostTextTemplatesExportError, + PostTextTemplatesExportResponse, + PostTextTemplatesPageData, + PostTextTemplatesPageError, + PostTextTemplatesPageResponse, + PostTextTemplatesUpdateData, + PostTextTemplatesUpdateError, + PostTextTemplatesUpdateResponse, + PostUsersCanUseTwoFactorError, + PostUsersCanUseTwoFactorResponse, + PostUsersChangePasswordData, + PostUsersChangePasswordError, + PostUsersChangePasswordResponse, + PostUsersCreateData, + PostUsersCreateError, + PostUsersCreateResponse, + PostUsersDeleteData, + PostUsersDeleteError, + PostUsersDeleteResponse, + PostUsersDisabledTwoFactorData, + PostUsersDisabledTwoFactorError, + PostUsersDisabledTwoFactorResponse, + PostUsersEnabledTwoFactorData, + PostUsersEnabledTwoFactorError, + PostUsersEnabledTwoFactorResponse, + PostUsersExportData, + PostUsersExportError, + PostUsersExportResponse, + PostUsersFindByUserNameData, + PostUsersFindByUserNameError, + PostUsersFindByUserNameResponse, + PostUsersGetQrCodeError, + PostUsersGetQrCodeResponse, + PostUsersListData, + PostUsersListError, + PostUsersListResponse, + PostUsersLockData, + PostUsersLockError, + PostUsersLockResponse, + PostUsersMyProfileError, + PostUsersMyProfileResponse, + PostUsersNeedChangePasswordError, + PostUsersNeedChangePasswordResponse, + PostUsersPageData, + PostUsersPageError, + PostUsersPageResponse, + PostUsersResetPasswordData, + PostUsersResetPasswordError, + PostUsersResetPasswordResponse, + PostUsersResetTwoFactorData, + PostUsersResetTwoFactorError, + PostUsersResetTwoFactorResponse, + PostUsersRoleData, + PostUsersRoleError, + PostUsersRoleResponse, + PostUsersUpdateData, + PostUsersUpdateError, + PostUsersUpdateResponse, +} from './types.gen'; + +import { + createClient, + createConfig, + formDataBodySerializer, +} from '@hey-api/client-axios'; + +export const client = createClient(createConfig()); + +export const getApiAbpApiDefinition = ( + options?: Options, +) => { + return (options?.client ?? client).get< + GetApiAbpApiDefinitionResponse, + GetApiAbpApiDefinitionError, + ThrowOnError + >({ + ...options, + url: '/api/abp/api-definition', + }); +}; + +export const getApiAbpApplicationConfiguration = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).get< + GetApiAbpApplicationConfigurationResponse, + GetApiAbpApplicationConfigurationError, + ThrowOnError + >({ + ...options, + url: '/api/abp/application-configuration', + }); +}; + +export const getApiAbpApplicationLocalization = < + ThrowOnError extends boolean = false, +>( + options: Options, +) => { + return (options?.client ?? client).get< + GetApiAbpApplicationLocalizationResponse, + GetApiAbpApplicationLocalizationError, + ThrowOnError + >({ + ...options, + url: '/api/abp/application-localization', + }); +}; + +export const getApiAppAbpProBasicApplicationConfiguration = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).get< + GetApiAppAbpProBasicApplicationConfigurationResponse, + GetApiAppAbpProBasicApplicationConfigurationError, + ThrowOnError + >({ + ...options, + url: '/api/app/abp-pro-basic-application-configuration', + }); +}; + +/** + * 登录 + */ +export const postApiAppAccountLogin = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostApiAppAccountLoginResponse, + PostApiAppAccountLoginError, + ThrowOnError + >({ + ...options, + url: '/api/app/account/login', + }); +}; + +/** + * 2FA登录 + */ +export const postApiAppAccountLogin2Fa = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostApiAppAccountLogin2FaResponse, + PostApiAppAccountLogin2FaError, + ThrowOnError + >({ + ...options, + url: '/api/app/account/login2FA', + }); +}; + +/** + * 第三方扩展登录 + */ +export const postApiAppAccountLoginOidc = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostApiAppAccountLoginOidcResponse, + PostApiAppAccountLoginOidcError, + ThrowOnError + >({ + ...options, + url: '/api/app/account/login-oidc', + }); +}; + +/** + * 刷新token + */ +export const postApiAppAccountRefreshToken = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostApiAppAccountRefreshTokenResponse, + PostApiAppAccountRefreshTokenError, + ThrowOnError + >({ + ...options, + url: '/api/app/account/refresh-token', + }); +}; + +/** + * 分页获取审计日志信息 + */ +export const postAuditLogsPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostAuditLogsPageResponse, + PostAuditLogsPageError, + ThrowOnError + >({ + ...options, + url: '/AuditLogs/page', + }); +}; + +/** + * 分页字典类型 + */ +export const postDataDictionaryPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryPageResponse, + PostDataDictionaryPageError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/page', + }); +}; + +/** + * 分页字典明细 + */ +export const postDataDictionaryPageDetail = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryPageDetailResponse, + PostDataDictionaryPageDetailError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/pageDetail', + }); +}; + +/** + * 创建字典类型 + */ +export const postDataDictionaryCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryCreateResponse, + PostDataDictionaryCreateError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/create', + }); +}; + +/** + * 创建字典明细 + */ +export const postDataDictionaryCreateDetail = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryCreateDetailResponse, + PostDataDictionaryCreateDetailError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/createDetail', + }); +}; + +/** + * 设置字典明细状态 + */ +export const postDataDictionaryStatus = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryStatusResponse, + PostDataDictionaryStatusError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/status', + }); +}; + +/** + * 更新字典明细 + */ +export const postDataDictionaryUpdateDetail = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryUpdateDetailResponse, + PostDataDictionaryUpdateDetailError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/updateDetail', + }); +}; + +/** + * 删除字典明细 + */ +export const postDataDictionaryDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryDeleteResponse, + PostDataDictionaryDeleteError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/delete', + }); +}; + +/** + * 删除字典类型 + */ +export const postDataDictionaryDeleteDataDictionaryType = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostDataDictionaryDeleteDataDictionaryTypeData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostDataDictionaryDeleteDataDictionaryTypeResponse, + PostDataDictionaryDeleteDataDictionaryTypeError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/deleteDataDictionaryType', + }); +}; + +/** + * 修改字典类型 + */ +export const postDataDictionaryUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataDictionaryUpdateResponse, + PostDataDictionaryUpdateError, + ThrowOnError + >({ + ...options, + url: '/DataDictionary/update', + }); +}; + +/** + * 获取类型 + */ +export const postDataTypesList = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostDataTypesListResponse, + PostDataTypesListError, + ThrowOnError + >({ + ...options, + url: '/DataTypes/List', + }); +}; + +/** + * 分页获取实体属性 + */ +export const postEntityModelsPageProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsPagePropertyResponse, + PostEntityModelsPagePropertyError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/PageProperty', + }); +}; + +/** + * 新增聚合根 + */ +export const postEntityModelsCreateAggregate = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsCreateAggregateResponse, + PostEntityModelsCreateAggregateError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/CreateAggregate', + }); +}; + +/** + * 更新聚合根 + */ +export const postEntityModelsUpdateAggregate = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsUpdateAggregateResponse, + PostEntityModelsUpdateAggregateError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/UpdateAggregate', + }); +}; + +/** + * 删除聚合根 + */ +export const postEntityModelsDeleteAggregate = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsDeleteAggregateResponse, + PostEntityModelsDeleteAggregateError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/DeleteAggregate', + }); +}; + +/** + * 新增实体 + */ +export const postEntityModelsCreateEntityModel = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsCreateEntityModelResponse, + PostEntityModelsCreateEntityModelError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/CreateEntityModel', + }); +}; + +/** + * 更新实体 + */ +export const postEntityModelsUpdateEntityModel = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsUpdateEntityModelResponse, + PostEntityModelsUpdateEntityModelError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/UpdateEntityModel', + }); +}; + +/** + * 删除实体 + */ +export const postEntityModelsDeleteEntityModel = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsDeleteEntityModelResponse, + PostEntityModelsDeleteEntityModelError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/DeleteEntityModel', + }); +}; + +/** + * 新增实体属性 + */ +export const postEntityModelsCreateEntityModelProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostEntityModelsCreateEntityModelPropertyData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostEntityModelsCreateEntityModelPropertyResponse, + PostEntityModelsCreateEntityModelPropertyError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/CreateEntityModelProperty', + }); +}; + +/** + * 更新实体属性 + */ +export const postEntityModelsUpdateEntityModelProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostEntityModelsUpdateEntityModelPropertyData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostEntityModelsUpdateEntityModelPropertyResponse, + PostEntityModelsUpdateEntityModelPropertyError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/UpdateEntityModelProperty', + }); +}; + +/** + * 删除实体属性 + */ +export const postEntityModelsDeleteEntityModelProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostEntityModelsDeleteEntityModelPropertyData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostEntityModelsDeleteEntityModelPropertyResponse, + PostEntityModelsDeleteEntityModelPropertyError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/DeleteEntityModelProperty', + }); +}; + +/** + * 获取实体树 + */ +export const postEntityModelsTree = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsTreeResponse, + PostEntityModelsTreeError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/Tree', + }); +}; + +/** + * 获取模型数据 + */ +export const postEntityModelsGet = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEntityModelsGetResponse, + PostEntityModelsGetError, + ThrowOnError + >({ + ...options, + url: '/EntityModels/Get', + }); +}; + +/** + * 分页获取枚举 + */ +export const postEnumTypesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesPageResponse, + PostEnumTypesPageError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/Page', + }); +}; + +/** + * 分页获取枚举属性 + */ +export const postEnumTypesPageProperty = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesPagePropertyResponse, + PostEnumTypesPagePropertyError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/PageProperty', + }); +}; + +/** + * 创建枚举 + */ +export const postEnumTypesCreateEnumType = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesCreateEnumTypeResponse, + PostEnumTypesCreateEnumTypeError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/CreateEnumType', + }); +}; + +/** + * 更新枚举 + */ +export const postEnumTypesUpdateEnumType = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesUpdateEnumTypeResponse, + PostEnumTypesUpdateEnumTypeError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/UpdateEnumType', + }); +}; + +/** + * 删除枚举 + */ +export const postEnumTypesDeleteEnumType = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesDeleteEnumTypeResponse, + PostEnumTypesDeleteEnumTypeError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/DeleteEnumType', + }); +}; + +/** + * 创建枚举属性 + */ +export const postEnumTypesCreateEnumTypeProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesCreateEnumTypePropertyResponse, + PostEnumTypesCreateEnumTypePropertyError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/CreateEnumTypeProperty', + }); +}; + +/** + * 更新枚举属性 + */ +export const postEnumTypesUpdateEnumTypeProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesUpdateEnumTypePropertyResponse, + PostEnumTypesUpdateEnumTypePropertyError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/UpdateEnumTypeProperty', + }); +}; + +/** + * 删除枚举属性 + */ +export const postEnumTypesDeleteEnumTypeProperty = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostEnumTypesDeleteEnumTypePropertyResponse, + PostEnumTypesDeleteEnumTypePropertyError, + ThrowOnError + >({ + ...options, + url: '/EnumTypes/DeleteEnumTypeProperty', + }); +}; + +/** + * 获取Features + */ +export const postFeaturesList = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFeaturesListResponse, + PostFeaturesListError, + ThrowOnError + >({ + ...options, + url: '/Features/list', + }); +}; + +/** + * 更新Features + */ +export const postFeaturesUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFeaturesUpdateResponse, + PostFeaturesUpdateError, + ThrowOnError + >({ + ...options, + url: '/Features/update', + }); +}; + +/** + * 删除Features + */ +export const postFeaturesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFeaturesDeleteResponse, + PostFeaturesDeleteError, + ThrowOnError + >({ + ...options, + url: '/Features/delete', + }); +}; + +/** + * 分页查询文件 + */ +export const postFilesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFilesPageResponse, + PostFilesPageError, + ThrowOnError + >({ + ...options, + url: '/Files/Page', + }); +}; + +/** + * 上传文件 + */ +export const postFilesUpload = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFilesUploadResponse, + PostFilesUploadError, + ThrowOnError + >({ + ...options, + ...formDataBodySerializer, + headers: { + 'Content-Type': null, + ...options?.headers, + }, + url: '/Files/Upload', + }); +}; + +/** + * 删除文件 + */ +export const postFilesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFilesDeleteResponse, + PostFilesDeleteError, + ThrowOnError + >({ + ...options, + url: '/Files/Delete', + }); +}; + +/** + * 下载文件 + */ +export const postFilesDownload = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostFilesDownloadResponse, + PostFilesDownloadError, + ThrowOnError + >({ + ...options, + url: '/Files/Download', + }); +}; + +/** + * 预览 + */ +export const postGeneratorPreViewCode = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostGeneratorPreViewCodeResponse, + PostGeneratorPreViewCodeError, + ThrowOnError + >({ + ...options, + url: '/Generator/PreViewCode', + }); +}; + +/** + * 下载 + */ +export const postGeneratorDown = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostGeneratorDownResponse, + PostGeneratorDownError, + ThrowOnError + >({ + ...options, + url: '/Generator/Down', + }); +}; + +/** + * 分页获取登录日志信息 + */ +export const postIdentitySecurityLogsPage = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostIdentitySecurityLogsPageResponse, + PostIdentitySecurityLogsPageError, + ThrowOnError + >({ + ...options, + url: '/IdentitySecurityLogs/page', + }); +}; + +/** + * 获取所有语言 + */ +export const postLanguagesAll = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesAllResponse, + PostLanguagesAllError, + ThrowOnError + >({ + ...options, + url: '/Languages/All', + }); +}; + +/** + * 分页查询语言 + */ +export const postLanguagesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesPageResponse, + PostLanguagesPageError, + ThrowOnError + >({ + ...options, + url: '/Languages/Page', + }); +}; + +/** + * 创建语言 + */ +export const postLanguagesCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesCreateResponse, + PostLanguagesCreateError, + ThrowOnError + >({ + ...options, + url: '/Languages/Create', + }); +}; + +/** + * 编辑语言 + */ +export const postLanguagesUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesUpdateResponse, + PostLanguagesUpdateError, + ThrowOnError + >({ + ...options, + url: '/Languages/Update', + }); +}; + +/** + * 删除语言 + */ +export const postLanguagesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesDeleteResponse, + PostLanguagesDeleteError, + ThrowOnError + >({ + ...options, + url: '/Languages/Delete', + }); +}; + +/** + * 设置默认语言 + */ +export const postLanguagesSetDefault = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguagesSetDefaultResponse, + PostLanguagesSetDefaultError, + ThrowOnError + >({ + ...options, + url: '/Languages/SetDefault', + }); +}; + +/** + * 获取所有资源 + */ +export const postLanguageTextsAllResource = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguageTextsAllResourceResponse, + PostLanguageTextsAllResourceError, + ThrowOnError + >({ + ...options, + url: '/LanguageTexts/AllResource', + }); +}; + +/** + * 分页查询语言文本 + */ +export const postLanguageTextsPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguageTextsPageResponse, + PostLanguageTextsPageError, + ThrowOnError + >({ + ...options, + url: '/LanguageTexts/Page', + }); +}; + +/** + * 创建语言文本 + */ +export const postLanguageTextsCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguageTextsCreateResponse, + PostLanguageTextsCreateError, + ThrowOnError + >({ + ...options, + url: '/LanguageTexts/Create', + }); +}; + +/** + * 编辑语言文本 + */ +export const postLanguageTextsUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostLanguageTextsUpdateResponse, + PostLanguageTextsUpdateError, + ThrowOnError + >({ + ...options, + url: '/LanguageTexts/Update', + }); +}; + +/** + * 获取用户菜单 + */ +export const postMenusUserMenu = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusUserMenuResponse, + PostMenusUserMenuError, + ThrowOnError + >({ + ...options, + url: '/Menus/UserMenu', + }); +}; + +/** + * 分页查询菜单 + */ +export const postMenusPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusPageResponse, + PostMenusPageError, + ThrowOnError + >({ + ...options, + url: '/Menus/Page', + }); +}; + +/** + * 创建菜单 + */ +export const postMenusCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusCreateResponse, + PostMenusCreateError, + ThrowOnError + >({ + ...options, + url: '/Menus/Create', + }); +}; + +/** + * 编辑菜单 + */ +export const postMenusUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusUpdateResponse, + PostMenusUpdateError, + ThrowOnError + >({ + ...options, + url: '/Menus/Update', + }); +}; + +/** + * 删除菜单 + */ +export const postMenusDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusDeleteResponse, + PostMenusDeleteError, + ThrowOnError + >({ + ...options, + url: '/Menus/Delete', + }); +}; + +/** + * 获取菜单树 + */ +export const postMenusTree = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostMenusTreeResponse, + PostMenusTreeError, + ThrowOnError + >({ + ...options, + url: '/Menus/Tree', + }); +}; + +/** + * 分页获取文本消息 + */ +export const postNotificationNotificationPage = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationNotificationPageResponse, + PostNotificationNotificationPageError, + ThrowOnError + >({ + ...options, + url: '/Notification/NotificationPage', + }); +}; + +/** + * 分页获取广播消息已读人数 + */ +export const postNotificationNotificationSubscriptionPage = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostNotificationNotificationSubscriptionPageData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostNotificationNotificationSubscriptionPageResponse, + PostNotificationNotificationSubscriptionPageError, + ThrowOnError + >({ + ...options, + url: '/Notification/NotificationSubscriptionPage', + }); +}; + +/** + * 删除消息 + */ +export const postNotificationDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationDeleteResponse, + PostNotificationDeleteError, + ThrowOnError + >({ + ...options, + url: '/Notification/Delete', + }); +}; + +/** + * 发送警告文本消息 + */ +export const postNotificationSendCommonWarningMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationSendCommonWarningMessageResponse, + PostNotificationSendCommonWarningMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendCommonWarningMessage', + }); +}; + +/** + * 发送普通文本消息 + */ +export const postNotificationSendCommonInformationMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostNotificationSendCommonInformationMessageData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostNotificationSendCommonInformationMessageResponse, + PostNotificationSendCommonInformationMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendCommonInformationMessage', + }); +}; + +/** + * 发送错误文本消息 + */ +export const postNotificationSendCommonErrorMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationSendCommonErrorMessageResponse, + PostNotificationSendCommonErrorMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendCommonErrorMessage', + }); +}; + +/** + * 发送警告广播消息 + */ +export const postNotificationSendBroadCastWarningMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostNotificationSendBroadCastWarningMessageData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostNotificationSendBroadCastWarningMessageResponse, + PostNotificationSendBroadCastWarningMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendBroadCastWarningMessage', + }); +}; + +/** + * 发送正常广播消息 + */ +export const postNotificationSendBroadCastInformationMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostNotificationSendBroadCastInformationMessageData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostNotificationSendBroadCastInformationMessageResponse, + PostNotificationSendBroadCastInformationMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendBroadCastInformationMessage', + }); +}; + +/** + * 发送错误广播消息 + */ +export const postNotificationSendBroadCastErrorMessage = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostNotificationSendBroadCastErrorMessageData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostNotificationSendBroadCastErrorMessageResponse, + PostNotificationSendBroadCastErrorMessageError, + ThrowOnError + >({ + ...options, + url: '/Notification/SendBroadCastErrorMessage', + }); +}; + +/** + * 消息设置为已读 + */ +export const postNotificationRead = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationReadResponse, + PostNotificationReadError, + ThrowOnError + >({ + ...options, + url: '/Notification/Read', + }); +}; + +/** + * 消息批量设置为已读 + */ +export const postNotificationBatchRead = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostNotificationBatchReadResponse, + PostNotificationBatchReadError, + ThrowOnError + >({ + ...options, + url: '/Notification/BatchRead', + }); +}; + +/** + * 获取组织机构树 + */ +export const postOrganizationUnitsTree = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsTreeResponse, + PostOrganizationUnitsTreeError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/tree', + }); +}; + +/** + * 创建组织机构 + */ +export const postOrganizationUnitsCreate = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsCreateResponse, + PostOrganizationUnitsCreateError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/create', + }); +}; + +/** + * 删除组织机构 + */ +export const postOrganizationUnitsDelete = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsDeleteResponse, + PostOrganizationUnitsDeleteError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/delete', + }); +}; + +/** + * 编辑组织机构 + */ +export const postOrganizationUnitsUpdate = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsUpdateResponse, + PostOrganizationUnitsUpdateError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/update', + }); +}; + +/** + * 向组织机构添加角色 + */ +export const postOrganizationUnitsAddRoleToOrganizationUnitAsync = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncResponse, + PostOrganizationUnitsAddRoleToOrganizationUnitAsyncError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/addRoleToOrganizationUnitAsync', + }); +}; + +/** + * 向组织机构删除角色 + */ +export const postOrganizationUnitsRemoveRoleFromOrganizationUnitAsync = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncResponse, + PostOrganizationUnitsRemoveRoleFromOrganizationUnitAsyncError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/removeRoleFromOrganizationUnitAsync', + }); +}; + +/** + * 向组织机构添加用户 + */ +export const postOrganizationUnitsAddUserToOrganizationUnit = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostOrganizationUnitsAddUserToOrganizationUnitData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsAddUserToOrganizationUnitResponse, + PostOrganizationUnitsAddUserToOrganizationUnitError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/addUserToOrganizationUnit', + }); +}; + +/** + * 向组织机构删除用户 + */ +export const postOrganizationUnitsRemoveUserFromOrganizationUnit = < + ThrowOnError extends boolean = false, +>( + options?: Options< + PostOrganizationUnitsRemoveUserFromOrganizationUnitData, + ThrowOnError + >, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsRemoveUserFromOrganizationUnitResponse, + PostOrganizationUnitsRemoveUserFromOrganizationUnitError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/removeUserFromOrganizationUnit', + }); +}; + +/** + * 分页获取组织机构下用户 + */ +export const postOrganizationUnitsGetUsers = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsGetUsersResponse, + PostOrganizationUnitsGetUsersError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/getUsers', + }); +}; + +/** + * 分页获取组织机构下角色 + */ +export const postOrganizationUnitsGetRoles = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsGetRolesResponse, + PostOrganizationUnitsGetRolesError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/getRoles', + }); +}; + +/** + * 获取不在组织机构的用户 + */ +export const postOrganizationUnitsGetUnAddUsers = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsGetUnAddUsersResponse, + PostOrganizationUnitsGetUnAddUsersError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/getUnAddUsers', + }); +}; + +/** + * 获取不在组织机构的角色 + */ +export const postOrganizationUnitsGetUnAddRoles = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostOrganizationUnitsGetUnAddRolesResponse, + PostOrganizationUnitsGetUnAddRolesError, + ThrowOnError + >({ + ...options, + url: '/OrganizationUnits/getUnAddRoles', + }); +}; + +/** + * 获取角色权限 + */ +export const postPermissionsTree = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostPermissionsTreeResponse, + PostPermissionsTreeError, + ThrowOnError + >({ + ...options, + url: '/Permissions/tree', + }); +}; + +/** + * 更新角色 + */ +export const postPermissionsUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostPermissionsUpdateResponse, + PostPermissionsUpdateError, + ThrowOnError + >({ + ...options, + url: '/Permissions/update', + }); +}; + +/** + * 获取所有项目 + */ +export const postProjectsAll = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsAllResponse, + PostProjectsAllError, + ThrowOnError + >({ + ...options, + url: '/Projects/All', + }); +}; + +/** + * 分页获取项目 + */ +export const postProjectsPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsPageResponse, + PostProjectsPageError, + ThrowOnError + >({ + ...options, + url: '/Projects/Page', + }); +}; + +/** + * 创建项目 + */ +export const postProjectsCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsCreateResponse, + PostProjectsCreateError, + ThrowOnError + >({ + ...options, + url: '/Projects/Create', + }); +}; + +/** + * 更新项目 + */ +export const postProjectsUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsUpdateResponse, + PostProjectsUpdateError, + ThrowOnError + >({ + ...options, + url: '/Projects/Update', + }); +}; + +/** + * 删除项目 + */ +export const postProjectsDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsDeleteResponse, + PostProjectsDeleteError, + ThrowOnError + >({ + ...options, + url: '/Projects/Delete', + }); +}; + +/** + * 获取项目和实体信息 + */ +export const postProjectsGetProjectAndEntity = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostProjectsGetProjectAndEntityResponse, + PostProjectsGetProjectAndEntityError, + ThrowOnError + >({ + ...options, + url: '/Projects/GetProjectAndEntity', + }); +}; + +/** + * 获取所有角色 + */ +export const postRolesAll = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostRolesAllResponse, + PostRolesAllError, + ThrowOnError + >({ + ...options, + url: '/Roles/all', + }); +}; + +/** + * 分页获取角色 + */ +export const postRolesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostRolesPageResponse, + PostRolesPageError, + ThrowOnError + >({ + ...options, + url: '/Roles/page', + }); +}; + +/** + * 创建角色 + */ +export const postRolesCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostRolesCreateResponse, + PostRolesCreateError, + ThrowOnError + >({ + ...options, + url: '/Roles/create', + }); +}; + +/** + * 更新角色 + */ +export const postRolesUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostRolesUpdateResponse, + PostRolesUpdateError, + ThrowOnError + >({ + ...options, + url: '/Roles/update', + }); +}; + +/** + * 删除角色 + */ +export const postRolesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostRolesDeleteResponse, + PostRolesDeleteError, + ThrowOnError + >({ + ...options, + url: '/Roles/delete', + }); +}; + +/** + * 获取所有Setting + */ +export const postSettingsAll = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostSettingsAllResponse, + PostSettingsAllError, + ThrowOnError + >({ + ...options, + url: '/Settings/all', + }); +}; + +/** + * 更新Setting + */ +export const postSettingsUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostSettingsUpdateResponse, + PostSettingsUpdateError, + ThrowOnError + >({ + ...options, + url: '/Settings/update', + }); +}; + +/** + * 获取所有模板组 + */ +export const postTemplatesAll = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesAllResponse, + PostTemplatesAllError, + ThrowOnError + >({ + ...options, + url: '/Templates/All', + }); +}; + +/** + * 分页获取模板组 + */ +export const postTemplatesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesPageResponse, + PostTemplatesPageError, + ThrowOnError + >({ + ...options, + url: '/Templates/Page', + }); +}; + +/** + * 创建模板组 + */ +export const postTemplatesCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesCreateResponse, + PostTemplatesCreateError, + ThrowOnError + >({ + ...options, + url: '/Templates/Create', + }); +}; + +/** + * 更新模板组 + */ +export const postTemplatesUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesUpdateResponse, + PostTemplatesUpdateError, + ThrowOnError + >({ + ...options, + url: '/Templates/Update', + }); +}; + +/** + * 删除模板组 + */ +export const postTemplatesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesDeleteResponse, + PostTemplatesDeleteError, + ThrowOnError + >({ + ...options, + url: '/Templates/Delete', + }); +}; + +/** + * 创建模板 + */ +export const postTemplatesCreateDetail = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesCreateDetailResponse, + PostTemplatesCreateDetailError, + ThrowOnError + >({ + ...options, + url: '/Templates/CreateDetail', + }); +}; + +/** + * 编辑模板 + */ +export const postTemplatesUpdateDetail = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesUpdateDetailResponse, + PostTemplatesUpdateDetailError, + ThrowOnError + >({ + ...options, + url: '/Templates/UpdateDetail', + }); +}; + +/** + * 编辑模板 + */ +export const postTemplatesUpdateDetailContent = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesUpdateDetailContentResponse, + PostTemplatesUpdateDetailContentError, + ThrowOnError + >({ + ...options, + url: '/Templates/UpdateDetailContent', + }); +}; + +/** + * 删除模板 + */ +export const postTemplatesDeleteDetail = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesDeleteDetailResponse, + PostTemplatesDeleteDetailError, + ThrowOnError + >({ + ...options, + url: '/Templates/DeleteDetail', + }); +}; + +/** + * 获取模板树形结构 + */ +export const postTemplatesTree = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesTreeResponse, + PostTemplatesTreeError, + ThrowOnError + >({ + ...options, + url: '/Templates/Tree', + }); +}; + +/** + * 获取所有模板 + */ +export const postTemplatesList = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesListResponse, + PostTemplatesListError, + ThrowOnError + >({ + ...options, + url: '/Templates/List', + }); +}; + +/** + * 获取模板策略 + */ +export const postTemplatesControlType = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesControlTypeResponse, + PostTemplatesControlTypeError, + ThrowOnError + >({ + ...options, + url: '/Templates/ControlType', + }); +}; + +/** + * 获取模板类型 + */ +export const postTemplatesTemplateType = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesTemplateTypeResponse, + PostTemplatesTemplateTypeError, + ThrowOnError + >({ + ...options, + url: '/Templates/TemplateType', + }); +}; + +/** + * 复制模板 + */ +export const postTemplatesCopy = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTemplatesCopyResponse, + PostTemplatesCopyError, + ThrowOnError + >({ + ...options, + url: '/Templates/Copy', + }); +}; + +/** + * 通过名称获取租户信息 + */ +export const postTenantsFind = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsFindResponse, + PostTenantsFindError, + ThrowOnError + >({ + ...options, + url: '/Tenants/find', + }); +}; + +/** + * 分页获取租户信息 + */ +export const postTenantsPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsPageResponse, + PostTenantsPageError, + ThrowOnError + >({ + ...options, + url: '/Tenants/page', + }); +}; + +/** + * 创建租户 + */ +export const postTenantsCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsCreateResponse, + PostTenantsCreateError, + ThrowOnError + >({ + ...options, + url: '/Tenants/create', + }); +}; + +/** + * 更新租户 + */ +export const postTenantsUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsUpdateResponse, + PostTenantsUpdateError, + ThrowOnError + >({ + ...options, + url: '/Tenants/update', + }); +}; + +/** + * 删除租户 + */ +export const postTenantsDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsDeleteResponse, + PostTenantsDeleteError, + ThrowOnError + >({ + ...options, + url: '/Tenants/delete', + }); +}; + +/** + * 分页租户连接字符串 + */ +export const postTenantsPageConnectionString = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsPageConnectionStringResponse, + PostTenantsPageConnectionStringError, + ThrowOnError + >({ + ...options, + url: '/Tenants/pageConnectionString', + }); +}; + +/** + * 新增或者更新租户所有连接字符串 + */ +export const postTenantsAddOrUpdateConnectionString = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsAddOrUpdateConnectionStringResponse, + PostTenantsAddOrUpdateConnectionStringError, + ThrowOnError + >({ + ...options, + url: '/Tenants/addOrUpdateConnectionString', + }); +}; + +/** + * 删除租户连接字符串 + */ +export const postTenantsDeleteConnectionString = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTenantsDeleteConnectionStringResponse, + PostTenantsDeleteConnectionStringError, + ThrowOnError + >({ + ...options, + url: '/Tenants/deleteConnectionString', + }); +}; + +/** + * 分页查询模板 + */ +export const postTextTemplatesPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTextTemplatesPageResponse, + PostTextTemplatesPageError, + ThrowOnError + >({ + ...options, + url: '/TextTemplates/Page', + }); +}; + +/** + * 创建模板 + */ +export const postTextTemplatesCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTextTemplatesCreateResponse, + PostTextTemplatesCreateError, + ThrowOnError + >({ + ...options, + url: '/TextTemplates/Create', + }); +}; + +/** + * 编辑模板 + */ +export const postTextTemplatesUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTextTemplatesUpdateResponse, + PostTextTemplatesUpdateError, + ThrowOnError + >({ + ...options, + url: '/TextTemplates/Update', + }); +}; + +/** + * 删除模板 + */ +export const postTextTemplatesDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTextTemplatesDeleteResponse, + PostTextTemplatesDeleteError, + ThrowOnError + >({ + ...options, + url: '/TextTemplates/Delete', + }); +}; + +/** + * 导出模板列表 + */ +export const postTextTemplatesExport = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostTextTemplatesExportResponse, + PostTextTemplatesExportError, + ThrowOnError + >({ + ...options, + url: '/TextTemplates/Export', + }); +}; + +/** + * 分页获取用户信息 + */ +export const postUsersPage = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersPageResponse, + PostUsersPageError, + ThrowOnError + >({ + ...options, + url: '/Users/page', + }); +}; + +/** + * 分页获取用户信息 + */ +export const postUsersList = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersListResponse, + PostUsersListError, + ThrowOnError + >({ + ...options, + url: '/Users/list', + }); +}; + +/** + * 导出用户列表 + */ +export const postUsersExport = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersExportResponse, + PostUsersExportError, + ThrowOnError + >({ + ...options, + url: '/Users/export', + }); +}; + +/** + * 创建用户 + */ +export const postUsersCreate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersCreateResponse, + PostUsersCreateError, + ThrowOnError + >({ + ...options, + url: '/Users/create', + }); +}; + +/** + * 编辑用户 + */ +export const postUsersUpdate = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersUpdateResponse, + PostUsersUpdateError, + ThrowOnError + >({ + ...options, + url: '/Users/update', + }); +}; + +/** + * 删除用户 + */ +export const postUsersDelete = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersDeleteResponse, + PostUsersDeleteError, + ThrowOnError + >({ + ...options, + url: '/Users/delete', + }); +}; + +/** + * 获取用户角色信息 + */ +export const postUsersRole = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersRoleResponse, + PostUsersRoleError, + ThrowOnError + >({ + ...options, + url: '/Users/role', + }); +}; + +/** + * 修改当前用户密码 + */ +export const postUsersChangePassword = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersChangePasswordResponse, + PostUsersChangePasswordError, + ThrowOnError + >({ + ...options, + url: '/Users/changePassword', + }); +}; + +/** + * 重置密码 + */ +export const postUsersResetPassword = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersResetPasswordResponse, + PostUsersResetPasswordError, + ThrowOnError + >({ + ...options, + url: '/Users/resetPassword', + }); +}; + +/** + * 锁定用户 + */ +export const postUsersLock = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersLockResponse, + PostUsersLockError, + ThrowOnError + >({ + ...options, + url: '/Users/lock', + }); +}; + +/** + * 通过用户名查找用户 + */ +export const postUsersFindByUserName = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersFindByUserNameResponse, + PostUsersFindByUserNameError, + ThrowOnError + >({ + ...options, + url: '/Users/findByUserName', + }); +}; + +/** + * 获取个人信息 + */ +export const postUsersMyProfile = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersMyProfileResponse, + PostUsersMyProfileError, + ThrowOnError + >({ + ...options, + url: '/Users/myProfile', + }); +}; + +/** + * 是否启用双因素验证 + */ +export const postUsersCanUseTwoFactor = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersCanUseTwoFactorResponse, + PostUsersCanUseTwoFactorError, + ThrowOnError + >({ + ...options, + url: '/Users/canUseTwoFactor', + }); +}; + +/** + * 获取双因素二维码 + */ +export const postUsersGetQrCode = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersGetQrCodeResponse, + PostUsersGetQrCodeError, + ThrowOnError + >({ + ...options, + url: '/Users/getQRCode', + }); +}; + +/** + * 开启双因素验证 + */ +export const postUsersEnabledTwoFactor = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersEnabledTwoFactorResponse, + PostUsersEnabledTwoFactorError, + ThrowOnError + >({ + ...options, + url: '/Users/enabledTwoFactor', + }); +}; + +/** + * 关闭双因素验证 + */ +export const postUsersDisabledTwoFactor = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersDisabledTwoFactorResponse, + PostUsersDisabledTwoFactorError, + ThrowOnError + >({ + ...options, + url: '/Users/disabledTwoFactor', + }); +}; + +/** + * 重置双因素验证 + */ +export const postUsersResetTwoFactor = ( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersResetTwoFactorResponse, + PostUsersResetTwoFactorError, + ThrowOnError + >({ + ...options, + url: '/Users/resetTwoFactor', + }); +}; + +/** + * 是否需要修改密码 + */ +export const postUsersNeedChangePassword = < + ThrowOnError extends boolean = false, +>( + options?: Options, +) => { + return (options?.client ?? client).post< + PostUsersNeedChangePasswordResponse, + PostUsersNeedChangePasswordError, + ThrowOnError + >({ + ...options, + url: '/Users/needChangePassword', + }); +}; 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..2398064 --- /dev/null +++ b/apps/web-antd/src/api-client/types.gen.ts @@ -0,0 +1,5004 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AbpLoginResult = { + readonly description?: null | string; + result?: LoginResultType; +}; + +export type AbpProApplicationConfigurationDto = { + multiTenancy?: MultiTenancyInfoDto; + oidcConfiguration?: ApplicationOidcConfigurationDto; +}; + +export type ActionApiDescriptionModel = { + allowAnonymous?: boolean | null; + httpMethod?: null | string; + implementFrom?: null | string; + name?: null | string; + parameters?: Array | null; + parametersOnMethod?: Array | null; + returnValue?: ReturnValueApiDescriptionModel; + supportedVersions?: Array | null; + uniqueName?: null | string; + url?: null | string; +}; + +export type AddOrUpdateConnectionStringInput = { + /** + * id + */ + id?: string; + /** + * 连接字符串名称 + */ + name?: null | string; + /** + * 连接字符串地址 + */ + value?: null | string; +}; + +export type AddRoleToOrganizationUnitInput = { + organizationUnitId?: string; + roleId?: Array | null; +}; + +export type AddUserToOrganizationUnitInput = { + organizationUnitId?: string; + userId?: Array | null; +}; + +export type AggregateRouteConfig = { + jsonPath?: null | string; + parameter?: null | string; + routeKey?: null | string; +}; + +export type ApplicationApiDescriptionModel = { + modules?: null | { + [key: string]: ModuleApiDescriptionModel; + }; + types?: null | { + [key: string]: TypeApiDescriptionModel; + }; +}; + +export type ApplicationAuthConfigurationDto = { + grantedPolicies?: null | { + [key: string]: boolean; + }; +}; + +export type ApplicationConfigurationDto = { + auth?: ApplicationAuthConfigurationDto; + clock?: ClockDto; + currentTenant?: CurrentTenantDto; + currentUser?: CurrentUserDto; + extraProperties?: null | { + [key: string]: unknown; + }; + features?: ApplicationFeatureConfigurationDto; + globalFeatures?: ApplicationGlobalFeatureConfigurationDto; + localization?: ApplicationLocalizationConfigurationDto; + multiTenancy?: MultiTenancyInfoDto; + objectExtensions?: ObjectExtensionsDto; + setting?: ApplicationSettingConfigurationDto; + timing?: TimingDto; +}; + +export type ApplicationFeatureConfigurationDto = { + values?: null | { + [key: string]: null | string; + }; +}; + +export type ApplicationGlobalFeatureConfigurationDto = { + enabledFeatures?: Array | null; +}; + +export type ApplicationLocalizationConfigurationDto = { + currentCulture?: CurrentCultureDto; + defaultResourceName?: null | string; + languageFilesMap?: null | { + [key: string]: Array; + }; + languages?: Array | null; + languagesMap?: null | { + [key: string]: Array; + }; + resources?: null | { + [key: string]: ApplicationLocalizationResourceDto; + }; + values?: null | { + [key: string]: { + [key: string]: string; + }; + }; +}; + +export type ApplicationLocalizationDto = { + currentCulture?: CurrentCultureDto; + resources?: null | { + [key: string]: ApplicationLocalizationResourceDto; + }; +}; + +export type ApplicationLocalizationResourceDto = { + baseResources?: Array | null; + texts?: null | { + [key: string]: string; + }; +}; + +export type ApplicationOidcConfigurationDto = { + /** + * 是否启用 + */ + enabled?: boolean; + oidcConfiguration?: Array | null; +}; + +export type ApplicationSettingConfigurationDto = { + values?: null | { + [key: string]: null | string; + }; +}; + +export type ChangePasswordInput = { + currentPassword?: null | string; + newPassword: string; +}; + +export type ClockDto = { + kind?: null | string; +}; + +export type ControllerApiDescriptionModel = { + actions?: null | { + [key: string]: ActionApiDescriptionModel; + }; + apiVersion?: null | string; + controllerGroupName?: null | string; + controllerName?: null | string; + interfaces?: Array | null; + isIntegrationService?: boolean; + isRemoteService?: boolean; + type?: null | string; +}; + +export type ControllerInterfaceApiDescriptionModel = { + methods?: Array | null; + name?: null | string; + type?: null | string; +}; + +/** + * 控制策略 + */ +export type ControlType = 10 | 20 | 30 | 40; + +export type CopyTemplateInput = { + id?: string; + /** + * 名称 + */ + name?: null | string; + /** + * 备注 + */ + remark?: null | string; +}; + +export type CreateAggregateInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + projectId?: string; +}; + +export type CreateDataDictinaryDetailInput = { + code?: null | string; + description?: null | string; + displayText?: null | string; + id?: string; + order?: number; +}; + +export type CreateDataDictinaryInput = { + code?: null | string; + description?: null | string; + displayText?: null | string; +}; + +export type CreateEntityModelInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + id?: string; + relationalType?: RelationalType; +}; + +export type CreateEntityModelPropertyInput = { + /** + * 允许添加 + */ + allowAdd?: boolean; + /** + * 允许编辑 + */ + allowEdit?: boolean; + /** + * 允许作为查询条件 + */ + allowSearch?: boolean; + /** + * 编码 + */ + code: string; + /** + * 数据类型Id + */ + dataTypeId?: null | string; + /** + * 当类型为decimal时的小数位数 (18,4) 中的18 + */ + decimalPrecision?: null | number; + /** + * 当类型为decimal时的字段长度 (18,4) 中的4 + */ + decimalScale?: null | number; + /** + * 描述 + */ + description: string; + /** + * 枚举类型Id + */ + enumTypeId?: null | string; + /** + * 实体模型Id + */ + id?: string; + /** + * 必填 + */ + isRequired?: boolean; + /** + * 字符串最大长度 + */ + maxLength?: null | number; + /** + * 字符串最小长度 + */ + minLength?: null | number; +}; + +export type CreateEnumTypeInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + /** + * 实体模型Id + */ + entityModelId?: string; + projectId?: string; +}; + +export type CreateEnumTypePropertyInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + /** + * Id + */ + enumTypeId?: string; + /** + * 枚举值 + */ + value?: number; +}; + +/** + * 创建语言 + */ +export type CreateLanguageInput = { + /** + * 语言名称 + */ + cultureName?: null | string; + /** + * 显示名称 + */ + displayName?: null | string; + /** + * 图标 + */ + flagIcon?: null | string; + /** + * 是否启用 + */ + isEnabled?: boolean; + /** + * Ui语言名称 + */ + uiCultureName?: null | string; +}; + +/** + * 创建语言文本 + */ +export type CreateLanguageTextInput = { + /** + * 语言名称 + */ + cultureName?: null | string; + /** + * 名称 + */ + name?: null | string; + /** + * 资源名称 + */ + resourceName?: null | string; + /** + * 值 + */ + value?: null | string; +}; + +/** + * 创建菜单 + */ +export type CreateMenuInput = { + /** + * 组件地址 + */ + component?: null | string; + /** + * 标题 + */ + displayTitle?: null | string; + /** + * 是否启用 + */ + enabled?: boolean; + /** + * 是否显示 + */ + hideInMenu: boolean; + /** + * 图标 + */ + icon?: null | string; + /** + * 是否缓存 + */ + keepAlive: boolean; + menuType?: MenuType; + /** + * 唯一编码 + */ + name: string; + openType?: OpenType; + /** + * 排序 + */ + order: number; + parentId?: null | string; + /** + * 路由地址 + */ + path: string; + /** + * 权限 + */ + policy?: null | string; + /** + * 标题 + */ + title: string; + /** + * 内外链地址 + */ + url?: null | string; +}; + +export type CreateOrganizationUnitInput = { + displayName?: null | string; + parentId?: null | string; +}; + +export type CreateProjectInput = { + /** + * 公司名称 + */ + companyName?: null | string; + /** + * 负责人 + */ + owner?: null | string; + /** + * 项目名称 + */ + projectName?: null | string; + /** + * 备注 + */ + remark?: null | string; + /** + * 是否支持多租户 + */ + supportTenant?: boolean; +}; + +export type CreateTemplateDetailInput = { + /** + * 模板内容 + */ + content?: null | string; + controlType?: ControlType; + /** + * 描述 + */ + description?: null | string; + /** + * 模板类型 + */ + name?: null | string; + parentId?: null | string; + /** + * 模板id + */ + templateId?: string; + templateType?: TemplateType; +}; + +export type CreateTemplateInput = { + /** + * 名称 + */ + name?: null | string; + /** + * 备注 + */ + remark?: null | string; +}; + +/** + * 创建模板 + */ +export type CreateTextTemplateInput = { + /** + * 编码 + */ + code: string; + /** + * 内容 + */ + content: string; + /** + * 语言 + */ + cultureName: string; + /** + * 名称 + */ + name: string; +}; + +export type CurrentCultureDto = { + cultureName?: null | string; + dateTimeFormat?: DateTimeFormatDto; + displayName?: null | string; + englishName?: null | string; + isRightToLeft?: boolean; + name?: null | string; + nativeName?: null | string; + threeLetterIsoLanguageName?: null | string; + twoLetterIsoLanguageName?: null | string; +}; + +export type CurrentTenantDto = { + id?: null | string; + isAvailable?: boolean; + name?: null | string; +}; + +export type CurrentUserDto = { + email?: null | string; + emailVerified?: boolean; + id?: null | string; + impersonatorTenantId?: null | string; + impersonatorTenantName?: null | string; + impersonatorUserId?: null | string; + impersonatorUserName?: null | string; + isAuthenticated?: boolean; + name?: null | string; + phoneNumber?: null | string; + phoneNumberVerified?: boolean; + roles?: Array | null; + sessionId?: null | string; + surName?: null | string; + tenantId?: null | string; + userName?: null | string; +}; + +export type DataTypeDto = { + /** + * 编码 + */ + code?: null | string; + /** + * 描述 + */ + description?: null | string; + id?: string; + /** + * 是否是枚举 + */ + isEnum?: boolean; +}; + +export type DateTimeFormatDto = { + calendarAlgorithmType?: null | string; + dateSeparator?: null | string; + dateTimeFormatLong?: null | string; + fullDateTimePattern?: null | string; + longTimePattern?: null | string; + shortDatePattern?: null | string; + shortTimePattern?: null | string; +}; + +export type DeleteAggregateInput = { + id?: string; +}; + +export type DeleteConnectionStringInput = { + /** + * 连接字符串名称 + */ + name?: null | string; + /** + * 租户id + */ + tenantId?: string; +}; + +export type DeleteDataDictionaryDetailInput = { + dataDictionaryId?: string; + dataDictionayDetailId?: string; +}; + +export type DeleteEntityModelInput = { + aggregateId?: string; + id?: string; +}; + +export type DeleteEntityModelPropertyInput = { + id?: string; + propertyId?: string; +}; + +export type DeleteEnumTypeInput = { + entityModelId?: string; + /** + * Id + */ + id?: string; +}; + +export type DeleteEnumTypePropertyInput = { + /** + * Id + */ + enumTypeId?: string; + /** + * Id + */ + id?: string; +}; + +export type DeleteFeatureInput = { + providerKey?: null | string; + providerName?: null | string; +}; + +/** + * 删除文件 + */ +export type DeleteFileObjectInput = { + /** + * 文件Id + */ + id?: string; +}; + +/** + * 删除语言 + */ +export type DeleteLanguageInput = { + /** + * 语言Id + */ + id?: string; +}; + +/** + * 删除菜单 + */ +export type DeleteMenuInput = { + /** + * 菜单Id + */ + id?: string; +}; + +export type DeleteMessageInput = { + id?: string; + /** + * 接受者Id + */ + receiverUserId?: null | string; +}; + +export type DeleteProjectInput = { + id?: string; +}; + +export type DeleteTemplateDetailInput = { + templateDetailId?: string; + templateId?: string; +}; + +export type DeleteTemplateInput = { + id?: string; +}; + +/** + * 删除模板 + */ +export type DeleteTextTemplateInput = { + /** + * 模板Id + */ + id?: string; +}; + +export type DisabledTwoFactorInput = { + /** + * 验证码 + */ + code: string; +}; + +export type DownCodeInput = { + entityId?: Array | null; + projectId?: string; + templateId?: string; +}; + +export type DownloadFileObjectInput = { + /** + * 文件Id + */ + id?: string; +}; + +export type EnabledTwoFactorInput = { + /** + * 验证码 + */ + code: string; + /** + * 密钥 + */ + secret: string; +}; + +export type EntityChangeType = 0 | 1 | 2; + +export type EntityExtensionDto = { + configuration?: null | { + [key: string]: unknown; + }; + properties?: null | { + [key: string]: ExtensionPropertyDto; + }; +}; + +export type EntityOutput = { + /** + * 编码 + */ + code?: null | string; + /** + * 首字母小写 + */ + readonly codeCamelCase?: null | string; + /** + * 复数形式 + */ + readonly codePluralized?: null | string; + /** + * 描述 + */ + description?: null | string; + id?: string; +}; + +export type ExtensionEnumDto = { + fields?: Array | null; + localizationResource?: null | string; +}; + +export type ExtensionEnumFieldDto = { + name?: null | string; + value?: unknown; +}; + +export type ExtensionPropertyApiCreateDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyApiDto = { + onCreate?: ExtensionPropertyApiCreateDto; + onGet?: ExtensionPropertyApiGetDto; + onUpdate?: ExtensionPropertyApiUpdateDto; +}; + +export type ExtensionPropertyApiGetDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyApiUpdateDto = { + isAvailable?: boolean; +}; + +export type ExtensionPropertyAttributeDto = { + config?: null | { + [key: string]: unknown; + }; + typeSimple?: null | string; +}; + +export type ExtensionPropertyDto = { + api?: ExtensionPropertyApiDto; + attributes?: Array | null; + configuration?: null | { + [key: string]: unknown; + }; + defaultValue?: unknown; + displayName?: LocalizableStringDto; + policy?: ExtensionPropertyPolicyDto; + type?: null | string; + typeSimple?: null | string; + ui?: ExtensionPropertyUiDto; +}; + +export type ExtensionPropertyFeaturePolicyDto = { + features?: Array | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyGlobalFeaturePolicyDto = { + features?: Array | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyPermissionPolicyDto = { + permissionNames?: Array | null; + requiresAll?: boolean; +}; + +export type ExtensionPropertyPolicyDto = { + features?: ExtensionPropertyFeaturePolicyDto; + globalFeatures?: ExtensionPropertyGlobalFeaturePolicyDto; + permissions?: ExtensionPropertyPermissionPolicyDto; +}; + +export type ExtensionPropertyUiDto = { + lookup?: ExtensionPropertyUiLookupDto; + onCreateForm?: ExtensionPropertyUiFormDto; + onEditForm?: ExtensionPropertyUiFormDto; + onTable?: ExtensionPropertyUiTableDto; +}; + +export type ExtensionPropertyUiFormDto = { + isVisible?: boolean; +}; + +export type ExtensionPropertyUiLookupDto = { + displayPropertyName?: null | string; + filterParamName?: null | string; + resultListPropertyName?: null | string; + url?: null | string; + valuePropertyName?: null | string; +}; + +export type ExtensionPropertyUiTableDto = { + isVisible?: boolean; +}; + +export type FeatureDto = { + depth?: number; + description?: null | string; + displayName?: null | string; + name?: null | string; + parentName?: null | string; + provider?: FeatureProviderDto; + value?: null | string; + valueType?: IStringValueType; +}; + +export type FeatureGroupDto = { + displayName?: null | string; + features?: Array | null; + name?: null | string; +}; + +export type FeatureProviderDto = { + key?: null | string; + name?: null | string; +}; + +export type FileAggregateRoute = { + aggregator?: null | string; + priority?: number; + routeIsCaseSensitive?: boolean; + routeKeys?: Array | null; + routeKeysConfig?: Array | null; + upstreamHost?: null | string; + readonly upstreamHttpMethod?: Array | null; + upstreamPathTemplate?: null | string; +}; + +export type FileAuthenticationOptions = { + allowedScopes?: Array | null; + authenticationProviderKey?: null | string; +}; + +export type FileCacheOptions = { + region?: null | string; + ttlSeconds?: number; +}; + +export type FileConfiguration = { + aggregates?: Array | null; + dynamicRoutes?: Array | null; + globalConfiguration?: FileGlobalConfiguration; + routes?: Array | null; +}; + +export type FileDynamicRoute = { + downstreamHttpVersion?: null | string; + rateLimitRule?: FileRateLimitRule; + serviceName?: null | string; +}; + +export type FileGlobalConfiguration = { + baseUrl?: null | string; + downstreamHttpVersion?: null | string; + downstreamScheme?: null | string; + httpHandlerOptions?: FileHttpHandlerOptions; + loadBalancerOptions?: FileLoadBalancerOptions; + qoSOptions?: FileQoSOptions; + rateLimitOptions?: FileRateLimitOptions; + requestIdKey?: null | string; + serviceDiscoveryProvider?: FileServiceDiscoveryProvider; +}; + +export type FileHostAndPort = { + host?: null | string; + port?: number; +}; + +export type FileHttpHandlerOptions = { + allowAutoRedirect?: boolean; + maxConnectionsPerServer?: number; + useCookieContainer?: boolean; + useProxy?: boolean; + useTracing?: boolean; +}; + +export type FileLoadBalancerOptions = { + expiry?: number; + key?: null | string; + type?: null | string; +}; + +export type FileQoSOptions = { + durationOfBreak?: number; + exceptionsAllowedBeforeBreaking?: number; + timeoutValue?: number; +}; + +export type FileRateLimitOptions = { + clientIdHeader?: null | string; + disableRateLimitHeaders?: boolean; + httpStatusCode?: number; + quotaExceededMessage?: null | string; + rateLimitCounterPrefix?: null | string; +}; + +export type FileRateLimitRule = { + clientWhitelist?: Array | null; + enableRateLimiting?: boolean; + limit?: number; + period?: null | string; + periodTimespan?: number; +}; + +export type FileRoute = { + addClaimsToRequest?: null | { + [key: string]: null | string; + }; + addHeadersToRequest?: null | { + [key: string]: null | string; + }; + addQueriesToRequest?: null | { + [key: string]: null | string; + }; + authenticationOptions?: FileAuthenticationOptions; + changeDownstreamPathTemplate?: null | { + [key: string]: null | string; + }; + dangerousAcceptAnyServerCertificateValidator?: boolean; + delegatingHandlers?: Array | null; + downstreamHeaderTransform?: null | { + [key: string]: null | string; + }; + downstreamHostAndPorts?: Array | null; + downstreamHttpMethod?: null | string; + downstreamHttpVersion?: null | string; + downstreamPathTemplate?: null | string; + downstreamScheme?: null | string; + fileCacheOptions?: FileCacheOptions; + httpHandlerOptions?: FileHttpHandlerOptions; + key?: null | string; + loadBalancerOptions?: FileLoadBalancerOptions; + priority?: number; + qoSOptions?: FileQoSOptions; + rateLimitOptions?: FileRateLimitRule; + requestIdKey?: null | string; + routeClaimsRequirement?: null | { + [key: string]: null | string; + }; + routeIsCaseSensitive?: boolean; + securityOptions?: FileSecurityOptions; + serviceName?: null | string; + serviceNamespace?: null | string; + timeout?: number; + upstreamHeaderTransform?: null | { + [key: string]: null | string; + }; + upstreamHost?: null | string; + upstreamHttpMethod?: Array | null; + upstreamPathTemplate?: null | string; +}; + +export type FileSecurityOptions = { + ipAllowedList?: Array | null; + ipBlockedList?: Array | null; +}; + +export type FileServiceDiscoveryProvider = { + configurationKey?: null | string; + host?: null | string; + namespace?: null | string; + pollingInterval?: number; + port?: number; + scheme?: null | string; + token?: null | string; + type?: null | string; +}; + +export type FindByUserNameInput = { + userName?: null | string; +}; + +export type FindTenantByNameInput = { + name?: null | string; +}; + +export type FindTenantResultDto = { + isActive?: boolean; + name?: null | string; + normalizedName?: null | string; + success?: boolean; + tenantId?: null | string; +}; + +export type GetDataTypeInput = { + entityModelId?: string; +}; + +export type GetDataTypeOutput = { + /** + * 枚举编码 + */ + code?: null | string; + /** + * 枚举描述 + */ + description?: null | string; + id?: string; +}; + +export type GetEntityModelInput = { + id?: string; +}; + +export type GetEntityModelOutput = { + /** + * 编码 + */ + code?: null | string; + /** + * 描述 + */ + description?: null | string; + entityModelOutputs?: Array | null; + /** + * 实体模型属性集合 + */ + entityModelProperties?: Array | null; + id?: string; + relationalType?: RelationalType; +}; + +export type GetEntityModelPropertyOutput = { + /** + * 名称 + */ + code?: null | string; + /** + * 数据类型Id + */ + dataTypeId?: null | string; + dataTypeOutput?: GetDataTypeOutput; + /** + * 当类型为decimal时的小数位数 (18,4) 中的18 + */ + decimalPrecision?: null | number; + /** + * 当类型为decimal时的字段长度 (18,4) 中的4 + */ + decimalScale?: null | number; + /** + * 描述 + */ + description?: null | string; + /** + * 实体模型Id + */ + entityModelId?: string; + /** + * 枚举类型Id + */ + enumTypeId?: null | string; + enumTypeOutput?: GetEnumTypeOutput; + id?: string; + isEnum?: boolean; + /** + * 必填 + */ + isRequired?: boolean; + /** + * 字符串最大长度 + */ + maxLength?: null | number; + /** + * 字符串最小长度 + */ + minLength?: null | number; +}; + +export type GetEntityModelTreeInput = { + projectId?: string; +}; + +export type GetEntityModelTreeOutput = { + children?: Array | null; + /** + * 描述 + */ + code?: null | string; + /** + * 描述 + */ + description?: null | string; + /** + * 图标 + */ + icon?: null | string; + /** + * 模板id + */ + key?: string; + /** + * 父类Id + */ + parentId?: null | string; + relationalType?: RelationalType; + /** + * 描述 + */ + title?: null | string; +}; + +export type GetEnumTypeOutput = { + /** + * 枚举编码 + */ + code?: null | string; + /** + * 枚举描述 + */ + description?: null | string; + id?: string; +}; + +export type GetFeatureListResultDto = { + groups?: Array | null; +}; + +export type GetFeatureListResultInput = { + providerKey?: null | string; + providerName?: null | string; +}; + +export type GetMenuTreeMetaOutput = { + displayTitle?: null | string; + /** + * 是否显示 + */ + hideInMenu?: boolean; + /** + * 图标 + */ + icon?: null | string; + /** + * 内链地址 + */ + iframeSrc?: null | string; + /** + * 是否缓存 + */ + keepAlive?: boolean; + /** + * 外链地址 + */ + link?: null | string; + /** + * 排序 + */ + order?: number; + title?: null | string; +}; + +export type GetMenuTreeOutput = { + children?: Array | null; + component?: null | string; + enabled?: boolean; + id?: string; + meta?: GetMenuTreeMetaOutput; + /** + * 名称 + */ + name?: null | string; + parentId?: null | string; + path?: null | string; +}; + +export type GetOrganizationUnitRoleInput = { + organizationUnitId?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type GetOrganizationUnitRoleOutput = { + id?: string; + name?: null | string; +}; + +export type GetOrganizationUnitRoleOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetOrganizationUnitUserInput = { + filter?: null | string; + organizationUnitId?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type GetOrganizationUnitUserOutput = { + email?: null | string; + id?: string; + userName?: null | string; +}; + +export type GetOrganizationUnitUserOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetPermissionInput = { + providerKey?: null | string; + providerName?: null | string; +}; + +export type GetProjectAndEntityInput = { + id?: string; +}; + +export type GetProjectAndEntityOutput = { + entities?: Array | null; + project?: ProjectOutput; +}; + +export type GetQRCodeOutput = { + /** + * base64 二维码 + */ + qrCode?: null | string; + /** + * 密钥 + */ + secret?: null | string; +}; + +export type GetTemplateTreeOutput = { + children?: Array | null; + /** + * 模板内容 + */ + content?: null | string; + controlType?: ControlType; + /** + * 描述 + */ + description?: null | string; + /** + * 图标 + */ + icon?: null | string; + /** + * 模板id + */ + key?: string; + /** + * 模板名称 + */ + name?: null | string; + templateType?: TemplateType; + /** + * 描述 + */ + title?: null | string; +}; + +export type GetTemplteTreeInput = { + templateId?: string; +}; + +export type GetUnAddRoleInput = { + filter?: null | string; + organizationUnitId?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type GetUnAddRoleOutput = { + id?: string; + name?: null | string; +}; + +export type GetUnAddRoleOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type GetUnAddUserInput = { + filter?: null | string; + organizationUnitId?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type GetUnAddUserOutput = { + email?: null | string; + id?: string; + userName?: null | string; +}; + +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?: null | string; +}; + +export type IdentityRoleCreateDto = { + readonly extraProperties?: null | { + [key: string]: unknown; + }; + isDefault?: boolean; + isPublic?: boolean; + name: string; +}; + +export type IdentityRoleDto = { + concurrencyStamp?: null | string; + creationTime?: string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + isDefault?: boolean; + isPublic?: boolean; + isStatic?: boolean; + name?: null | string; +}; + +export type IdentityRoleDtoListResultDto = { + items?: Array | null; +}; + +export type IdentityRoleDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type IdentityRoleUpdateDto = { + concurrencyStamp?: null | string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + isDefault?: boolean; + isPublic?: boolean; + name: string; +}; + +export type IdentityUserCreateDto = { + email: string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + isActive?: boolean; + lockoutEnabled?: boolean; + name?: null | string; + password: string; + phoneNumber?: null | string; + roleNames?: Array | null; + surname?: null | string; + userName: string; +}; + +export type IdentityUserDto = { + accessFailedCount?: number; + concurrencyStamp?: null | string; + creationTime?: string; + creatorId?: null | string; + deleterId?: null | string; + deletionTime?: null | string; + email?: null | string; + emailConfirmed?: boolean; + entityVersion?: number; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + isActive?: boolean; + isDeleted?: boolean; + lastModificationTime?: null | string; + lastModifierId?: null | string; + lastPasswordChangeTime?: null | string; + lockoutEnabled?: boolean; + lockoutEnd?: null | string; + name?: null | string; + phoneNumber?: null | string; + phoneNumberConfirmed?: boolean; + surname?: null | string; + tenantId?: null | string; + userName?: null | string; +}; + +export type IdentityUserUpdateDto = { + concurrencyStamp?: null | string; + email: string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + isActive?: boolean; + lockoutEnabled?: boolean; + name?: null | string; + password?: null | string; + phoneNumber?: null | string; + roleNames?: Array | null; + surname?: null | string; + userName: string; +}; + +export type IdInput = { + id?: string; +}; + +export type InterfaceMethodApiDescriptionModel = { + name?: null | string; + parametersOnMethod?: Array | null; + returnValue?: ReturnValueApiDescriptionModel; +}; + +export type IStringValueType = { + readonly name?: null | string; + readonly properties?: null | { + [key: string]: unknown; + }; + validator?: IValueValidator; +}; + +export type IValueValidator = { + readonly name?: null | string; + readonly properties?: null | { + [key: string]: unknown; + }; +}; + +export type LanguageInfo = { + cultureName?: null | string; + displayName?: null | string; + readonly twoLetterISOLanguageName?: null | string; + uiCultureName?: null | string; +}; + +export type LocalizableStringDto = { + name?: null | string; + resource?: null | string; +}; + +export type LockUserInput = { + locked?: boolean; + userId?: string; +}; + +/** + * 登录 + */ +export type Login2FAInput = { + /** + * 双因素验证码 + */ + code?: null | string; + /** + * 用户名或者邮箱 + */ + name?: null | string; + /** + * 密码 + */ + password?: null | string; +}; + +/** + * 登录 + */ +export type LoginInput = { + /** + * 用户名或者邮箱 + */ + name?: null | string; + /** + * 密码 + */ + password?: null | string; +}; + +/** + * 登录 + */ +export type LoginOidcInput = { + /** + * code + */ + code: string; + /** + * Provider + */ + state: string; +}; + +export type LoginOutput = { + id?: string; + name?: null | string; + refreshToken?: null | string; + roles?: Array | null; + token?: null | string; + userName?: null | string; +}; + +export type LoginResultType = 1 | 2 | 3 | 4 | 5; + +/** + * 菜单类型 + */ +export type MenuType = 10 | 20; + +/** + * 消息等级 + */ +export type MessageLevel = 10 | 20 | 30; + +/** + * 消息类型 + */ +export type MessageType = 10 | 20; + +export type MethodParameterApiDescriptionModel = { + defaultValue?: unknown; + isOptional?: boolean; + name?: null | string; + type?: null | string; + typeAsString?: null | string; + typeSimple?: null | string; +}; + +export type ModuleApiDescriptionModel = { + controllers?: null | { + [key: string]: ControllerApiDescriptionModel; + }; + remoteServiceName?: null | string; + rootPath?: null | string; +}; + +export type ModuleExtensionDto = { + configuration?: null | { + [key: string]: unknown; + }; + entities?: null | { + [key: string]: EntityExtensionDto; + }; +}; + +export type MultiTenancyInfoDto = { + isEnabled?: boolean; +}; + +export type MyProfileOutput = { + email?: null | string; + isActive?: boolean; + name?: null | string; + phoneNumber?: null | string; + surname?: null | string; + tenantId?: null | string; + twoFactorEnabled?: boolean; + userName?: null | string; +}; + +export type NameValue = { + name?: null | string; + value?: null | string; +}; + +export type NeedChangePasswordOutput = { + message?: null | string; + needChangePassword?: boolean; +}; + +export type ObjectExtensionsDto = { + enums?: null | { + [key: string]: ExtensionEnumDto; + }; + modules?: null | { + [key: string]: ModuleExtensionDto; + }; +}; + +export type OidcConfiguration = { + /** + * 认证地址 + */ + authUri?: null | string; + /** + * client_id + */ + clientId?: null | string; + /** + * 应用名称 + */ + clientName?: null | string; + /** + * 是否启用 + */ + enabled?: boolean; + /** + * 应用图标 + */ + icon?: null | string; + /** + * 类型 + */ + type?: null | string; +}; + +/** + * 打开类型 + */ +export type OpenType = 10 | 20 | 30 | 40; + +export type PageEntityModelInput = { + filter?: null | string; + id?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PageEntityModelPropertyOutput = { + /** + * 允许添加 + */ + allowAdd?: boolean; + /** + * 允许编辑 + */ + allowEdit?: boolean; + /** + * 允许作为查询条件 + */ + allowSearch?: boolean; + /** + * 名称 + */ + code?: null | string; + dataTypeCode?: null | string; + dataTypeDescription?: null | string; + dataTypeId?: string; + /** + * 当类型为decimal时的小数位数 (18,4) 中的18 + */ + decimalPrecision?: null | number; + /** + * 当类型为decimal时的字段长度 (18,4) 中的4 + */ + decimalScale?: null | number; + /** + * 描述 + */ + description?: null | string; + /** + * 实体模型Id + */ + entityModelId?: string; + id?: null | string; + isEnum?: boolean; + /** + * 必填 + */ + isRequired?: boolean; + /** + * 字符串最大长度 + */ + maxLength?: null | number; + /** + * 字符串最小长度 + */ + minLength?: null | number; +}; + +export type PageEntityModelPropertyOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageEnumTypeInput = { + filter?: null | string; + id?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PageEnumTypeOutput = { + /** + * 名称 + */ + code?: null | string; + creationTime?: string; + /** + * 描述 + */ + description?: null | string; + /** + * 实体模型Id + */ + entityModelId?: string; + id?: null | string; +}; + +export type PageEnumTypeOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageEnumTypePropertyInput = { + filter?: null | string; + id?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PageEnumTypePropertyOutput = { + /** + * 名称 + */ + code?: null | string; + creationTime?: string; + /** + * 描述 + */ + description?: null | string; + id?: null | string; + /** + * 名称 + */ + value?: number; +}; + +export type PageEnumTypePropertyOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +/** + * 分页查询文件 + */ +export type PageFileObjectInput = { + /** + * 结束创建时间 + */ + endCreationTime?: null | string; + /** + * 文件名称 + */ + fileName?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; + /** + * 开始创建时间 + */ + startCreationTime?: null | string; +}; + +/** + * 分页查询文件 + */ +export type PageFileObjectOutput = { + readonly beautifySize?: null | string; + /** + * 文件名称 + */ + contentType?: null | string; + /** + * 创建时间 + */ + creationTime?: string; + /** + * 文件名称 + */ + fileName?: null | string; + /** + * 文件大小 + */ + fileSize?: number; + /** + * 文件Id + */ + id?: string; +}; + +export type PageFileObjectOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageIdentityUserOutput = { + accessFailedCount?: number; + concurrencyStamp?: null | string; + creationTime?: string; + creatorId?: null | string; + deleterId?: null | string; + deletionTime?: null | string; + email?: null | string; + emailConfirmed?: boolean; + entityVersion?: number; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + isActive?: boolean; + isDeleted?: boolean; + lastModificationTime?: null | string; + lastModifierId?: null | string; + lastPasswordChangeTime?: null | string; + lockoutEnabled?: boolean; + lockoutEnd?: null | string; + name?: null | string; + phoneNumber?: null | string; + phoneNumberConfirmed?: boolean; + surname?: null | string; + tenantId?: null | string; + /** + * 是否开启双因素验证码 + */ + twoFactorEnabled?: boolean; + userName?: null | string; +}; + +export type PageIdentityUserOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +/** + * 创建语言 + */ +export type PageLanguageInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +/** + * 创建语言 + */ +export type PageLanguageOutput = { + /** + * 创建时间 + */ + creationTime?: string; + /** + * 语言名称 + */ + cultureName?: null | string; + /** + * 显示名称 + */ + displayName?: null | string; + /** + * 图标 + */ + flagIcon?: null | string; + /** + * 语言Id + */ + id?: string; + /** + * 是否是默认语言 + */ + isDefault?: boolean; + /** + * 是否启用 + */ + isEnabled?: boolean; + /** + * Ui语言名称 + */ + uiCultureName?: null | string; +}; + +export type PageLanguageOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +/** + * 创建语言文本 + */ +export type PageLanguageTextInput = { + /** + * 语言 + */ + cultureName?: null | string; + /** + * 查询条件 name or value + */ + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 资源 + */ + resourceName?: null | string; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +/** + * 创建语言文本 + */ +export type PageLanguageTextOutput = { + /** + * 名称 + */ + name?: null | string; + /** + * 资源名称 + */ + resourceName?: null | string; + /** + * 值 + */ + value?: null | string; +}; + +export type PageLanguageTextOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +/** + * 分页查询菜单 + */ +export type PageMenuInput = { + /** + * 结束创建时间 + */ + endCreationTime?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; + /** + * 开始创建时间 + */ + startCreationTime?: null | string; +}; + +/** + * 分页查询菜单 + */ +export type PageMenuOutput = { + /** + * 组件地址 + */ + component?: null | string; + /** + * 创建时间 + */ + creationTime?: string; + /** + * 标题 + */ + displayTitle?: null | string; + /** + * 是否启用 + */ + enabled?: boolean; + /** + * 是否显示 + */ + hideInMenu?: boolean; + /** + * 图标 + */ + icon?: null | string; + /** + * 菜单Id + */ + id?: string; + /** + * 是否缓存 + */ + keepAlive?: boolean; + /** + * 标题 + */ + localizationTitle?: null | string; + menuType?: MenuType; + readonly menuTypeDescription?: null | string; + /** + * 唯一编码 + */ + name?: null | string; + openType?: OpenType; + readonly openTypeDescription?: null | string; + /** + * 排序 + */ + order?: number; + parentId?: null | string; + /** + * 路由/接口地址 + */ + path?: null | string; + /** + * 权限 + */ + policy?: null | string; + /** + * 标题 + */ + title?: null | string; + /** + * 内外链地址 + */ + url?: null | string; +}; + +export type PageMenuOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PageProjectInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PageTemplateInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PageTenantConnectionStringInput = { + /** + * 租户id + */ + id?: string; + /** + * 连接字符串名称 + */ + name?: null | string; + /** + * 连接字符串地址 + */ + value?: null | string; +}; + +export type PageTenantConnectionStringOutput = { + /** + * 连接字符串名称 + */ + name?: null | string; + /** + * 租户id + */ + tenantId?: string; + /** + * 连接字符串地址 + */ + value?: null | string; +}; + +export type PageTenantConnectionStringOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +/** + * 分页查询模板 + */ +export type PageTextTemplateInput = { + /** + * 编码 + */ + code?: null | string; + /** + * 内容 + */ + content?: null | string; + /** + * 结束创建时间 + */ + endCreationTime?: null | string; + /** + * 名称 + */ + name?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; + /** + * 开始创建时间 + */ + startCreationTime?: null | string; +}; + +/** + * 分页查询模板 + */ +export type PageTextTemplateOutput = { + /** + * 编码 + */ + code?: null | string; + /** + * 内容 + */ + content?: null | string; + /** + * 创建时间 + */ + creationTime?: string; + /** + * 语言 + */ + cultureName?: null | string; + /** + * 模板Id + */ + id?: string; + /** + * 名称 + */ + name?: null | string; +}; + +export type PageTextTemplateOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingAuditLogActionOutput = { + auditLogId?: string; + executionDuration?: number; + executionTime?: null | string; + extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + methodName?: null | string; + parameters?: null | string; + serviceName?: null | string; + tenantId?: null | string; +}; + +export type PagingAuditLogInput = { + /** + * 应用程序名称 + */ + applicationName?: null | string; + /** + * 客户端IP + */ + clientIpAddress?: null | string; + /** + * RequestId + */ + correlationId?: null | string; + /** + * 结束时间 + */ + endTime?: null | string; + /** + * 是否有异常 + */ + hasException?: boolean | null; + /** + * 请求方法 + */ + httpMethod?: null | string; + httpStatusCode?: HttpStatusCode; + /** + * 最大执行时间 + */ + maxExecutionDuration?: null | number; + /** + * 最小执行时间 + */ + minExecutionDuration?: null | number; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + */ + sorting?: null | string; + /** + * 开始时间 + */ + startTime?: null | string; + /** + * 请求地址 + */ + url?: null | string; + /** + * 用户Id + */ + userId?: null | string; + /** + * 用户名 + */ + userName?: null | string; +}; + +export type PagingAuditLogOutput = { + actions?: Array | null; + applicationName?: null | string; + browserInfo?: null | string; + clientId?: null | string; + clientIpAddress?: null | string; + clientName?: null | string; + comments?: null | string; + correlationId?: null | string; + entityChanges?: Array | null; + exceptions?: null | string; + executionDuration?: number; + executionTime?: null | string; + httpMethod?: null | string; + httpStatusCode?: null | number; + impersonatorTenantId?: null | string; + impersonatorUserId?: null | string; + tenantId?: null | string; + tenantName?: null | string; + url?: null | string; + userId?: null | string; + userName?: null | string; +}; + +export type PagingAuditLogOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingDataDictionaryDetailInput = { + dataDictionaryId?: string; + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PagingDataDictionaryDetailOutput = { + /** + * 字典明细编码 + */ + code?: null | string; + /** + * 所属字典Id + */ + dataDictionaryId?: string; + /** + * 描述 + */ + description?: null | string; + /** + * 英文显示名 + */ + displayText?: null | string; + id?: string; + /** + * 启/停用(默认启用) + */ + isEnabled?: boolean; + /** + * 展现列表时排序用 + */ + order?: number; +}; + +export type PagingDataDictionaryDetailOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingDataDictionaryInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PagingDataDictionaryOutput = { + /** + * 字典编码 + */ + code?: null | string; + /** + * 描述 + */ + description?: null | string; + /** + * 显示名 + */ + displayText?: null | string; + id?: string; +}; + +export type PagingDataDictionaryOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingEntityChangeOutput = { + auditLogId?: string; + changeTime?: null | string; + changeType?: EntityChangeType; + changeTypeDescription?: null | string; + entityId?: null | string; + entityTenantId?: null | string; + entityTypeFullName?: null | string; + extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + propertyChanges?: Array | null; + tenantId?: null | string; +}; + +export type PagingEntityPropertyChangeOutput = { + entityChangeId?: string; + id?: string; + newValue?: null | string; + originalValue?: null | string; + propertyName?: null | string; + propertyTypeFullName?: null | string; + tenantId?: null | string; +}; + +export type PagingIdentitySecurityLogInput = { + /** + * 请求地址 + */ + action?: null | string; + /** + * 应用程序名称 + */ + applicationName?: null | string; + /** + * ClientId + */ + clientId?: null | string; + /** + * RequestId + */ + correlationId?: null | string; + /** + * 结束时间 + */ + endTime?: null | string; + identity?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + */ + sorting?: null | string; + /** + * 开始时间 + */ + startTime?: null | string; + /** + * 用户Id + */ + userId?: null | string; + /** + * 用户名 + */ + userName?: null | string; +}; + +export type PagingIdentitySecurityLogOutput = { + action?: null | string; + applicationName?: null | string; + browserInfo?: null | string; + clientId?: null | string; + clientIpAddress?: null | string; + correlationId?: null | string; + creationTime?: string; + id?: string; + identity?: null | string; + tenantId?: null | string; + tenantName?: null | string; + userId?: null | string; + userName?: null | string; +}; + +export type PagingIdentitySecurityLogOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingNotificationInput = { + /** + * 内容 + */ + content?: null | string; + /** + * 已读结束时间 + */ + endReadTime?: null | string; + messageLevel?: MessageLevel; + messageType?: MessageType; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 是否已读 + */ + read?: boolean | null; + /** + * 接受者Id + */ + receiverUserId?: null | string; + /** + * 接受者名称 + */ + receiverUserName?: null | string; + /** + * 发送者Id + */ + senderUserId?: null | string; + /** + * 发送者名称 + */ + senderUserName?: null | string; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; + /** + * 已读开始时间 + */ + startReadTime?: null | string; + /** + * 标题 + */ + title?: null | string; +}; + +export type PagingNotificationOutput = { + /** + * 消息内容 + */ + content?: null | string; + creationTime?: string; + id?: string; + messageLevel?: MessageLevel; + readonly messageLevelName?: null | string; + messageType?: MessageType; + readonly messageTypeName?: null | string; + /** + * 是否已读 + */ + read?: boolean; + /** + * 已读时间 + */ + readTime?: null | string; + /** + * 订阅人 + * 消息类型是广播消息时,订阅人为空 + */ + receiveUserId?: null | string; + /** + * 接收人用户名 + * 消息类型是广播消息时,订接收人用户名为空 + */ + receiveUserName?: null | string; + /** + * 发送人 + */ + senderUserId?: string; + /** + * 发送人用户名 + */ + senderUserName?: null | string; + /** + * 租户id + */ + tenantId?: null | string; + /** + * 消息标题 + */ + title?: null | string; +}; + +export type PagingNotificationOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingNotificationSubscriptionInput = { + /** + * 已读结束时间 + */ + endReadTime?: null | string; + notificationId?: string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 是否已读 + */ + read?: boolean | null; + /** + * 接受者Id + */ + receiverUserId?: null | string; + /** + * 接受者名称 + */ + receiverUserName?: null | string; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; + /** + * 已读开始时间 + */ + startReadTime?: null | string; +}; + +export type PagingNotificationSubscriptionOutput = { + /** + * 消息内容 + */ + content?: null | string; + id?: string; + messageLevel?: MessageLevel; + readonly messageLevelName?: null | string; + messageType?: MessageType; + readonly messageTypeName?: null | string; + /** + * 消息Id + */ + notificationId?: string; + /** + * 是否已读 + */ + read?: boolean; + /** + * 已读时间 + */ + readTime?: string; + /** + * 接收人id + */ + receiveUserId?: string; + /** + * 接收人用户名 + */ + receiveUserName?: null | string; + /** + * 发送人 + */ + senderUserId?: string; + /** + * 发送人用户名 + */ + senderUserName?: null | string; + /** + * 租户id + */ + tenantId?: null | string; + /** + * 消息标题 + */ + title?: null | string; +}; + +export type PagingNotificationSubscriptionOutputPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type PagingRoleListInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PagingTenantInput = { + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type PagingUserListInput = { + /** + * 关键字 + */ + filter?: null | string; + /** + * 当前页面.默认从1开始 + */ + pageIndex?: number; + /** + * 每页多少条.每页显示多少记录 + */ + pageSize?: number; + /** + * 跳过多少条 + */ + readonly skipCount?: number; + /** + * 排序 + * + * name desc + * + */ + sorting?: null | string; +}; + +export type ParameterApiDescriptionModel = { + bindingSourceId?: null | string; + constraintTypes?: Array | null; + defaultValue?: unknown; + descriptorName?: null | string; + isOptional?: boolean; + jsonName?: null | string; + name?: null | string; + nameOnMethod?: null | string; + type?: null | string; + typeSimple?: null | string; +}; + +export type PermissionOutput = { + allGrants?: Array | null; + grants?: Array | null; + permissions?: Array | null; +}; + +export type PermissionTreeDto = { + children?: Array | null; + key?: null | string; + title?: null | string; +}; + +export type PreViewCodeInput = { + entityId?: Array | null; + projectId?: string; + templateId?: string; +}; + +export type ProjectDto = { + /** + * 公司名称 + */ + companyName?: null | string; + creationTime?: string; + creatorId?: null | string; + id?: string; + lastModificationTime?: null | string; + lastModifierId?: null | string; + /** + * 名称空间 + */ + nameSpace?: null | string; + /** + * 负责人 + */ + owner?: null | string; + /** + * 项目名称 + */ + projectName?: null | string; + /** + * 备注 + */ + remark?: null | string; + /** + * 是否支持多租户 + */ + supportTenant?: boolean; + tenantId?: null | string; +}; + +export type ProjectDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type ProjectOutput = { + /** + * 公司名称 + */ + companyName?: null | string; + id?: string; + /** + * 项目名称 + */ + projectName?: null | string; +}; + +export type PropertyApiDescriptionModel = { + isRequired?: boolean; + jsonName?: null | string; + maximum?: null | string; + maxLength?: null | number; + minimum?: null | string; + minLength?: null | number; + name?: null | string; + regex?: null | string; + type?: null | string; + typeSimple?: null | string; +}; + +export type RefreshTokenInput = { + refreshToken: string; + userId?: string; +}; + +export type RefreshTokenOutput = { + message?: null | string; + refreshToken?: null | string; + success?: boolean; + token?: null | string; +}; + +export type RelationalType = 10 | 20; + +export type RemoteServiceErrorInfo = { + code?: null | string; + data?: null | { + [key: string]: unknown; + }; + details?: null | string; + message?: null | string; + validationErrors?: Array | null; +}; + +export type RemoteServiceErrorResponse = { + error?: RemoteServiceErrorInfo; +}; + +export type RemoteServiceValidationErrorInfo = { + members?: Array | null; + message?: null | string; +}; + +export type RemoteStreamContent = { + readonly contentLength?: null | number; + contentType?: null | string; + fileName?: null | string; +}; + +export type RemoveRoleToOrganizationUnitInput = { + organizationUnitId?: string; + roleId?: string; +}; + +export type RemoveUserToOrganizationUnitInput = { + organizationUnitId?: string; + userId?: string; +}; + +export type ResetPasswordInput = { + password: string; + userId?: string; +}; + +export type ResetTwoFactorInput = { + userId?: string; +}; + +export type ReturnValueApiDescriptionModel = { + type?: null | string; + typeSimple?: null | string; +}; + +export type SendBroadCastMessageInput = { + /** + * 消息内容 + */ + content?: null | string; + /** + * 消息标题 + */ + title?: null | string; +}; + +export type SendCommonMessageInput = { + /** + * 消息内容 + */ + content?: null | string; + /** + * 发送人 + */ + receiveUserId?: string; + /** + * 发送人名称 + */ + receiveUserName?: null | string; + /** + * 消息标题 + */ + title?: null | string; +}; + +export type SetBatchReadInput = { + ids?: Array | null; +}; + +export type SetDataDictinaryDetailInput = { + dataDictionaryId?: string; + dataDictionayDetailId?: string; + isEnabled: boolean; +}; + +export type SetReadInput = { + id?: string; +}; + +export type SettingItemOutput = { + /** + * 描述 + */ + description?: null | string; + /** + * 显示名称 + */ + displayName?: null | string; + /** + * 名称 + */ + name?: null | string; + /** + * 前端控件类型 + */ + type?: null | string; + /** + * 值 + */ + value?: null | string; +}; + +export type SettingOutput = { + /** + * 分组 + */ + group?: null | string; + /** + * 分组显示名称 + */ + groupDisplayName?: null | string; + settingItemOutput?: Array | null; +}; + +export type StringInt32KeyValuePair = { + key?: null | string; + value?: number; +}; + +export type StringStringFromSelector = { + readonly label?: null | string; + readonly value?: null | string; +}; + +/** + * 模板明细 + */ +export type TemplateDetailDto = { + /** + * 模板内容 + */ + content?: null | string; + controlType?: ControlType; + /** + * 描述 + */ + description?: null | string; + id?: string; + /** + * 模板名称 + */ + name?: null | string; + /** + * 父级id + */ + parentId?: null | string; + /** + * 模板id + */ + templateId?: string; + templateType?: TemplateType; +}; + +/** + * 模板 + */ +export type TemplateDto = { + creationTime?: string; + creatorId?: null | string; + id?: string; + lastModificationTime?: null | string; + lastModifierId?: null | string; + /** + * 名称 + */ + name?: null | string; + /** + * 备注 + */ + remark?: null | string; + /** + * 关联属性1:N 模板明细集合 + */ + templateDetails?: Array | null; + tenantId?: null | string; +}; + +export type TemplateDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type TemplateTreeDto = { + children?: Array | null; + /** + * 模板内容 + */ + content?: null | string; + controlType?: ControlType; + /** + * 描述 + */ + description?: null | string; + /** + * 图标 + */ + icon?: null | string; + /** + * 是否是文件夹 + */ + isFolder?: boolean; + /** + * 模板id + */ + key?: string; + /** + * 模板名称 + */ + name?: null | string; + templateType?: TemplateType; + /** + * 描述 + */ + title?: null | string; +}; + +export type TemplateType = 10 | 20; + +export type TenantCreateDto = { + adminEmailAddress: string; + adminPassword: string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + name: string; +}; + +export type TenantDto = { + concurrencyStamp?: null | string; + readonly extraProperties?: null | { + [key: string]: unknown; + }; + id?: string; + name?: null | string; +}; + +export type TenantDtoPagedResultDto = { + items?: Array | null; + totalCount?: number; +}; + +export type TimeZone = { + iana?: IanaTimeZone; + windows?: WindowsTimeZone; +}; + +export type TimingDto = { + timeZone?: TimeZone; +}; + +export type TreeOutput = { + children?: Array | null; + key?: string; + title?: null | string; +}; + +export type TypeApiDescriptionModel = { + baseType?: null | string; + enumNames?: Array | null; + enumValues?: Array | null; + genericArguments?: Array | null; + isEnum?: boolean; + properties?: Array | null; +}; + +export type UpdateAggregateInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + id?: string; +}; + +export type UpdateDataDictinaryInput = { + code?: null | string; + description?: null | string; + displayText?: null | string; + id?: string; +}; + +export type UpdateDetailInput = { + dataDictionaryId?: string; + description?: null | string; + displayText?: null | string; + id?: string; + order?: number; +}; + +export type UpdateEntityModelInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + id?: string; + relationalType?: RelationalType; +}; + +export type UpdateEntityModelPropertyInput = { + /** + * 允许添加 + */ + allowAdd?: boolean; + /** + * 允许编辑 + */ + allowEdit?: boolean; + /** + * 允许作为查询条件 + */ + allowSearch?: boolean; + /** + * 编码 + */ + code: string; + /** + * 数据类型Id + */ + dataTypeId?: null | string; + /** + * 当类型为decimal时的小数位数 (18,4) 中的18 + */ + decimalPrecision?: null | number; + /** + * 当类型为decimal时的字段长度 (18,4) 中的4 + */ + decimalScale?: null | number; + /** + * 描述 + */ + description: string; + /** + * 实体模型Id + */ + entityModelId?: string; + /** + * 枚举类型Id + */ + enumTypeId?: null | string; + id?: string; + /** + * 必填 + */ + isRequired?: boolean; + /** + * 字符串最大长度 + */ + maxLength?: null | number; + /** + * 字符串最小长度 + */ + minLength?: null | number; + propertyId?: string; +}; + +export type UpdateEnumTypeInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + id?: string; +}; + +export type UpdateEnumTypePropertyInput = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description: string; + /** + * Id + */ + enumTypeId?: string; + /** + * Id + */ + id?: string; + /** + * 枚举值 + */ + value?: number; +}; + +export type UpdateFeatureDto = { + name?: null | string; + value?: null | string; +}; + +export type UpdateFeatureInput = { + providerKey?: null | string; + providerName?: null | string; + updateFeaturesDto?: UpdateFeaturesDto; +}; + +export type UpdateFeaturesDto = { + features?: Array | null; +}; + +/** + * 删除语言 + */ +export type UpdateLanguageInput = { + /** + * 语言名称 + */ + cultureName?: null | string; + /** + * 显示名称 + */ + displayName?: null | string; + /** + * 图标 + */ + flagIcon?: null | string; + /** + * 语言Id + */ + id?: string; + /** + * 是否启用 + */ + isEnabled?: boolean; + /** + * Ui语言名称 + */ + uiCultureName?: null | string; +}; + +/** + * 删除语言文本 + */ +export type UpdateLanguageTextInput = { + /** + * 语言名称 + */ + cultureName: string; + /** + * 名称 + */ + name: string; + /** + * 资源名称 + */ + resourceName: string; + /** + * 值 + */ + value: string; +}; + +/** + * 更新菜单 + */ +export type UpdateMenuInput = { + /** + * 组件地址 + */ + component?: null | string; + enabled?: boolean; + /** + * 是否显示 + */ + hideInMenu: boolean; + /** + * 图标 + */ + icon?: null | string; + /** + * 菜单Id + */ + id?: string; + /** + * 是否缓存 + */ + keepAlive: boolean; + menuType?: MenuType; + /** + * 唯一编码 + */ + name: string; + openType?: OpenType; + /** + * 排序 + */ + order: number; + /** + * 路由地址 + */ + path: string; + /** + * 权限 + */ + policy?: null | string; + /** + * 标题 + */ + title: string; + /** + * 内外链地址 + */ + url?: null | string; +}; + +export type UpdateOrganizationUnitInput = { + displayName?: null | string; + id?: string; +}; + +export type UpdatePermissionDto = { + isGranted?: boolean; + name?: null | string; +}; + +export type UpdatePermissionsDto = { + permissions?: Array | null; +}; + +export type UpdateProjectInput = { + /** + * 公司名称 + */ + companyName?: null | string; + id?: string; + /** + * 负责人 + */ + owner?: null | string; + /** + * 项目名称 + */ + projectName?: null | string; + /** + * 备注 + */ + remark?: null | string; + /** + * 是否支持多租户 + */ + supportTenant?: boolean; +}; + +export type UpdateRoleInput = { + roleId?: string; + roleInfo?: IdentityRoleUpdateDto; +}; + +export type UpdateRolePermissionsInput = { + providerKey?: null | string; + providerName?: null | string; + updatePermissionsDto?: UpdatePermissionsDto; +}; + +export type UpdateSettingInput = { + values?: null | { + [key: string]: null | string; + }; +}; + +export type UpdateTemplateDetailContentInput = { + /** + * 模板内容 + */ + content?: null | string; + templateDetailId?: string; + /** + * 模板id + */ + templateId?: string; +}; + +export type UpdateTemplateDetailInput = { + /** + * 模板内容 + */ + content?: null | string; + controlType?: ControlType; + /** + * 描述 + */ + description?: null | string; + /** + * 模板类型 + */ + name?: null | string; + templateDetailId?: string; + /** + * 模板id + */ + templateId?: string; +}; + +export type UpdateTemplateInput = { + id?: string; + /** + * 名称 + */ + name?: null | string; + /** + * 备注 + */ + remark?: null | string; +}; + +export type UpdateTenantInput = { + id?: string; + name?: null | string; +}; + +/** + * 更新模板 + */ +export type UpdateTextTemplateInput = { + /** + * 编码 + */ + code: string; + /** + * 内容 + */ + content: string; + /** + * 语言 + */ + cultureName: string; + /** + * 模板Id + */ + id?: string; + /** + * 名称 + */ + name: string; +}; + +export type UpdateUserInput = { + userId?: string; + userInfo?: IdentityUserUpdateDto; +}; + +export type UserLoginInfo = { + password: string; + rememberMe?: boolean; + userNameOrEmailAddress: string; +}; + +export type WindowsTimeZone = { + timeZoneId?: null | string; +}; + +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 GetApiAppAbpProBasicApplicationConfigurationResponse = + AbpProApplicationConfigurationDto; + +export type GetApiAppAbpProBasicApplicationConfigurationError = + RemoteServiceErrorResponse; + +export type PostApiAppAccountLoginData = { + body?: LoginInput; +}; + +export type PostApiAppAccountLoginResponse = LoginOutput; + +export type PostApiAppAccountLoginError = RemoteServiceErrorResponse; + +export type PostApiAppAccountLogin2FaData = { + body?: Login2FAInput; +}; + +export type PostApiAppAccountLogin2FaResponse = LoginOutput; + +export type PostApiAppAccountLogin2FaError = RemoteServiceErrorResponse; + +export type PostApiAppAccountLoginOidcData = { + body?: LoginOidcInput; +}; + +export type PostApiAppAccountLoginOidcResponse = LoginOutput; + +export type PostApiAppAccountLoginOidcError = RemoteServiceErrorResponse; + +export type PostApiAppAccountRefreshTokenData = { + body?: RefreshTokenInput; +}; + +export type PostApiAppAccountRefreshTokenResponse = RefreshTokenOutput; + +export type PostApiAppAccountRefreshTokenError = 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 PostDataTypesListData = { + body?: GetDataTypeInput; +}; + +export type PostDataTypesListResponse = Array; + +export type PostDataTypesListError = RemoteServiceErrorResponse; + +export type PostEntityModelsPagePropertyData = { + body?: PageEntityModelInput; +}; + +export type PostEntityModelsPagePropertyResponse = + PageEntityModelPropertyOutputPagedResultDto; + +export type PostEntityModelsPagePropertyError = RemoteServiceErrorResponse; + +export type PostEntityModelsCreateAggregateData = { + body?: CreateAggregateInput; +}; + +export type PostEntityModelsCreateAggregateResponse = unknown; + +export type PostEntityModelsCreateAggregateError = RemoteServiceErrorResponse; + +export type PostEntityModelsUpdateAggregateData = { + body?: UpdateAggregateInput; +}; + +export type PostEntityModelsUpdateAggregateResponse = unknown; + +export type PostEntityModelsUpdateAggregateError = RemoteServiceErrorResponse; + +export type PostEntityModelsDeleteAggregateData = { + body?: DeleteAggregateInput; +}; + +export type PostEntityModelsDeleteAggregateResponse = unknown; + +export type PostEntityModelsDeleteAggregateError = RemoteServiceErrorResponse; + +export type PostEntityModelsCreateEntityModelData = { + body?: CreateEntityModelInput; +}; + +export type PostEntityModelsCreateEntityModelResponse = unknown; + +export type PostEntityModelsCreateEntityModelError = RemoteServiceErrorResponse; + +export type PostEntityModelsUpdateEntityModelData = { + body?: UpdateEntityModelInput; +}; + +export type PostEntityModelsUpdateEntityModelResponse = unknown; + +export type PostEntityModelsUpdateEntityModelError = RemoteServiceErrorResponse; + +export type PostEntityModelsDeleteEntityModelData = { + body?: DeleteEntityModelInput; +}; + +export type PostEntityModelsDeleteEntityModelResponse = unknown; + +export type PostEntityModelsDeleteEntityModelError = RemoteServiceErrorResponse; + +export type PostEntityModelsCreateEntityModelPropertyData = { + body?: CreateEntityModelPropertyInput; +}; + +export type PostEntityModelsCreateEntityModelPropertyResponse = unknown; + +export type PostEntityModelsCreateEntityModelPropertyError = + RemoteServiceErrorResponse; + +export type PostEntityModelsUpdateEntityModelPropertyData = { + body?: UpdateEntityModelPropertyInput; +}; + +export type PostEntityModelsUpdateEntityModelPropertyResponse = unknown; + +export type PostEntityModelsUpdateEntityModelPropertyError = + RemoteServiceErrorResponse; + +export type PostEntityModelsDeleteEntityModelPropertyData = { + body?: DeleteEntityModelPropertyInput; +}; + +export type PostEntityModelsDeleteEntityModelPropertyResponse = unknown; + +export type PostEntityModelsDeleteEntityModelPropertyError = + RemoteServiceErrorResponse; + +export type PostEntityModelsTreeData = { + body?: GetEntityModelTreeInput; +}; + +export type PostEntityModelsTreeResponse = Array; + +export type PostEntityModelsTreeError = RemoteServiceErrorResponse; + +export type PostEntityModelsGetData = { + body?: GetEntityModelInput; +}; + +export type PostEntityModelsGetResponse = Array; + +export type PostEntityModelsGetError = RemoteServiceErrorResponse; + +export type PostEnumTypesPageData = { + body?: PageEnumTypeInput; +}; + +export type PostEnumTypesPageResponse = PageEnumTypeOutputPagedResultDto; + +export type PostEnumTypesPageError = RemoteServiceErrorResponse; + +export type PostEnumTypesPagePropertyData = { + body?: PageEnumTypePropertyInput; +}; + +export type PostEnumTypesPagePropertyResponse = + PageEnumTypePropertyOutputPagedResultDto; + +export type PostEnumTypesPagePropertyError = RemoteServiceErrorResponse; + +export type PostEnumTypesCreateEnumTypeData = { + body?: CreateEnumTypeInput; +}; + +export type PostEnumTypesCreateEnumTypeResponse = unknown; + +export type PostEnumTypesCreateEnumTypeError = RemoteServiceErrorResponse; + +export type PostEnumTypesUpdateEnumTypeData = { + body?: UpdateEnumTypeInput; +}; + +export type PostEnumTypesUpdateEnumTypeResponse = unknown; + +export type PostEnumTypesUpdateEnumTypeError = RemoteServiceErrorResponse; + +export type PostEnumTypesDeleteEnumTypeData = { + body?: DeleteEnumTypeInput; +}; + +export type PostEnumTypesDeleteEnumTypeResponse = unknown; + +export type PostEnumTypesDeleteEnumTypeError = RemoteServiceErrorResponse; + +export type PostEnumTypesCreateEnumTypePropertyData = { + body?: CreateEnumTypePropertyInput; +}; + +export type PostEnumTypesCreateEnumTypePropertyResponse = unknown; + +export type PostEnumTypesCreateEnumTypePropertyError = + RemoteServiceErrorResponse; + +export type PostEnumTypesUpdateEnumTypePropertyData = { + body?: UpdateEnumTypePropertyInput; +}; + +export type PostEnumTypesUpdateEnumTypePropertyResponse = unknown; + +export type PostEnumTypesUpdateEnumTypePropertyError = + RemoteServiceErrorResponse; + +export type PostEnumTypesDeleteEnumTypePropertyData = { + body?: DeleteEnumTypePropertyInput; +}; + +export type PostEnumTypesDeleteEnumTypePropertyResponse = unknown; + +export type PostEnumTypesDeleteEnumTypePropertyError = + 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 PostFilesPageData = { + body?: PageFileObjectInput; +}; + +export type PostFilesPageResponse = PageFileObjectOutputPagedResultDto; + +export type PostFilesPageError = RemoteServiceErrorResponse; + +export type PostFilesUploadData = { + body?: { + files?: Array; + }; +}; + +export type PostFilesUploadResponse = unknown; + +export type PostFilesUploadError = RemoteServiceErrorResponse; + +export type PostFilesDeleteData = { + body?: DeleteFileObjectInput; +}; + +export type PostFilesDeleteResponse = unknown; + +export type PostFilesDeleteError = RemoteServiceErrorResponse; + +export type PostFilesDownloadData = { + body?: DownloadFileObjectInput; +}; + +export type PostFilesDownloadResponse = RemoteStreamContent; + +export type PostFilesDownloadError = RemoteServiceErrorResponse; + +export type PostGeneratorPreViewCodeData = { + body?: PreViewCodeInput; +}; + +export type PostGeneratorPreViewCodeResponse = Array; + +export type PostGeneratorPreViewCodeError = RemoteServiceErrorResponse; + +export type PostGeneratorDownData = { + body?: DownCodeInput; +}; + +export type PostGeneratorDownResponse = Blob | File; + +export type PostGeneratorDownError = 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 PostMenusUserMenuResponse = Array; + +export type PostMenusUserMenuError = RemoteServiceErrorResponse; + +export type PostMenusPageData = { + body?: PageMenuInput; +}; + +export type PostMenusPageResponse = PageMenuOutputPagedResultDto; + +export type PostMenusPageError = RemoteServiceErrorResponse; + +export type PostMenusCreateData = { + body?: CreateMenuInput; +}; + +export type PostMenusCreateResponse = unknown; + +export type PostMenusCreateError = RemoteServiceErrorResponse; + +export type PostMenusUpdateData = { + body?: UpdateMenuInput; +}; + +export type PostMenusUpdateResponse = unknown; + +export type PostMenusUpdateError = RemoteServiceErrorResponse; + +export type PostMenusDeleteData = { + body?: DeleteMenuInput; +}; + +export type PostMenusDeleteResponse = unknown; + +export type PostMenusDeleteError = RemoteServiceErrorResponse; + +export type PostMenusTreeResponse = Array; + +export type PostMenusTreeError = 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 PostNotificationDeleteData = { + body?: DeleteMessageInput; +}; + +export type PostNotificationDeleteResponse = unknown; + +export type PostNotificationDeleteError = 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 PostProjectsAllResponse = Array; + +export type PostProjectsAllError = RemoteServiceErrorResponse; + +export type PostProjectsPageData = { + body?: PageProjectInput; +}; + +export type PostProjectsPageResponse = ProjectDtoPagedResultDto; + +export type PostProjectsPageError = RemoteServiceErrorResponse; + +export type PostProjectsCreateData = { + body?: CreateProjectInput; +}; + +export type PostProjectsCreateResponse = unknown; + +export type PostProjectsCreateError = RemoteServiceErrorResponse; + +export type PostProjectsUpdateData = { + body?: UpdateProjectInput; +}; + +export type PostProjectsUpdateResponse = unknown; + +export type PostProjectsUpdateError = RemoteServiceErrorResponse; + +export type PostProjectsDeleteData = { + body?: DeleteProjectInput; +}; + +export type PostProjectsDeleteResponse = unknown; + +export type PostProjectsDeleteError = RemoteServiceErrorResponse; + +export type PostProjectsGetProjectAndEntityData = { + body?: GetProjectAndEntityInput; +}; + +export type PostProjectsGetProjectAndEntityResponse = GetProjectAndEntityOutput; + +export type PostProjectsGetProjectAndEntityError = 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 PostTemplatesAllResponse = Array; + +export type PostTemplatesAllError = RemoteServiceErrorResponse; + +export type PostTemplatesPageData = { + body?: PageTemplateInput; +}; + +export type PostTemplatesPageResponse = TemplateDtoPagedResultDto; + +export type PostTemplatesPageError = RemoteServiceErrorResponse; + +export type PostTemplatesCreateData = { + body?: CreateTemplateInput; +}; + +export type PostTemplatesCreateResponse = unknown; + +export type PostTemplatesCreateError = RemoteServiceErrorResponse; + +export type PostTemplatesUpdateData = { + body?: UpdateTemplateInput; +}; + +export type PostTemplatesUpdateResponse = unknown; + +export type PostTemplatesUpdateError = RemoteServiceErrorResponse; + +export type PostTemplatesDeleteData = { + body?: DeleteTemplateInput; +}; + +export type PostTemplatesDeleteResponse = unknown; + +export type PostTemplatesDeleteError = RemoteServiceErrorResponse; + +export type PostTemplatesCreateDetailData = { + body?: CreateTemplateDetailInput; +}; + +export type PostTemplatesCreateDetailResponse = unknown; + +export type PostTemplatesCreateDetailError = RemoteServiceErrorResponse; + +export type PostTemplatesUpdateDetailData = { + body?: UpdateTemplateDetailInput; +}; + +export type PostTemplatesUpdateDetailResponse = unknown; + +export type PostTemplatesUpdateDetailError = RemoteServiceErrorResponse; + +export type PostTemplatesUpdateDetailContentData = { + body?: UpdateTemplateDetailContentInput; +}; + +export type PostTemplatesUpdateDetailContentResponse = unknown; + +export type PostTemplatesUpdateDetailContentError = RemoteServiceErrorResponse; + +export type PostTemplatesDeleteDetailData = { + body?: DeleteTemplateDetailInput; +}; + +export type PostTemplatesDeleteDetailResponse = unknown; + +export type PostTemplatesDeleteDetailError = RemoteServiceErrorResponse; + +export type PostTemplatesTreeData = { + body?: GetTemplteTreeInput; +}; + +export type PostTemplatesTreeResponse = Array; + +export type PostTemplatesTreeError = RemoteServiceErrorResponse; + +export type PostTemplatesListResponse = Array; + +export type PostTemplatesListError = RemoteServiceErrorResponse; + +export type PostTemplatesControlTypeResponse = Array; + +export type PostTemplatesControlTypeError = RemoteServiceErrorResponse; + +export type PostTemplatesTemplateTypeResponse = Array; + +export type PostTemplatesTemplateTypeError = RemoteServiceErrorResponse; + +export type PostTemplatesCopyData = { + body?: CopyTemplateInput; +}; + +export type PostTemplatesCopyResponse = unknown; + +export type PostTemplatesCopyError = 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 PostTextTemplatesPageData = { + body?: PageTextTemplateInput; +}; + +export type PostTextTemplatesPageResponse = + PageTextTemplateOutputPagedResultDto; + +export type PostTextTemplatesPageError = RemoteServiceErrorResponse; + +export type PostTextTemplatesCreateData = { + body?: CreateTextTemplateInput; +}; + +export type PostTextTemplatesCreateResponse = unknown; + +export type PostTextTemplatesCreateError = RemoteServiceErrorResponse; + +export type PostTextTemplatesUpdateData = { + body?: UpdateTextTemplateInput; +}; + +export type PostTextTemplatesUpdateResponse = unknown; + +export type PostTextTemplatesUpdateError = RemoteServiceErrorResponse; + +export type PostTextTemplatesDeleteData = { + body?: DeleteTextTemplateInput; +}; + +export type PostTextTemplatesDeleteResponse = unknown; + +export type PostTextTemplatesDeleteError = RemoteServiceErrorResponse; + +export type PostTextTemplatesExportData = { + body?: PageTextTemplateInput; +}; + +export type PostTextTemplatesExportResponse = Blob | File; + +export type PostTextTemplatesExportError = 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 PostUsersResetPasswordData = { + body?: ResetPasswordInput; +}; + +export type PostUsersResetPasswordResponse = boolean; + +export type PostUsersResetPasswordError = 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; + +export type PostUsersCanUseTwoFactorResponse = boolean; + +export type PostUsersCanUseTwoFactorError = RemoteServiceErrorResponse; + +export type PostUsersGetQrCodeResponse = GetQRCodeOutput; + +export type PostUsersGetQrCodeError = RemoteServiceErrorResponse; + +export type PostUsersEnabledTwoFactorData = { + body?: EnabledTwoFactorInput; +}; + +export type PostUsersEnabledTwoFactorResponse = unknown; + +export type PostUsersEnabledTwoFactorError = RemoteServiceErrorResponse; + +export type PostUsersDisabledTwoFactorData = { + body?: DisabledTwoFactorInput; +}; + +export type PostUsersDisabledTwoFactorResponse = unknown; + +export type PostUsersDisabledTwoFactorError = RemoteServiceErrorResponse; + +export type PostUsersResetTwoFactorData = { + body?: ResetTwoFactorInput; +}; + +export type PostUsersResetTwoFactorResponse = unknown; + +export type PostUsersResetTwoFactorError = RemoteServiceErrorResponse; + +export type PostUsersNeedChangePasswordResponse = NeedChangePasswordOutput; + +export type PostUsersNeedChangePasswordError = RemoteServiceErrorResponse; 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..e8ca4df --- /dev/null +++ b/apps/web-antd/src/api/core/menu.ts @@ -0,0 +1,39 @@ +/** + * 获取用户所有菜单 + */ +export async function getAllMenusApi() { + const dashboardMenus = [ + { + meta: { + order: -1, + title: 'page.dashboard.title', + }, + name: 'Dashboard', + path: '/dashboard', + redirect: '/analytics', + children: [ + { + name: 'Analytics', + path: '/analytics', + component: '/dashboard/analytics/index', + meta: { + affixTab: true, + title: 'page.dashboard.analytics', + authority: ['FileManagement.File1'], + }, + }, + { + name: 'Workspace', + path: '/workspace', + component: '/dashboard/workspace/index', + meta: { + title: 'page.dashboard.workspace', + }, + }, + ], + }, + ]; + debugger; + return dashboardMenus; + // 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..7f9bde9 --- /dev/null +++ b/apps/web-antd/src/bootstrap.ts @@ -0,0 +1,81 @@ +import { createApp, watchEffect } from 'vue'; + +import { registerAccessDirective } from '@vben/access'; +import { registerLoadingDirective } from '@vben/common-ui/es/loading'; +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 '#/hooks/useLoadIcon'; +import 'vue3-json-viewer/dist/index.css'; + +async function bootstrap(namespace: string) { + // 初始化组件适配器 + await initComponentAdapter(); + + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // zIndex: 1020, + // }); + + const app = createApp(App); + + // 注册v-loading指令 + registerLoadingDirective(app, { + loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令 + spinning: 'spinning', + }); + + // 国际化 i18n 配置 + await setupI18n(app); + + // 配置 pinia-tore + await initStores(app, { namespace }); + + // 安装权限指令 + registerAccessDirective(app); + + // 初始化 tippy + const { initTippy } = await import('@vben/common-ui/es/tippy'); + initTippy(app); + + // 配置路由及路由守卫 + app.use(router); + // 配置 json-viewer + app.use(JsonViewer); + + // 配置Motion插件 + const { MotionPlugin } = await import('@vben/plugins/motion'); + app.use(MotionPlugin); + + // 动态更新标题 + 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..1e07b03 --- /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..8f5cc51 --- /dev/null +++ b/apps/web-antd/src/components/Loading/src/useLoading.ts @@ -0,0 +1,62 @@ +import type { Ref } from 'vue'; + +import type { LoadingProps } from './typing'; + +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..139ba45 --- /dev/null +++ b/apps/web-antd/src/components/table-action/table-action.vue @@ -0,0 +1,227 @@ + + + + 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/useLoadIcon.ts b/apps/web-antd/src/hooks/useLoadIcon.ts new file mode 100644 index 0000000..90119d2 --- /dev/null +++ b/apps/web-antd/src/hooks/useLoadIcon.ts @@ -0,0 +1,23 @@ +import { addCollection } from '@vben/icons'; + +import AntDesignIcons from '@iconify/json/json/ant-design.json'; +import CarbonIcons from '@iconify/json/json/carbon.json'; +import EpIcons from '@iconify/json/json/ep.json'; +import IcIcons from '@iconify/json/json/ic.json'; +import LogosIcons from '@iconify/json/json/logos.json'; +import LucideIcons from '@iconify/json/json/lucide.json'; +import MdiIcons from '@iconify/json/json/mdi.json'; +import OuiIcons from '@iconify/json/json/oui.json'; +import PhosphorIcons from '@iconify/json/json/ph.json'; +import UnIcons from '@iconify/json/json/uil.json'; + +addCollection(AntDesignIcons); +addCollection(LucideIcons); +addCollection(CarbonIcons); +addCollection(IcIcons as any); +addCollection(LogosIcons as any); +addCollection(PhosphorIcons as any); +addCollection(UnIcons); +addCollection(OuiIcons); +addCollection(MdiIcons); +addCollection(EpIcons); diff --git a/apps/web-antd/src/hooks/useSignalR.ts b/apps/web-antd/src/hooks/useSignalR.ts new file mode 100644 index 0000000..be1f038 --- /dev/null +++ b/apps/web-antd/src/hooks/useSignalR.ts @@ -0,0 +1,127 @@ +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 { + const userStore = useUserStore(); + if (userStore.checkUserLoginExpire()) { + console.debug('未检测到用户信息,登录之后才会链接SignalR.'); + return; + } + connectionsignalR(); + await connection.start(); + } catch (error) { + console.error(error); + setTimeout(() => startConnect(), 5000); + } + } + + /** + * 关闭SignalR连接 + */ + function closeConnect(): void { + 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..7101ad2 --- /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..ae1237d --- /dev/null +++ b/apps/web-antd/src/layouts/basic.vue @@ -0,0 +1,281 @@ + + + diff --git a/apps/web-antd/src/layouts/change-password.vue b/apps/web-antd/src/layouts/change-password.vue new file mode 100644 index 0000000..db48135 --- /dev/null +++ b/apps/web-antd/src/layouts/change-password.vue @@ -0,0 +1,108 @@ + + + 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..e94cf35 --- /dev/null +++ b/apps/web-antd/src/layouts/my-profile.vue @@ -0,0 +1,403 @@ + + + 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..cab0e93 --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/abp.json @@ -0,0 +1,163 @@ +{ + "login": { + "selectTenant": "Please select Tenant and ignore the non-tenant mode", + "inputCode": "Please enter the two-factor authentication code. If two-factor authentication has not been enabled for your account, please ignore this message.", + "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", + "file": "FileManagement", + "menu": "MenuManagement" + }, + "user": { + "user": "User", + "userName": "UserName", + "name": "Name", + "surname": "Surname", + "email": "Email", + "phone": "Phone", + "password": "Password", + "currentPassword": "CurrentPassword", + "newPassword": "NewPassword", + "confirmNewPassword": "ConfirmNewPassword", + "changePassword": "ChangePassword", + "resetPassword": "ResetPassword", + "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" + }, + "file": { + "file": "File", + "name": "FileName", + "size": "Size", + "contentType": "ContentType" + }, + "dynamicMenu": { + "name": "RouteName", + "title": "Title", + "displayTitle": "DisplayTitle", + "path": "Path", + "component": "Component", + "policy": "Policy", + "menuType": "MenuType", + "enabled": "Enabled", + "hideInMenu": "HideInMenu", + "keepAlive": "keepAlive", + "order": "Order", + "openType": "OpenType", + "parentId": "Parent", + "icon": "Icon", + "url": "Url", + "menu": "Menu", + "folder": "Folder", + "componentType": "Component", + "internalLink": "InternalLink", + "externalLink": "ExternalLink" + } +} 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..85b3a51 --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/common.json @@ -0,0 +1,41 @@ +{ + "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", + "upload": "Upload", + "download": "Download" +} diff --git a/apps/web-antd/src/locales/langs/en-US/demos.json b/apps/web-antd/src/locales/langs/en-US/demos.json new file mode 100644 index 0000000..0715643 --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/demos.json @@ -0,0 +1,12 @@ +{ + "title": "Demos", + "antd": "Ant Design Vue", + "vben": { + "title": "Project", + "about": "About", + "document": "Document", + "antdv": "Ant Design Vue Version", + "naive-ui": "Naive UI Version", + "element-plus": "Element Plus Version" + } +} 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/en-US/textTemplate.json b/apps/web-antd/src/locales/langs/en-US/textTemplate.json new file mode 100644 index 0000000..1fd5d89 --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/textTemplate.json @@ -0,0 +1,8 @@ +{ + "templateManagement": "TemplateManagement", + "templateList": "TemplateList", + "name": "Name", + "code": "Code", + "content": "Content", + "cultureName": "Language" +} 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..ee05d2f --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/abp.json @@ -0,0 +1,163 @@ +{ + "login": { + "selectTenant": "请选择租户,非租户模式请忽略", + "inputCode": "请输入双因素验证码,如果账户没有开启双因素验证请忽略", + "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": "预览", + "file": "文件管理", + "menu": "菜单管理" + }, + "user": { + "user": "用户", + "userName": "用户名", + "name": "名称", + "surname": "姓氏", + "email": "邮箱", + "phone": "手机号", + "password": "密码", + "currentPassword": "当前密码", + "newPassword": "新密码", + "confirmNewPassword": "确认新密码", + "changePassword": "修改密码", + "resetPassword": "重置密码", + "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": "连接字符串" + }, + "file": { + "file": "文件", + "name": "文件名称", + "size": "文件大小", + "contentType": "文件类型" + }, + "dynamicMenu": { + "name": "路由名称", + "title": "标题", + "displayTitle": "标题(多语言)", + "path": "路由地址", + "component": "组件地址", + "policy": "授权策略", + "menuType": "菜单类型", + "enabled": "是否启用", + "hideInMenu": "是否隐藏", + "keepAlive": "是否缓存", + "order": "排序", + "openType": "打开类型", + "parentId": "所属上级", + "icon": "图标", + "url": "内外链地址", + "menu": "菜单", + "folder": "目录", + "componentType": "组件", + "internalLink": "内链", + "externalLink": "外链" + } +} 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..3204c62 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/common.json @@ -0,0 +1,41 @@ +{ + "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": "验证", + "upload": "上传", + "download": "下载" +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/demos.json b/apps/web-antd/src/locales/langs/zh-CN/demos.json new file mode 100644 index 0000000..93ee722 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/demos.json @@ -0,0 +1,12 @@ +{ + "title": "演示", + "antd": "Ant Design Vue", + "vben": { + "title": "项目", + "about": "关于", + "document": "文档", + "antdv": "Ant Design Vue 版本", + "naive-ui": "Naive UI 版本", + "element-plus": "Element Plus 版本" + } +} 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/locales/langs/zh-CN/textTemplate.json b/apps/web-antd/src/locales/langs/zh-CN/textTemplate.json new file mode 100644 index 0000000..75343e8 --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/textTemplate.json @@ -0,0 +1,8 @@ +{ + "templateManagement": "模板管理", + "templateList": "模板列表", + "name": "名称", + "code": "编码", + "content": "内容", + "cultureName": "语言" +} diff --git a/apps/web-antd/src/main.ts b/apps/web-antd/src/main.ts new file mode 100644 index 0000000..d2004e9 --- /dev/null +++ b/apps/web-antd/src/main.ts @@ -0,0 +1,34 @@ +import { initPreferences } from '@vben/preferences'; +import { unmountGlobalLoading } from '@vben/utils'; + +// eslint-disable-next-line unused-imports/no-unused-imports +import client from '#/api-client-config/index'; + +import { overridesPreferences } from './preferences'; + +/** + * 应用初始化完成之后再进行页面加载渲染 + */ +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..58c4e9c --- /dev/null +++ b/apps/web-antd/src/preferences.ts @@ -0,0 +1,28 @@ +import { defineOverridesPreferences } from '@vben/preferences'; + +/** + * @description 项目配置文件 + * 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置 + * !!! 更改配置后请清空缓存,否则可能不生效 + */ +export const overridesPreferences = defineOverridesPreferences({ + // overrides + app: { + name: import.meta.env.VITE_APP_TITLE, + // 是否开启检查更新 + enableCheckUpdates: false, + // 检查更新的时间间隔,单位为分钟 + checkUpdatesInterval: 1, + // accessMode: 'backend', // 默认值frontend|backend 默认值frontend可不填写 + defaultAvatar: '/public/avatar-v1.webp', // 默认头像 + }, + theme: { + mode: 'light', + }, + copyright: { + companyName: 'Abp Vben5 Antd', + }, + logo: { + source: '/logo-v1.webp', // 网站图标 + }, +}); diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts new file mode 100644 index 0000000..2a3a4ad --- /dev/null +++ b/apps/web-antd/src/router/access.ts @@ -0,0 +1,43 @@ +import type { + ComponentRecordType, + GenerateMenuAndRoutesOptions, +} from '@vben/types'; + +import { generateAccessible } from '@vben/access'; +import { preferences } from '@vben/preferences'; + +// import { message } from 'ant-design-vue'; +import { postMenusUserMenu } from '#/api-client/index'; +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, + // }); + const resp = await postMenusUserMenu(); + + return resp.data as any; + }, + // 可以指定没有权限跳转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..0df1316 --- /dev/null +++ b/apps/web-antd/src/router/guard.ts @@ -0,0 +1,138 @@ +import type { Router } from 'vue-router'; + +import { 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 || + preferences.app.defaultHomePath, + ); + } + 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 === preferences.app.defaultHomePath + ? {} + : { 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 === preferences.app.defaultHomePath + ? userStore.userInfo?.homePath || preferences.app.defaultHomePath + : 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..b88b2d7 --- /dev/null +++ b/apps/web-antd/src/router/routes/core.ts @@ -0,0 +1,105 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { LOGIN_PATH } from '@vben/constants'; +import { preferences } from '@vben/preferences'; + +import { $t } from '#/locales'; + +const BasicLayout = () => import('#/layouts/basic.vue'); +const AuthPageLayout = () => import('#/layouts/auth.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: preferences.app.defaultHomePath, + children: [], + }, + { + component: AuthPageLayout, + meta: { + hideInTab: true, + title: 'Authentication', + }, + name: 'Authentication', + path: '/auth', + redirect: LOGIN_PATH, + children: [ + { + name: 'Login', + path: 'login', + component: () => import('#/views/_core/authentication/login.vue'), + 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: 'OidcLogin', + path: 'oidc-login', + component: () => import('#/views/_core/authentication/oidc-login.vue'), + meta: { + title: $t('page.auth.thirdPartyLogin'), + }, + }, + { + 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/code.ts b/apps/web-antd/src/router/routes/modules/code.ts new file mode 100644 index 0000000..0b932d0 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/code.ts @@ -0,0 +1,82 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { BasicLayout } from '#/layouts'; +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'ant-design:format-painter-filled', + order: 3, + title: $t('abp.menu.code'), + authority: ['AbpCodeManagement'], + }, + name: 'code', + path: '/code', + children: [ + { + name: 'project', + path: 'project', + component: () => import('#/views/code/project/index.vue'), + meta: { + icon: 'ant-design:profile-outlined', + title: $t('abp.menu.code-project'), + authority: ['AbpCodeManagement.Project'], + }, + }, + { + name: 'template', + path: 'template', + component: () => import('#/views/code/template/index.vue'), + meta: { + icon: 'ant-design:file-markdown-filled', + title: $t('abp.menu.code-template'), + authority: ['AbpCodeManagement.Template'], + }, + }, + { + name: 'generate', + path: 'generate', + component: () => import('#/views/code/generate/index.vue'), + meta: { + icon: 'ant-design:copyright-circle-filled', + title: $t('abp.menu.code-genarate'), + authority: ['AbpCodeManagement.Generator'], + }, + }, + { + name: 'EntityModel', + path: 'entityModel', + component: () => import('#/views/code/project/entityModel/index.vue'), + meta: { + icon: 'ant-design:file-markdown-filled', + title: $t('abp.menu.code-entity'), + hideInMenu: true, + }, + }, + { + name: 'TemplateDetail', + path: 'templateDetail', + component: () => import('#/views/code/template/TemplateDetail.vue'), + meta: { + icon: 'ant-design:file-markdown-filled', + title: $t('abp.menu.code-template-detail'), + hideInMenu: true, + }, + }, + { + name: 'preview', + path: 'Preview', + component: () => import('#/views/code/generate/preview.vue'), + meta: { + icon: 'ant-design:file-markdown-filled', + title: $t('abp.menu.code-Preview'), + hideInMenu: true, + }, + }, + ], + }, +]; + +export default 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/demos.ts b/apps/web-antd/src/router/routes/modules/demos.ts new file mode 100644 index 0000000..e0011f5 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/demos.ts @@ -0,0 +1,41 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { SvgAntdvLogoIcon } from '@vben/icons'; + +import { BasicLayout } from '#/layouts'; +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'ic:baseline-view-in-ar', + keepAlive: true, + order: 1000, + title: $t('demos.title'), + }, + name: 'Demos', + path: '/demos', + children: [ + { + meta: { + title: $t('demos.antd'), + icon: SvgAntdvLogoIcon, + }, + name: 'AntDesignDemos', + path: '/demos/ant-design', + component: () => import('#/views/demos/antd/index.vue'), + }, + // { + // meta: { + // title: '列表页示例', + // }, + // name: 'ListPageDemos', + // path: '/demos/list-page', + // component: () => import('#/views/demos/listPage/index.vue'), + // }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/modules/file.ts b/apps/web-antd/src/router/routes/modules/file.ts new file mode 100644 index 0000000..308456c --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/file.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:folder-open-outlined', + order: 3, + title: $t('abp.menu.file'), + authority: ['FileManagement'], + }, + name: 'file', + path: '/file', + children: [ + { + name: 'abpFile', + path: 'page', + component: () => import('#/views/system/abpfiles/index.vue'), + meta: { + icon: 'ant-design:file-text-twotone', + title: $t('abp.menu.file'), + authority: ['FileManagement.File'], + }, + }, + ], + }, +]; + +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..d9229d4 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/system.ts @@ -0,0 +1,154 @@ +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: 'AbpLanguage', + path: 'language', + component: () => import('#/views/system/abplanguage/language.vue'), + meta: { + title: $t('abp.menu.language'), + authority: ['AbpIdentity.Languages'], + icon: 'ant-design:read-outlined', + }, + }, + { + name: 'AbpLanguageText', + 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: 'dataDictionary', + 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', + }, + }, + { + path: 'menu', + name: 'AbpMenu', + component: () => import('#/views/system/abpmenu/index.vue'), + meta: { + icon: 'ant-design:bars-outlined', + title: $t('abp.menu.menu'), + authority: ['AbpIdentity.DynamicMenuManagement'], + }, + }, + ], + }, +]; + +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/router/routes/modules/textTemplate.ts b/apps/web-antd/src/router/routes/modules/textTemplate.ts new file mode 100644 index 0000000..bad0b65 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/textTemplate.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:tool-outlined', + // order: 998, + title: $t('textTemplate.templateManagement'), + authority: ['AbpTemplateManagement'], + }, + name: 'TextTemplate', + path: '/TextTemplate', + children: [ + { + path: 'page', + name: 'TextTemplatePage', + component: () => import('#/views/textTemplate/index.vue'), + meta: { + icon: 'ant-design:file-markdown-filled', + title: $t('textTemplate.templateList'), + authority: ['AbpTemplateManagement.Template'], + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/modules/vben.ts b/apps/web-antd/src/router/routes/modules/vben.ts new file mode 100644 index 0000000..453afe5 --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/vben.ts @@ -0,0 +1,94 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { SvgAntdvLogoIcon } from '@vben/icons'; + +import { BasicLayout, IFrameView } from '#/layouts'; +import { $t } from '#/locales'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + badgeType: 'dot', + icon: 'ph:file-doc-light', + order: 9999, + title: $t('demos.vben.title'), + }, + name: 'VbenProject', + path: '/vben-admin', + children: [ + // { + // name: 'VbenAbout', + // path: '/vben-admin/about', + // component: () => import('#/views/_core/about/index.vue'), + // meta: { + // icon: 'lucide:copyright', + // title: $t('demos.vben.about'), + // }, + // }, + { + name: 'VbenDocument', + path: '/vben-admin/document', + component: IFrameView, + meta: { + icon: 'lucide:book-open-text', + link: 'https://doc.cncore.club/', + title: 'ABPPro文档', + }, + }, + { + name: 'VbenDocument', + path: '/vben-admin/document', + component: IFrameView, + meta: { + icon: 'lucide:book-open-text', + link: 'http://doc.china.cncore.club:81/', + title: 'ABPPro国内文档', + }, + }, + { + name: 'VbenDocument', + path: '/vben-admin/document', + component: IFrameView, + meta: { + icon: 'lucide:book-open-text', + link: 'https://abp.io/docs/latest/', + title: 'ABP官方文档', + }, + }, + { + name: 'VbenGithub', + path: '/vben-admin/github', + component: IFrameView, + meta: { + icon: 'mdi:github', + link: 'https://github.com/WangJunZzz/abp-vnext-pro', + title: 'Github', + }, + }, + { + name: 'VbenGithub', + path: '/vben-admin/github', + component: IFrameView, + meta: { + icon: 'ant-design:google-circle-filled', + link: 'https://gitee.com/WangJunZzz/abp-vnext-pro', + title: 'Gitee', + }, + }, + { + name: 'VbenGithub', + path: '/vben-admin/github', + component: IFrameView, + meta: { + icon: SvgAntdvLogoIcon, + // link: 'https://www.antdv.com/components/overview-cn/', + iframeSrc: 'https://doc.cncore.club/', + title: 'Ant Design Vue', + }, + }, + ], + }, +]; + +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..1d8ae1a --- /dev/null +++ b/apps/web-antd/src/store/auth.ts @@ -0,0 +1,158 @@ +import type { Recordable, UserInfo } from '@vben/types'; + +import type { + ApplicationAuthConfigurationDto, + ApplicationConfigurationDto, +} from '#/api-client'; + +import { ref } from 'vue'; +import { useRouter } from 'vue-router'; + +import { LOGIN_PATH } from '@vben/constants'; +import { preferences } from '@vben/preferences'; +import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; + +import { message as Message, notification } from 'ant-design-vue'; +import { defineStore } from 'pinia'; + +import { + getApiAbpApplicationConfiguration, + postApiAppAccountLogin2Fa, + 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 postApiAppAccountLogin2Fa({ + body: { + ...params, + }, + }); + // 如果成功获取到 accessToken + if (data.token) { + accessStore.setAccessToken(data.token); + accessStore.setRefreshToken(data.refreshToken); + userInfo = data as any; + userStore.setUserInfo(userInfo as any); + await getApplicationConfiguration(); + if (accessStore.loginExpired) { + accessStore.setLoginExpired(false); + } else { + onSuccess + ? await onSuccess?.() + : await router.push( + userInfo?.homePath || preferences.app.defaultHomePath, + ); + } + + 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..3747959 --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/login.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-antd/src/views/_core/authentication/oidc-login.vue b/apps/web-antd/src/views/_core/authentication/oidc-login.vue new file mode 100644 index 0000000..2680eb7 --- /dev/null +++ b/apps/web-antd/src/views/_core/authentication/oidc-login.vue @@ -0,0 +1,55 @@ + + + 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/code/generate/index.vue b/apps/web-antd/src/views/code/generate/index.vue new file mode 100644 index 0000000..7b73fa9 --- /dev/null +++ b/apps/web-antd/src/views/code/generate/index.vue @@ -0,0 +1,137 @@ + + + diff --git a/apps/web-antd/src/views/code/generate/preview.vue b/apps/web-antd/src/views/code/generate/preview.vue new file mode 100644 index 0000000..ea05eae --- /dev/null +++ b/apps/web-antd/src/views/code/generate/preview.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/apps/web-antd/src/views/code/project/AddModal.vue b/apps/web-antd/src/views/code/project/AddModal.vue new file mode 100644 index 0000000..e4c6219 --- /dev/null +++ b/apps/web-antd/src/views/code/project/AddModal.vue @@ -0,0 +1,54 @@ + + diff --git a/apps/web-antd/src/views/code/project/EditModal.vue b/apps/web-antd/src/views/code/project/EditModal.vue new file mode 100644 index 0000000..be525fa --- /dev/null +++ b/apps/web-antd/src/views/code/project/EditModal.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-antd/src/views/code/project/entityModel/AddAggregateRootModal.vue b/apps/web-antd/src/views/code/project/entityModel/AddAggregateRootModal.vue new file mode 100644 index 0000000..b07afb5 --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/AddAggregateRootModal.vue @@ -0,0 +1,74 @@ + + diff --git a/apps/web-antd/src/views/code/project/entityModel/AddEditEntityModal.vue b/apps/web-antd/src/views/code/project/entityModel/AddEditEntityModal.vue new file mode 100644 index 0000000..9c1f516 --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/AddEditEntityModal.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/web-antd/src/views/code/project/entityModel/AddEditEntityPropertyModal.vue b/apps/web-antd/src/views/code/project/entityModel/AddEditEntityPropertyModal.vue new file mode 100644 index 0000000..ea74d55 --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/AddEditEntityPropertyModal.vue @@ -0,0 +1,190 @@ + + diff --git a/apps/web-antd/src/views/code/project/entityModel/AddEditEnumModal.vue b/apps/web-antd/src/views/code/project/entityModel/AddEditEnumModal.vue new file mode 100644 index 0000000..54f197a --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/AddEditEnumModal.vue @@ -0,0 +1,96 @@ + + + diff --git a/apps/web-antd/src/views/code/project/entityModel/AddEditEnumPropertyModal.vue b/apps/web-antd/src/views/code/project/entityModel/AddEditEnumPropertyModal.vue new file mode 100644 index 0000000..4d9958c --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/AddEditEnumPropertyModal.vue @@ -0,0 +1,121 @@ + + + diff --git a/apps/web-antd/src/views/code/project/entityModel/index.vue b/apps/web-antd/src/views/code/project/entityModel/index.vue new file mode 100644 index 0000000..eb67379 --- /dev/null +++ b/apps/web-antd/src/views/code/project/entityModel/index.vue @@ -0,0 +1,806 @@ + + + + + diff --git a/apps/web-antd/src/views/code/project/index.vue b/apps/web-antd/src/views/code/project/index.vue new file mode 100644 index 0000000..42095f3 --- /dev/null +++ b/apps/web-antd/src/views/code/project/index.vue @@ -0,0 +1,173 @@ + + + + diff --git a/apps/web-antd/src/views/code/project/schema.ts b/apps/web-antd/src/views/code/project/schema.ts new file mode 100644 index 0000000..a4094a6 --- /dev/null +++ b/apps/web-antd/src/views/code/project/schema.ts @@ -0,0 +1,169 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('code.projectName'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { field: 'companyName', title: $t('code.companyName'), minWidth: '150' }, + { + field: 'projectName', + title: $t('code.projectName'), + minWidth: '150', + }, + + { field: 'nameSpace', title: $t('code.namespace'), minWidth: '150' }, + { + field: 'supportTenant', + title: $t('code.supportTenant'), + minWidth: '150', + slots: { default: 'supportTenant' }, + }, + { field: 'remark', title: $t('code.remark'), 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: '250', + slots: { default: 'action' }, + }, +]); + +export const addFormSchema = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'companyName', + label: $t('code.companyName'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.companyName'), + }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'projectName', + label: $t('code.projectName'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.projectEnglishName'), + }), + }, + // { + // component: 'Input', + // componentProps: {}, + // fieldName: 'nameSpace', + // label: $t('code.namespace'), + // rules: z + // .string() + // .min(1, { message: $t('common.pleaseInput') + $t('code.namespace') }), + // }, + { + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + defaultValue: 0, + fieldName: 'supportTenant', + label: $t('code.supportTenant'), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'remark', + label: $t('code.remark'), + }, +]); + +export const editFormSchema = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'id', + label: 'id', + dependencies: { + show: () => false, + triggerFields: ['id'], + }, + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'companyName', + label: $t('code.companyName'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.companyName'), + }), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'projectName', + label: $t('code.projectName'), + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.projectEnglishName'), + }), + }, + // { + // component: 'Input', + // componentProps: {}, + // fieldName: 'nameSpace', + // label: $t('code.namespace'), + // rules: z + // .string() + // .min(1, { message: $t('common.pleaseInput') + $t('code.namespace') }), + // }, + { + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + defaultValue: 0, + fieldName: 'supportTenant', + label: $t('code.supportTenant'), + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'remark', + label: $t('code.remark'), + }, +]); diff --git a/apps/web-antd/src/views/code/template/AddEditTemplateModal.vue b/apps/web-antd/src/views/code/template/AddEditTemplateModal.vue new file mode 100644 index 0000000..edaf58e --- /dev/null +++ b/apps/web-antd/src/views/code/template/AddEditTemplateModal.vue @@ -0,0 +1,128 @@ + + diff --git a/apps/web-antd/src/views/code/template/AddModal.vue b/apps/web-antd/src/views/code/template/AddModal.vue new file mode 100644 index 0000000..fb4dd07 --- /dev/null +++ b/apps/web-antd/src/views/code/template/AddModal.vue @@ -0,0 +1,52 @@ + + diff --git a/apps/web-antd/src/views/code/template/CopyModal.vue b/apps/web-antd/src/views/code/template/CopyModal.vue new file mode 100644 index 0000000..9ae6f8d --- /dev/null +++ b/apps/web-antd/src/views/code/template/CopyModal.vue @@ -0,0 +1,74 @@ + + diff --git a/apps/web-antd/src/views/code/template/EditModal.vue b/apps/web-antd/src/views/code/template/EditModal.vue new file mode 100644 index 0000000..f508337 --- /dev/null +++ b/apps/web-antd/src/views/code/template/EditModal.vue @@ -0,0 +1,63 @@ + + diff --git a/apps/web-antd/src/views/code/template/TemplateDetail.vue b/apps/web-antd/src/views/code/template/TemplateDetail.vue new file mode 100644 index 0000000..95a028b --- /dev/null +++ b/apps/web-antd/src/views/code/template/TemplateDetail.vue @@ -0,0 +1,432 @@ + + + + + diff --git a/apps/web-antd/src/views/code/template/index.vue b/apps/web-antd/src/views/code/template/index.vue new file mode 100644 index 0000000..9cb2296 --- /dev/null +++ b/apps/web-antd/src/views/code/template/index.vue @@ -0,0 +1,212 @@ + + + + diff --git a/apps/web-antd/src/views/code/template/schema.ts b/apps/web-antd/src/views/code/template/schema.ts new file mode 100644 index 0000000..63e64d3 --- /dev/null +++ b/apps/web-antd/src/views/code/template/schema.ts @@ -0,0 +1,80 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('code.templateName'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { title: $t('code.templateName'), field: 'name', minWidth: '150' }, + { title: $t('code.remark'), field: 'remark', minWidth: '150' }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '300', + slots: { default: 'action' }, + }, +]); + +export const addFormSchema = computed(() => [ + { + fieldName: 'name', + label: $t('code.templateName'), + component: 'Input', + componentProps: {}, + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.templateName'), + }), + }, + { + fieldName: 'remark', + label: $t('code.remark'), + component: 'Input', + componentProps: {}, + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.remark'), + }), + }, +]); + +export const editFormSchema = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'id', + label: 'id', + dependencies: { + show: () => false, + triggerFields: ['id'], + }, + }, + { + fieldName: 'name', + label: $t('code.templateName'), + component: 'Input', + componentProps: {}, + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.templateName'), + }), + }, + { + fieldName: 'remark', + label: $t('code.remark'), + component: 'Input', + componentProps: {}, + rules: z.string().min(1, { + message: $t('common.pleaseInput') + $t('code.remark'), + }), + }, +]); 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/demos/antd/index.vue b/apps/web-antd/src/views/demos/antd/index.vue new file mode 100644 index 0000000..b3b05cc --- /dev/null +++ b/apps/web-antd/src/views/demos/antd/index.vue @@ -0,0 +1,66 @@ + + + diff --git a/apps/web-antd/src/views/demos/listPage/AddEditModal.vue b/apps/web-antd/src/views/demos/listPage/AddEditModal.vue new file mode 100644 index 0000000..21e2f8f --- /dev/null +++ b/apps/web-antd/src/views/demos/listPage/AddEditModal.vue @@ -0,0 +1,106 @@ + + diff --git a/apps/web-antd/src/views/demos/listPage/index.vue b/apps/web-antd/src/views/demos/listPage/index.vue new file mode 100644 index 0000000..097f94a --- /dev/null +++ b/apps/web-antd/src/views/demos/listPage/index.vue @@ -0,0 +1,188 @@ + + + diff --git a/apps/web-antd/src/views/demos/listPage/mock.ts b/apps/web-antd/src/views/demos/listPage/mock.ts new file mode 100644 index 0000000..75f3b2e --- /dev/null +++ b/apps/web-antd/src/views/demos/listPage/mock.ts @@ -0,0 +1,22 @@ +import dayjs from 'dayjs'; + +export const getExampleTableApi = (params: any) => { + const list: any[] = []; + for (let i = 0; i < 20; i++) { + list.push({ + id: i, + category: `category${i}`, + productName: `productName${i}`, + price: 20 + (i + 1) * 2, + releaseDate: dayjs().subtract(i, 'day').format('YYYY-MM-DD'), + color: `color${i}`, + }); + } + + return new Promise((resolve) => { + resolve({ + totalCount: 30, + items: list, + }); + }); +}; 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..053b7a0 --- /dev/null +++ b/apps/web-antd/src/views/system/abpdatadictionary/index.vue @@ -0,0 +1,358 @@ + + + + + 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/abpfiles/AddModal.vue b/apps/web-antd/src/views/system/abpfiles/AddModal.vue new file mode 100644 index 0000000..ec0d58f --- /dev/null +++ b/apps/web-antd/src/views/system/abpfiles/AddModal.vue @@ -0,0 +1,39 @@ + + diff --git a/apps/web-antd/src/views/system/abpfiles/index.vue b/apps/web-antd/src/views/system/abpfiles/index.vue new file mode 100644 index 0000000..4a38edf --- /dev/null +++ b/apps/web-antd/src/views/system/abpfiles/index.vue @@ -0,0 +1,150 @@ + + + + diff --git a/apps/web-antd/src/views/system/abpfiles/schema.ts b/apps/web-antd/src/views/system/abpfiles/schema.ts new file mode 100644 index 0000000..8590eea --- /dev/null +++ b/apps/web-antd/src/views/system/abpfiles/schema.ts @@ -0,0 +1,98 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { useUserStore } from '@vben/stores'; + +import dayjs from 'dayjs'; + +import { postFilesDelete } from '#/api-client/index'; +import { $t } from '#/locales'; + +const userStore = useUserStore(); +export const querySchema = computed(() => [ + { + component: 'RangePicker', + fieldName: 'time', + label: $t('common.createTime'), + componentProps: { + 'value-format': 'YYYY-MM-DD', + }, + defaultValue: [ + // 最近7天 + dayjs().subtract(7, 'day').format('YYYY-MM-DD'), + dayjs().subtract(-1, 'day').format('YYYY-MM-DD'), + ], + }, + { + component: 'Input', + fieldName: 'fileName', + label: $t('abp.file.name'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { + title: $t('abp.file.name'), + minWidth: '150', + field: 'fileName', + }, + { + title: $t('abp.file.size'), + minWidth: '150', + field: 'beautifySize', + }, + { + title: $t('abp.file.contentType'), + minWidth: '150', + field: 'contentType', + }, + { + 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 addFormSchema = computed(() => [ + { + component: 'Upload', + fieldName: 'files', + label: $t('abp.file.file'), + componentProps: () => { + return { + listType: 'picture-card', + autoUpload: true, + multiple: true, + name: 'files', + action: `${import.meta.env.VITE_APP_API_ADDRESS}/Files/Upload?access_token=${ + userStore.userInfo?.token + }`, + onPreview: () => {}, + onRemove: async (file: any) => { + await postFilesDelete({ + body: { + id: file.response[0].id, + }, + }); + }, + }; + }, + renderComponentContent: () => { + return { + default: () => 'Upload', + }; + }, + }, +]); 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..5e1c5f6 --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/AddLanguageTextModal.vue @@ -0,0 +1,74 @@ + + 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..8ed66bf --- /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..a61d0ce --- /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..749f0b6 --- /dev/null +++ b/apps/web-antd/src/views/system/abplanguage/schema.ts @@ -0,0 +1,175 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { $t } from '@vben/locales'; + +export const languageQuerySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('common.keyword'), + }, +]); + +export const languageTableSchema: any = computed( + (): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed( + (): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed(() => [ + { + 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..f0d482a --- /dev/null +++ b/apps/web-antd/src/views/system/abplog/audit.vue @@ -0,0 +1,96 @@ + + + + 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..9e43a48 --- /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..bd23d3f --- /dev/null +++ b/apps/web-antd/src/views/system/abplog/schema.ts @@ -0,0 +1,120 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const logQuerySchema = computed(() => [ + { + 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 = computed((): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed( + (): VxeGridProps['columns'] => [ + { 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/abpmenu/AddModal.vue b/apps/web-antd/src/views/system/abpmenu/AddModal.vue new file mode 100644 index 0000000..f1b1adf --- /dev/null +++ b/apps/web-antd/src/views/system/abpmenu/AddModal.vue @@ -0,0 +1,54 @@ + + diff --git a/apps/web-antd/src/views/system/abpmenu/EditModal.vue b/apps/web-antd/src/views/system/abpmenu/EditModal.vue new file mode 100644 index 0000000..37d6481 --- /dev/null +++ b/apps/web-antd/src/views/system/abpmenu/EditModal.vue @@ -0,0 +1,80 @@ + + diff --git a/apps/web-antd/src/views/system/abpmenu/index.vue b/apps/web-antd/src/views/system/abpmenu/index.vue new file mode 100644 index 0000000..5253322 --- /dev/null +++ b/apps/web-antd/src/views/system/abpmenu/index.vue @@ -0,0 +1,180 @@ + + + + diff --git a/apps/web-antd/src/views/system/abpmenu/schema.ts b/apps/web-antd/src/views/system/abpmenu/schema.ts new file mode 100644 index 0000000..dceadc8 --- /dev/null +++ b/apps/web-antd/src/views/system/abpmenu/schema.ts @@ -0,0 +1,483 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed, h } from 'vue'; + +import dayjs from 'dayjs'; + +import { postMenusTree } from '#/api-client/index'; +import { Icon } from '#/components/icon'; +import { $t } from '#/locales'; + +async function getMenusTree() { + const response = await postMenusTree(); + return response.data; +} +export const querySchema = computed(() => [ + { + component: 'RangePicker', + fieldName: 'time', + label: $t('common.createTime'), + componentProps: { + 'value-format': 'YYYY-MM-DD', + }, + defaultValue: [ + // 最近7天 + dayjs().subtract(7, 'day').format('YYYY-MM-DD'), + dayjs().subtract(-1, 'day').format('YYYY-MM-DD'), + ], + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { + field: 'title', + title: '菜单名称', + treeNode: true, + align: 'left', + slots: { + default: ({ row }) => { + return row.icon + ? h('span', {}, [ + h(Icon, { + icon: row.icon, + }), + h( + 'span', + { + style: { + paddingLeft: '6px', + }, + }, + row.localizationTitle, + ), + ]) + : h('span', {}, row.localizationTitle); + }, + }, + }, + { + field: 'name', + title: $t('abp.dynamicMenu.name'), + }, + + { field: 'path', title: $t('abp.dynamicMenu.path') }, + { field: 'component', title: $t('abp.dynamicMenu.component') }, + { + field: 'policy', + title: $t('abp.dynamicMenu.policy'), + }, + { + field: 'menuType', + title: $t('abp.dynamicMenu.menuType'), + width: '100', + slots: { default: 'menuType' }, + }, + { + field: 'enabled', + title: $t('abp.dynamicMenu.enabled'), + width: '100', + slots: { default: 'enabled' }, + }, + { + field: 'hideInMenu', + title: $t('abp.dynamicMenu.hideInMenu'), + slots: { default: 'hideInMenu' }, + width: '100', + }, + { + field: 'keepAlive', + title: $t('abp.dynamicMenu.keepAlive'), + slots: { default: 'keepAlive' }, + width: '100', + }, + + { + field: 'order', + title: $t('abp.dynamicMenu.order'), + minWidth: '75', + width: '75', + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '200', + slots: { default: 'action' }, + }, +]); + +export const addFormSchema = computed(() => [ + { + fieldName: 'menuType', + label: $t('abp.dynamicMenu.menuType'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { label: $t('abp.dynamicMenu.folder'), value: 10 }, + { label: $t('abp.dynamicMenu.menu'), value: 20 }, + ], + }, + }, + { + fieldName: 'openType', + label: $t('abp.dynamicMenu.openType'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { label: $t('abp.dynamicMenu.componentType'), value: 20 }, + { label: $t('abp.dynamicMenu.internalLink'), value: 30 }, + { label: $t('abp.dynamicMenu.externalLink'), value: 40 }, + ], + }, + dependencies: { + triggerFields: ['menuType'], + disabled: (values) => { + // 打开方式只有菜单==2才需配置 + values.component = values.menuType === 10 ? '' : ''; + values.openType = 20; + return values.menuType !== 20; + }, + }, + }, + { + fieldName: 'parentId', + label: $t('abp.dynamicMenu.parentId'), + component: 'ApiTreeSelect', + componentProps: { + childrenField: 'children', + allowClear: true, + api: getMenusTree, + labelField: 'meta.title', + valueField: 'id', + }, + }, + { + fieldName: 'name', + label: $t('abp.dynamicMenu.name'), + rules: 'required', + help: 'route.name', + component: 'Input', + }, + { + fieldName: 'path', + label: $t('abp.dynamicMenu.path'), + rules: 'required', + component: 'Input', + help: 'route.path', + }, + { + fieldName: 'policy', + label: $t('abp.dynamicMenu.policy'), + help: 'route.policy', + component: 'Input', + dependencies: { + triggerFields: ['menuType'], + disabled: (values) => { + if (values.menuType === 10) { + values.policy = ''; + return true; + } + }, + }, + }, + { + fieldName: 'title', + label: $t('abp.dynamicMenu.title'), + help: 'route.title', + rules: 'required', + component: 'Input', + }, + { + fieldName: 'displayTitle', + label: $t('abp.dynamicMenu.displayTitle'), + help: 'route.displayTitle', + component: 'Input', + }, + + { + fieldName: 'component', + label: $t('abp.dynamicMenu.component'), + help: 'route.component', + component: 'Input', + dependencies: { + triggerFields: ['openType', 'menuType'], + disabled: (values) => { + if ( + values.openType === 30 || + values.openType === 40 || + values.menuType === 10 + ) { + values.component = values.menuType === 10 ? '' : 'IFrameView'; + + return true; + } else { + values.component = ''; + } + }, + }, + }, + { + fieldName: 'icon', + label: $t('abp.dynamicMenu.icon'), + component: 'IconPicker', + }, + + { + fieldName: 'url', + label: $t('abp.dynamicMenu.url'), + component: 'Input', + dependencies: { + triggerFields: ['openType'], + disabled: (values) => { + if (values.openType === 20) { + return true; + } + }, + }, + }, + { + fieldName: 'keepAlive', + label: $t('abp.dynamicMenu.keepAlive'), + defaultValue: false, + help: 'meta.keepAlive', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'hideInMenu', + label: $t('abp.dynamicMenu.hideInMenu'), + help: 'meta.hideInMenu', + defaultValue: false, + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'enabled', + label: $t('abp.dynamicMenu.enabled'), + defaultValue: true, + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'order', + label: $t('abp.dynamicMenu.order'), + defaultValue: 1, + component: 'InputNumber', + }, +]); +export const editFormSchema = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'id', + label: 'id', + dependencies: { + show: () => false, + triggerFields: ['id'], + }, + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'parentId', + label: 'parentId', + dependencies: { + show: () => false, + triggerFields: ['parentId'], + }, + }, + { + fieldName: 'menuType', + label: $t('abp.dynamicMenu.menuType'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { label: $t('abp.dynamicMenu.folder'), value: 10 }, + { label: $t('abp.dynamicMenu.menu'), value: 20 }, + ], + }, + }, + { + fieldName: 'openType', + label: $t('abp.dynamicMenu.openType'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { label: $t('abp.dynamicMenu.componentType'), value: 20 }, + { label: $t('abp.dynamicMenu.internalLink'), value: 30 }, + { label: $t('abp.dynamicMenu.externalLink'), value: 40 }, + ], + }, + }, + { + fieldName: 'parentId', + label: $t('abp.dynamicMenu.parentId'), + component: 'ApiTreeSelect', + componentProps: { + childrenField: 'children', + allowClear: true, + api: getMenusTree, + labelField: 'meta.title', + valueField: 'id', + }, + }, + { + fieldName: 'name', + label: $t('abp.dynamicMenu.name'), + rules: 'required', + help: 'route.name', + component: 'Input', + }, + { + fieldName: 'path', + label: $t('abp.dynamicMenu.path'), + rules: 'required', + component: 'Input', + help: 'route.path', + }, + { + fieldName: 'policy', + label: $t('abp.dynamicMenu.policy'), + help: 'route.policy', + component: 'Input', + dependencies: { + triggerFields: ['menuType'], + disabled: (values) => { + if (values.menuType === 10) { + values.policy = ''; + return true; + } + }, + }, + }, + { + fieldName: 'title', + label: $t('abp.dynamicMenu.title'), + help: 'route.title', + rules: 'required', + component: 'Input', + }, + { + fieldName: 'displayTitle', + label: $t('abp.dynamicMenu.displayTitle'), + help: 'route.displayTitle', + component: 'Input', + }, + + { + fieldName: 'component', + label: $t('abp.dynamicMenu.component'), + help: 'route.component', + component: 'Input', + }, + { + fieldName: 'icon', + label: $t('abp.dynamicMenu.icon'), + component: 'IconPicker', + }, + + { + fieldName: 'url', + label: $t('abp.dynamicMenu.url'), + component: 'Input', + }, + { + fieldName: 'keepAlive', + label: $t('abp.dynamicMenu.keepAlive'), + defaultValue: false, + help: 'meta.keepAlive', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'hideInMenu', + label: $t('abp.dynamicMenu.hideInMenu'), + help: 'meta.hideInMenu', + defaultValue: true, + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'enabled', + label: $t('abp.dynamicMenu.enabled'), + defaultValue: true, + component: 'RadioGroup', + componentProps: { + options: [ + { + label: $t('common.yes'), + value: true, + }, + { + label: $t('common.no'), + value: false, + }, + ], + }, + }, + { + fieldName: 'order', + label: $t('abp.dynamicMenu.order'), + defaultValue: 1, + component: 'InputNumber', + }, +]); 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..55707d5 --- /dev/null +++ b/apps/web-antd/src/views/system/abpnotification/message.vue @@ -0,0 +1,292 @@ + + + + + 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..87ffee5 --- /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..b00a770 --- /dev/null +++ b/apps/web-antd/src/views/system/abpnotification/schema.ts @@ -0,0 +1,288 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + 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 = computed((): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'userName', + label: $t('abp.message.receiver'), + required: true, + }, + { + component: 'Input', + componentProps: {}, + fieldName: 'title', + label: $t('abp.message.title'), + required: true, + }, + { + component: 'Textarea', + componentProps: {}, + fieldName: 'content', + label: $t('abp.message.content'), + required: true, + }, + { + 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 = computed((): VxeGridProps['columns'] => [ + { 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.sender'), + minWidth: '150', + }, + { + field: 'receiveUserName', + title: $t('abp.message.receiver'), + 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 = computed(() => [ + { + 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..a5d78ec --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/OrgTreeEditModal.vue @@ -0,0 +1,72 @@ + + 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..1cfa71c --- /dev/null +++ b/apps/web-antd/src/views/system/abporganizationunit/index.vue @@ -0,0 +1,705 @@ + + + + + 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..f55ffca --- /dev/null +++ b/apps/web-antd/src/views/system/abprole/index.vue @@ -0,0 +1,346 @@ + + + + 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..b788c53 --- /dev/null +++ b/apps/web-antd/src/views/system/abprole/schema.ts @@ -0,0 +1,71 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.role.roleName'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { + field: 'name', + title: $t('abp.role.roleName'), + minWidth: '150', + sortable: true, + }, + { + 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 = computed(() => [ + { + 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..d8ab0fd --- /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..995ac44 --- /dev/null +++ b/apps/web-antd/src/views/system/abptenant/schema.ts @@ -0,0 +1,78 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.tenant.name'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed(() => [ + { + 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..7291bec --- /dev/null +++ b/apps/web-antd/src/views/system/abpuser/index.vue @@ -0,0 +1,428 @@ + + + + + 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..853358b --- /dev/null +++ b/apps/web-antd/src/views/system/abpuser/schema.ts @@ -0,0 +1,170 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { z } from '@vben/common-ui'; + +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + { + component: 'Input', + fieldName: 'filter', + label: $t('abp.user.userName'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { 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 = computed(() => [ + { + 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 = computed(() => [ + { + 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/src/views/textTemplate/AddModal.vue b/apps/web-antd/src/views/textTemplate/AddModal.vue new file mode 100644 index 0000000..b00d24a --- /dev/null +++ b/apps/web-antd/src/views/textTemplate/AddModal.vue @@ -0,0 +1,58 @@ + + diff --git a/apps/web-antd/src/views/textTemplate/EditModal.vue b/apps/web-antd/src/views/textTemplate/EditModal.vue new file mode 100644 index 0000000..5239521 --- /dev/null +++ b/apps/web-antd/src/views/textTemplate/EditModal.vue @@ -0,0 +1,67 @@ + + diff --git a/apps/web-antd/src/views/textTemplate/index.vue b/apps/web-antd/src/views/textTemplate/index.vue new file mode 100644 index 0000000..a4b9cb5 --- /dev/null +++ b/apps/web-antd/src/views/textTemplate/index.vue @@ -0,0 +1,176 @@ + + + + diff --git a/apps/web-antd/src/views/textTemplate/schema.ts b/apps/web-antd/src/views/textTemplate/schema.ts new file mode 100644 index 0000000..c344329 --- /dev/null +++ b/apps/web-antd/src/views/textTemplate/schema.ts @@ -0,0 +1,155 @@ +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { computed } from 'vue'; + +import { $t } from '#/locales'; + +export const querySchema = computed(() => [ + // { + // component: 'RangePicker', + // fieldName: 'time', + // label: $t('common.createTime'), + // componentProps: { + // 'value-format': 'YYYY-MM-DD', + // }, + // defaultValue: [ + // // 最近7天 + // dayjs().subtract(7, 'day').format('YYYY-MM-DD'), + // dayjs().subtract(-1, 'day').format('YYYY-MM-DD'), + // ], + // }, + { + component: 'Input', + fieldName: 'name', + label: $t('textTemplate.name'), + }, + { + component: 'Input', + fieldName: 'code', + label: $t('textTemplate.code'), + }, + { + component: 'Input', + fieldName: 'content', + label: $t('textTemplate.content'), + }, +]); + +export const tableSchema: any = computed((): VxeGridProps['columns'] => [ + { title: $t('common.seq'), type: 'seq', width: 50 }, + { + title: $t('textTemplate.name'), + minWidth: '150', + field: 'name', + }, + { + title: $t('textTemplate.code'), + minWidth: '150', + field: 'code', + }, + { + title: $t('textTemplate.content'), + minWidth: '150', + field: 'content', + }, + { + title: $t('textTemplate.cultureName'), + minWidth: '150', + field: 'cultureName', + }, + { + title: $t('common.action'), + field: 'action', + fixed: 'right', + width: '150', + slots: { default: 'action' }, + }, +]); + +export const addFormSchema = computed(() => [ + { + fieldName: 'name', + label: $t('textTemplate.name'), + rules: 'required', + component: 'Input', + }, + { + fieldName: 'code', + label: $t('textTemplate.code'), + rules: 'required', + component: 'Input', + }, + { + fieldName: 'content', + label: $t('textTemplate.content'), + rules: 'required', + component: 'Textarea', + }, + { + fieldName: 'cultureName', + label: $t('textTemplate.cultureName'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { + label: 'en', + value: 'en', + }, + { + label: '简体中文', + value: 'zh-Hans', + }, + ], + }, + }, +]); + +export const editFormSchema = computed(() => [ + { + component: 'Input', + componentProps: {}, + fieldName: 'id', + label: 'id', + dependencies: { + show: () => false, + triggerFields: ['id'], + }, + }, + { + fieldName: 'name', + label: $t('textTemplate.name'), + rules: 'required', + component: 'Input', + }, + { + fieldName: 'code', + label: $t('textTemplate.code'), + rules: 'required', + component: 'Input', + }, + { + fieldName: 'content', + label: $t('textTemplate.content'), + rules: 'required', + component: 'Textarea', + }, + { + fieldName: 'cultureName', + label: $t('textTemplate.cultureName'), + rules: 'required', + component: 'Select', + componentProps: { + options: [ + { + label: 'en', + value: 'en', + }, + { + label: '简体中文', + value: 'zh-Hans', + }, + ], + }, + }, +]); 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..c17cde2 --- /dev/null +++ b/internal/lint-configs/commitlint-config/package.json @@ -0,0 +1,33 @@ +{ + "name": "@vben/commitlint-config", + "version": "5.5.6", + "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..44cf5b6 --- /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: false }, + ], + '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..136bfa3 --- /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': [ + 'off', + { + 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..a64c55a --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/vue.ts @@ -0,0 +1,153 @@ +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); + + const flatEssential = pluginVue.configs?.['flat/essential'] || []; + const flatStronglyRecommended = + pluginVue.configs?.['flat/strongly-recommended'] || []; + const flatRecommended = pluginVue.configs?.['flat/recommended'] || []; + + return [ + ...flatEssential, + ...flatStronglyRecommended, + ...flatRecommended, + { + 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, + + '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/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..27c3e2f --- /dev/null +++ b/internal/lint-configs/eslint-config/src/custom-config.ts @@ -0,0 +1,168 @@ +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', + }, + }, + { + files: ['**/**.vue'], + ignores: restrictedImportIgnores, + rules: { + '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..08ac823 --- /dev/null +++ b/internal/lint-configs/stylelint-config/index.mjs @@ -0,0 +1,141 @@ +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-deprecated': null, + '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..ee55c70 --- /dev/null +++ b/internal/lint-configs/stylelint-config/package.json @@ -0,0 +1,43 @@ +{ + "name": "@vben/stylelint-config", + "version": "5.5.6", + "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..782c0b3 --- /dev/null +++ b/internal/node-utils/package.json @@ -0,0 +1,43 @@ +{ + "name": "@vben/node-utils", + "version": "5.5.6", + "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..c7044ea --- /dev/null +++ b/internal/tailwind-config/package.json @@ -0,0 +1,66 @@ +{ + "name": "@vben/tailwind-config", + "version": "5.5.6", + "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..dbd3bcc --- /dev/null +++ b/internal/tailwind-config/tsconfig.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/node.json", + "compilerOptions": { + "moduleResolution": "bundler" + }, + "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..dd4f632 --- /dev/null +++ b/internal/tsconfig/package.json @@ -0,0 +1,25 @@ +{ + "name": "@vben/tsconfig", + "version": "5.5.6", + "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..d7ba6a6 --- /dev/null +++ b/internal/vite-config/package.json @@ -0,0 +1,59 @@ +{ + "name": "@vben/vite-config", + "version": "5.5.6", + "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..2b74613 --- /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..f730bdb --- /dev/null +++ b/internal/vite-config/src/typing.ts @@ -0,0 +1,343 @@ +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'; + +/** + * ImportMap 配置接口 + * @description 用于配置模块导入映射,支持自定义导入路径和范围 + * @example + * ```typescript + * { + * imports: { + * 'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js' + * }, + * scopes: { + * 'https://site.com/': { + * 'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js' + * } + * } + * } + * ``` + */ +interface IImportMap { + /** 模块导入映射 */ + imports?: Record; + /** 作用域特定的导入映射 */ + scopes?: { + [scope: string]: Record; + }; +} + +/** + * 打印插件配置选项 + * @description 用于配置控制台打印信息 + */ +interface PrintPluginOptions { + /** + * 打印的数据映射 + * @description 键值对形式的数据,将在控制台打印 + * @example + * ```typescript + * { + * 'App Version': '1.0.0', + * 'Build Time': '2024-01-01' + * } + * ``` + */ + infoMap?: Record; +} + +/** + * Nitro Mock 插件配置选项 + * @description 用于配置 Nitro Mock 服务器的行为 + */ +interface NitroMockPluginOptions { + /** + * Mock 服务器包名 + * @default '@vbenjs/nitro-mock' + */ + mockServerPackage?: string; + + /** + * Mock 服务端口 + * @default 3000 + */ + port?: number; + + /** + * 是否打印 Mock 日志 + * @default false + */ + verbose?: boolean; +} + +/** + * 归档插件配置选项 + * @description 用于配置构建产物的压缩归档 + */ +interface ArchiverPluginOptions { + /** + * 输出文件名 + * @default 'dist' + */ + name?: string; + /** + * 输出目录 + * @default '.' + */ + outputDir?: string; +} + +/** + * ImportMap 插件配置 + * @description 用于配置模块的 CDN 导入 + */ +interface ImportmapPluginOptions { + /** + * CDN 供应商 + * @default 'jspm.io' + * @description 支持 esm.sh 和 jspm.io 两种 CDN 供应商 + */ + defaultProvider?: 'esm.sh' | 'jspm.io'; + /** + * ImportMap 配置数组 + * @description 配置需要从 CDN 导入的包 + * @example + * ```typescript + * [ + * { name: 'vue' }, + * { name: 'pinia', range: '^2.0.0' } + * ] + * ``` + */ + importmap?: Array<{ name: string; range?: string }>; + /** + * 手动配置 ImportMap + * @description 自定义 ImportMap 配置 + */ + inputMap?: IImportMap; +} + +/** + * 条件插件配置 + * @description 用于根据条件动态加载插件 + */ +interface ConditionPlugin { + /** + * 判断条件 + * @description 当条件为 true 时加载插件 + */ + condition?: boolean; + /** + * 插件对象 + * @description 返回插件数组或 Promise + */ + plugins: () => PluginOption[] | PromiseLike; +} + +/** + * 通用插件配置选项 + * @description 所有插件共用的基础配置 + */ +interface CommonPluginOptions { + /** + * 是否开启开发工具 + * @default false + */ + devtools?: boolean; + /** + * 环境变量 + * @description 自定义环境变量 + */ + env?: Record; + /** + * 是否注入元数据 + * @default true + */ + injectMetadata?: boolean; + /** + * 是否为构建模式 + * @default false + */ + isBuild?: boolean; + /** + * 构建模式 + * @default 'development' + */ + mode?: string; + /** + * 是否开启依赖分析 + * @default false + * @description 使用 rollup-plugin-visualizer 分析依赖 + */ + visualizer?: boolean | PluginVisualizerOptions; +} + +/** + * 应用插件配置选项 + * @description 用于配置应用构建时的插件选项 + */ +interface ApplicationPluginOptions extends CommonPluginOptions { + /** + * 是否开启压缩归档 + * @default false + * @description 开启后会在打包目录生成 zip 文件 + */ + archiver?: boolean; + /** + * 压缩归档插件配置 + * @description 配置压缩归档的行为 + */ + archiverPluginOptions?: ArchiverPluginOptions; + /** + * 是否开启压缩 + * @default false + * @description 支持 gzip 和 brotli 压缩 + */ + compress?: boolean; + /** + * 压缩类型 + * @default ['gzip'] + * @description 可选的压缩类型 + */ + compressTypes?: ('brotli' | 'gzip')[]; + /** + * 是否抽离配置文件 + * @default false + * @description 在构建时抽离配置文件 + */ + extraAppConfig?: boolean; + /** + * 是否开启 HTML 插件 + * @default true + */ + html?: boolean; + /** + * 是否开启国际化 + * @default false + */ + i18n?: boolean; + /** + * 是否开启 ImportMap CDN + * @default false + */ + importmap?: boolean; + /** + * ImportMap 插件配置 + */ + importmapOptions?: ImportmapPluginOptions; + /** + * 是否注入应用加载动画 + * @default true + */ + injectAppLoading?: boolean; + /** + * 是否注入全局 SCSS + * @default true + */ + injectGlobalScss?: boolean; + /** + * 是否注入版权信息 + * @default true + */ + license?: boolean; + /** + * 是否开启 Nitro Mock + * @default false + */ + nitroMock?: boolean; + /** + * Nitro Mock 插件配置 + */ + nitroMockOptions?: NitroMockPluginOptions; + /** + * 是否开启控制台打印 + * @default false + */ + print?: boolean; + /** + * 打印插件配置 + */ + printInfoMap?: PrintPluginOptions['infoMap']; + /** + * 是否开启 PWA + * @default false + */ + pwa?: boolean; + /** + * PWA 插件配置 + */ + pwaOptions?: Partial; + /** + * 是否开启 VXE Table 懒加载 + * @default false + */ + vxeTableLazyImport?: boolean; +} + +/** + * 库插件配置选项 + * @description 用于配置库构建时的插件选项 + */ +interface LibraryPluginOptions extends CommonPluginOptions { + /** + * 是否开启 DTS 输出 + * @default true + * @description 生成 TypeScript 类型声明文件 + */ + dts?: boolean | PluginOptions; +} + +/** + * 应用配置选项类型 + */ +type ApplicationOptions = ApplicationPluginOptions; + +/** + * 库配置选项类型 + */ +type LibraryOptions = LibraryPluginOptions; + +/** + * 应用配置定义函数类型 + * @description 用于定义应用构建配置 + */ +type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{ + /** 应用插件配置 */ + application?: ApplicationOptions; + /** Vite 配置 */ + vite?: UserConfig; +}>; + +/** + * 库配置定义函数类型 + * @description 用于定义库构建配置 + */ +type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{ + /** 库插件配置 */ + library?: LibraryOptions; + /** Vite 配置 */ + vite?: UserConfig; +}>; + +/** + * 配置定义类型 + * @description 应用或库的配置定义 + */ +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/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..7280174 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,76 @@ +# EXAMPLE USAGE: +# +# Refer for explanation to following link: +# https://lefthook.dev/configuration/ +# +# pre-push: +# jobs: +# - name: packages audit +# tags: +# - frontend +# - security +# run: yarn audit +# +# - name: gems audit +# tags: +# - backend +# - security +# run: bundle audit +# +# pre-commit: +# parallel: true +# jobs: +# - run: yarn eslint {staged_files} +# glob: "*.{js,ts,jsx,tsx}" +# +# - name: rubocop +# glob: "*.rb" +# exclude: +# - config/application.rb +# - config/routes.rb +# run: bundle exec rubocop --force-exclusion {all_files} +# +# - name: govet +# files: git ls-files -m +# glob: "*.go" +# run: go vet {files} +# +# - script: "hello.js" +# runner: node +# +# - script: "hello.go" +# runner: go run + +pre-commit: + parallel: true + commands: + code-workspace: + run: pnpm vsh code-workspace --auto-commit + lint-md: + run: pnpm prettier --cache --ignore-unknown --write {staged_files} + glob: '*.md' + lint-vue: + run: pnpm prettier --write {staged_files} && pnpm eslint --cache --fix {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files} + glob: '*.vue' + lint-js: + run: pnpm prettier --cache --ignore-unknown --write {staged_files} && pnpm eslint --cache --fix {staged_files} + glob: '*.{js,jsx,ts,tsx}' + lint-style: + run: pnpm prettier --cache --ignore-unknown --write {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files} + glob: '*.{scss,less,styl,html,vue,css}' + lint-package: + run: pnpm prettier --cache --write {staged_files} + glob: 'package.json' + lint-json: + run: pnpm prettier --cache --write --parser json {staged_files} + glob: '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}' + +post-merge: + commands: + install: + run: pnpm install + +commit-msg: + commands: + commitlint: + run: pnpm exec commitlint --edit $1 diff --git a/package.json b/package.json new file mode 100644 index 0000000..1592c44 --- /dev/null +++ b/package.json @@ -0,0 +1,117 @@ +{ + "name": "vben-admin-monorepo", + "version": "5.5.6", + "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", + "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", + "catalog": "pnpx codemod pnpm/catalog" + }, + "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:", + "is-ci": "catalog:", + "lefthook": "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@10.10.0", + "pnpm": { + "peerDependencyRules": { + "allowedVersions": { + "eslint": "*" + } + }, + "overrides": { + "@ast-grep/napi": "catalog:", + "@ctrl/tinycolor": "catalog:", + "clsx": "catalog:", + "esbuild": "0.25.3", + "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..4bdfbe3 --- /dev/null +++ b/packages/@core/base/design/package.json @@ -0,0 +1,41 @@ +{ + "name": "@vben-core/design", + "version": "5.5.6", + "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..3881041 --- /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