Cen_J 1 mesiac pred
rodič
commit
6446dac2d7
100 zmenil súbory, kde vykonal 27661 pridanie a 0 odobranie
  1. 5 0
      .browserslistrc
  2. 19 0
      .dockerignore
  3. 11 0
      .gitattributes
  4. 36 0
      .gitignore
  5. 4 0
      .gitmodules
  6. 21 0
      .npmrc
  7. 9 0
      .prettierignore
  8. 2 0
      .stylelintignore
  9. 13 0
      .vscode/extensions.json
  10. 13 0
      .vscode/launch.json
  11. 112 0
      .vscode/settings.json
  12. 20 0
      .vscode/vue3.3.code-snippets
  13. 81 0
      CHANGELOG.md
  14. 29 0
      Dockerfile
  15. 21 0
      LICENSE
  16. 89 0
      README.md
  17. 34 0
      commitlint.config.mjs
  18. 15 0
      docker-compose.yml
  19. 206 0
      eslint.config.mjs
  20. 14 0
      index.html
  21. 8 0
      lint-staged.config.mjs
  22. 83 0
      mocks/_util.ts
  23. 38 0
      mocks/demo/dict.ts
  24. 1978 0
      mocks/demo/hero/_heroList.json
  25. 7380 0
      mocks/demo/hero/_lolHeroList.json
  26. 37 0
      mocks/demo/hero/index.ts
  27. 23 0
      mocks/demo/select.ts
  28. 25 0
      mocks/index.ts
  29. 28 0
      mocks/list.ts
  30. 24 0
      mocks/user.ts
  31. 22 0
      nx.json
  32. 111 0
      openapi.config.ts
  33. 161 0
      package.json
  34. 10 0
      packages/components/index.ts
  35. 54 0
      packages/components/package.json
  36. 19 0
      packages/components/tsconfig.dts.json
  37. 10 0
      packages/components/tsconfig.json
  38. 108 0
      packages/components/vite.config.ts
  39. 19 0
      packages/vite-plugin-http2-proxy/package.json
  40. 128 0
      packages/vite-plugin-http2-proxy/src/index.ts
  41. 13 0
      packages/vite-plugin-http2-proxy/tsconfig.json
  42. 1 0
      packages/vite-plugin-msw/.gitignore
  43. 99 0
      packages/vite-plugin-msw/README.md
  44. 55 0
      packages/vite-plugin-msw/package.json
  45. 58 0
      packages/vite-plugin-msw/src/browser/enableMocking.ts
  46. 1 0
      packages/vite-plugin-msw/src/browser/index.ts
  47. 37 0
      packages/vite-plugin-msw/src/browser/vitePlugin.ts
  48. 60 0
      packages/vite-plugin-msw/src/buildLocalMswFile.ts
  49. 59 0
      packages/vite-plugin-msw/src/index.ts
  50. 107 0
      packages/vite-plugin-msw/src/node/index.ts
  51. 44 0
      packages/vite-plugin-msw/src/utils/isMatchHandler.ts
  52. 7 0
      packages/vite-plugin-msw/src/utils/log.ts
  53. 28 0
      packages/vite-plugin-msw/tsconfig.json
  54. 47 0
      packages/vite-plugin-msw/tsup.config.ts
  55. 4 0
      packages/vite-plugin-msw/types/module.d.ts
  56. 12 0
      packages/vite-plugin-tinymce-resource/package.json
  57. 69 0
      packages/vite-plugin-tinymce-resource/src/index.ts
  58. 12 0
      packages/vite-plugin-tinymce-resource/tsconfig.json
  59. 11890 0
      pnpm-lock.yaml
  60. 2 0
      pnpm-workspace.yaml
  61. 11 0
      prettier.config.mjs
  62. BIN
      public/favicon.ico
  63. 1 0
      public/iconfont.js
  64. 12 0
      src/App.vue
  65. 70 0
      src/api/backend/api/account.ts
  66. 35 0
      src/api/backend/api/auth.ts
  67. 23 0
      src/api/backend/api/authEmail.ts
  68. 38 0
      src/api/backend/api/authSms.ts
  69. 82 0
      src/api/backend/api/businessTodo.ts
  70. 23 0
      src/api/backend/api/captcha.ts
  71. 73 0
      src/api/backend/api/health.ts
  72. 60 0
      src/api/backend/api/index.ts
  73. 151 0
      src/api/backend/api/netDiskManage.ts
  74. 16 0
      src/api/backend/api/netDiskOverview.ts
  75. 45 0
      src/api/backend/api/systemAccountConfiguration.ts
  76. 135 0
      src/api/backend/api/systemClientUser.ts
  77. 82 0
      src/api/backend/api/systemDept.ts
  78. 111 0
      src/api/backend/api/systemDictItem.ts
  79. 102 0
      src/api/backend/api/systemDictType.ts
  80. 23 0
      src/api/backend/api/systemEmail.ts
  81. 80 0
      src/api/backend/api/systemLog.ts
  82. 90 0
      src/api/backend/api/systemMenu.ts
  83. 28 0
      src/api/backend/api/systemOnline.ts
  84. 94 0
      src/api/backend/api/systemParamConfig.ts
  85. 91 0
      src/api/backend/api/systemRole.ts
  86. 16 0
      src/api/backend/api/systemServe.ts
  87. 22 0
      src/api/backend/api/systemSse.ts
  88. 133 0
      src/api/backend/api/systemTask.ts
  89. 83 0
      src/api/backend/api/systemTopic.ts
  90. 110 0
      src/api/backend/api/systemUser.ts
  91. 47 0
      src/api/backend/api/toolsStorage.ts
  92. 52 0
      src/api/backend/api/toolsUpload.ts
  93. 1833 0
      src/api/backend/api/typings.d.ts
  94. 11 0
      src/api/demo/dict.ts
  95. 33 0
      src/api/demo/hero.ts
  96. 14 0
      src/api/demo/select.ts
  97. 5 0
      src/api/dict.ts
  98. 4 0
      src/api/index.ts
  99. 197 0
      src/api/middleground.ts
  100. 0 0
      src/api/middleground.type.ts

+ 5 - 0
.browserslistrc

@@ -0,0 +1,5 @@
+> 1%
+last 2 versions
+not dead
+not ie 11
+chrome 79

+ 19 - 0
.dockerignore

@@ -0,0 +1,19 @@
+.DS_Store
+node_modules/
+dist/
+.vscode/
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+tests/**/coverage/
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+ 

+ 11 - 0
.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

+ 36 - 0
.gitignore

@@ -0,0 +1,36 @@
+node_modules
+.DS_Store
+dist
+.cache
+.turbo
+.nx
+.nx/cache
+
+tests/server/static
+tests/server/static/upload
+
+.local
+# local env files
+.env.local
+.env.*.local
+.eslintcache
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+*pnpm-debug.log*
+
+# Editor directories and files
+.idea
+# .vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# auto generate file
+types/auto-imports.d.ts
+types/components.d.ts
+ 

+ 4 - 0
.gitmodules

@@ -0,0 +1,4 @@
+[submodule "docs"]
+	path = docs
+	url = https://github.com/buqiyuan/vue3-antdv-admin-docs.git
+	branch = main

+ 21 - 0
.npmrc

@@ -0,0 +1,21 @@
+# 使用淘宝镜像源
+registry = https://registry.npmmirror.com
+# registry = https://registry.npmjs.org
+
+# 根据需要提升含有以下的依赖包到根 node_modules 目录下
+public-hoist-pattern[]=husky
+public-hoist-pattern[]=*eslint*
+public-hoist-pattern[]=@eslint*
+public-hoist-pattern[]=*prettier*
+public-hoist-pattern[]=lint-staged
+public-hoist-pattern[]=*stylelint*
+public-hoist-pattern[]=@commitlint* 
+public-hoist-pattern[]=core-js 
+
+# 提升所有依赖到根 node_modules 目录下,相当于 public-hoist-pattern[]=*,与上面一种方式一般二选一使用
+# 极不推荐用这样的方式解决依赖问题,这样没有充分利用 pnpm 依赖访问安全性的优势,又走回了 npm / yarn 的老路。
+# shamefully-hoist=true
+
+enable-pre-post-scripts=true
+engine-strict=true
+package-manager-strict=false

+ 9 - 0
.prettierignore

@@ -0,0 +1,9 @@
+/dist/*
+.local
+.output.js
+/node_modules/**
+
+**/*.svg
+**/*.sh
+
+/public/*

+ 2 - 0
.stylelintignore

@@ -0,0 +1,2 @@
+/dist/*
+/public/*

+ 13 - 0
.vscode/extensions.json

@@ -0,0 +1,13 @@
+{
+  "recommendations": [
+    "Vue.volar",
+    "dbaeumer.vscode-eslint",
+    "stylelint.vscode-stylelint",
+    "esbenp.prettier-vscode",
+    "mrmlnc.vscode-less",
+    "lokalise.i18n-ally",
+    "antfu.iconify",
+    "antfu.unocss",
+    "mikestead.dotenv"
+  ]
+}

+ 13 - 0
.vscode/launch.json

@@ -0,0 +1,13 @@
+{
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "type": "chrome",
+      "request": "launch",
+      "name": "Launch Chrome",
+      "url": "http://localhost:8080",
+      "webRoot": "${workspaceFolder}/src",
+      "sourceMaps": true
+    }
+  ]
+}

+ 112 - 0
.vscode/settings.json

@@ -0,0 +1,112 @@
+{
+  "typescript.tsdk": "./node_modules/typescript/lib",
+  "typescript.tsserver.maxTsServerMemory": 4096,
+  "npm.packageManager": "pnpm",
+  "editor.tabSize": 2,
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
+  "files.eol": "\n",
+  "editor.guides.bracketPairs": true,
+  "editor.bracketPairColorization.enabled": true,
+  "vue.inlayHints.missingProps": true,
+  "vue.autoInsert.dotValue": true,
+  "vue.server.maxOldSpaceSize": 4096,
+  "explorer.copyRelativePathSeparator": "/",
+  "search.exclude": {
+    "**/node_modules": true,
+    "**/*.log": true,
+    "**/*.log*": true,
+    "**/bower_components": true,
+    "**/dist": true,
+    "**/elehukouben": true,
+    "**/.git": true,
+    "**/.gitignore": true,
+    "**/.svn": true,
+    "**/.DS_Store": true,
+    "**/.idea": true,
+    "**/.vscode": false,
+    "**/yarn.lock": true,
+    "**/tmp": true,
+    "out": true,
+    "dist": true,
+    "node_modules": true,
+    "CHANGELOG.md": true,
+    "examples": true,
+    "res": true,
+    "screenshots": true,
+    "yarn-error.log": true,
+    "**/.yarn": true
+  },
+  "files.exclude": {
+    "**/.cache": true,
+    "**/.editorconfig": true,
+    "**/.eslintcache": true,
+    "**/bower_components": true,
+    "**/.idea": true,
+    "**/tmp": true,
+    "**/.git": true,
+    "**/.svn": true,
+    "**/.hg": true,
+    "**/CVS": true,
+    "**/.DS_Store": 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
+  },
+  "eslint.useFlatConfig": true,
+  "stylelint.enable": true,
+  "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
+  "path-intellisense.mappings": {
+    "@/": "${workspaceRoot}/src"
+  },
+  "[javascriptreact]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescriptreact]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[html]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[css]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[less]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[scss]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[markdown]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "editor.codeActionsOnSave": {
+    "source.fixAll.eslint": "explicit",
+    "source.fixAll.stylelint": "explicit"
+  },
+  "[vue]": {
+    "editor.codeActionsOnSave": {
+      "source.fixAll.eslint": "explicit",
+      "source.fixAll.stylelint": "explicit"
+    },
+    "editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
+  },
+  "i18n-ally.localesPaths": ["src/locales/lang"],
+  "i18n-ally.keystyle": "nested",
+  "i18n-ally.sortKeys": true,
+  "i18n-ally.namespace": true,
+  "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
+  "i18n-ally.enabledParsers": ["json"],
+  "i18n-ally.sourceLanguage": "en",
+  "i18n-ally.displayLanguage": "zh-CN",
+  "i18n-ally.enabledFrameworks": ["vue", "react"]
+}

+ 20 - 0
.vscode/vue3.3.code-snippets

@@ -0,0 +1,20 @@
+{
+  "Vue3.3+defineOptions快速生成模板": {
+    "scope": "vue",
+    "prefix": "Vue3.3+",
+    "body": [
+      "<script setup lang='ts'>",
+      "defineOptions({",
+      "\tname: '${TM_FILENAME_BASE}'",
+      "})",
+      "</script>\n",
+      "<template>",
+      "\t<div>test</div>",
+      "</template>\n",
+      "<style lang='less' scoped>\n",
+      "</style>",
+      "$2"
+    ],
+    "description": "Vue3.3+defineOptions快速生成模板"
+  }
+}

+ 81 - 0
CHANGELOG.md

@@ -0,0 +1,81 @@
+# 1.1.0 (2022-09-02)
+
+### Bug Fixes
+
+- :bug: router navigation bug ([b550a7a](https://github.com/buqiyuan/vite-vue3-admin/commit/b550a7a01b486cfd161ccb8efd7bca9a0ed35627))
+- :bug:生成路由出错问题 ([917e3f0](https://github.com/buqiyuan/vite-vue3-admin/commit/917e3f07209851a3df0b7e220e38df4df7612a68))
+- :bug:修复某些权限码传参错误 ([47071ef](https://github.com/buqiyuan/vite-vue3-admin/commit/47071efa7beb2e210151405e2a1c7e74d6dff4f1))
+- :bug:fix BASE_URL to VITE_BASE_URL ([3d32e82](https://github.com/buqiyuan/vite-vue3-admin/commit/3d32e82b838aea3c8a928989d2aa55c5d125a8ab))
+- 面包屑导航和弹窗拖拽后宽度问题 ([ae96559](https://github.com/buqiyuan/vite-vue3-admin/commit/ae96559fb82a87908a40b425701eaa0ee1993aa7))
+- 删除一些多余的旧代码 ([9eaa568](https://github.com/buqiyuan/vite-vue3-admin/commit/9eaa568a104e7ab1980c0d2069cbedddb4a4934b))
+- add menu type judgment ([144a539](https://github.com/buqiyuan/vite-vue3-admin/commit/144a53942a9229cb5e0286ae3452b644d66621e6))
+- **component:** :bug:修复 dynamicTable ts 类型错误 ([58b9275](https://github.com/buqiyuan/vite-vue3-admin/commit/58b9275758625f583aed644923431df72acb9687))
+- **components:** [dynamic-table] initial fetchData did not carry the default value ([3aaedcf](https://github.com/buqiyuan/vite-vue3-admin/commit/3aaedcf3c0551477e05dec85fb86d4e5af62b193))
+- **components:** [dynamic-table] parameter missing ([1e306d7](https://github.com/buqiyuan/vite-vue3-admin/commit/1e306d77d205cc9fe69fb19d860f5e014e8accc8))
+- **dynamic-table:** add onChangeParams param for dataRequest ([f381c79](https://github.com/buqiyuan/vite-vue3-admin/commit/f381c793529b6711994e001d29d1b8e6dc016631))
+- fix the aformPropsKeys ([#22](https://github.com/buqiyuan/vite-vue3-admin/issues/22)) ([e1c21be](https://github.com/buqiyuan/vite-vue3-admin/commit/e1c21bea3dddee1fefc9465142f390b0252ebcb4))
+- invalid regular expression in safari ([3939f82](https://github.com/buqiyuan/vite-vue3-admin/commit/3939f8229561959cb46982f64c54f4348258a1bd)), closes [#20](https://github.com/buqiyuan/vite-vue3-admin/issues/20)
+- isAsyncFunction ([71aca13](https://github.com/buqiyuan/vite-vue3-admin/commit/71aca13b8055cd38c9f49a4d370c935312fa4d6f))
+- **pages:** about page link issues ([62c840c](https://github.com/buqiyuan/vite-vue3-admin/commit/62c840ccec3aa4b4237a182d750db933797c1c92))
+- **projects:** 修复 tabs-view 下拉菜单溢出 ([a43353d](https://github.com/buqiyuan/vite-vue3-admin/commit/a43353dc89f8395278b6988f7a2dd8c372ff0d7f))
+- remove topLevelAwait usage ([6653da6](https://github.com/buqiyuan/vite-vue3-admin/commit/6653da65f7a6d9738a39c955fb4dcb6d4f553235))
+- router redirect error when logout ([4073cb6](https://github.com/buqiyuan/vite-vue3-admin/commit/4073cb651b3bf45c16ce5f965fb7dddd3fab3bcd))
+- **router:** 第一次进入页面缓存失效问题 ([1b79adc](https://github.com/buqiyuan/vite-vue3-admin/commit/1b79adc072c1c9b6518cc4c05846dfd47c954989))
+- **schema-form:** update props issue ([ff1da5e](https://github.com/buqiyuan/vite-vue3-admin/commit/ff1da5e4f9723392f8af6a5286131f8cbf3c2bf8))
+- some css style issues ([9db10b0](https://github.com/buqiyuan/vite-vue3-admin/commit/9db10b058c8ba212cf51c94c10d2f37705ff7112))
+- some route file path error ([c89b131](https://github.com/buqiyuan/vite-vue3-admin/commit/c89b131d77c0ee8036813a2d377774bb854c652d))
+- some ts type issue ([60ea702](https://github.com/buqiyuan/vite-vue3-admin/commit/60ea702d7fe9cc88f85c07cdb0cd6fe5f3c56669))
+- svg can not loaded ([6aec46a](https://github.com/buqiyuan/vite-vue3-admin/commit/6aec46a00412a2b02e4090faca6722717a739550))
+- **utils:** [is] always false of isPromise ([8479111](https://github.com/buqiyuan/vite-vue3-admin/commit/84791110a87ab48f131c91e73508c2547fff8b25))
+- xlsx.js not default export in new versions [#8](https://github.com/buqiyuan/vite-vue3-admin/issues/8) ([a0b0fc8](https://github.com/buqiyuan/vite-vue3-admin/commit/a0b0fc8c78e1cf75e5ed7e48aee03dc7ce364db4))
+
+### Features
+
+- 表格列设置工具栏 ([a934e12](https://github.com/buqiyuan/vite-vue3-admin/commit/a934e123426fab27fcbfbf47181f3355f584974a))
+- 当前用户角色权限变更时实时更新权限菜单 ([89918a2](https://github.com/buqiyuan/vite-vue3-admin/commit/89918a2195b119f480f498d420bb29016d557846))
+- 服务监控页面 ([0c3d61f](https://github.com/buqiyuan/vite-vue3-admin/commit/0c3d61fbdf4b0ecb1375990c06f5b039bed37085))
+- 全局挂载 Reflect 反射对象 ([f6f4675](https://github.com/buqiyuan/vite-vue3-admin/commit/f6f4675fba8e94b8b8bb67eff79d1205e3b06fff))
+- 新增按钮权限 ([5538d38](https://github.com/buqiyuan/vite-vue3-admin/commit/5538d387925b7bd53f332643903f9e4cacad0908))
+- **components:** [dynamic-table] cell support defaultEditable ([125bb08](https://github.com/buqiyuan/vite-vue3-admin/commit/125bb08ef2563f4dd4f3883da679e739e3f80bad))
+- **components:** [dynamic-table] support cell edit ([4411b0e](https://github.com/buqiyuan/vite-vue3-admin/commit/4411b0e49feeb93b3d1034fc038c9a778d7312af))
+- **components:** [ProjectSetting] add layout mode ([815b0c2](https://github.com/buqiyuan/vite-vue3-admin/commit/815b0c2cdc063a848b88cfe35519b0755b279282))
+- edit-row-table support save loading ([4d0eea6](https://github.com/buqiyuan/vite-vue3-admin/commit/4d0eea6d30d8b09d30cafb6e3bb4b80bb806c675))
+- support for nested routes ([9d9e1d8](https://github.com/buqiyuan/vite-vue3-admin/commit/9d9e1d856f01e0164c88a18583957d20ace95654))
+- **tools:** :art: add project config drawer ([c1f0de0](https://github.com/buqiyuan/vite-vue3-admin/commit/c1f0de05f25bbbadbcbc9f4a105e8d721b008bbb))
+- update basic-form demo ([27f95ec](https://github.com/buqiyuan/vite-vue3-admin/commit/27f95ec4e7c1b57fca5af379165960167aea2e1b))
+- **views:** add about page ([0a34802](https://github.com/buqiyuan/vite-vue3-admin/commit/0a34802b7ef2d2727df4b3b769bd4d664ace2bfa))
+
+### Performance Improvements
+
+- **tableColumns:** customRender is easy ([#10](https://github.com/buqiyuan/vite-vue3-admin/issues/10)) ([e069f3c](https://github.com/buqiyuan/vite-vue3-admin/commit/e069f3c164f92e414638cb2f681013c7dc7727a0))
+- use vite-plugin-style-import replace unplugin-vue-components [#5](https://github.com/buqiyuan/vite-vue3-admin/issues/5) ([10540eb](https://github.com/buqiyuan/vite-vue3-admin/commit/10540eb1de36f4cd6048f86e5b0363109d571760))
+
+## 1.0.2 (2022-03-15)
+
+### Bug Fixes
+
+- :bug: router navigation bug ([b550a7a](https://github.com/buqiyuan/vite-vue3-admin/commit/b550a7a01b486cfd161ccb8efd7bca9a0ed35627))
+- :bug:生成路由出错问题 ([917e3f0](https://github.com/buqiyuan/vite-vue3-admin/commit/917e3f07209851a3df0b7e220e38df4df7612a68))
+- :bug:修复某些权限码传参错误 ([47071ef](https://github.com/buqiyuan/vite-vue3-admin/commit/47071efa7beb2e210151405e2a1c7e74d6dff4f1))
+- :bug:fix BASE_URL to VITE_BASE_URL ([3d32e82](https://github.com/buqiyuan/vite-vue3-admin/commit/3d32e82b838aea3c8a928989d2aa55c5d125a8ab))
+- 面包屑导航和弹窗拖拽后宽度问题 ([ae96559](https://github.com/buqiyuan/vite-vue3-admin/commit/ae96559fb82a87908a40b425701eaa0ee1993aa7))
+- 删除一些多余的旧代码 ([9eaa568](https://github.com/buqiyuan/vite-vue3-admin/commit/9eaa568a104e7ab1980c0d2069cbedddb4a4934b))
+- **component:** :bug:修复 dynamicTable ts 类型错误 ([58b9275](https://github.com/buqiyuan/vite-vue3-admin/commit/58b9275758625f583aed644923431df72acb9687))
+- remove topLevelAwait usage ([6653da6](https://github.com/buqiyuan/vite-vue3-admin/commit/6653da65f7a6d9738a39c955fb4dcb6d4f553235))
+- **router:** 第一次进入页面缓存失效问题 ([1b79adc](https://github.com/buqiyuan/vite-vue3-admin/commit/1b79adc072c1c9b6518cc4c05846dfd47c954989))
+- some route file path error ([c89b131](https://github.com/buqiyuan/vite-vue3-admin/commit/c89b131d77c0ee8036813a2d377774bb854c652d))
+- svg can not loaded ([6aec46a](https://github.com/buqiyuan/vite-vue3-admin/commit/6aec46a00412a2b02e4090faca6722717a739550))
+- xlsx.js not default export in new versions [#8](https://github.com/buqiyuan/vite-vue3-admin/issues/8) ([a0b0fc8](https://github.com/buqiyuan/vite-vue3-admin/commit/a0b0fc8c78e1cf75e5ed7e48aee03dc7ce364db4))
+
+### Features
+
+- 表格列设置工具栏 ([a934e12](https://github.com/buqiyuan/vite-vue3-admin/commit/a934e123426fab27fcbfbf47181f3355f584974a))
+- 服务监控页面 ([0c3d61f](https://github.com/buqiyuan/vite-vue3-admin/commit/0c3d61fbdf4b0ecb1375990c06f5b039bed37085))
+- 全局挂载 Reflect 反射对象 ([f6f4675](https://github.com/buqiyuan/vite-vue3-admin/commit/f6f4675fba8e94b8b8bb67eff79d1205e3b06fff))
+- 新增按钮权限 ([5538d38](https://github.com/buqiyuan/vite-vue3-admin/commit/5538d387925b7bd53f332643903f9e4cacad0908))
+- **views:** add about page ([0a34802](https://github.com/buqiyuan/vite-vue3-admin/commit/0a34802b7ef2d2727df4b3b769bd4d664ace2bfa))
+
+### Performance Improvements
+
+- **tableColumns:** customRender is easy ([#10](https://github.com/buqiyuan/vite-vue3-admin/issues/10)) ([e069f3c](https://github.com/buqiyuan/vite-vue3-admin/commit/e069f3c164f92e414638cb2f681013c7dc7727a0))
+- use vite-plugin-style-import replace unplugin-vue-components [#5](https://github.com/buqiyuan/vite-vue3-admin/issues/5) ([10540eb](https://github.com/buqiyuan/vite-vue3-admin/commit/10540eb1de36f4cd6048f86e5b0363109d571760))

+ 29 - 0
Dockerfile

@@ -0,0 +1,29 @@
+
+# https://stackoverflow.com/questions/53681522/share-variable-in-multi-stage-dockerfile-arg-before-from-not-substituted
+ARG PROJECT_DIR=/vue3-antdv-admin
+
+FROM node:18 as builder
+ARG PROJECT_DIR
+WORKDIR $PROJECT_DIR
+
+# 安装pnpm
+RUN npm install -g pnpm
+
+COPY . ./
+# 安装依赖
+# 若网络不通,可以使用淘宝源
+RUN pnpm config set registry https://registry.npmmirror.com
+RUN pnpm install
+
+# 构建项目
+ENV VITE_BASE_URL=/
+RUN pnpm build
+
+
+FROM nginx:alpine as production
+ARG PROJECT_DIR
+
+COPY --from=builder $PROJECT_DIR/dist/ /usr/share/nginx/html
+# COPY --from=builder $PROJECT_DIR/nginx.conf /etc/nginx/nginx.conf
+
+EXPOSE 80

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 bqy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 89 - 0
README.md

@@ -0,0 +1,89 @@
+# vue3-antdv-admin
+
+基于 vite5.x + vue3.x + antd-design-vue4.x + typescript5.x 的后台管理系统
+
+- 账号:admin,密码:a123456
+- [在线预览](http://buqiyuan.gitee.io/vue3-antdv-admin/)
+- [项目文档](https://buqiyuan.github.io/vue3-antdv-admin-docs/)
+- [swagger 文档](https://nest-api.buqiyuan.site/api-docs/)
+- [后端仓库地址](https://github.com/buqiyuan/nest-admin)
+- [gitee 地址](https://gitee.com/buqiyuan/vue3-antdv-admin)
+- 根据 JSON 生成 typescript 的工具:[http://json2ts.com/](http://json2ts.com/)
+
+## 安装使用
+
+- 获取项目代码
+
+```bash
+git clone https://github.com/buqiyuan/vue3-antdv-admin
+```
+
+- 安装依赖
+
+```bash
+cd vue3-antdv-admin
+
+pnpm install
+
+```
+
+- 运行
+
+```bash
+pnpm dev
+```
+
+- 打包
+
+```bash
+pnpm build
+```
+
+## vscode 配置
+
+安装项目根目录 `.vscode` 推荐的插件,再安装 `Volar`,并禁用 `Vetur`,重启 vscode 即可。
+
+> 使用了 Vue3.x 全家桶、ant-design-vue4.x 和 typescript5.x,实践 vue3.x 的新特性以及玩法,不得不说 vue3.x 的 Composition API 相比于 vue2.x 的 Options API 灵活很多,让我们可以灵活地组合组件逻辑,我们可以很轻松的使用 hooks 的形式去代替以前 mixins 等的写法。更多 hooks 可以参考[vueuse](https://vueuse.org/functions.html)
+
+### todolist
+
+- [x] 动态表格(完善中)
+- [x] 动态表单(完善中)
+- [ ] 电商 SKU 功能演示
+- [ ] 纯前端导出 PDF 动态分页
+- [ ] 其他...
+
+## Git 贡献提交规范
+
+- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
+
+  - `feat` 增加新功能
+  - `fix` 修复问题/BUG
+  - `style` 代码风格相关无影响运行结果的
+  - `perf` 优化/性能提升
+  - `refactor` 重构
+  - `revert` 撤销修改
+  - `test` 测试相关
+  - `docs` 文档/注释
+  - `chore` 依赖更新/脚手架配置修改等
+  - `workflow` 工作流改进
+  - `ci` 持续集成
+  - `types` 类型定义文件更改
+  - `wip` 开发中
+
+## 更新日志
+
+[CHANGELOG](./CHANGELOG.md)
+
+## 赞赏
+
+如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
+
+| 微信 | 支付宝 |
+| :-: | :-: |
+| <img src="https://cdn.jsdelivr.net/gh/buqiyuan/MyImageHosting/imgs/vue3-antdv-admin/weixin.jpg" height="220" /> | <img src="https://cdn.jsdelivr.net/gh/buqiyuan/MyImageHosting/imgs/vue3-antdv-admin/zhifubao.jpg" height="220" /> |
+
+## 感谢 JetBrains 免费的开源授权
+
+<a href="https://www.jetbrains.com/?from=Mybatis-PageHelper" target="_blank">
+<img src="https://user-images.githubusercontent.com/1787798/69898077-4f4e3d00-138f-11ea-81f9-96fb7c49da89.png" height="200"/></a>

+ 34 - 0
commitlint.config.mjs

@@ -0,0 +1,34 @@
+/** @type {import("@commitlint/types").UserConfig} */
+export default {
+  ignores: [(commit) => commit.includes('init')],
+  extends: ['@commitlint/config-conventional'],
+  rules: {
+    'body-leading-blank': [2, 'always'],
+    'footer-leading-blank': [1, 'always'],
+    'header-max-length': [2, 'always', 108],
+    'subject-empty': [2, 'never'],
+    'type-empty': [2, 'never'],
+    'subject-case': [0],
+    'type-enum': [
+      2,
+      'always',
+      [
+        'feat',
+        'fix',
+        'perf',
+        'style',
+        'docs',
+        'test',
+        'refactor',
+        'build',
+        'ci',
+        'chore',
+        'revert',
+        'wip',
+        'workflow',
+        'types',
+        'release',
+      ],
+    ],
+  },
+};

+ 15 - 0
docker-compose.yml

@@ -0,0 +1,15 @@
+version: '3'
+
+services:
+  vue3-antdv-admin:
+    # 从当前路径构建镜像
+    build:
+      context: .
+      dockerfile: Dockerfile
+      target: production
+    image: buqiyuan/vue3-antdv-admin:latest
+    ports:
+      - '80:80'
+    env_file:
+      - .env
+      - .env.production

+ 206 - 0
eslint.config.mjs

@@ -0,0 +1,206 @@
+import js from '@eslint/js';
+import pluginVue from 'eslint-plugin-vue';
+import * as parserVue from 'vue-eslint-parser';
+import configPrettier from 'eslint-config-prettier';
+import pluginPrettier from 'eslint-plugin-prettier';
+import pluginImport from 'eslint-plugin-import';
+import { defineFlatConfig } from 'eslint-define-config';
+import * as parserTypeScript from '@typescript-eslint/parser';
+import pluginTypeScript from '@typescript-eslint/eslint-plugin';
+import unusedImports from 'eslint-plugin-unused-imports';
+
+export default defineFlatConfig([
+  {
+    ...js.configs.recommended,
+    plugins: {
+      prettier: pluginPrettier,
+    },
+    rules: {
+      ...configPrettier.rules,
+      ...pluginPrettier.configs.recommended.rules,
+      'no-debugger': 'off',
+      'no-unused-vars': [
+        'error',
+        {
+          argsIgnorePattern: '^_',
+          varsIgnorePattern: '^_',
+        },
+      ],
+      'prettier/prettier': [
+        'error',
+        {
+          endOfLine: 'auto',
+        },
+      ],
+    },
+  },
+  {
+    files: ['**/*.?([cm])ts', '**/*.?([cm])tsx'],
+    languageOptions: {
+      parser: parserTypeScript,
+      parserOptions: {
+        sourceType: 'module',
+      },
+    },
+    plugins: {
+      '@typescript-eslint': pluginTypeScript,
+    },
+    rules: {
+      ...pluginTypeScript.configs.strict.rules,
+      '@typescript-eslint/ban-types': 'off',
+      '@typescript-eslint/no-unused-vars': 'off',
+      '@typescript-eslint/no-unused-expressions': 'off',
+      '@typescript-eslint/no-invalid-void-type': 'off',
+      '@typescript-eslint/no-redeclare': 'error',
+      '@typescript-eslint/ban-ts-comment': 'off',
+      '@typescript-eslint/prefer-ts-expect-error': 'off',
+      '@typescript-eslint/no-explicit-any': 'off',
+      '@typescript-eslint/prefer-as-const': 'warn',
+      '@typescript-eslint/no-empty-function': 'off',
+      '@typescript-eslint/no-empty-object-type': 'off',
+      '@typescript-eslint/no-non-null-assertion': 'off',
+      '@typescript-eslint/no-import-type-side-effects': 'error',
+      '@typescript-eslint/explicit-module-boundary-types': 'off',
+      '@typescript-eslint/consistent-type-imports': [
+        'error',
+        { disallowTypeAnnotations: false, fixStyle: 'inline-type-imports' },
+      ],
+      '@typescript-eslint/prefer-literal-enum-member': ['error', { allowBitwiseExpressions: true }],
+    },
+  },
+  {
+    files: ['**/*.d.ts'],
+    rules: {
+      'eslint-comments/no-unlimited-disable': 'off',
+      'import/no-duplicates': 'off',
+      'unused-imports/no-unused-vars': 'off',
+    },
+  },
+  {
+    files: ['**/*.?([cm])js'],
+    rules: {
+      '@typescript-eslint/no-require-imports': 'off',
+      '@typescript-eslint/no-var-requires': 'off',
+    },
+  },
+  {
+    files: ['**/*.vue'],
+    languageOptions: {
+      parser: parserVue,
+      parserOptions: {
+        ecmaFeatures: {
+          jsx: true,
+        },
+        extraFileExtensions: ['.vue'],
+        parser: parserTypeScript,
+        sourceType: 'module',
+      },
+    },
+    plugins: {
+      vue: pluginVue,
+    },
+    processor: pluginVue.processors['.vue'],
+    rules: {
+      ...pluginVue.configs.base.rules,
+      ...pluginVue.configs['vue3-essential'].rules,
+      ...pluginVue.configs['vue3-recommended'].rules,
+      'no-undef': 'off',
+      'no-unused-vars': 'off',
+      'vue/no-v-html': 'off',
+      'vue/require-default-prop': 'off',
+      'vue/require-explicit-emits': 'off',
+      'vue/multi-word-component-names': 'off',
+      'vue/no-setup-props-reactivity-loss': 'off',
+      'vue/html-self-closing': [
+        'error',
+        {
+          html: {
+            void: 'always',
+            normal: 'always',
+            component: 'always',
+          },
+          svg: 'always',
+          math: 'always',
+        },
+      ],
+    },
+  },
+  {
+    files: ['**/*.vue', '**/*.?([cm])ts', '**/*.?([cm])tsx'],
+    plugins: {
+      import: pluginImport,
+      'unused-imports': unusedImports,
+    },
+    rules: {
+      'import/first': 'error',
+      'import/no-duplicates': 'error',
+      'import/order': [
+        'error',
+        {
+          groups: [
+            'builtin',
+            'external',
+            'internal',
+            'parent',
+            'sibling',
+            'index',
+            'object',
+            'type',
+          ],
+
+          pathGroups: [
+            {
+              pattern: 'vue',
+              group: 'external',
+              position: 'before',
+            },
+            {
+              pattern: '@vue/**',
+              group: 'external',
+              position: 'before',
+            },
+            {
+              pattern: 'ant-design-vue',
+              group: 'internal',
+            },
+          ],
+          pathGroupsExcludedImportTypes: ['type'],
+        },
+      ],
+
+      'unused-imports/no-unused-imports': 'error',
+      // 如需保存时自动删除未引用代码,可注释掉该规则
+      'unused-imports/no-unused-vars': [
+        'warn',
+        {
+          vars: 'all',
+          varsIgnorePattern: '^_',
+          args: 'after-used',
+          argsIgnorePattern: '^_',
+        },
+      ],
+    },
+  },
+  {
+    linterOptions: {
+      reportUnusedDisableDirectives: 'off',
+    },
+    ignores: [
+      'src/assets/**',
+      '*.sh',
+      'node_modules',
+      '*.md',
+      '*.woff',
+      '*.ttf',
+      '.vscode',
+      '.idea',
+      'dist',
+      '/public',
+      '/docs',
+      '.husky',
+      '.local',
+      '/bin',
+      'Dockerfile',
+    ],
+  },
+]);

+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!doctype html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="referrer" content="origin" />
+    <link rel="icon" href="/favicon.ico" />
+    <meta name="viewport" content="user-scalable=yes" />
+    <title>Vite App</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>

+ 8 - 0
lint-staged.config.mjs

@@ -0,0 +1,8 @@
+/**  @type {import('lint-staged').Config} */
+export default {
+  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
+  '*.json': ['prettier --write'],
+  '*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix --allow-empty-input'],
+  '*.{scss,less,styl,html}': ['stylelint --fix --allow-empty-input', 'prettier --write'],
+  '*.md': ['prettier --write'],
+};

+ 83 - 0
mocks/_util.ts

@@ -0,0 +1,83 @@
+// Interface data format used to return a unified format
+import type { DefaultBodyType, StrictRequest } from 'msw';
+import { ResultEnum } from '@/enums/httpEnum';
+import { uniqueSlash } from '@/utils/urlUtils';
+
+const baseApiUrl = new URL(import.meta.env.VITE_BASE_API_URL, location.origin).toString();
+
+/**
+ * msw 官方不支持配置 baseUrl, 需要自己手动处理
+ * @see https://github.com/mswjs/msw/issues/397#issuecomment-751230924
+ */
+export const serverApi = (path: string) => {
+  return uniqueSlash(baseApiUrl + path);
+};
+
+export function resultSuccess<T = Recordable>(data: T, { message = 'ok' } = {}) {
+  return {
+    code: ResultEnum.SUCCESS,
+    data,
+    message,
+    type: 'success',
+  };
+}
+
+export function resultPageSuccess<T = any>(
+  page: number,
+  pageSize: number,
+  list: T[],
+  { message = 'ok' } = {},
+) {
+  const pageData = pagination(page, pageSize, list);
+
+  return {
+    ...resultSuccess({
+      items: pageData,
+      meta: {
+        currentPage: ~~page,
+        totalItems: list.length,
+        totalPages: Math.ceil(list.length / pageSize),
+      },
+    }),
+    message,
+  };
+}
+
+export function resultError(
+  message = 'Request failed',
+  { code = ResultEnum.ERROR, data = null } = {},
+) {
+  return {
+    code,
+    data,
+    message,
+    type: 'error',
+  };
+}
+
+export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
+  const offset = (pageNo - 1) * Number(pageSize);
+  return offset + Number(pageSize) >= array.length
+    ? array.slice(offset, array.length)
+    : array.slice(offset, offset + Number(pageSize));
+}
+
+export interface requestParams {
+  method: string;
+  body: any;
+  headers?: { authorization?: string };
+  query: any;
+}
+
+/**
+ * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改
+ *
+ */
+export function getRequestToken({ headers }: requestParams): string | undefined {
+  return headers?.authorization;
+}
+
+export const getQuery = (request: StrictRequest<DefaultBodyType>) => {
+  const url = new URL(request.url);
+  return Object.fromEntries<any>(url.searchParams.entries());
+};

+ 38 - 0
mocks/demo/dict.ts

@@ -0,0 +1,38 @@
+import { http, HttpResponse, delay } from 'msw';
+import { getQuery, resultSuccess, serverApi } from '../_util';
+
+const getDictData = (dictType: string) => {
+  console.log('dictType', dictType);
+  if (dictType === 'gender') {
+    return [
+      {
+        label: '男',
+        value: 1,
+      },
+      {
+        label: '女',
+        value: 0,
+      },
+    ];
+  } else if (dictType === 'sell_status') {
+    return [
+      {
+        label: '已售罄',
+        value: 0,
+      },
+      {
+        label: '热卖中',
+        value: 1,
+      },
+    ];
+  }
+  return [];
+};
+
+export default [
+  http.get(serverApi('/dict/data'), async ({ request }) => {
+    await delay(1800);
+    const { type } = getQuery(request);
+    return HttpResponse.json(resultSuccess(getDictData(type)));
+  }),
+];

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1978 - 0
mocks/demo/hero/_heroList.json


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 7380 - 0
mocks/demo/hero/_lolHeroList.json


+ 37 - 0
mocks/demo/hero/index.ts

@@ -0,0 +1,37 @@
+import { HttpResponse, delay, http } from 'msw';
+import { getQuery, resultPageSuccess, resultSuccess, serverApi } from '../../_util';
+import heroListJson from './_heroList.json';
+import heroLoLListJson from './_lolHeroList.json';
+
+export default [
+  http.get(serverApi('/demo/wzry/hero_list'), async ({ request }) => {
+    await delay(500);
+    const { page = 1, pageSize = 10, cname = '', title = '' } = getQuery(request);
+
+    const filterResult = heroListJson.filter((n) => {
+      return n.cname.includes(cname) && n.title.includes(title);
+    });
+
+    return HttpResponse.json(resultPageSuccess(page, pageSize, filterResult));
+  }),
+  http.get(serverApi('/demo/lol/hero_list'), async ({ request }) => {
+    // 接口地址: https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js
+    await delay(500);
+
+    const { page = 1, pageSize = 10, title = '', name = '' } = getQuery(request);
+
+    const filterResult = heroLoLListJson.filter((n) => {
+      return n.title.includes(title) && n.name.includes(name);
+    });
+
+    return HttpResponse.json(resultPageSuccess(page, pageSize, filterResult));
+  }),
+  http.get(serverApi('/demo/lol/hero_info/:id'), async ({ params }) => {
+    await delay(300);
+    const { id } = params;
+
+    const result = heroLoLListJson.find((n) => n.heroId == id);
+
+    return HttpResponse.json(resultSuccess(result));
+  }),
+];

+ 23 - 0
mocks/demo/select.ts

@@ -0,0 +1,23 @@
+import { http, HttpResponse, delay } from 'msw';
+import { getQuery, resultSuccess, serverApi } from '../_util';
+
+const demoList = (keyword, count = 20) => {
+  const result = [] as any[];
+
+  for (let index = 0; index < count; index++) {
+    result.push({
+      name: `${keyword ?? ''}选项${index}`,
+      id: `${index}`,
+    });
+  }
+  return result;
+};
+
+export default [
+  http.get(serverApi('/select/getDemoOptions'), async ({ request }) => {
+    await delay(1000);
+    const { keyword, count } = getQuery(request);
+
+    return HttpResponse.json(resultSuccess(demoList(keyword, count)));
+  }),
+];

+ 25 - 0
mocks/index.ts

@@ -0,0 +1,25 @@
+import { enableMocking } from '@admin-pkg/vite-plugin-msw';
+import { HttpHandler } from 'msw';
+
+const modules = import.meta.glob<any>('./**/*.ts', {
+  eager: true,
+});
+
+export const setupMock = async () => {
+  const handlers = Object.values(modules).reduce<HttpHandler[]>((prev, curr) => {
+    const arr = curr?.default;
+    if (Array.isArray(arr)) {
+      arr.forEach((item) => {
+        if (item instanceof HttpHandler) {
+          prev.push(item);
+        }
+      });
+    }
+    return prev;
+  }, []);
+  // console.log('handlers', handlers);
+  await enableMocking(handlers, {
+    // 设置为 true 则不会在浏览器控制台输出 log 信息
+    quiet: false,
+  });
+};

+ 28 - 0
mocks/list.ts

@@ -0,0 +1,28 @@
+import { http, HttpResponse, delay } from 'msw';
+import { faker } from '@faker-js/faker/locale/zh_CN';
+import { serverApi } from './_util';
+
+export default [
+  http.get(serverApi('/list'), async () => {
+    await delay(1000);
+    return HttpResponse.json(
+      Array.from({ length: 10 }).map(() => ({
+        fullname: faker.person.fullName(),
+        email: faker.internet.email(),
+        avatar: faker.image.avatar(),
+        address: faker.location.streetAddress(),
+      })),
+    );
+  }),
+  http.get(serverApi('/list'), async () => {
+    await delay(1000);
+    return HttpResponse.json(
+      Array.from({ length: 10 }).map(() => ({
+        fullname: faker.person.fullName(),
+        email: faker.internet.email(),
+        avatar: faker.image.avatar(),
+        address: faker.location.streetAddress(),
+      })),
+    );
+  }),
+];

+ 24 - 0
mocks/user.ts

@@ -0,0 +1,24 @@
+import { http, HttpResponse, delay } from 'msw';
+import { faker } from '@faker-js/faker/locale/zh_CN';
+import { serverApi } from './_util';
+
+export default [
+  http.get(serverApi('/user/:id'), async () => {
+    await delay(1000);
+    return HttpResponse.json(
+      Array.from({ length: 10 }).map(() => ({
+        fullname: faker.person.fullName(),
+        email: faker.internet.email(),
+        avatar: faker.image.avatar(),
+        address: faker.location.streetAddress(),
+      })),
+    );
+  }),
+  http.get(serverApi('/login'), async () => {
+    await delay(1000);
+    return HttpResponse.json({
+      code: 200,
+      data: '登录成功',
+    });
+  }),
+];

+ 22 - 0
nx.json

@@ -0,0 +1,22 @@
+{
+  "$schema": "./node_modules/nx/schemas/nx-schema.json",
+  "parallel": 5,
+  "targetDefaults": {
+    "build": {
+      "dependsOn": ["^build"],
+      "inputs": ["default"],
+      "outputs": ["{projectRoot}/dist"],
+      "cache": true
+    },
+    "test": {
+      "dependsOn": ["build"],
+      "inputs": ["default"],
+      "cache": true
+    },
+    "e2e": {
+      "dependsOn": ["build"],
+      "inputs": ["default"],
+      "cache": true
+    }
+  }
+}

+ 111 - 0
openapi.config.ts

@@ -0,0 +1,111 @@
+import { generateService } from '@umijs/openapi';
+import type { RequestOptions } from './src/utils/request';
+
+const re = /controller[-_ .](\w)/gi;
+
+// swagger-typescript-api
+generateService({
+  schemaPath: 'http://127.0.0.1:7501/api-docs-json',
+  serversPath: './src/api/backend',
+  requestOptionsType: 'RequestOptions',
+  // 自定义网络请求函数路径
+  requestImportStatement: `
+  /**
+   * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+   * */
+
+  import { request, type RequestOptions } from "@/utils/request";
+  `,
+  hook: {
+    afterOpenApiDataInited(openAPIData) {
+      const schemas = openAPIData.components?.schemas;
+      if (schemas) {
+        Object.values(schemas).forEach((schema) => {
+          if ('$ref' in schema) {
+            return;
+          }
+          if (schema.properties) {
+            Object.values(schema.properties).forEach((prop) => {
+              if ('$ref' in prop) {
+                return;
+              }
+              // 匡正文件上传的参数类型
+              if (prop.format === 'binary') {
+                prop.type = 'object';
+              }
+            });
+          }
+        });
+      }
+      Object.keys(openAPIData.paths).forEach((path) => {
+        // 屏蔽特定接口生成
+        if (path.startsWith('/api/forward') || path.startsWith('/api/client')) {
+          // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+          delete openAPIData.paths[path];
+        }
+      });
+      return openAPIData;
+    },
+    // @ts-ignore
+    customFunctionName(operationObject, apiPath) {
+      const { operationId } = operationObject;
+
+      if (!operationId) {
+        console.warn('[Warning] no operationId', apiPath);
+        return;
+      }
+
+      const funcName = operationId.replace(re, (_all, letter) => letter.toUpperCase());
+
+      operationObject.operationId = funcName;
+
+      return funcName;
+    },
+    // @ts-ignore
+    customFileNames(operationObject, apiPath) {
+      const { operationId } = operationObject;
+
+      if (!operationId) {
+        console.warn('[Warning] no operationId', apiPath);
+        return;
+      }
+      const controllerName = operationId.split(re)[0];
+      const moduleName = operationObject.tags?.[0].split(' - ')[0];
+
+      // 移除 query 参数的默认值
+      operationObject.parameters?.forEach((param) => {
+        if ('in' in param && param.in === 'query' && param.schema) {
+          if (!('$ref' in param.schema) && param.schema.default) {
+            Reflect.deleteProperty(param.schema, 'default');
+          }
+        }
+      });
+
+      if (moduleName === controllerName) {
+        return [controllerName];
+      } else if (moduleName && moduleName !== controllerName) {
+        return [`${moduleName}_${controllerName}`];
+      }
+      return;
+    },
+    customType(schemaObject, namespace, defaultGetType) {
+      const type = defaultGetType(schemaObject, namespace);
+      // 提取出 data 的类型
+      const regex = /API\.ResOp & { 'data'\?: (.+); }/;
+      return type.replace(regex, '$1');
+    },
+    customOptionsDefaultValue(data): RequestOptions {
+      const { summary } = data;
+
+      if (summary?.startsWith('创建') || summary?.startsWith('新增')) {
+        return { successMsg: '创建成功' };
+      } else if (summary?.startsWith('更新')) {
+        return { successMsg: '更新成功' };
+      } else if (summary?.startsWith('删除')) {
+        return { successMsg: '删除成功' };
+      }
+
+      return {};
+    },
+  },
+});

+ 161 - 0
package.json

@@ -0,0 +1,161 @@
+{
+  "name": "vue3-antdv-admin",
+  "version": "2.0.0",
+  "packageManager": "pnpm@9.4.0",
+  "type": "module",
+  "engines": {
+    "node": ">=18",
+    "pnpm": ">=8.0.2"
+  },
+  "author": {
+    "name": "buqiyuan",
+    "email": "1743369777@qq.com",
+    "url": "https://github.com/buqiyuan"
+  },
+  "scripts": {
+    "preinstall": "npx only-allow pnpm",
+    "postinstall": "pnpm nx:build",
+    "bootstrap": "pnpm install",
+    "serve": "npm run dev",
+    "dev": "vite dev",
+    "build:test": "rimraf dist && cross-env NODE_ENV=test vite build",
+    "build": "rimraf dist && cross-env NODE_ENV=production vite build",
+    "build:watch": "rimraf dist && cross-env NODE_ENV=production vite build --watch",
+    "build:pkg": "pnpm -r --paralle --filter=\"./packages/*\" run build",
+    "nx:build": "nx run-many -t build --exclude @admin-pkg/components",
+    "nx:build:watch": "nx watch --all -- nx run \\$NX_PROJECT_NAME:build",
+    "preview": "npm run build --watch && vite preview",
+    "preview:dist": "vite preview",
+    "openapi": "npx tsx openapi.config.ts",
+    "clean:cache": "npx rimraf node_modules/.cache/ && npx rimraf node_modules/.vite",
+    "clean:lib": "npx rimraf node_modules packages/*/node_modules",
+    "lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint",
+    "lint:eslint": "eslint --cache --max-warnings 0  \"{src,mocks}/**/*.{vue,ts,tsx}\" --fix",
+    "lint:prettier": "prettier --write  \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
+    "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
+    "lint:lint-staged": "lint-staged",
+    "prepare": "husky",
+    "release": "git push && git push origin --tags",
+    "gen:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
+    "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && pnpm clean:lib && npm run bootstrap",
+    "test:gzip": "npx http-server dist --cors --gzip -c-1",
+    "test:br": "npx http-server dist --cors --brotli -c-1"
+  },
+  "dependencies": {
+    "@ant-design/icons-vue": "~7.0.1",
+    "@iconify/vue": "^4.2.0",
+    "@tinymce/tinymce-vue": "^6.1.0",
+    "@vueup/vue-quill": "^1.2.0",
+    "@vueuse/core": "~12.2.0",
+    "ali-oss": "^6.22.0",
+    "ant-design-vue": "~4.2.6",
+    "axios": "~1.7.9",
+    "crypto-js": "^4.2.0",
+    "dayjs": "~1.11.13",
+    "echarts": "^5.5.1",
+    "file-saver": "~2.0.5",
+    "lodash-es": "~4.17.21",
+    "mitt": "~3.0.1",
+    "nprogress": "~1.0.0-1",
+    "pinia": "~2.2.4",
+    "pinia-plugin-persistedstate": "^4.1.1",
+    "qiniu-js": "^3.4.2",
+    "qs": "~6.13.0",
+    "quill": "^2.0.3",
+    "sortablejs": "~1.15.6",
+    "tinymce": "^7.6.0",
+    "uuid": "^8.3.2",
+    "vue": "~3.5.13",
+    "vue-echarts": "^7.0.3",
+    "vue-i18n": "~10.0.4",
+    "vue-router": "~4.4.5",
+    "vue-types": "~5.1.3",
+    "vue-virtual-scroller": "2.0.0-beta.8",
+    "xlsx": "~0.18.5"
+  },
+  "devDependencies": {
+    "@admin-pkg/components": "workspace:*",
+    "@admin-pkg/vite-plugin-http2-proxy": "workspace:*",
+    "@admin-pkg/vite-plugin-msw": "workspace:*",
+    "@admin-pkg/vite-plugin-tinymce-resource": "workspace:*",
+    "@commitlint/cli": "~19.5.0",
+    "@commitlint/config-conventional": "~19.5.0",
+    "@faker-js/faker": "^9.0.3",
+    "@iconify-json/ant-design": "^1.2.5",
+    "@iconify-json/ep": "^1.2.2",
+    "@iconify/json": "^2.2.288",
+    "@types/crypto-js": "^4.2.2",
+    "@types/lodash-es": "~4.17.12",
+    "@types/node": "~22.7.4",
+    "@types/qs": "^6.9.16",
+    "@types/sortablejs": "^1.15.8",
+    "@typescript-eslint/eslint-plugin": "~8.18.2",
+    "@typescript-eslint/parser": "~8.18.2",
+    "@umijs/openapi": "^1.13.0",
+    "@vitejs/plugin-vue": "~5.2.1",
+    "@vitejs/plugin-vue-jsx": "~4.1.1",
+    "@vue/tsconfig": "^0.7.0",
+    "commitizen": "~4.3.1",
+    "conventional-changelog-cli": "~4.1.0",
+    "core-js": "^3.39.0",
+    "cross-env": "~7.0.3",
+    "eslint": "~9.17.0",
+    "eslint-config-prettier": "~9.1.0",
+    "eslint-define-config": "~2.1.0",
+    "eslint-plugin-import": "~2.31.0",
+    "eslint-plugin-prettier": "~5.2.1",
+    "eslint-plugin-unused-imports": "^4.1.4",
+    "eslint-plugin-vue": "~9.32.0",
+    "husky": "~9.1.7",
+    "less": "~4.2.1",
+    "lint-staged": "~15.2.11",
+    "msw": "^2.4.9",
+    "nx": "^20.3.0",
+    "postcss": "~8.4.49",
+    "postcss-html": "~1.7.0",
+    "postcss-less": "~6.0.0",
+    "prettier": "~3.4.2",
+    "rimraf": "~5.0.9",
+    "stylelint": "~16.12.0",
+    "stylelint-config-property-sort-order-smacss": "^10.0.0",
+    "stylelint-config-recommended": "~14.0.1",
+    "stylelint-config-recommended-vue": "~1.5.0",
+    "stylelint-config-standard": "~36.0.1",
+    "stylelint-order": "~6.0.4",
+    "stylelint-prettier": "^5.0.2",
+    "typescript": "~5.7.2",
+    "unocss": "^0.65.3",
+    "unplugin-vue-components": "~0.28.0",
+    "vite": "~6.0.6",
+    "vite-plugin-checker": "~0.8.0",
+    "vite-plugin-inspect": "^0.10.6",
+    "vite-plugin-mkcert": "^1.17.6",
+    "vite-plugin-svg-icons": "~2.0.1",
+    "vite-plugin-vue-inspector": "^5.3.1",
+    "vue-eslint-parser": "~9.4.3",
+    "vue-tsc": "~2.2.0"
+  },
+  "__npminstall_done": false,
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/buqiyuan/vue3-antdv-admin"
+  },
+  "homepage": "https://buqiyuan.gitee.io/vue3-antdv-admin",
+  "keywords": [
+    "vue",
+    "ant-design-vue",
+    "vue3",
+    "ts",
+    "tsx",
+    "admin",
+    "typescript"
+  ],
+  "license": "MIT",
+  "target": "web",
+  "pnpm": {
+    "overrides": {},
+    "peerDependencyRules": {
+      "allowedVersions": {}
+    }
+  }
+}

+ 10 - 0
packages/components/index.ts

@@ -0,0 +1,10 @@
+import 'uno.css';
+
+/**
+ * 此包供 playground 在线测试使用,不建议在生产环境中使用
+ */
+
+export * from '@/components/core/dynamic-table/';
+export * from '@/components/core/schema-form/';
+
+console.log('[@admin-pkg/components] load');

+ 54 - 0
packages/components/package.json

@@ -0,0 +1,54 @@
+{
+  "name": "@admin-pkg/components",
+  "version": "0.0.5",
+  "description": "",
+  "type": "module",
+  "module": "./dist/index.es.js",
+  "main": "../dist/index.es.js",
+  "types": "dist/types/index.es.d.ts",
+  "jsdelivr": "./dist/index.es.js",
+  "unpkg": "./dist/index.es.js",
+  "files": [
+    "dist"
+  ],
+  "exports": {
+    ".": {
+      "types": "./dist/types/index.es.d.ts",
+      "import": "./dist/index.es.js",
+      "require": "./dist/index.umd.js"
+    },
+    "./*": "./*"
+  },
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build && npm run build:dts",
+    "build:dts": "tsc -p tsconfig.dts.json || true"
+  },
+  "keywords": [
+    "ant-design-vue",
+    "procomponents",
+    "vue"
+  ],
+  "author": {
+    "name": "buqiyuan",
+    "email": "1743369777@qq.com",
+    "url": "https://github.com/buqiyuan"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/buqiyuan/vue3-antdv-admin/tree/main/packages/components",
+    "directory": "packages/components"
+  },
+  "homepage": "https://github.com/buqiyuan/vue3-antdv-admin/tree/main/packages/components#readme",
+  "license": "MIT",
+  "publishConfig": {
+    "access": "public",
+    "registry": "https://registry.npmjs.org/"
+  },
+  "devDependencies": {
+    "typescript": "~5.5.4"
+  },
+  "peerDependencies": {
+    "vue": "^3.4.0"
+  }
+}

+ 19 - 0
packages/components/tsconfig.dts.json

@@ -0,0 +1,19 @@
+{
+  "extends": "@vue/tsconfig/tsconfig.dom.json",
+  "compilerOptions": {
+    "allowJs": true,
+    "checkJs": false,
+    // Generate d.ts files
+    "declaration": true,
+    // only output d.ts files
+    "emitDeclarationOnly": true,
+    "declarationDir": "dist/types",
+    "strict": false,
+    "noEmit": false,
+    "target": "ESNext",
+    "module": "ESNext",
+    "moduleResolution": "Bundler",
+    "lib": ["ESNext", "DOM"]
+  },
+  "include": ["./dist/index.es.js"]
+}

+ 10 - 0
packages/components/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "paths": {
+      "@/*": ["../../src/*"]
+    }
+  },
+  "include": ["index.ts", "../../src/**/*.ts"],
+  "exclude": ["node_modules", "test", "dist", "**/src/views/**"]
+}

+ 108 - 0
packages/components/vite.config.ts

@@ -0,0 +1,108 @@
+import { resolve } from 'node:path';
+import { defineConfig, type PluginOption } from 'vite';
+import vue from '@vitejs/plugin-vue';
+import vueJsx from '@vitejs/plugin-vue-jsx';
+import Components from 'unplugin-vue-components/vite';
+import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
+import Unocss from 'unocss/vite';
+
+const sourceDir = resolve(__dirname, '../../src');
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  publicDir: false,
+  resolve: {
+    alias: [
+      {
+        find: '@',
+        replacement: sourceDir,
+      },
+    ],
+  },
+  esbuild: {
+    drop: ['debugger'],
+    pure: ['console.log'],
+  },
+  // 打包配置
+  build: {
+    target: 'esnext',
+    lib: {
+      entry: resolve(__dirname, './index.ts'), // 设置入口文件
+      formats: ['es'],
+      name: 'components', // 起个名字,安装、引入用
+      fileName: (format) => `index.${format}.js`, // 打包后的文件名
+    },
+    rollupOptions: {
+      treeshake: true,
+      // make sure to externalize deps that shouldn't be bundled
+      // into your library
+      external: ['vue', 'ant-design-vue'],
+      output: {
+        // minifyInternalExports: false,
+        //   // Provide global variables to use in the UMD build
+        //   // for externalized deps
+        //   globals: {
+        //     vue: 'Vue',
+        //     'ant-design-vue': 'AntDesignVue',
+        //   },
+        // manualChunks: {
+        //   library: ['lodash-es', 'vue-i18n'],
+        // },
+        manualChunks(id) {
+          if (id.includes('/src/locales/helper.ts')) {
+            console.log('id: ', id);
+            return 'vendor';
+          } else if (id.includes('ant-design-vue')) {
+            return 'vendor';
+          }
+        },
+      },
+    },
+  },
+  plugins: [
+    vue(),
+    vueJsx(),
+    Unocss(),
+    myPlugin(),
+    Components({
+      dts: false,
+      dirs: ['../../src/components'],
+      resolvers: [
+        AntDesignVueResolver({
+          importStyle: false, // css in js
+          exclude: ['Button'],
+        }),
+        (componentName) => {
+          // where `componentName` is always CapitalCase
+          if (componentName === 'AButton') {
+            return { name: componentName, from: resolve(sourceDir, 'components/basic/button/') };
+          }
+        },
+      ],
+    }),
+  ],
+});
+
+function myPlugin(): PluginOption {
+  const file = resolve(sourceDir, './permission');
+
+  return {
+    name: '@admin-pkg/components:transform-file',
+
+    // transform(src, id) {
+    //   if (id.includes(file)) {
+    //     console.log('transform id: ', id);
+    //     return {
+    //       code: `export const hasPermission = () => true`,
+    //       map: null,
+    //     };
+    //   }
+    // },
+    load(id) {
+      if (id.includes(file)) {
+        console.log('load id: ', id);
+        return `export const hasPermission = () => true`;
+      }
+    },
+  };
+}

+ 19 - 0
packages/vite-plugin-http2-proxy/package.json

@@ -0,0 +1,19 @@
+{
+  "name": "@admin-pkg/vite-plugin-http2-proxy",
+  "version": "0.0.2",
+  "type": "module",
+  "description": "",
+  "main": "./dist/index.js",
+  "types": "./dist/index.d.ts",
+  "exports": "./dist/index.js",
+  "scripts": {
+    "build": "tsc"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "MIT",
+  "dependencies": {
+    "http2-proxy": "^5.0.53"
+  },
+  "peerDependencies": {}
+}

+ 128 - 0
packages/vite-plugin-http2-proxy/src/index.ts

@@ -0,0 +1,128 @@
+import http2Proxy from 'http2-proxy';
+import type { Plugin, PluginOption, ProxyOptions } from 'vite';
+
+const error = (message: string): never => {
+  throw new Error(message);
+};
+
+export default (options?: Record<string, ProxyOptions>): PluginOption => {
+  let routes: Record<string, ProxyOptions>;
+
+  const configure: Plugin['configureServer'] = ({ middlewares, httpServer }) => {
+    const proxyOptions = options || routes;
+    for (const [regexp, serverOptions] of Object.entries(proxyOptions)) {
+      const { target, rewrite, headers, ws, secure = true, timeout = 30_000 } = serverOptions;
+      if (!target) {
+        continue;
+      }
+
+      const re = new RegExp(regexp);
+      const urlObj = new URL(target.toString());
+
+      if (!urlObj.pathname.endsWith('/')) {
+        urlObj.pathname += '/';
+      }
+
+      const protocol = /^(http|ws)s?:$/.test(urlObj.protocol)
+        ? (urlObj.protocol as 'https' | 'http')
+        : error(`Invalid protocol: ${urlObj.href}`);
+
+      const port =
+        urlObj.port === ''
+          ? { https: 443, http: 80 }[protocol]
+          : /^\d+$/.test(urlObj.port)
+            ? Number(urlObj.port)
+            : error(`Invalid port: ${urlObj.href}`);
+
+      // TODO unfinished
+      if (ws && httpServer) {
+        httpServer?.on('upgrade', (req, socket, head) => {
+          if (req.url && re.test(req.url)) {
+            const url = (rewrite?.(req.url) ?? req.url).replace(/^\/+/, '');
+            const { pathname, search } = new URL(url, urlObj);
+
+            http2Proxy.ws(
+              req,
+              socket,
+              head,
+              {
+                port: 443,
+                path: pathname + search,
+                proxyTimeout: timeout,
+                hostname: urlObj.hostname,
+                ['rejectUnauthorized' as never]: secure,
+                ...serverOptions,
+              },
+              (err) => {
+                if (err) {
+                  console.error('proxy error', err);
+                  socket.destroy();
+                }
+              },
+            );
+          }
+        });
+      } else {
+        middlewares.use((req, res, next) => {
+          if (req.url && re.test(req.url)) {
+            const url = (rewrite?.(req.url) ?? req.url).replace(/^\/+/, '');
+            const { pathname, search } = new URL(url, urlObj);
+
+            http2Proxy.web(
+              req,
+              res,
+              {
+                protocol,
+                port,
+                hostname: urlObj.hostname,
+                path: pathname + search,
+                proxyTimeout: timeout,
+                onReq: async (_, options) => {
+                  options.headers = {
+                    ...options.headers,
+                    ...headers,
+                  };
+                },
+                ['rejectUnauthorized' as never]: secure,
+                ...serverOptions,
+              },
+              (err) => err && next(err),
+            );
+          } else {
+            next();
+          }
+        });
+      }
+    }
+  };
+
+  // @ts-ignore
+  return {
+    name: '@admin-pkg/vite-plugin-http2-proxy',
+    config: (config) => {
+      const { server } = config;
+      routes = Object.entries(server?.proxy ?? {}).reduce(
+        (prev, [key, value]) => {
+          if (typeof value === 'string') {
+            prev[key] = {
+              target: value,
+            };
+          } else {
+            prev[key] = value;
+          }
+          return prev;
+        },
+        {} as Record<string, ProxyOptions>,
+      );
+
+      if (server) {
+        // https://cn.vitejs.dev/config/server-options#server-https
+        Reflect.deleteProperty(server, 'proxy');
+      }
+      return config;
+    },
+    configureServer: configure,
+    // @ts-ignore
+    configurePreviewServer: configure,
+  };
+};

+ 13 - 0
packages/vite-plugin-http2-proxy/tsconfig.json

@@ -0,0 +1,13 @@
+{
+  "compilerOptions": {
+    "target": "ESNext",
+    "moduleResolution": "Node",
+    "module": "ESNext",
+    "outDir": "dist",
+    "declaration": true,
+    "strict": true,
+    "skipLibCheck": true,
+    "useUnknownInCatchVariables": false,
+    "allowSyntheticDefaultImports": true
+  }
+}

+ 1 - 0
packages/vite-plugin-msw/.gitignore

@@ -0,0 +1 @@
+src/mockServiceWorker.js

+ 99 - 0
packages/vite-plugin-msw/README.md

@@ -0,0 +1,99 @@
+# @admin-pkg/vite-plugin-msw
+
+Mock Service Worker browser and node integration for Vite.
+
+## Usage
+
+### Install
+
+```sh
+npm install --save-dev @admin-pkg/vite-plugin-msw
+# yarn add --dev @admin-pkg/vite-plugin-msw
+# pnpm add --save-dev @admin-pkg/vite-plugin-msw
+```
+
+### Define mocks
+
+https://mswjs.io/docs/getting-started/mocks
+
+---
+
+## Config
+
+```ts
+interface VitePluginMswOptions {
+  handlers?: RequestHandler[];
+  mode?: 'browser' | 'node';
+  build?: boolean;
+}
+```
+
+### Handlers
+
+- Optional
+
+MSW handlers. More information on how to define these: https://mswjs.io/docs/getting-started/mocks
+
+### Mode
+
+- Optional
+- Default: `browser`
+
+#### Browser
+
+To start MSW in the client, please follow the [Configure worker step](https://mswjs.io/docs/getting-started/integrate/browser#configure-worker) and [Start worker step](https://mswjs.io/docs/getting-started/integrate/browser#start-worker) in the MSW docs. The `mockServiceWorker.js` file will be provided by the Vite Dev Server.
+
+##### Example vite application
+
+```ts
+import { enableMocking } from '@admin-pkg/vite-plugin-msw';
+import { HttpHandler } from 'msw';
+
+const modules = import.meta.glob<any>('./**/*.ts', {
+  eager: true,
+});
+
+export const setupMock = async () => {
+  const handlers = Object.values(modules).reduce<HttpHandler[]>((prev, curr) => {
+    const arr = curr?.default;
+    if (Array.isArray(arr)) {
+      arr.forEach((item) => {
+        if (item instanceof HttpHandler) {
+          prev.push(item);
+        }
+      });
+    }
+    return prev;
+  }, []);
+  // console.log('handlers', handlers);
+  await enableMocking(handlers);
+};
+```
+
+#### Node
+
+This will handle the mocked service worker handlers via a Vite Dev Server plugin.
+
+##### Add to Vite config
+
+```ts
+// Import plugin
+import msw from '@admin-pkg/vite-plugin-msw';
+
+// Import msw handlers
+import { handlers } from '../mocks/handlers';
+
+// Pass them to plugin
+export default defineConfig({
+  plugins: [msw({ handlers })],
+});
+```
+
+### Build
+
+- Optional
+- Default: `false`
+
+A true value will output MSW's `mockServiceWorker.js` file to the Vite build directory, in case if MSW is needed in production.
+
+---

+ 55 - 0
packages/vite-plugin-msw/package.json

@@ -0,0 +1,55 @@
+{
+  "name": "@admin-pkg/vite-plugin-msw",
+  "version": "0.0.9",
+  "type": "module",
+  "description": "",
+  "module": "./dist/browser/index.js",
+  "main": "./dist/browser/index.js",
+  "files": [
+    "dist"
+  ],
+  "exports": {
+    ".": {
+      "import": "./dist/browser/index.js"
+    },
+    "./vite": {
+      "import": "./dist/index.js"
+    }
+  },
+  "scripts": {
+    "dev": "rimraf dist && tsup --watch",
+    "build": "rimraf dist && tsup"
+  },
+  "keywords": [
+    "msw",
+    "mock",
+    "vite"
+  ],
+  "author": {
+    "name": "buqiyuan",
+    "email": "1743369777@qq.com",
+    "url": "https://github.com/buqiyuan"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/buqiyuan/vue3-antdv-admin/tree/main/packages/vite-plugin-msw",
+    "directory": "packages/vite-plugin-msw"
+  },
+  "homepage": "https://github.com/buqiyuan/vue3-antdv-admin/tree/main/packages/vite-plugin-msw#readme",
+  "license": "MIT",
+  "publishConfig": {
+    "access": "public",
+    "registry": "https://registry.npmjs.org/"
+  },
+  "dependencies": {
+    "@mswjs/interceptors": "^0.36.1",
+    "headers-polyfill": "^4.0.3",
+    "strict-event-emitter": "^0.5.1"
+  },
+  "devDependencies": {
+    "tsup": "^8.3.0"
+  },
+  "peerDependencies": {
+    "msw": "^2.3.0"
+  }
+}

+ 58 - 0
packages/vite-plugin-msw/src/browser/enableMocking.ts

@@ -0,0 +1,58 @@
+import { type StartOptions, setupWorker } from 'msw/browser';
+import { log } from '../utils/log';
+import type { HttpHandler } from 'msw';
+
+const genMessage = (handlers: HttpHandler[]) => {
+  return {
+    type: 'updateMockHeaders',
+    mockHeaders: handlers.map((n) => n.info.header),
+  };
+};
+
+const postMsg = (registration: ServiceWorkerRegistration, handlers: HttpHandler[]) => {
+  const serviceWorker = registration.active;
+  if (serviceWorker) {
+    serviceWorker.postMessage(genMessage(handlers));
+
+    registration.addEventListener('updatefound', () => {
+      serviceWorker.postMessage(genMessage(handlers));
+      // If updatefound is fired, it means that there's a new service worker being installed.
+      log(`Value of updateViaCache: ${registration.updateViaCache}`);
+    });
+  }
+};
+
+export const enableMocking = async (handlers: HttpHandler[], options?: StartOptions) => {
+  const scriptURL = `${import.meta.env.BASE_URL || ''}/mockServiceWorker.js`.replace(
+    /\/{2,}/g,
+    '/',
+  );
+  const worker = setupWorker(...handlers);
+
+  if (import.meta.env.DEV) {
+    globalThis.__msw_worker = worker;
+  }
+
+  const serviceWorkerRegistration = await worker.start({
+    onUnhandledRequest: 'bypass',
+    // quiet: true,
+    serviceWorker: {
+      url: scriptURL,
+      options: {
+        updateViaCache: 'none',
+      },
+    },
+    ...options,
+  });
+
+  if (serviceWorkerRegistration) {
+    postMsg(serviceWorkerRegistration, handlers);
+  } else if (navigator.serviceWorker) {
+    navigator.serviceWorker.ready.then((registration) => {
+      // log('serviceWorker ready', registration, this.genMessage());
+      postMsg(registration, handlers);
+    });
+  }
+
+  return serviceWorkerRegistration;
+};

+ 1 - 0
packages/vite-plugin-msw/src/browser/index.ts

@@ -0,0 +1 @@
+export { enableMocking } from './enableMocking';

+ 37 - 0
packages/vite-plugin-msw/src/browser/vitePlugin.ts

@@ -0,0 +1,37 @@
+import { readFile, copyFile } from 'node:fs/promises';
+import { dirname, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import type { Connect } from 'vite';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const swFileName = 'mockServiceWorker.js';
+const localMswDistPath = resolve(__dirname, swFileName);
+
+export const createBrowserMiddleware = (): Connect.NextHandleFunction => {
+  return async (req, res, next) => {
+    try {
+      if (req.method !== 'GET' || !req.url?.includes(`/${swFileName}`)) {
+        next();
+        return;
+      }
+
+      const swContent = await readFile(localMswDistPath, 'utf8');
+      res.setHeader('content-type', 'application/javascript');
+      res.statusCode = 200;
+      res.end(swContent);
+    } catch (error) {
+      console.error(error);
+      res.statusCode = 500;
+      res.end(error.toString());
+    }
+  };
+};
+
+interface BuildBrowserSupportOptions {
+  outDir: string;
+}
+
+export const buildMswForBrowser = async ({ outDir }: BuildBrowserSupportOptions) => {
+  const outputPath = resolve(process.cwd(), outDir, swFileName);
+  await copyFile(localMswDistPath, outputPath);
+};

+ 60 - 0
packages/vite-plugin-msw/src/buildLocalMswFile.ts

@@ -0,0 +1,60 @@
+import { readFile, writeFile } from 'node:fs/promises';
+import { createRequire } from 'node:module';
+import { resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = fileURLToPath(new URL('.', import.meta.url));
+
+const require = createRequire(import.meta.url);
+const swFileName = 'mockServiceWorker.js';
+const mswDir = require.resolve(`msw`);
+const mswPath = resolve(mswDir, `../../${swFileName}`);
+const localMswPath = resolve(__dirname, swFileName);
+
+const replaceCodeParts = [
+  {
+    from: 'const INTEGRITY_CHECKSUM = ',
+    to: `
+// Inject by @admin-pkg/vite-plugin-msw
+import { isMatchHandler } from './utils/isMatchHandler';
+const INTEGRITY_CHECKSUM = `,
+  },
+  {
+    from: `self.addEventListener('message', async function (event) {`,
+    to: `
+self.addEventListener('message', async function (event) {
+  // Inject by @admin-pkg/vite-plugin-msw
+  if (event.data?.type === 'updateMockHeaders') {
+    globalThis.mockHeaders = event.data.mockHeaders || [];
+    // console.log('globalThis.mockHeaders', globalThis.mockHeaders);
+  }
+`,
+  },
+  {
+    from: `
+self.addEventListener('fetch', function (event) {
+  const { request } = event`,
+    to: `
+self.addEventListener('fetch', function (event) {
+  const { request } = event
+
+  // Inject by @admin-pkg/vite-plugin-msw
+  const isMockRequest = isMatchHandler(request);
+  // console.log('isMockRequest', request.url, isMockRequest);
+  if (isMockRequest === false) {
+    return;
+  }
+`,
+  },
+];
+
+export const genLocalMswFile = async () => {
+  const swContent = await readFile(mswPath, { encoding: 'utf8' });
+
+  const newSwContent = replaceCodeParts.reduce((prev, { from, to }) => {
+    return prev.replace(from, to);
+  }, swContent);
+
+  await writeFile(localMswPath, newSwContent);
+};

+ 59 - 0
packages/vite-plugin-msw/src/index.ts

@@ -0,0 +1,59 @@
+import { createNodeMiddleware } from './node/';
+import { buildMswForBrowser, createBrowserMiddleware } from './browser/vitePlugin';
+import type { HttpHandler } from 'msw';
+import type { PluginOption } from 'vite';
+
+export interface VitePluginMswOptions {
+  mode?: 'browser' | 'node';
+  handlers?: HttpHandler[];
+  build?: boolean;
+}
+
+interface BrowserIntegrationOptions {
+  build?: boolean;
+}
+
+const browserIntegration = ({ build }: BrowserIntegrationOptions): PluginOption => {
+  let outDir;
+  return {
+    name: 'vite-plugin-msw:browser-integration',
+    configureServer(devServer) {
+      const { isProduction } = devServer.config;
+      if (!isProduction) {
+        devServer.middlewares.use(createBrowserMiddleware());
+      }
+    },
+    configResolved(config) {
+      outDir = config.build.outDir;
+    },
+    async closeBundle() {
+      const isProduction = process.env.NODE_ENV === 'production';
+      if (isProduction && build) {
+        await buildMswForBrowser({ outDir });
+      }
+    },
+  };
+};
+
+const getNodeIntegration = (handlers: HttpHandler[]): PluginOption => {
+  return {
+    name: 'vite-plugin-msw:node-integration',
+    configureServer(devServer) {
+      devServer.middlewares.use(createNodeMiddleware()(...handlers));
+    },
+  };
+};
+
+function vitePluginMsw(
+  options: Omit<VitePluginMswOptions, 'handlers'> & { mode?: 'browser' },
+): PluginOption;
+function vitePluginMsw(options: VitePluginMswOptions): PluginOption {
+  const { mode = 'browser', handlers = [], build = false } = options;
+  if (mode === 'node') {
+    return getNodeIntegration(handlers);
+  } else {
+    return browserIntegration({ build });
+  }
+}
+
+export default vitePluginMsw;

+ 107 - 0
packages/vite-plugin-msw/src/node/index.ts

@@ -0,0 +1,107 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+import { randomUUID } from 'node:crypto';
+import { HttpHandler, handleRequest } from 'msw';
+import { Emitter } from 'strict-event-emitter';
+import { Headers } from 'headers-polyfill';
+import { encodeBuffer } from '@mswjs/interceptors';
+import type { IncomingHttpHeaders } from 'node:http';
+import type { Connect } from 'vite';
+
+const emitter = new Emitter();
+
+async function transformReadableStramToUint8Array(stream: ReadableStream): Promise<Uint8Array> {
+  const reader = stream.getReader();
+  const chunks: Uint8Array[] = [];
+
+  // eslint-disable-next-line no-constant-condition
+  while (true) {
+    const { done, value } = await reader.read();
+    if (done) break;
+    chunks.push(new Uint8Array(value));
+  }
+
+  let totalLength = 0;
+  for (let i = 0; i < chunks.length; i++) {
+    totalLength += chunks[i].length;
+  }
+
+  const result = new Uint8Array(totalLength);
+
+  let offset = 0;
+  for (let i = 0; i < chunks.length; i++) {
+    result.set(chunks[i], offset);
+    offset += chunks[i].length;
+  }
+
+  return result;
+}
+
+const sanitizeHeaders = (headers: IncomingHttpHeaders) =>
+  Object.entries({ ...headers }).reduce((acc, [key, value]) => {
+    if (typeof key === 'string' && !key.startsWith(':')) {
+      // @ts-ignore
+      acc[key] = value;
+    }
+    return acc;
+  }, {});
+
+export const createNodeMiddleware =
+  (serverOrigin = `http://localhost`) =>
+  (...handlers: HttpHandler[]): Connect.NextHandleFunction => {
+    return async (req, res, next) => {
+      if (!req.method || !req.url) {
+        next();
+      } else {
+        let requestBody;
+        if (!['GET', 'HEAD'].includes(req.method)) {
+          requestBody = encodeBuffer(
+            // @ts-ignore
+            typeof req.body === 'string' ? req.body : JSON.stringify(req.body),
+          );
+        }
+
+        // Treat all relative URLs as the ones coming from the server.
+        const mockedRequest = new Request(new URL(req.url, serverOrigin), {
+          method: req.method,
+          headers: new Headers(sanitizeHeaders(req.headers)),
+          credentials: 'omit',
+          body: requestBody,
+        });
+
+        await handleRequest(
+          mockedRequest,
+          randomUUID(),
+          handlers,
+          {
+            onUnhandledRequest: () => null,
+          },
+          // @ts-ignore
+          emitter,
+          {
+            resolutionContext: {
+              /**
+               * @note Resolve relative request handler URLs against
+               * the server's origin (no relative URLs in Node.js).
+               */
+              baseUrl: serverOrigin,
+            },
+            async onMockedResponse(mockedResponse) {
+              const { status, statusText, headers, body } = mockedResponse;
+              res.statusCode = status;
+              headers.forEach((value, name) => {
+                res.setHeader(name, value);
+              });
+
+              // ReadableStream to Uint8Array
+              let returnBody;
+              if (body) returnBody = await transformReadableStramToUint8Array(body);
+              res.end(returnBody ? returnBody : statusText);
+            },
+            onPassthroughResponse() {
+              next();
+            },
+          },
+        );
+      }
+    };
+  };

+ 44 - 0
packages/vite-plugin-msw/src/utils/isMatchHandler.ts

@@ -0,0 +1,44 @@
+import { matchRequestUrl } from 'msw';
+// import { log } from './log';
+
+const isStringEqual = (actual: string, expected: string) => {
+  return actual.toLowerCase() === expected.toLowerCase();
+};
+
+const matchMethod = (method, actualMethod: string) => {
+  return method instanceof RegExp ? method.test(actualMethod) : isStringEqual(method, actualMethod);
+};
+
+/**
+ * 判断请求是否为 Mock 请求
+ * @see https://github.com/mswjs/msw/blob/main/src/core/handlers/HttpHandler.ts#L127-L131
+ */
+export const isMatchHandler = (request: Request) => {
+  const url = new URL(request.url);
+  const mockHeaders: string[] = globalThis.mockHeaders || [];
+  // log('mockHeaders', mockHeaders);
+  return mockHeaders.some((n) => {
+    const [method, path] = n.split(' ');
+
+    const hasMatchingMethod = matchMethod(method, request.method);
+    const hasMatchingUrl = matchRequestUrl(url, path, url.origin).matches;
+    // log(n, '===', hasMatchingMethod && hasMatchingUrl);
+    return hasMatchingMethod && hasMatchingUrl;
+  });
+};
+
+// 参考自官方的匹配方法 import { getResponse } from 'msw/lib/core/utils/getResponse';
+// 由于在 Service worker 监听 fetch 时的回调函数的 respondWith 只能是同步调用,所以不能通过异步的方式做判断
+// const isMatchHandler = async (request: Request) => {
+//   let result;
+
+//   for (const handler of handlers) {
+//     result = await handler.test({ request });
+
+//     if (result) {
+//       return true;
+//     }
+//   }
+
+//   return handlers.length && result;
+// };

+ 7 - 0
packages/vite-plugin-msw/src/utils/log.ts

@@ -0,0 +1,7 @@
+import { name } from '../../package.json';
+
+const LIBRARY_PREFIX = `[${name}]`;
+
+export const log = (...msg) => {
+  console.log(`%c${LIBRARY_PREFIX}`, 'font-weight:bold;', ...msg);
+};

+ 28 - 0
packages/vite-plugin-msw/tsconfig.json

@@ -0,0 +1,28 @@
+{
+  "compilerOptions": {
+    "baseUrl": ".",
+    "target": "esnext",
+    "module": "esnext",
+    "moduleResolution": "node",
+    "outDir": "dist",
+    "declaration": true,
+    "esModuleInterop": true,
+    "resolveJsonModule": true,
+    "skipLibCheck": true,
+    "skipDefaultLibCheck": true,
+    "strictNullChecks": true,
+    "strictFunctionTypes": true,
+    "strictPropertyInitialization": true,
+    "useUnknownInCatchVariables": false,
+    "noImplicitThis": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true,
+    "allowSyntheticDefaultImports": true,
+    "experimentalDecorators": true,
+    "emitDecoratorMetadata": true,
+    "types": ["node", "vite/client"]
+  },
+  "include": ["**/*.ts"]
+}

+ 47 - 0
packages/vite-plugin-msw/tsup.config.ts

@@ -0,0 +1,47 @@
+import { defineConfig } from 'tsup';
+import { genLocalMswFile } from './src/buildLocalMswFile';
+
+export default defineConfig(async () => {
+  await genLocalMswFile();
+
+  return [
+    {
+      entry: ['src/index.ts'],
+      splitting: false,
+      sourcemap: true,
+      // clean: ['!mockServiceWorker.*'],
+      dts: true,
+      outDir: 'dist',
+      format: ['esm'],
+    },
+    {
+      entry: ['src/browser/index.ts'],
+      splitting: false,
+      outDir: 'dist/browser',
+      format: ['esm'],
+      dts: true,
+      /**
+       * fix build msw/browser err
+       * @see: https://github.com/egoist/tsup/issues/978
+       */
+      platform: 'browser',
+      minify: false,
+      // 排除自定义的 vite 虚拟模块
+      external: ['virtual:vite-plugin-msw'],
+    },
+    {
+      entry: ['src/mockServiceWorker.js'],
+      splitting: false,
+      outDir: 'dist',
+      format: ['esm'],
+      platform: 'browser',
+      minify: false,
+      noExternal: ['msw', '@mswjs/interceptors', 'strict-event-emitter'],
+      outExtension() {
+        return {
+          js: `.js`,
+        };
+      },
+    },
+  ];
+});

+ 4 - 0
packages/vite-plugin-msw/types/module.d.ts

@@ -0,0 +1,4 @@
+declare module 'virtual:vite-plugin-msw' {
+  import type { HttpHandler } from 'msw';
+  export const mockModules: Record<string, HttpHandler[]>;
+}

+ 12 - 0
packages/vite-plugin-tinymce-resource/package.json

@@ -0,0 +1,12 @@
+{
+  "name": "@admin-pkg/vite-plugin-tinymce-resource",
+  "version": "0.0.5",
+  "type": "module",
+  "main": "./dist/index.js",
+  "types": "./dist/index.d.ts",
+  "exports": "./dist/index.js",
+  "scripts": {
+    "build": "tsc"
+  },
+  "peerDependencies": {}
+}

+ 69 - 0
packages/vite-plugin-tinymce-resource/src/index.ts

@@ -0,0 +1,69 @@
+import { cp, readFile } from 'node:fs/promises';
+import { createRequire } from 'node:module';
+import { resolve, dirname } from 'node:path';
+import type { PluginOption } from 'vite';
+
+const require = createRequire(import.meta.url);
+
+const tinymceDir = dirname(require.resolve('tinymce'));
+let outDir: string;
+let base: string;
+
+type Options = {
+  /** Public Dir  */
+  baseUrl: string;
+  /**
+   * 要复制的目标文件夹
+   * @default: ['skins/content/default', 'skins/ui/oxide', 'skins/ui/oxide-dark']
+   **/
+  destDir?: string | string[];
+};
+
+const defaultDestDir = ['skins/content/default', 'skins/ui/oxide', 'skins/ui/oxide-dark'] as const;
+
+export default (options: Options): PluginOption => {
+  const { baseUrl, destDir = defaultDestDir } = options;
+
+  return {
+    name: 'vite-plugin-tinymce-resource',
+    configResolved(config) {
+      outDir = config.build.outDir;
+      base = config.base;
+    },
+    configureServer(server) {
+      server.middlewares.use(async (req, res, next) => {
+        const urlPrefix = `${base}/${baseUrl}`.replace(/\/{2,}/, '/');
+        if (!req.url?.startsWith(urlPrefix)) {
+          return next();
+        }
+        try {
+          const url = resolve(tinymceDir, req.url.replace(urlPrefix, ''));
+          const content = await readFile(url);
+          // console.log('req.url', req.url);
+          res.setHeader('Content-Type', 'text/css');
+          res.end(content);
+        } catch (error) {
+          console.error(error);
+          res.statusCode = 500;
+          res.end(error.toString());
+        }
+      });
+    },
+    async closeBundle() {
+      Array<string>()
+        .concat(destDir)
+        .forEach(async (dir) => {
+          const sourceDir = resolve(tinymceDir, dir);
+          const destinationDir = resolve(outDir, `./${baseUrl}`, dir);
+          // console.log(sourceDir);
+          // console.log(destinationDir);
+
+          try {
+            await cp(sourceDir, destinationDir, { recursive: true, force: true });
+          } catch (error) {
+            console.error('[@admin-pkg/vite-plugin-tinymce-resource]: ', error);
+          }
+        });
+    },
+  };
+};

+ 12 - 0
packages/vite-plugin-tinymce-resource/tsconfig.json

@@ -0,0 +1,12 @@
+{
+  "compilerOptions": {
+    "target": "ESNext",
+    "moduleResolution": "Node",
+    "module": "ESNext",
+    "outDir": "dist",
+    "declaration": true,
+    "strict": true,
+    "skipLibCheck": true,
+    "useUnknownInCatchVariables": false
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 11890 - 0
pnpm-lock.yaml


+ 2 - 0
pnpm-workspace.yaml

@@ -0,0 +1,2 @@
+packages:
+  - 'packages/*'

+ 11 - 0
prettier.config.mjs

@@ -0,0 +1,11 @@
+/**  @type {import('prettier').Config} */
+export default {
+  printWidth: 100,
+  semi: true,
+  vueIndentScriptAndStyle: true,
+  singleQuote: true,
+  trailingComma: 'all',
+  proseWrap: 'never',
+  htmlWhitespaceSensitivity: 'strict',
+  endOfLine: 'auto',
+};

BIN
public/favicon.ico


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
public/iconfont.js


+ 12 - 0
src/App.vue

@@ -0,0 +1,12 @@
+<template>
+  <ProConfigProvider>
+    <router-view #="{ Component }">
+      <component :is="Component" />
+    </router-view>
+    <!-- <LockScreen /> -->
+  </ProConfigProvider>
+</template>
+
+<script setup lang="ts">
+  // import { LockScreen } from '@/components/basic/lockscreen';
+</script>

+ 70 - 0
src/api/backend/api/account.ts

@@ -0,0 +1,70 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 账户登出 GET /api/account/logout */
+export async function accountLogout(options?: RequestOptions) {
+  return request<any>("/api/account/logout", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 获取菜单列表 GET /api/account/menus */
+export async function accountMenu(options?: RequestOptions) {
+  return request<API.AccountMenus[]>("/api/account/menus", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 更改账户密码 POST /api/account/password */
+export async function accountPassword(
+  body: API.PasswordUpdateDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/account/password", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 获取权限列表 GET /api/account/permissions */
+export async function accountPermissions(options?: RequestOptions) {
+  return request<string[]>("/api/account/permissions", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 获取账户资料 GET /api/account/profile */
+export async function accountProfile(options?: RequestOptions) {
+  return request<API.AccountInfo>("/api/account/profile", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 更改账户资料 PUT /api/account/update */
+export async function accountUpdate(
+  body: API.AccountUpdateDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/account/update", {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 35 - 0
src/api/backend/api/auth.ts

@@ -0,0 +1,35 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 登录 POST /api/auth/login */
+export async function authLogin(body: API.LoginDto, options?: RequestOptions) {
+  return request<API.LoginToken>("/api/auth/login", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 注册 POST /api/auth/register */
+export async function authRegister(
+  body: API.RegisterDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/auth/register", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 23 - 0
src/api/backend/api/authEmail.ts

@@ -0,0 +1,23 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 发送邮箱验证码 POST /api/auth/email/send */
+export async function emailSendEmailCode(
+  body: API.SendEmailCodeDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/auth/email/send", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 38 - 0
src/api/backend/api/authSms.ts

@@ -0,0 +1,38 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 中台调用发送短信验证码 POST /api/auth/sms/middlegroundSend */
+export async function smsMiddlegroundSendSms(
+  body: string[],
+  options?: RequestOptions
+) {
+  return request<any>("/api/auth/sms/middlegroundSend", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 发送短信验证码 GET /api/auth/sms/send */
+export async function smsSendSmsCode(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.SmsSendSmsCodeParams,
+  options?: RequestOptions
+) {
+  return request<any>("/api/auth/sms/send", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}

+ 82 - 0
src/api/backend/api/businessTodo.ts

@@ -0,0 +1,82 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取Todo列表 GET /api/todos */
+export async function todoList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TodoListParams,
+  options?: RequestOptions
+) {
+  return request<API.TodoEntity[]>("/api/todos", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 创建Todo POST /api/todos */
+export async function todoCreate(body: API.TodoDto, options?: RequestOptions) {
+  return request<any>("/api/todos", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 获取Todo详情 GET /api/todos/${param0} */
+export async function todoInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TodoInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.TodoEntity>(`/api/todos/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新Todo PUT /api/todos/${param0} */
+export async function todoUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TodoUpdateParams,
+  body: API.TodoUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/todos/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除Todo DELETE /api/todos/${param0} */
+export async function todoDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TodoDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/todos/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}

+ 23 - 0
src/api/backend/api/captcha.ts

@@ -0,0 +1,23 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取登录图片验证码 GET /api/auth/captcha/img */
+export async function captchaCaptchaByImg(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.CaptchaCaptchaByImgParams,
+  options?: RequestOptions
+) {
+  return request<API.ImageCaptcha>("/api/auth/captcha/img", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}

+ 73 - 0
src/api/backend/api/health.ts

@@ -0,0 +1,73 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 此处后端没有提供注释 GET /api/health/database */
+export async function healthCheckDatabase(options?: RequestOptions) {
+  return request<{
+    status?: string;
+    info?: Record<string, any>;
+    error?: Record<string, any>;
+    details?: Record<string, any>;
+  }>("/api/health/database", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 GET /api/health/disk */
+export async function healthCheckDisk(options?: RequestOptions) {
+  return request<{
+    status?: string;
+    info?: Record<string, any>;
+    error?: Record<string, any>;
+    details?: Record<string, any>;
+  }>("/api/health/disk", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 GET /api/health/memory-heap */
+export async function healthCheckMemoryHeap(options?: RequestOptions) {
+  return request<{
+    status?: string;
+    info?: Record<string, any>;
+    error?: Record<string, any>;
+    details?: Record<string, any>;
+  }>("/api/health/memory-heap", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 GET /api/health/memory-rss */
+export async function healthCheckMemoryRss(options?: RequestOptions) {
+  return request<{
+    status?: string;
+    info?: Record<string, any>;
+    error?: Record<string, any>;
+    details?: Record<string, any>;
+  }>("/api/health/memory-rss", {
+    method: "GET",
+    ...(options || {}),
+  });
+}
+
+/** 此处后端没有提供注释 GET /api/health/network */
+export async function healthCheckNetwork(options?: RequestOptions) {
+  return request<{
+    status?: string;
+    info?: Record<string, any>;
+    error?: Record<string, any>;
+    details?: Record<string, any>;
+  }>("/api/health/network", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 60 - 0
src/api/backend/api/index.ts

@@ -0,0 +1,60 @@
+// @ts-ignore
+/* eslint-disable */
+// API 更新时间:
+// API 唯一标识:
+import * as systemClientUser from './systemClientUser';
+import * as systemRole from './systemRole';
+import * as systemMenu from './systemMenu';
+import * as systemParamConfig from './systemParamConfig';
+import * as systemTopic from './systemTopic';
+import * as systemAccountConfiguration from './systemAccountConfiguration';
+import * as auth from './auth';
+import * as account from './account';
+import * as captcha from './captcha';
+import * as authEmail from './authEmail';
+import * as authSms from './authSms';
+import * as systemUser from './systemUser';
+import * as systemLog from './systemLog';
+import * as systemDept from './systemDept';
+import * as systemDictType from './systemDictType';
+import * as systemDictItem from './systemDictItem';
+import * as systemTask from './systemTask';
+import * as systemOnline from './systemOnline';
+import * as systemSse from './systemSse';
+import * as systemServe from './systemServe';
+import * as toolsStorage from './toolsStorage';
+import * as systemEmail from './systemEmail';
+import * as toolsUpload from './toolsUpload';
+import * as health from './health';
+import * as netDiskManage from './netDiskManage';
+import * as netDiskOverview from './netDiskOverview';
+import * as businessTodo from './businessTodo';
+export default {
+  systemClientUser,
+  systemRole,
+  systemMenu,
+  systemParamConfig,
+  systemTopic,
+  systemAccountConfiguration,
+  auth,
+  account,
+  captcha,
+  authEmail,
+  authSms,
+  systemUser,
+  systemLog,
+  systemDept,
+  systemDictType,
+  systemDictItem,
+  systemTask,
+  systemOnline,
+  systemSse,
+  systemServe,
+  toolsStorage,
+  systemEmail,
+  toolsUpload,
+  health,
+  netDiskManage,
+  netDiskOverview,
+  businessTodo,
+};

+ 151 - 0
src/api/backend/api/netDiskManage.ts

@@ -0,0 +1,151 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 复制文件或文件夹,支持批量 POST /api/netdisk/manage/copy */
+export async function netDiskManageCopy(
+  body: API.FileOpDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/copy", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 剪切文件或文件夹,支持批量 POST /api/netdisk/manage/cut */
+export async function netDiskManageCut(
+  body: API.FileOpDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/cut", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 删除文件或文件夹 POST /api/netdisk/manage/delete */
+export async function netDiskManageDelete(
+  body: API.DeleteDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/delete", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 获取下载链接,不支持下载文件夹 GET /api/netdisk/manage/download */
+export async function netDiskManageDownload(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.NetDiskManageDownloadParams,
+  options?: RequestOptions
+) {
+  return request<string>("/api/netdisk/manage/download", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 获取文件详细信息 GET /api/netdisk/manage/info */
+export async function netDiskManageInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.NetDiskManageInfoParams,
+  options?: RequestOptions
+) {
+  return request<API.SFileInfoDetail>("/api/netdisk/manage/info", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 获取文件列表 GET /api/netdisk/manage/list */
+export async function netDiskManageList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.NetDiskManageListParams,
+  options?: RequestOptions
+) {
+  return request<API.SFileList>("/api/netdisk/manage/list", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 添加文件备注 POST /api/netdisk/manage/mark */
+export async function netDiskManageMark(
+  body: API.MarkFileDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/mark", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 创建文件夹,支持多级 POST /api/netdisk/manage/mkdir */
+export async function netDiskManageMkdir(
+  body: API.MKDirDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/mkdir", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 重命名文件或文件夹 POST /api/netdisk/manage/rename */
+export async function netDiskManageRename(
+  body: API.RenameDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/netdisk/manage/rename", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 获取上传Token,无Token前端无法上传 GET /api/netdisk/manage/token */
+export async function netDiskManageToken(options?: RequestOptions) {
+  return request<API.UploadToken>("/api/netdisk/manage/token", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 16 - 0
src/api/backend/api/netDiskOverview.ts

@@ -0,0 +1,16 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取网盘空间数据统计 GET /api/netdisk/overview/desc */
+export async function netDiskOverviewSpace(options?: RequestOptions) {
+  return request<API.OverviewSpaceInfo>("/api/netdisk/overview/desc", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 45 - 0
src/api/backend/api/systemAccountConfiguration.ts

@@ -0,0 +1,45 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from '@/utils/request';
+
+/** 删除账户配置 删除账户配置 DELETE /api/system/accountConfiguration/delete/${param0} */
+export async function accountConfigurationDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.AccountConfigurationDeleteParams,
+  options?: RequestOptions,
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/accountConfiguration/delete/${param0}`, {
+    method: 'DELETE',
+    params: { ...queryParams },
+    ...(options || { successMsg: '删除成功' }),
+  });
+}
+
+/** 账户配置详情 获取账户配置详情 GET /api/system/accountConfiguration/detail */
+export async function accountConfigurationDetail(options?: RequestOptions) {
+  return request<API.AccountConfigurationEntity>('/api/system/accountConfiguration/detail', {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
+/** 更新账户配置 更新账户配置 POST /api/system/accountConfiguration/update */
+export async function accountConfigurationUpdate(
+  body: API.AccountConfigurationUpdateDto,
+  options?: RequestOptions,
+) {
+  return request<any>('/api/system/accountConfiguration/update', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || { successMsg: '更新成功' }),
+  });
+}

+ 135 - 0
src/api/backend/api/systemClientUser.ts

@@ -0,0 +1,135 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取用户列表 GET /api/system/client/users */
+export async function clientUserList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.ClientUser[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/client/users", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增用户 POST /api/system/client/users */
+export async function clientUserCreate(
+  body: API.ClientUserDto,
+  options?: RequestOptions
+) {
+  return request<API.ClientUser>("/api/system/client/users", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询用户 GET /api/system/client/users/${param0} */
+export async function clientUserRead(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserReadParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.ClientUser>(`/api/system/client/users/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新用户 PUT /api/system/client/users/${param0} */
+export async function clientUserUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserUpdateParams,
+  body: API.ClientUserUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/client/users/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除用户 DELETE /api/system/client/users/${param0} */
+export async function clientUserDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/client/users/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 开通会员 PUT /api/system/client/users/${param0}/openMember */
+export async function clientUserOpenMember(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserOpenMemberParams,
+  body: API.OpenMemberDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.ClientUser>(
+    `/api/system/client/users/${param0}/openMember`,
+    {
+      method: "PUT",
+      headers: {
+        "Content-Type": "application/json",
+      },
+      params: { ...queryParams },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
+/** 更改用户密码 POST /api/system/client/users/${param0}/password */
+export async function clientUserPassword(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ClientUserPasswordParams,
+  body: API.UserPasswordDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/client/users/${param0}/password`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 82 - 0
src/api/backend/api/systemDept.ts

@@ -0,0 +1,82 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取部门列表 GET /api/system/depts */
+export async function deptList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DeptListParams,
+  options?: RequestOptions
+) {
+  return request<API.DeptEntity[]>("/api/system/depts", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 创建部门 POST /api/system/depts */
+export async function deptCreate(body: API.DeptDto, options?: RequestOptions) {
+  return request<any>("/api/system/depts", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询部门信息 GET /api/system/depts/${param0} */
+export async function deptInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DeptInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.DeptEntity>(`/api/system/depts/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新部门 PUT /api/system/depts/${param0} */
+export async function deptUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DeptUpdateParams,
+  body: API.DeptDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/depts/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除部门 DELETE /api/system/depts/${param0} */
+export async function deptDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DeptDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/depts/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}

+ 111 - 0
src/api/backend/api/systemDictItem.ts

@@ -0,0 +1,111 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取字典项列表 GET /api/system/dict-item */
+export async function dictItemList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictItemListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.DictItemEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/dict-item", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增字典项 POST /api/system/dict-item */
+export async function dictItemCreate(
+  body: API.DictItemDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/system/dict-item", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询字典项信息 GET /api/system/dict-item/${param0} */
+export async function dictItemInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictItemInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.DictItemEntity>(`/api/system/dict-item/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新字典项 POST /api/system/dict-item/${param0} */
+export async function dictItemUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictItemUpdateParams,
+  body: API.DictItemDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/dict-item/${param0}`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除指定的字典项 DELETE /api/system/dict-item/${param0} */
+export async function dictItemDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictItemDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/dict-item/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 查询字典列表 GET /api/system/dict-item/list/${param0} */
+export async function dictItemCode(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictItemCodeParams,
+  options?: RequestOptions
+) {
+  const { code: param0, ...queryParams } = params;
+  return request<API.LabelValueOptionsDto[]>(
+    `/api/system/dict-item/list/${param0}`,
+    {
+      method: "GET",
+      params: { ...queryParams },
+      ...(options || {}),
+    }
+  );
+}

+ 102 - 0
src/api/backend/api/systemDictType.ts

@@ -0,0 +1,102 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取字典类型列表 GET /api/system/dict-type */
+export async function dictTypeList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictTypeListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.DictTypeEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/dict-type", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增字典类型 POST /api/system/dict-type */
+export async function dictTypeCreate(
+  body: API.DictTypeDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/system/dict-type", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询字典类型信息 GET /api/system/dict-type/${param0} */
+export async function dictTypeInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictTypeInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.DictTypeEntity>(`/api/system/dict-type/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新字典类型 POST /api/system/dict-type/${param0} */
+export async function dictTypeUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictTypeUpdateParams,
+  body: API.DictTypeDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/dict-type/${param0}`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除指定的字典类型 DELETE /api/system/dict-type/${param0} */
+export async function dictTypeDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.DictTypeDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/dict-type/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 一次性获取所有的字典类型(不分页) GET /api/system/dict-type/select-options */
+export async function dictTypeGetAll(options?: RequestOptions) {
+  return request<API.DictTypeEntity[]>("/api/system/dict-type/select-options", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 23 - 0
src/api/backend/api/systemEmail.ts

@@ -0,0 +1,23 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 发送邮件 POST /api/tools/email/send */
+export async function emailSend(
+  body: API.EmailSendDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/tools/email/send", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 80 - 0
src/api/backend/api/systemLog.ts

@@ -0,0 +1,80 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 查询验证码日志列表 GET /api/system/log/captcha/list */
+export async function logCaptchaList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.LogCaptchaListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.CaptchaLogEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/log/captcha/list", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 查询登录日志列表 GET /api/system/log/login/list */
+export async function logLoginLogPage(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.LogLoginLogPageParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.LoginLogInfo[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/log/login/list", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 查询任务日志列表 GET /api/system/log/task/list */
+export async function logTaskList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.LogTaskListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.TaskLogEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/log/task/list", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}

+ 90 - 0
src/api/backend/api/systemMenu.ts

@@ -0,0 +1,90 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取所有菜单列表 GET /api/system/menus */
+export async function menuList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.MenuListParams,
+  options?: RequestOptions
+) {
+  return request<API.MenuItemInfo[]>("/api/system/menus", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增菜单或权限 POST /api/system/menus */
+export async function menuCreate(body: API.MenuDto, options?: RequestOptions) {
+  return request<any>("/api/system/menus", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 获取菜单或权限信息 GET /api/system/menus/${param0} */
+export async function menuInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.MenuInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/menus/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新菜单或权限 PUT /api/system/menus/${param0} */
+export async function menuUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.MenuUpdateParams,
+  body: API.MenuUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/menus/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除菜单或权限 DELETE /api/system/menus/${param0} */
+export async function menuDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.MenuDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/menus/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 获取后端定义的所有权限集 GET /api/system/menus/permissions */
+export async function menuGetPermissions(options?: RequestOptions) {
+  return request<string[]>("/api/system/menus/permissions", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 28 - 0
src/api/backend/api/systemOnline.ts

@@ -0,0 +1,28 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 下线指定在线用户 POST /api/system/online/kick */
+export async function onlineKick(body: API.KickDto, options?: RequestOptions) {
+  return request<any>("/api/system/online/kick", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 查询当前在线用户 GET /api/system/online/list */
+export async function onlineList(options?: RequestOptions) {
+  return request<API.OnlineUserInfo[]>("/api/system/online/list", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 94 - 0
src/api/backend/api/systemParamConfig.ts

@@ -0,0 +1,94 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取参数配置列表 GET /api/system/param-config */
+export async function paramConfigList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ParamConfigListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.ParamConfigEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/param-config", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增参数配置 POST /api/system/param-config */
+export async function paramConfigCreate(
+  body: API.ParamConfigDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/system/param-config", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询参数配置信息 GET /api/system/param-config/${param0} */
+export async function paramConfigInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ParamConfigInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.ParamConfigEntity>(`/api/system/param-config/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新参数配置 POST /api/system/param-config/${param0} */
+export async function paramConfigUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ParamConfigUpdateParams,
+  body: API.ParamConfigDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/param-config/${param0}`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除指定的参数配置 DELETE /api/system/param-config/${param0} */
+export async function paramConfigDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.ParamConfigDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/param-config/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}

+ 91 - 0
src/api/backend/api/systemRole.ts

@@ -0,0 +1,91 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取角色列表 GET /api/system/roles */
+export async function roleList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.RoleListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.RoleEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/roles", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增角色 POST /api/system/roles */
+export async function roleCreate(body: API.RoleDto, options?: RequestOptions) {
+  return request<any>("/api/system/roles", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 获取角色信息 GET /api/system/roles/${param0} */
+export async function roleInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.RoleInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.RoleInfo>(`/api/system/roles/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新角色 PUT /api/system/roles/${param0} */
+export async function roleUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.RoleUpdateParams,
+  body: API.RoleUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/roles/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除角色 DELETE /api/system/roles/${param0} */
+export async function roleDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.RoleDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/roles/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}

+ 16 - 0
src/api/backend/api/systemServe.ts

@@ -0,0 +1,16 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取服务器运行信息 GET /api/system/serve/stat */
+export async function serveStat(options?: RequestOptions) {
+  return request<API.ServeStatInfo>("/api/system/serve/stat", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

+ 22 - 0
src/api/backend/api/systemSse.ts

@@ -0,0 +1,22 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 服务端推送消息 GET /api/sse/${param0} */
+export async function sseSse(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.SseSseParams,
+  options?: RequestOptions
+) {
+  const { uid: param0, ...queryParams } = params;
+  return request<Record<string, any>>(`/api/sse/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}

+ 133 - 0
src/api/backend/api/systemTask.ts

@@ -0,0 +1,133 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取任务列表 GET /api/system/tasks */
+export async function taskList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.TaskEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/tasks", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 添加任务 POST /api/system/tasks */
+export async function taskCreate(body: API.TaskDto, options?: RequestOptions) {
+  return request<any>("/api/system/tasks", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 查询任务详细信息 GET /api/system/tasks/${param0} */
+export async function taskInfo(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskInfoParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.TaskEntity>(`/api/system/tasks/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新任务 PUT /api/system/tasks/${param0} */
+export async function taskUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskUpdateParams,
+  body: API.TaskUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/tasks/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除任务 DELETE /api/system/tasks/${param0} */
+export async function taskDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/tasks/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 手动执行一次任务 PUT /api/system/tasks/${param0}/once */
+export async function taskOnce(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskOnceParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/tasks/${param0}/once`, {
+    method: "PUT",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 启动任务 PUT /api/system/tasks/${param0}/start */
+export async function taskStart(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskStartParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/tasks/${param0}/start`, {
+    method: "PUT",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 停止任务 PUT /api/system/tasks/${param0}/stop */
+export async function taskStop(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TaskStopParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/tasks/${param0}/stop`, {
+    method: "PUT",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}

+ 83 - 0
src/api/backend/api/systemTopic.ts

@@ -0,0 +1,83 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 同步专题数据 POST /api/system/topic/syncTopics */
+export async function topicSyncTopics(options?: RequestOptions) {
+  return request<any>("/api/system/topic/syncTopics", {
+    method: "POST",
+    ...(options || {}),
+  });
+}
+
+/** 专题详情 POST /api/system/topic/topicDetails */
+export async function topicDetails(
+  body: API.TopicDetailsQueryDto,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.TopicDetailsDto[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/topic/topicDetails", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 专题列表 GET /api/system/topic/topicList */
+export async function topicList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TopicListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.TopicEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/topic/topicList", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 更新专题 PUT /api/system/topic/updateTopic/${param0} */
+export async function topicUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.TopicUpdateParams,
+  body: API.TopicDtoUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/topic/updateTopic/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}

+ 110 - 0
src/api/backend/api/systemUser.ts

@@ -0,0 +1,110 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 获取用户列表 GET /api/system/users */
+export async function userList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.UserListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.UserEntity[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/system/users", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+/** 新增用户 POST /api/system/users */
+export async function userCreate(body: API.UserDto, options?: RequestOptions) {
+  return request<any>("/api/system/users", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "创建成功" }),
+  });
+}
+
+/** 查询用户 GET /api/system/users/${param0} */
+export async function userRead(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.UserReadParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<API.UserEntity>(`/api/system/users/${param0}`, {
+    method: "GET",
+    params: { ...queryParams },
+    ...(options || {}),
+  });
+}
+
+/** 更新用户 PUT /api/system/users/${param0} */
+export async function userUpdate(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.UserUpdateParams,
+  body: API.UserUpdateDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/users/${param0}`, {
+    method: "PUT",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || { successMsg: "更新成功" }),
+  });
+}
+
+/** 删除用户 DELETE /api/system/users/${param0} */
+export async function userDelete(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.UserDeleteParams,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/users/${param0}`, {
+    method: "DELETE",
+    params: { ...queryParams },
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 更改用户密码 POST /api/system/users/${param0}/password */
+export async function userPassword(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.UserPasswordParams,
+  body: API.UserPasswordDto,
+  options?: RequestOptions
+) {
+  const { id: param0, ...queryParams } = params;
+  return request<any>(`/api/system/users/${param0}/password`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    params: { ...queryParams },
+    data: body,
+    ...(options || {}),
+  });
+}

+ 47 - 0
src/api/backend/api/toolsStorage.ts

@@ -0,0 +1,47 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 删除文件 POST /api/tools/storage/delete */
+export async function storageDelete(
+  body: API.StorageDeleteDto,
+  options?: RequestOptions
+) {
+  return request<any>("/api/tools/storage/delete", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+    },
+    data: body,
+    ...(options || { successMsg: "删除成功" }),
+  });
+}
+
+/** 获取本地存储列表 GET /api/tools/storage/list */
+export async function storageList(
+  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
+  params: API.StorageListParams,
+  options?: RequestOptions
+) {
+  return request<{
+    items?: API.StorageInfo[];
+    meta?: {
+      itemCount?: number;
+      totalItems?: number;
+      itemsPerPage?: number;
+      totalPages?: number;
+      currentPage?: number;
+    };
+  }>("/api/tools/storage/list", {
+    method: "GET",
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}

+ 52 - 0
src/api/backend/api/toolsUpload.ts

@@ -0,0 +1,52 @@
+// @ts-ignore
+/* eslint-disable */
+
+/**
+ * 该文件为 @umijs/openapi 插件自动生成,请勿随意修改。如需修改请通过配置 openapi.config.ts 进行定制化。
+ * */
+
+import { request, type RequestOptions } from "@/utils/request";
+
+/** 上传 POST /api/tools/upload */
+export async function uploadUpload(
+  body: API.FileUploadDto,
+  file?: File,
+  options?: RequestOptions
+) {
+  const formData = new FormData();
+
+  if (file) {
+    formData.append("file", file);
+  }
+
+  Object.keys(body).forEach((ele) => {
+    const item = (body as any)[ele];
+
+    if (item !== undefined && item !== null) {
+      if (typeof item === "object" && !(item instanceof File)) {
+        if (item instanceof Array) {
+          item.forEach((f) => formData.append(ele, f || ""));
+        } else {
+          formData.append(ele, JSON.stringify(item));
+        }
+      } else {
+        formData.append(ele, item);
+      }
+    }
+  });
+
+  return request<any>("/api/tools/upload", {
+    method: "POST",
+    data: formData,
+    requestType: "form",
+    ...(options || {}),
+  });
+}
+
+/** 获取阿里云sts token GET /api/tools/upload/getSTSToken */
+export async function uploadGetStsToken(options?: RequestOptions) {
+  return request<API.STSTokenVo>("/api/tools/upload/getSTSToken", {
+    method: "GET",
+    ...(options || {}),
+  });
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1833 - 0
src/api/backend/api/typings.d.ts


+ 11 - 0
src/api/demo/dict.ts

@@ -0,0 +1,11 @@
+import { request } from '@/utils/request';
+
+export type DictType = 'gender' | 'sell_status';
+
+export async function getDictData(params: { type: DictType }) {
+  return request<LabelValueOptions>({
+    url: '/dict/data',
+    method: 'GET',
+    params,
+  });
+}

+ 33 - 0
src/api/demo/hero.ts

@@ -0,0 +1,33 @@
+import { request } from '@/utils/request';
+
+/**
+ * @description 获取王者荣耀英雄列表
+ */
+export function getWzryHeroList(query: API.PageParams) {
+  return request({
+    url: '/demo/wzry/hero_list',
+    method: 'get',
+    params: query,
+  });
+}
+
+/**
+ * @description 获取英雄联盟英雄列表
+ */
+export function getLolHeroList(query: API.PageParams) {
+  return request({
+    url: '/demo/lol/hero_list',
+    method: 'get',
+    params: query,
+  });
+}
+
+/**
+ * @description 获取英雄联盟英雄列表
+ */
+export function getLolHeroInfo({ id }) {
+  return request({
+    url: `/demo/lol/hero_info/${id}`,
+    method: 'get',
+  });
+}

+ 14 - 0
src/api/demo/select.ts

@@ -0,0 +1,14 @@
+import { request } from '@/utils/request';
+
+interface DemoOptionsItem {
+  name: string;
+  id: string;
+}
+
+export async function optionsListApi(params?: Recordable) {
+  return request<DemoOptionsItem[]>({
+    url: '/select/getDemoOptions',
+    method: 'GET',
+    params,
+  });
+}

+ 5 - 0
src/api/dict.ts

@@ -0,0 +1,5 @@
+import Api from '@/api/';
+export type DictType = string;
+export async function getDictData(params: { type: DictType }) {
+  return Api.systemDictItem.dictItemCode({ code: params.type });
+}

+ 4 - 0
src/api/index.ts

@@ -0,0 +1,4 @@
+import Api from './backend/api';
+export { Api };
+
+export default Api;

+ 197 - 0
src/api/middleground.ts

@@ -0,0 +1,197 @@
+import type {
+  AddBannerConfigType,
+  BackSysIndustryListType,
+  EntityNameAndCodeListType,
+  FootConfigDetailType,
+} from './middleground.type';
+import { request, type RequestOptions } from '@/utils/request';
+
+/**
+ *
+ * 获取 行业列表
+ * @export
+ * @param {RequestOptions} [options]
+ * @return {*}
+ */
+export async function getBackSysIndustry(
+  options?: RequestOptions,
+): Promise<BackSysIndustryListType[]> {
+  return request<BackSysIndustryListType[]>('/api/forward/middleground/getBackSysIndustry', {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
+/**
+ *
+ * 根据公司名称查询对应公司名称和信用编码
+ * @export
+ * @param {RequestOptions} [options]
+ * @return {*}
+ */
+export async function getEntityNameAndCode(
+  params,
+  options?: RequestOptions,
+): Promise<EntityNameAndCodeListType> {
+  return request<EntityNameAndCodeListType>('/api/forward/middleground/getentitynameandcode', {
+    method: 'GET',
+    params,
+    ...(options || {}),
+  });
+}
+
+/**
+ *
+ * 新增轮播图
+ * @export
+ * @param {RequestOptions} [options]
+ * @return {*}
+ */
+export async function addBannerConfig(
+  body,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/bannerConfig/add', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}
+
+export async function listBannerConfig(
+  params,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/page/bannerConfig/list', {
+    method: 'GET',
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+export async function putBannerConfig(
+  body,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/bannerConfig/edit', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}
+export async function delBannerConfig(id, options?: RequestOptions): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/bannerConfig/delete?ids=' + id, {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
+/**
+ *
+ * 新增轮播图
+ * @export
+ * @param {RequestOptions} [options]
+ * @return {*}
+ */
+export async function addArticleConfig(
+  body,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/article/add', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}
+
+export async function listArticleConfig(
+  params,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/page/article/list', {
+    method: 'GET',
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+export async function putArticleConfig(
+  body,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/article/edit', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}
+export async function delArticleConfig(id, options?: RequestOptions): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/middleground/article/delete?ids=' + id, {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
+export async function listFootConfig(
+  params,
+  options?: RequestOptions,
+): Promise<AddBannerConfigType> {
+  return request<AddBannerConfigType>('/api/forward/page/footConfig/list', {
+    method: 'GET',
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
+export async function detailFootConfig(options?: RequestOptions): Promise<FootConfigDetailType> {
+  return request<FootConfigDetailType>('/api/forward/middleground/footConfig/detail', {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
+export async function addFooterConfig(
+  body,
+  options?: RequestOptions,
+): Promise<FootConfigDetailType> {
+  return request<FootConfigDetailType>('/api/forward/middleground/footConfig/add', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}
+
+export async function putFooterConfig(
+  body,
+  options?: RequestOptions,
+): Promise<FootConfigDetailType> {
+  return request<FootConfigDetailType>('/api/forward/middleground/footConfig/edit', {
+    method: 'POST',
+    data: body,
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+  });
+}

+ 0 - 0
src/api/middleground.type.ts


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov