Compare commits

..

105 Commits

Author SHA1 Message Date
vben
05a52b0540 chore: release v5.2.0 2024-08-29 22:35:38 +08:00
Vben
a77cc00e9f feat: core components support simple locale switching (#4273)
* feat: core components support simple locale switching

* fix: test error

* fix: test error
2024-08-29 22:31:49 +08:00
Vben
98da0672e7 feat: add archive plug-in to output dist.zip after build (#4272)
* feat: add the archiver plug-in to output dist.zip after build

* chore: update env
2024-08-29 21:47:00 +08:00
moyaojun
be3bcc1122 fix(@vben/preferences): fix hidden header navigation bar causes the settings button to not be displayed (#4271)
bug #4268
2024-08-29 21:37:29 +08:00
handsomeFu
88a7a9b1ee perf: reset value after reopen LockScreenModal (#4269)
* perf: replace deprecated @keypress with @keydown for Enter key handling

* perf: reset value after reopen LockScreenModal
2024-08-29 17:21:08 +08:00
dependabot[bot]
3b2ed948f5 chore(deps): bump the non-breaking-changes group with 9 updates (#4266)
* chore(deps): bump the non-breaking-changes group with 9 updates

Bumps the non-breaking-changes group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.5.0` | `22.5.1` |
| [turbo](https://github.com/vercel/turborepo) | `2.0.14` | `2.1.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.241` | `2.2.242` |
| [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography) | `0.5.14` | `0.5.15` |
| [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) | `19.4.0` | `19.4.1` |
| [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional) | `19.2.2` | `19.4.1` |
| [eslint-config-turbo](https://github.com/vercel/turborepo/tree/HEAD/packages/eslint-config-turbo) | `2.0.14` | `2.1.0` |
| [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) | `3.2.0` | `3.3.0` |
| [stylelint](https://github.com/stylelint/stylelint) | `16.8.2` | `16.9.0` |


Updates `@types/node` from 22.5.0 to 22.5.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `turbo` from 2.0.14 to 2.1.0
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/compare/v2.0.14...v2.1.0)

Updates `@iconify/json` from 2.2.241 to 2.2.242
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.241...2.2.242)

Updates `@tailwindcss/typography` from 0.5.14 to 0.5.15
- [Release notes](https://github.com/tailwindlabs/tailwindcss-typography/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss-typography/compare/v0.5.14...v0.5.15)

Updates `@commitlint/cli` from 19.4.0 to 19.4.1
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.4.1/@commitlint/cli)

Updates `@commitlint/config-conventional` from 19.2.2 to 19.4.1
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.4.1/@commitlint/config-conventional)

Updates `eslint-config-turbo` from 2.0.14 to 2.1.0
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/commits/v2.1.0/packages/eslint-config-turbo)

Updates `eslint-plugin-perfectionist` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases)
- [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md)
- [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v3.2.0...v3.3.0)

Updates `stylelint` from 16.8.2 to 16.9.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/16.8.2...16.9.0)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: turbo
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@tailwindcss/typography"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@commitlint/cli"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@commitlint/config-conventional"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint-config-turbo
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-perfectionist
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: stylelint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: update deps

* chore: update ci

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: vince <vince292007@gmail.com>
2024-08-29 07:28:23 +08:00
Li Kui
08acaf05f1 fix: solve the problem of recursive call to logout api (#4265) 2024-08-28 22:37:47 +08:00
Vben
36e7ca19a1 perf: improve modal and drawer component documentation and fix known problems (#4264)
* feat: improve modal and drawer component documentation and fix known problems

* chore: update ci
2024-08-28 22:26:35 +08:00
Li Kui
84816ef769 chore: add badges (#4260)
* chore: add badges

* docs: fix editLink
2024-08-28 20:43:24 +08:00
handsomeFu
1bd6c2e5f2 fix: fix modal position after drag to prevent offset on reopen (#4261)
* fix: fix typo

* fix: fix modal position after drag to prevent offset on reopen
2024-08-28 20:43:03 +08:00
handsomeFu
c439d5601f fix: replace deprecated @keypress with @keydown for Enter key handling (#4258) 2024-08-28 17:39:47 +08:00
前端爱码士
453a3a8f84 chore(docs): correct the file path in the markdown for the GitHub website (#4254) 2024-08-28 10:07:16 +08:00
Li Kui
c6b9a56b73 fix: clearPreferencesAndLogout does not take effect when the preferences button is at the top (#4253) 2024-08-28 09:58:59 +08:00
dependabot[bot]
6d24369272 chore(deps): bump the non-breaking-changes group with 2 updates (#4251)
Bumps the non-breaking-changes group with 2 updates: [rollup](https://github.com/rollup/rollup) and [radix-vue](https://github.com/radix-vue/radix-vue).


Updates `rollup` from 4.21.0 to 4.21.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.21.0...v4.21.1)

Updates `radix-vue` from 1.9.4 to 1.9.5
- [Release notes](https://github.com/radix-vue/radix-vue/releases)
- [Commits](https://github.com/radix-vue/radix-vue/compare/v1.9.4...v1.9.5)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: radix-vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 08:12:52 +08:00
Vben
cbf601581d feat(@vben/docs): preview components are supported within documents (#4250) 2024-08-27 23:22:34 +08:00
Li Kui
d47d051b19 fix: search and menu buttons overlapped (#4249) 2024-08-27 21:54:07 +08:00
dependabot[bot]
3b5c935bb8 chore(deps-dev): bump jsdom from 24.1.1 to 25.0.0 (#4245)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 24.1.1 to 25.0.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/24.1.1...25.0.0)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: vince <vince292007@gmail.com>
2024-08-27 11:30:38 +08:00
handsomeFu
8adb22847d perf: optimize the access directive to support string passing (#4246)
* perf: 优化access指令用法并改进参数类型

重构access权限指令以接受角色和代码形式的权限检查。通过支持数组和字符串作为指令值来简化用法,从而提高灵活性。此外,改进指令绑定类型定义以提升类型安全性。

* docs: 更新中英文文档示例以支持字符串权限码绑定更新了中文和英文文档中的示例
2024-08-27 11:17:04 +08:00
dependabot[bot]
2ba28488a4 chore(deps): bump the non-breaking-changes group with 13 updates (#4244)
Bumps the non-breaking-changes group with 13 updates:

| Package | From | To |
| --- | --- | --- |
| [ora](https://github.com/sindresorhus/ora) | `8.0.1` | `8.1.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.240` | `2.2.241` |
| [vite-plugin-vue-devtools](https://github.com/vuejs/devtools-next/tree/HEAD/packages/vite) | `7.3.8` | `7.3.9` |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.9.0` | `9.9.1` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.2.0` | `8.3.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.2.0` | `8.3.0` |
| [eslint](https://github.com/eslint/eslint) | `9.9.0` | `9.9.1` |
| [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) | `9.6.0` | `9.6.1` |
| [stylelint-scss](https://github.com/stylelint-scss/stylelint-scss) | `6.5.0` | `6.5.1` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.435.0` | `0.436.0` |
| [@vueuse/core](https://github.com/vueuse/vueuse/tree/HEAD/packages/core) | `11.0.1` | `11.0.3` |
| [@vueuse/integrations](https://github.com/vueuse/vueuse/tree/HEAD/packages/integrations) | `11.0.1` | `11.0.3` |
| [vitepress](https://github.com/vuejs/vitepress) | `1.3.3` | `1.3.4` |


Updates `ora` from 8.0.1 to 8.1.0
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v8.0.1...v8.1.0)

Updates `@iconify/json` from 2.2.240 to 2.2.241
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.240...2.2.241)

Updates `vite-plugin-vue-devtools` from 7.3.8 to 7.3.9
- [Release notes](https://github.com/vuejs/devtools-next/releases)
- [Commits](https://github.com/vuejs/devtools-next/commits/v7.3.9/packages/vite)

Updates `@eslint/js` from 9.9.0 to 9.9.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.9.1/packages/js)

Updates `@typescript-eslint/eslint-plugin` from 8.2.0 to 8.3.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.2.0 to 8.3.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/parser)

Updates `eslint` from 9.9.0 to 9.9.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.9.0...v9.9.1)

Updates `@types/eslint` from 9.6.0 to 9.6.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/eslint)

Updates `stylelint-scss` from 6.5.0 to 6.5.1
- [Release notes](https://github.com/stylelint-scss/stylelint-scss/releases)
- [Changelog](https://github.com/stylelint-scss/stylelint-scss/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint-scss/stylelint-scss/compare/v6.5.0...v6.5.1)

Updates `lucide-vue-next` from 0.435.0 to 0.436.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.436.0/packages/lucide-vue-next)

Updates `@vueuse/core` from 11.0.1 to 11.0.3
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v11.0.3/packages/core)

Updates `@vueuse/integrations` from 11.0.1 to 11.0.3
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v11.0.3/packages/integrations)

Updates `vitepress` from 1.3.3 to 1.3.4
- [Release notes](https://github.com/vuejs/vitepress/releases)
- [Changelog](https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vitepress/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: ora
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite-plugin-vue-devtools
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@eslint/js"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@types/eslint"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: stylelint-scss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/integrations"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vitepress
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 09:56:27 +08:00
Vben
d2f3a9d04f feat: preference button supports automatic positioning (#4243) 2024-08-26 23:17:27 +08:00
Vben
dc5cfab319 fix: tabbar does not meet expectations in a mixed layout (#4242) 2024-08-26 22:58:49 +08:00
Vben
87cc8a154c fix: sidebar scrolling does not meet expectations (#4241) 2024-08-26 22:09:18 +08:00
Vben
54a622ad05 chore: update vscode settings.json (#4240) 2024-08-26 21:50:56 +08:00
Vben
8a0b1e0c72 refactor: package chart-ui integrated into plugins (#4238)
* refactor: package chart-ui integrated into plugins

* fix: lint error
2024-08-26 21:42:56 +08:00
Vben
fd7b3479b4 fix: improve the display of modal and drawer on mobile (#4237) 2024-08-26 20:54:20 +08:00
handsomeFu
577cc85851 fix: change deprecated func (#4236) 2024-08-26 20:32:02 +08:00
afe1
5ca746b021 fix: ease-out (#4233)
Co-authored-by: afe1 <yunfei.zhu@nwowtec.com>
2024-08-26 10:12:24 +08:00
Donny Wang
04f29614aa chore: fix typo (#4232) 2024-08-26 10:02:09 +08:00
Li Kui
df7757d001 fix: when the 'refreshToken' expires, it does not re-authenticate (#4231) 2024-08-26 09:54:42 +08:00
Vben
20a3868594 feat: add modal and drawer components and examples (#4229)
* feat: add modal component

* feat: add drawer component

* feat: apply new modal and drawer components to the layout

* chore: typo

* feat: add some unit tests
2024-08-25 23:40:52 +08:00
vben
edb55b1fc0 chore: release v5.1.2 2024-08-25 11:02:15 +08:00
afe1
137e2073cb chore: typos (#4227) 2024-08-25 10:54:03 +08:00
dependabot[bot]
bc04286f1d chore(deps): bump the non-breaking-changes group with 6 updates (#4225)
Bumps the non-breaking-changes group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [pkg-types](https://github.com/unjs/pkg-types) | `1.1.3` | `1.2.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.239` | `2.2.240` |
| [@iconify/tailwind](https://github.com/iconify/iconify/tree/HEAD/plugins/tailwind) | `1.1.2` | `1.1.3` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.429.0` | `0.435.0` |
| [axios](https://github.com/axios/axios) | `1.7.4` | `1.7.5` |
| [element-plus](https://github.com/element-plus/element-plus) | `2.8.0` | `2.8.1` |


Updates `pkg-types` from 1.1.3 to 1.2.0
- [Release notes](https://github.com/unjs/pkg-types/releases)
- [Changelog](https://github.com/unjs/pkg-types/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unjs/pkg-types/compare/v1.1.3...v1.2.0)

Updates `@iconify/json` from 2.2.239 to 2.2.240
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.239...2.2.240)

Updates `@iconify/tailwind` from 1.1.2 to 1.1.3
- [Commits](https://github.com/iconify/iconify/commits/HEAD/plugins/tailwind)

Updates `lucide-vue-next` from 0.429.0 to 0.435.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.435.0/packages/lucide-vue-next)

Updates `axios` from 1.7.4 to 1.7.5
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.4...v1.7.5)

Updates `element-plus` from 2.8.0 to 2.8.1
- [Release notes](https://github.com/element-plus/element-plus/releases)
- [Changelog](https://github.com/element-plus/element-plus/blob/dev/CHANGELOG.en-US.md)
- [Commits](https://github.com/element-plus/element-plus/compare/2.8.0...2.8.1)

---
updated-dependencies:
- dependency-name: pkg-types
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/tailwind"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: element-plus
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Vben <ann.vben@gmail.com>
2024-08-24 12:51:11 +08:00
Li Kui
7fa4410eab fix: correct the SVG icon format (#4224)
* fix: correct the SVG icon format

closes #4220

* fix: ci fail

* chore: apply suggestion
2024-08-24 12:43:48 +08:00
invalid w
8230493651 feat(@vben/docs): support english documents (#4202)
* chore(@vben/docs): 完成guide文档的翻译

* chore(@vben/docs): 完成other文档的翻译

* chore: 翻译部分文档

* chore: 完成英文config的配置

* chore: 完成in-depth的文档翻译

* chore: 调整调整链接

* chore: typo

* chore: typo

* chore: update links

---------

Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
2024-08-23 19:46:51 +08:00
Hannah Jensen
c27b97f933 feat(@vben/web-antd): perf: home page analysis card adjusted to grid layout (#4219)
Co-authored-by: DreamyTZK <i@tzki.cn>
2024-08-23 12:59:59 +08:00
handsomeFu
d5655f02e3 chore(docs): update function parameter comments (#4215)
* docs(other): update function parameters jsdoc

- 移除`vue-router.d.ts`中`activePath`属性的默认值注释。
- 重构`generateRoutes`函数签名,增加`options`参数。
- 调整`authLogin`函数文档,增加`onSuccess`回调函数的说明。

* docs: 删除 `activePath` 属性的默认值注释

在路线文档中,移除了`activePath`属性的默认值注释,以清晰说明其行为。此更改更新了文档内容,使其更准确地反映代码实现。
2024-08-22 21:52:44 +08:00
苗大
e2732f334c chore: update vscode configuration (#4210)
* chore: vscode 配置package.json默认匹配为json而不是jsonc, 以修复依赖悬浮提示信息

* fix: settings.json eslint
2024-08-22 21:51:04 +08:00
afe1
5b24661b78 chore(docs): updated title slot description (#4192)
* fix: slots

* fix: reademe

---------

Co-authored-by: afe1 <yunfei.zhu@nwowtec.com>
2024-08-22 21:48:05 +08:00
前端爱码士
97e7bd6827 chore(docs): correct the naming convention typo in the test files (#4216) 2024-08-22 21:44:54 +08:00
dependabot[bot]
08265262e1 chore(deps): bump the non-breaking-changes group with 3 updates (#4212)
Bumps the non-breaking-changes group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [stylelint-config-recess-order](https://github.com/stormwarning/stylelint-config-recess-order) and [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next).


Updates `@types/node` from 22.4.1 to 22.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `stylelint-config-recess-order` from 5.0.1 to 5.1.0
- [Release notes](https://github.com/stormwarning/stylelint-config-recess-order/releases)
- [Changelog](https://github.com/stormwarning/stylelint-config-recess-order/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stormwarning/stylelint-config-recess-order/compare/v5.0.1...v5.1.0)

Updates `lucide-vue-next` from 0.428.0 to 0.429.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.429.0/packages/lucide-vue-next)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: stylelint-config-recess-order
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-22 09:55:09 +08:00
afe1
c3631ef555 chore: error note (#4209)
Co-authored-by: afe1 <yunfei.zhu@nwowtec.com>
2024-08-21 18:27:34 +08:00
dependabot[bot]
18627833e9 chore(deps): bump the non-breaking-changes group with 5 updates (#4206)
Bumps the non-breaking-changes group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) | `8.14.1` | `8.14.2` |
| [husky](https://github.com/typicode/husky) | `9.1.4` | `9.1.5` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `5.4.1` | `5.4.2` |
| [dayjs](https://github.com/iamkun/dayjs) | `1.11.12` | `1.11.13` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.238` | `2.2.239` |


Updates `cspell` from 8.14.1 to 8.14.2
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/commits/v8.14.2/packages/cspell)

Updates `husky` from 9.1.4 to 9.1.5
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v9.1.4...v9.1.5)

Updates `vite` from 5.4.1 to 5.4.2
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.2/packages/vite)

Updates `dayjs` from 1.11.12 to 1.11.13
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/v1.11.13/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.12...v1.11.13)

Updates `@iconify/json` from 2.2.238 to 2.2.239
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.238...2.2.239)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 10:10:26 +08:00
Li Kui
cd652941cd fix: switching language does not load the translation of the component correctly (#4205)
closes #4191
2024-08-21 10:06:06 +08:00
前端爱码士
fab92ee7e1 fix: Ignore vscode-history plug-in directory git submissions (#4207) 2024-08-21 09:57:57 +08:00
vben
04c2b9d242 ci: update workflows [skip ci] 2024-08-20 22:38:45 +08:00
Vben
2288827265 fix: fixed the failure to refresh the page when login failed (#4204) 2024-08-20 22:33:25 +08:00
Li Kui
fecf55139d fix: element-plus styles (#4203)
closes #4201
2024-08-20 21:53:09 +08:00
Zhao-sj
5962804f92 style: element-plus theme info adaptation (#4082)
Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
2024-08-20 21:39:57 +08:00
zyy
4d7e6bba56 docs: fix document typos (#4196) 2024-08-20 10:27:07 +08:00
dependabot[bot]
33637584a8 chore(deps): bump the non-breaking-changes group with 8 updates (#4195)
Bumps the non-breaking-changes group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.4.0` | `22.4.1` |
| [postcss-preset-env](https://github.com/csstools/postcss-plugins/tree/HEAD/plugin-packs/postcss-preset-env) | `10.0.1` | `10.0.2` |
| [rollup](https://github.com/rollup/rollup) | `4.20.0` | `4.21.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.1.0` | `8.2.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.1.0` | `8.2.0` |
| [@stylistic/stylelint-plugin](https://github.com/stylelint-stylistic/stylelint-stylistic) | `3.0.0` | `3.0.1` |
| [@vueuse/core](https://github.com/vueuse/vueuse/tree/HEAD/packages/core) | `11.0.0` | `11.0.1` |
| [@vueuse/integrations](https://github.com/vueuse/vueuse/tree/HEAD/packages/integrations) | `11.0.0` | `11.0.1` |


Updates `@types/node` from 22.4.0 to 22.4.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `postcss-preset-env` from 10.0.1 to 10.0.2
- [Changelog](https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/CHANGELOG.md)
- [Commits](https://github.com/csstools/postcss-plugins/commits/HEAD/plugin-packs/postcss-preset-env)

Updates `rollup` from 4.20.0 to 4.21.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.20.0...v4.21.0)

Updates `@typescript-eslint/eslint-plugin` from 8.1.0 to 8.2.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.2.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.1.0 to 8.2.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.2.0/packages/parser)

Updates `@stylistic/stylelint-plugin` from 3.0.0 to 3.0.1
- [Release notes](https://github.com/stylelint-stylistic/stylelint-stylistic/releases)
- [Changelog](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint-stylistic/stylelint-stylistic/compare/v3.0.0...v3.0.1)

Updates `@vueuse/core` from 11.0.0 to 11.0.1
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v11.0.1/packages/core)

Updates `@vueuse/integrations` from 11.0.0 to 11.0.1
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v11.0.1/packages/integrations)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: postcss-preset-env
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@stylistic/stylelint-plugin"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/integrations"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-20 10:16:56 +08:00
vben
e7a4ab70d5 chore: release v5.1.1 [skip ci] 2024-08-19 23:32:24 +08:00
Vben
1db87ff7ce fix: fix keepAlive parameter error (#4194)
* fix: mock server deployment error

* chore: typo
2024-08-19 23:28:14 +08:00
Li Kui
01d60336a6 feat: refactor and improve the request client and support refreshToken (#4157)
* feat: refreshToken

* chore: store refreshToken

* chore: generate token using jsonwebtoken

* chore: set refreshToken in httpOnly cookie

* perf: authHeader verify

* chore: add add response interceptor

* chore: test refresh

* chore: handle logout

* chore: type

* chore: update pnpm-lock.yaml

* chore: remove test code

* chore: add todo comment

* chore: update pnpm-lock.yaml

* chore: remove default interceptors

* chore: copy codes

* chore: handle refreshToken invalid

* chore: add refreshToken preference

* chore: typo

* chore: refresh token逻辑调整

* refactor: interceptor presets

* chore: copy codes

* fix: ci errors

* chore: add missing await

* feat: 完善refresh-token逻辑及文档

* fix: ci error

* chore: filename

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-08-19 22:59:42 +08:00
vben
f8485e8861 fix: ci error 2024-08-18 08:46:22 +08:00
Vben
9120d20143 chore: update deps and docs (#4184)
* chore: update deps

* chore: update docs

* chore: update menu
2024-08-18 08:43:00 +08:00
Vben
5f41c51770 perf: supplement login interface documents and add configuration parameters (#4175) 2024-08-17 22:38:37 +08:00
Vben
3c17f4e9f8 perf: all icons used in the core are offline (#4173)
* perf: all icons used in the core are offline

* chore: update default icon

* chore: update shadow
2024-08-17 21:11:07 +08:00
Vben
66808582ff fix: header theme color error (#4170)
* fix: header theme color error

* fix: ci error

* fix: ci error
2024-08-16 22:47:28 +08:00
Vben
0faf7810b6 perf: optimization of tabbar display (#4169)
* perf: optimization of tabbar display

* fix: ci error

* chore: typo

* chore: typo
2024-08-16 22:20:18 +08:00
dependabot[bot]
8987067b5a chore(deps): bump the non-breaking-changes group with 12 updates (#4165)
* chore(deps): bump the non-breaking-changes group with 12 updates

Bumps the non-breaking-changes group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [turbo](https://github.com/vercel/turborepo) | `2.0.13` | `2.0.14` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `5.4.0` | `5.4.1` |
| [vue](https://github.com/vuejs/core) | `3.4.37` | `3.4.38` |
| [execa](https://github.com/sindresorhus/execa) | `9.3.0` | `9.3.1` |
| [eslint-config-turbo](https://github.com/vercel/turborepo/tree/HEAD/packages/eslint-config-turbo) | `2.0.13` | `2.0.14` |
| [eslint-plugin-no-only-tests](https://github.com/levibuzolic/eslint-plugin-no-only-tests) | `3.1.0` | `3.3.0` |
| [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) | `3.1.3` | `3.2.0` |
| [stylelint](https://github.com/stylelint/stylelint) | `16.8.1` | `16.8.2` |
| [pinia](https://github.com/vuejs/pinia) | `2.2.1` | `2.2.2` |
| [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared) | `3.4.37` | `3.4.38` |
| [watermark-js-plus](https://github.com/zhensherlock/watermark-js-plus) | `1.5.2` | `1.5.3` |
| [publint](https://github.com/bluwy/publint/tree/HEAD/pkg) | `0.2.9` | `0.2.10` |


Updates `turbo` from 2.0.13 to 2.0.14
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/compare/v2.0.13...v2.0.14)

Updates `vite` from 5.4.0 to 5.4.1
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.1/packages/vite)

Updates `vue` from 3.4.37 to 3.4.38
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/v3.4.38/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.37...v3.4.38)

Updates `execa` from 9.3.0 to 9.3.1
- [Release notes](https://github.com/sindresorhus/execa/releases)
- [Commits](https://github.com/sindresorhus/execa/compare/v9.3.0...v9.3.1)

Updates `eslint-config-turbo` from 2.0.13 to 2.0.14
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/commits/v2.0.14/packages/eslint-config-turbo)

Updates `eslint-plugin-no-only-tests` from 3.1.0 to 3.3.0
- [Release notes](https://github.com/levibuzolic/eslint-plugin-no-only-tests/releases)
- [Changelog](https://github.com/levibuzolic/eslint-plugin-no-only-tests/blob/main/CHANGELOG.md)
- [Commits](https://github.com/levibuzolic/eslint-plugin-no-only-tests/compare/v3.1.0...v3.3.0)

Updates `eslint-plugin-perfectionist` from 3.1.3 to 3.2.0
- [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases)
- [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md)
- [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v3.1.3...v3.2.0)

Updates `stylelint` from 16.8.1 to 16.8.2
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/16.8.1...16.8.2)

Updates `pinia` from 2.2.1 to 2.2.2
- [Release notes](https://github.com/vuejs/pinia/releases)
- [Commits](https://github.com/vuejs/pinia/compare/pinia@2.2.1...pinia@2.2.2)

Updates `@vue/shared` from 3.4.37 to 3.4.38
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/v3.4.38/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/commits/v3.4.38/packages/shared)

Updates `watermark-js-plus` from 1.5.2 to 1.5.3
- [Release notes](https://github.com/zhensherlock/watermark-js-plus/releases)
- [Changelog](https://github.com/zhensherlock/watermark-js-plus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/zhensherlock/watermark-js-plus/compare/v1.5.2...v1.5.3)

Updates `publint` from 0.2.9 to 0.2.10
- [Release notes](https://github.com/bluwy/publint/releases)
- [Commits](https://github.com/bluwy/publint/commits/v0.2.10/pkg)

---
updated-dependencies:
- dependency-name: turbo
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: execa
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-config-turbo
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-no-only-tests
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-perfectionist
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: stylelint
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: pinia
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vue/shared"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: watermark-js-plus
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: publint
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: update deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: vben <ann.vben@gmail.com>
2024-08-16 09:47:45 +08:00
Vben
d71a20ad0a perf: improve tabs-view scrolling (#4164) 2024-08-15 23:30:07 +08:00
P2K0
eb280ffeb7 feat: add left and right scroll buttons to Tabs bar (#4161) (#4162) 2024-08-15 21:54:55 +08:00
Vben
debb32d353 fix: page spinner is styled incorrectly when scrolling (#4163)
* feat: add contributor information to documents

* fix: page spinner is styled incorrectly when scrolling
2024-08-15 21:48:52 +08:00
Zhang Zhi Chao
11551903f0 fix: newTabTitle does not work as expected (#4160)
* fix: cloneDeep tab close #4158

* Revert "fix: cloneDeep tab close #4158"

This reverts commit 8e2f4b39ad.

* fix:  deep clone meta.newTabTitle
2024-08-15 21:47:54 +08:00
dependabot[bot]
187f946d2a chore(deps): bump the non-breaking-changes group with 8 updates (#4155)
Bumps the non-breaking-changes group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.2.0` | `22.3.0` |
| [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue-jsx) | `4.0.0` | `4.0.1` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.9` | `3.4.10` |
| [turbo](https://github.com/vercel/turborepo) | `2.0.12` | `2.0.13` |
| [postcss-preset-env](https://github.com/csstools/postcss-plugins/tree/HEAD/plugin-packs/postcss-preset-env) | `10.0.0` | `10.0.1` |
| [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) | `4.0.2` | `4.0.3` |
| [eslint-config-turbo](https://github.com/vercel/turborepo/tree/HEAD/packages/eslint-config-turbo) | `2.0.12` | `2.0.13` |
| [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) | `50.2.0` | `50.2.2` |


Updates `@types/node` from 22.2.0 to 22.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-vue-jsx` from 4.0.0 to 4.0.1
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue-jsx/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue-jsx@4.0.1/packages/plugin-vue-jsx)

Updates `tailwindcss` from 3.4.9 to 3.4.10
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.10/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.9...v3.4.10)

Updates `turbo` from 2.0.12 to 2.0.13
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/compare/v2.0.12...v2.0.13)

Updates `postcss-preset-env` from 10.0.0 to 10.0.1
- [Changelog](https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/CHANGELOG.md)
- [Commits](https://github.com/csstools/postcss-plugins/commits/HEAD/plugin-packs/postcss-preset-env)

Updates `vite-plugin-dts` from 4.0.2 to 4.0.3
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v4.0.2...v4.0.3)

Updates `eslint-config-turbo` from 2.0.12 to 2.0.13
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/release.md)
- [Commits](https://github.com/vercel/turborepo/commits/v2.0.13/packages/eslint-config-turbo)

Updates `eslint-plugin-jsdoc` from 50.2.0 to 50.2.2
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v50.2.0...v50.2.2)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vitejs/plugin-vue-jsx"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: turbo
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: postcss-preset-env
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-config-turbo
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-15 21:23:13 +08:00
vben
e2d9d08ced chore: release v5.1.0 [skip ci] 2024-08-14 23:04:44 +08:00
Vben
30223f18db feat: supports specifying the position of the preference button (#4154) 2024-08-14 23:02:39 +08:00
Vben
9c6e059aac chore: semiDarkMenu renamed semiDarkSidebar (#4152) 2024-08-14 22:20:10 +08:00
Vben
8f40d5107c feat: support custom background colors for sidebar and header (#4151)
* feat: support custom background colors for sidebar and header

* fix: type error
2024-08-14 21:47:37 +08:00
Vben
83fcdec37c feat: add swap component (#4149) 2024-08-14 20:37:21 +08:00
dependabot[bot]
b28740042b chore(deps): bump the non-breaking-changes group with 5 updates (#4147)
Bumps the non-breaking-changes group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [lint-staged](https://github.com/lint-staged/lint-staged) | `15.2.8` | `15.2.9` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.236` | `2.2.237` |
| [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) | `50.0.1` | `50.2.0` |
| [radix-vue](https://github.com/radix-vue/radix-vue) | `1.9.3` | `1.9.4` |
| [axios](https://github.com/axios/axios) | `1.7.3` | `1.7.4` |


Updates `lint-staged` from 15.2.8 to 15.2.9
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v15.2.8...v15.2.9)

Updates `@iconify/json` from 2.2.236 to 2.2.237
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.236...2.2.237)

Updates `eslint-plugin-jsdoc` from 50.0.1 to 50.2.0
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v50.0.1...v50.2.0)

Updates `radix-vue` from 1.9.3 to 1.9.4
- [Release notes](https://github.com/radix-vue/radix-vue/releases)
- [Commits](https://github.com/radix-vue/radix-vue/compare/v1.9.3...v1.9.4)

Updates `axios` from 1.7.3 to 1.7.4
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.3...v1.7.4)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: radix-vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-14 05:45:17 +08:00
Li Kui
6a1e6ad99f fix: the translation is incorrect when switching languages for the first time (#4146)
* fix: the translation is incorrect when switching languages for the first time

closes #4138

* chore: merge locale message even if default locale not exist
2024-08-14 05:29:31 +08:00
Vben
3b0f72330a fix: automatic hiding and displaying of headers can only be used on content (#4145) 2024-08-13 22:09:46 +08:00
Li Kui
963e79063f fix: some icons behave inconsistently on menu and tab (#4144) 2024-08-13 22:07:02 +08:00
Vben
4793c4c0db perf: staticRoutes is renamed externalRoutes (#4143) 2024-08-13 21:48:01 +08:00
Li Kui
1a4d61cc17 fix: type Component is not assignable to RouteMeta (#4140)
* fix: type `Component` is not assignable to `RouteMeta`

* fix: ci fail
2024-08-13 21:30:14 +08:00
Vben
738bc456c8 perf: improve login page UI (#4142)
* perf: improve login page UI

* chore: update docs
2024-08-13 21:17:10 +08:00
invalid w
e8dff517ba fix(@vben/common-ui): text omission component expansion exception (#4139)
* fix(@vben/common-ui): 修复文本省略组件展开异常

* chore: 增加点击展开切换的测试
2024-08-13 20:58:47 +08:00
Netfan
843ec1e749 fix: tab close by key, fixed: #4132 (#4136) 2024-08-13 11:49:02 +08:00
invalid w
f20c5d9e2e feat(@vben/playground): add full-screen examples (#4126)
* feat(@vben/playground): add full-screen examples

* chore: rm unuse class

* chore: move fullScreen demo to features router

* chore: responsive

* chore: 调整路由路径

* chore: card增加间距

---------

Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
2024-08-13 11:37:03 +08:00
invalid w
6e6e35ae4a chore(@vben/playground): add a clipboard example (#4133)
* chore(@vben/playground): 增加剪切板示例

* chore: rm unuse code
2024-08-13 11:11:13 +08:00
dependabot[bot]
bf021a0578 chore(deps): bump the non-breaking-changes group with 10 updates (#4131)
Bumps the non-breaking-changes group with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) | `8.13.2` | `8.13.3` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.235` | `2.2.236` |
| [vite-plugin-vue-devtools](https://github.com/vuejs/devtools-next/tree/HEAD/packages/vite) | `7.3.7` | `7.3.8` |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.8.0` | `9.9.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.0.1` | `8.1.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.0.1` | `8.1.0` |
| [eslint](https://github.com/eslint/eslint) | `9.8.0` | `9.9.0` |
| [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) | `50.0.0` | `50.0.1` |
| [eslint-plugin-unused-imports](https://github.com/sweepline/eslint-plugin-unused-imports) | `4.1.2` | `4.1.3` |
| [tailwind-merge](https://github.com/dcastil/tailwind-merge) | `2.4.0` | `2.5.2` |


Updates `cspell` from 8.13.2 to 8.13.3
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/commits/v8.13.3/packages/cspell)

Updates `@iconify/json` from 2.2.235 to 2.2.236
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.235...2.2.236)

Updates `vite-plugin-vue-devtools` from 7.3.7 to 7.3.8
- [Release notes](https://github.com/vuejs/devtools-next/releases)
- [Commits](https://github.com/vuejs/devtools-next/commits/v7.3.8/packages/vite)

Updates `@eslint/js` from 9.8.0 to 9.9.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.9.0/packages/js)

Updates `@typescript-eslint/eslint-plugin` from 8.0.1 to 8.1.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.1.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.0.1 to 8.1.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.1.0/packages/parser)

Updates `eslint` from 9.8.0 to 9.9.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.8.0...v9.9.0)

Updates `eslint-plugin-jsdoc` from 50.0.0 to 50.0.1
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v50.0.0...v50.0.1)

Updates `eslint-plugin-unused-imports` from 4.1.2 to 4.1.3
- [Commits](https://github.com/sweepline/eslint-plugin-unused-imports/compare/v4.1.2...v4.1.3)

Updates `tailwind-merge` from 2.4.0 to 2.5.2
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/compare/v2.4.0...v2.5.2)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite-plugin-vue-devtools
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@eslint/js"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-unused-imports
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: tailwind-merge
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 08:05:59 +08:00
Vben
7b46780af7 perf: optimize the diffPreferences logic and adjust the unit test (#4130) 2024-08-12 21:05:01 +08:00
Vben
3f9ce63868 feat: support vue file unit testing, add some components unit testing (#4119) 2024-08-11 21:01:22 +08:00
Vben
517acada1a refactor: adjust all sample pages and use page components (#4118) 2024-08-11 20:05:52 +08:00
Li Kui
3015912f1a feat: page component (#4087)
* feat: page component

* chore: basic page

* chore: add demos

* chore: add header-sticky support

* chore: update web-ele

* chore: rename slot name

---------

Co-authored-by: Vben <ann.vben@gmail.com>
2024-08-11 16:29:39 +08:00
Vben
b464b87ac5 refactor: migrate demo applications to playground (#4116)
* chore: detail adjustment

* refactor: Migrate demo applications to playground

* perf: logic optimization

* chore: update docs

* chore: update docs
2024-08-11 16:09:32 +08:00
falcon-jin
654bf90c0d fix: missing route data in guard of web-ele and web-naive, fixed: #4108 (#4115) (#4117) 2024-08-11 15:49:17 +08:00
Netfan
9d6cc22dfa fix: missing route data in guard, fixed: #4108 (#4115) 2024-08-11 09:25:55 +08:00
afe1
7a9ad7de63 perf: remove duplicate code (#4083)
Co-authored-by: afe1 <yunfei.zhu@nwowtec.com>
Co-authored-by: Vben <ann.vben@gmail.com>
2024-08-10 18:58:10 +08:00
Netfan
cdeadafda5 fix: activePath not working in menu, fixed: #4112 (#4113) 2024-08-10 18:54:57 +08:00
Netfan
ec49a04151 fix: use correct route data in tabbar, fixed: #4107 (#4110) 2024-08-10 16:33:38 +08:00
P2K0
4d4327cb25 fix: TabsToolMore cannot be opened in a new window (#4107) (#4109) 2024-08-10 16:31:09 +08:00
zmcode
6c117b4130 fix: 修复vben/styles/global 全局注入的问题 (#4106)
https://doc.vben.pro/guide/essentials/styles.html#bem-%E8%A7%84%E8%8C%83

在widow下无法注册成功
2024-08-10 16:26:00 +08:00
Vben
8725a01301 fix: inconsistent performance between breadcrumbs and tabs (#4105) 2024-08-10 10:30:15 +08:00
dependabot[bot]
ed14282999 chore(deps): bump cheerio from 1.0.0-rc.12 to 1.0.0 (#4104)
Bumps [cheerio](https://github.com/cheeriojs/cheerio) from 1.0.0-rc.12 to 1.0.0.
- [Release notes](https://github.com/cheeriojs/cheerio/releases)
- [Commits](https://github.com/cheeriojs/cheerio/compare/v1.0.0-rc.12...v1.0.0)

---
updated-dependencies:
- dependency-name: cheerio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Vben <ann.vben@gmail.com>
2024-08-10 09:15:55 +08:00
dependabot[bot]
07cdebb7f1 chore(deps): bump the non-breaking-changes group with 6 updates (#4103)
Bumps the non-breaking-changes group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.1.0` | `22.2.0` |
| [cssnano](https://github.com/cssnano/cssnano) | `7.0.4` | `7.0.5` |
| [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) | `4.0.1` | `4.0.2` |
| [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) | `0.6.5` | `0.6.6` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.426.0` | `0.427.0` |
| [element-plus](https://github.com/element-plus/element-plus) | `2.7.8` | `2.8.0` |


Updates `@types/node` from 22.1.0 to 22.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `cssnano` from 7.0.4 to 7.0.5
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/compare/cssnano@7.0.4...cssnano@7.0.5)

Updates `vite-plugin-dts` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v4.0.1...v4.0.2)

Updates `prettier-plugin-tailwindcss` from 0.6.5 to 0.6.6
- [Release notes](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/compare/v0.6.5...v0.6.6)

Updates `lucide-vue-next` from 0.426.0 to 0.427.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.427.0/packages/lucide-vue-next)

Updates `element-plus` from 2.7.8 to 2.8.0
- [Release notes](https://github.com/element-plus/element-plus/releases)
- [Changelog](https://github.com/element-plus/element-plus/blob/dev/CHANGELOG.en-US.md)
- [Commits](https://github.com/element-plus/element-plus/compare/2.7.8...2.8.0)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: cssnano
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: prettier-plugin-tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: element-plus
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-10 09:07:16 +08:00
Vben
344c499462 fix: when borderRaidus is a string, the component displays an exception (#4102) 2024-08-09 23:43:32 +08:00
Vben
992b9bae6c chore: update eslint configuration and adjust docker command [skip ci] (#4101) 2024-08-09 23:27:18 +08:00
aonoa
5b56c300ab perf: correct cloneDeep spelling errors [skip ci] (#4099)
Signed-off-by: aonoa <1991849113@qq.com>
2024-08-09 18:24:52 +08:00
dependabot[bot]
ca164b0f9b chore(deps): bump the non-breaking-changes group with 14 updates (#4092)
* chore(deps): bump the non-breaking-changes group with 14 updates

Bumps the non-breaking-changes group with 14 updates:

| Package | From | To |
| --- | --- | --- |
| [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) | `8.13.1` | `8.13.2` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.7` | `3.4.9` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `5.3.5` | `5.4.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.234` | `2.2.235` |
| [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography) | `0.5.13` | `0.5.14` |
| [vite-plugin-dts](https://github.com/qmhc/vite-plugin-dts) | `4.0.0` | `4.0.1` |
| [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) | `3.1.2` | `3.1.3` |
| [eslint-plugin-unused-imports](https://github.com/sweepline/eslint-plugin-unused-imports) | `4.0.1` | `4.1.2` |
| [vue](https://github.com/vuejs/core) | `3.4.36` | `3.4.37` |
| [pinia](https://github.com/vuejs/pinia) | `2.2.0` | `2.2.1` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.424.0` | `0.426.0` |
| [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared) | `3.4.36` | `3.4.37` |
| [@vueuse/core](https://github.com/vueuse/vueuse/tree/HEAD/packages/core) | `10.11.0` | `10.11.1` |
| [@vueuse/integrations](https://github.com/vueuse/vueuse/tree/HEAD/packages/integrations) | `10.11.0` | `10.11.1` |


Updates `cspell` from 8.13.1 to 8.13.2
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/commits/v8.13.2/packages/cspell)

Updates `tailwindcss` from 3.4.7 to 3.4.9
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.9/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.7...v3.4.9)

Updates `vite` from 5.3.5 to 5.4.0
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@5.4.0/packages/vite)

Updates `@iconify/json` from 2.2.234 to 2.2.235
- [Commits](https://github.com/iconify/icon-sets/compare/2.2.234...2.2.235)

Updates `@tailwindcss/typography` from 0.5.13 to 0.5.14
- [Release notes](https://github.com/tailwindlabs/tailwindcss-typography/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss-typography/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss-typography/compare/v0.5.13...v0.5.14)

Updates `vite-plugin-dts` from 4.0.0 to 4.0.1
- [Release notes](https://github.com/qmhc/vite-plugin-dts/releases)
- [Changelog](https://github.com/qmhc/vite-plugin-dts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/qmhc/vite-plugin-dts/compare/v4.0.0...v4.0.1)

Updates `eslint-plugin-perfectionist` from 3.1.2 to 3.1.3
- [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases)
- [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md)
- [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v3.1.2...v3.1.3)

Updates `eslint-plugin-unused-imports` from 4.0.1 to 4.1.2
- [Commits](https://github.com/sweepline/eslint-plugin-unused-imports/commits/v4.1.2)

Updates `vue` from 3.4.36 to 3.4.37
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.36...v3.4.37)

Updates `pinia` from 2.2.0 to 2.2.1
- [Release notes](https://github.com/vuejs/pinia/releases)
- [Commits](https://github.com/vuejs/pinia/compare/pinia@2.2.0...pinia@2.2.1)

Updates `lucide-vue-next` from 0.424.0 to 0.426.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.426.0/packages/lucide-vue-next)

Updates `@vue/shared` from 3.4.36 to 3.4.37
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/commits/v3.4.37/packages/shared)

Updates `@vueuse/core` from 10.11.0 to 10.11.1
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v10.11.1/packages/core)

Updates `@vueuse/integrations` from 10.11.0 to 10.11.1
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v10.11.1/packages/integrations)

---
updated-dependencies:
- dependency-name: cspell
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@tailwindcss/typography"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vite-plugin-dts
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-perfectionist
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-unused-imports
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: pinia
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vue/shared"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/integrations"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: update pnpm.overrides

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: vince <vince292007@gmail.com>
2024-08-09 14:31:48 +08:00
invalid w
9487156938 chore: add colorInfo in SeedToken (#4096)
resolve #4095
2024-08-09 14:01:34 +08:00
invalid w
f1e0278bd8 chore: define examples router & add ellipsis comp (#4019)
* chore: define components router

* chore: 组件路由放置到演示路由下

* Revert "chore: 组件路由放置到演示路由下"

This reverts commit 3c24632ad5.

* chore: typo

* chore: 增加密码强度组件

* chore: 国际化密码强度的菜单

* chore(@vben/web-antd): 迁移文本省略组件

* chore: typo

* chore: 组件命名方式遵从packages

* chore: Optimize the onExpand function

* chore: update css

* chore(@vben/web-antd): optimize the getPosition function

* chore: add ellipsis-text in comm-ui

* chore: 文本省略组件迁移至common-ui

* feat(@vben/common-ui): Tooltip的tip支持style传参

* chore: 优化组件渲染

* chore: 使用css module解决样式冲突

* chore: update props

* chore: 优化css

* chore: rm unuse attr

---------

Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
2024-08-09 10:57:46 +08:00
Li Kui
de90b07b6f fix: menu-badge color not correct (#4089) 2024-08-09 10:52:47 +08:00
621 changed files with 20147 additions and 6015 deletions

View File

@@ -1,5 +1,42 @@
# Contributing Guide
# Vben Admin Contributing Guide
1. Make sure you put things in the right category!
2. Always add your items to the end of a list. To be fair, the order is first-come-first-serve.
3. If you think something belongs in the wrong category, or think there needs to be a new category, feel free to edit things too.
Hi! We're really excited that you are interested in contributing to Vben Admin. Before submitting your contribution, please make sure to take a moment and read through the following guidelines:
- [Pull Request Guidelines](#pull-request-guidelines)
## Contributor Code of Conduct
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
## Pull Request Guidelines
- Checkout a topic branch from the relevant branch, e.g. main, and merge back against that branch.
- If adding a new feature:
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
- If fixing bug:
- Provide a detailed description of the bug in the PR. Live demo preferred.
- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.
## Development Setup
You will need [pnpm](https://pnpm.io/)
After cloning the repo, run:
```bash
# install the dependencies of the project
$ pnpm install
# start the project
$ pnpm run dev
```

16
.github/labeler.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name
feature:
- head-branch: ["^feat", "feat"]
bug:
- head-branch: ["^fix", "fix"]
chore:
- head-branch: ["^chore", "chore"]
perf:
- head-branch: ["^perf", "perf"]
documentation:
- changed-files:
- any-glob-to-any-file: ["**/*.md", "docs/**"]

View File

@@ -13,18 +13,21 @@ categories:
- title: "🚀 Features"
labels:
- "feature"
- "enhancement"
- title: "🐞 Bug Fixes"
labels:
- "bug"
- title: 📝 Documentation updates
- title: "📈 Performance"
labels:
- "perf"
- "enhancement"
- title: 📝 Documentation
labels:
- "documentation"
- title: 👻 Maintenance
labels:
- "chore"
- "dependencies"
collapse-after: 5
# collapse-after: 12
- title: 🚦 Tests
labels:
- "tests"
@@ -34,12 +37,15 @@ categories:
version-resolver:
major:
labels:
- "major"
- "breaking"
minor:
labels:
- "feature"
- "minor"
patch:
labels:
- "feature"
- "patch"
- "bug"
- "maintenance"
- "docs"

View File

@@ -23,7 +23,7 @@ jobs:
matrix:
os:
- ubuntu-latest
- macos-latest
# - macos-latest
- windows-latest
timeout-minutes: 20
steps:
@@ -62,7 +62,7 @@ jobs:
matrix:
os:
- ubuntu-latest
- macos-latest
# - macos-latest
- windows-latest
steps:
@@ -85,7 +85,7 @@ jobs:
matrix:
os:
- ubuntu-latest
- macos-latest
# - macos-latest
- windows-latest
steps:
- name: Checkout code

View File

@@ -6,8 +6,63 @@ on:
- main
jobs:
deploy-push-ftp:
name: Deploy Push Ftp
deploy-playground-ftp:
name: Deploy Push Playground Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sed Config Base
shell: bash
run: |
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./playground/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./playground/.env.production
cat ./playground/.env.production
- name: Setup Node
uses: ./.github/actions/setup-node
- name: Build
run: pnpm build:play
- name: Sync Playground files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
password: ${{ secrets.WEB_PLAYGROUND_FTP_PWSSWORD }}
local-dir: ./playground/dist/
deploy-docs-ftp:
name: Deploy Push Docs Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: ./.github/actions/setup-node
- name: Build
run: pnpm build:docs
- name: Sync Docs files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
password: ${{ secrets.WEBSITE_FTP_PASSWORD }}
local-dir: ./docs/.vitepress/dist/
deploy-antd-ftp:
name: Deploy Push Antd Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
steps:
@@ -22,9 +77,65 @@ jobs:
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-antd/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-antd/.env.production
cat ./apps/web-antd/.env.production
- name: Setup Node
uses: ./.github/actions/setup-node
- name: Build
run: pnpm run build:antd
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
password: ${{ secrets.WEB_ANTD_FTP_PASSWORD }}
local-dir: ./apps/web-antd/dist/
deploy-ele-ftp:
name: Deploy Push Element Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sed Config Base
shell: bash
run: |
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-ele/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-ele/.env.production
cat ./apps/web-ele/.env.production
- name: Setup Node
uses: ./.github/actions/setup-node
- name: Build
run: pnpm run build:ele
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
password: ${{ secrets.WEB_ELE_FTP_PASSWORD }}
local-dir: ./apps/web-ele/dist/
deploy-naive-ftp:
name: Deploy Push Naive Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sed Config Base
shell: bash
run: |
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-naive/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-naive/.env.production
cat ./apps/web-naive/.env.production
@@ -33,36 +144,12 @@ jobs:
uses: ./.github/actions/setup-node
- name: Build
run: pnpm run build
run: pnpm run build:naive
- name: Sync Web Antd files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
password: ${{ secrets.WEB_ANTD_FTP_PASSWORD }}
local-dir: ./apps/web-antd/dist/
- name: Sync Web Naive files
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}
password: ${{ secrets.WEB_NAIVE_FTP_PASSWORD }}
local-dir: ./apps/web-naive/dist/
- name: Sync Web Ele files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
password: ${{ secrets.WEB_ELE_FTP_PASSWORD }}
local-dir: ./apps/web-ele/dist/
- name: Sync Docs files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
password: ${{ secrets.WEBSITE_FTP_PASSWORD }}
local-dir: ./docs/.vitepress/dist/

View File

@@ -21,5 +21,5 @@ jobs:
with:
actions: "close-issues" # 执行动作:关闭 Issues
token: ${{ secrets.GITHUB_TOKEN }} # GitHub Token用于认证
labels: "need reproduction" # 目标标签
labels: "needs reproduction" # 目标标签
inactive-day: 3 # 未活动天数阈值

22
.github/workflows/labeler.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: PR Labeler
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
label:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Label PR based on title or file changes
uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml

1
.gitignore vendored
View File

@@ -48,3 +48,4 @@ vite.config.ts.*
*.njsproj
*.sln
*.sw?
.history

2
.npmrc
View File

@@ -1,4 +1,4 @@
# registry = "https://registry.npmmirror.com"
registry = "https://registry.npmmirror.com"
public-hoist-pattern[]=husky
public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier

View File

@@ -10,10 +10,6 @@
"esbenp.prettier-vscode",
// 支持 dotenv 文件语法
"mikestead.dotenv",
// 获取每个 CSS 属性的初始值。
"dzhavat.css-initial-value",
// 使 VSCode 中的 TypeScript 错误更漂亮、更易于理解
"yoavbls.pretty-ts-errors",
// 源代码的拼写检查器
"streetsidesoftware.code-spell-checker",
// Tailwind CSS 的官方 VS Code 插件

15
.vscode/launch.json vendored
View File

@@ -4,18 +4,27 @@
"configurations": [
{
"type": "chrome",
"name": "vben admin antd dev",
"name": "vben admin playground dev",
"request": "launch",
"url": "http://localhost:5555",
"env": { "NODE_ENV": "development" },
"sourceMaps": true,
"webRoot": "${workspaceFolder}/playground/src"
},
{
"type": "chrome",
"name": "vben admin antd dev",
"request": "launch",
"url": "http://localhost:5666",
"env": { "NODE_ENV": "development" },
"sourceMaps": true,
"webRoot": "${workspaceFolder}/apps/web-antd/src"
},
{
"type": "chrome",
"name": "vben admin ele dev",
"request": "launch",
"url": "http://localhost:5666",
"url": "http://localhost:5777",
"env": { "NODE_ENV": "development" },
"sourceMaps": true,
"webRoot": "${workspaceFolder}/apps/web-ele/src"
@@ -24,7 +33,7 @@
"type": "chrome",
"name": "vben admin naive dev",
"request": "launch",
"url": "http://localhost:5777",
"url": "http://localhost:5888",
"env": { "NODE_ENV": "development" },
"sourceMaps": true,
"webRoot": "${workspaceFolder}/apps/web-naive/src"

37
.vscode/settings.json vendored
View File

@@ -14,7 +14,6 @@
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.cursorBlinking": "expand",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.largeFileOptimizations": false,
"editor.accessibilitySupport": "off",
"editor.cursorSmoothCaretAnimation": "on",
@@ -37,7 +36,34 @@
"source.fixAll.stylelint": "explicit",
"source.organizeImports": "never"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// extensions
"extensions.ignoreRecommendations": true,
@@ -56,7 +82,8 @@
"*.ejs": "html",
"*.art": "html",
"**/tsconfig.json": "jsonc",
"*.json": "jsonc"
"*.json": "jsonc",
"package.json": "json"
},
"files.exclude": {
@@ -167,8 +194,10 @@
"i18n-ally.localesPaths": [
"packages/locales/src/langs",
"playground/src/locales/langs",
"apps/*/src/locales/langs"
],
"i18n-ally.pathMatcher": "{locale}.json",
"i18n-ally.enabledParsers": ["json", "ts", "js", "yaml"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
@@ -183,7 +212,7 @@
"*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
"Dockerfile": "Dockerfile,.docker*,docker-entrypoint.sh,build-local-docker*",
"Dockerfile": "Dockerfile,.docker*,docker-entrypoint.sh,build-local-docker*,nginx.conf",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,.ls-lint*,cspell.json",
"tailwind.config.mjs": "postcss.*"
},

View File

@@ -21,9 +21,9 @@ RUN echo "Builder Success 🎉"
FROM nginx:stable-alpine as production
RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf
COPY --from=builder /app/apps/web-antd/dist /usr/share/nginx/html
COPY --from=builder /app/playground/dist /usr/share/nginx/html
COPY ./deploy/nginx.conf /etc/nginx/nginx.conf
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 8080

View File

@@ -1,10 +1,12 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp"> </a> <br> <br>
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
**日本語** | [English](./README.md) | [中文](./README.zh-CN.md)
## 紹介
@@ -78,7 +80,7 @@ pnpm build
## 変更ログ
[CHANGELOG](./CHANGELOG.zh_CN.md)
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## 貢献方法
@@ -127,14 +129,15 @@ pnpm build
このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.5/source/sponsor.png)
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## 貢献者
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img src="https://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord

View File

@@ -1,10 +1,12 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp"> </a> <br> <br>
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
**English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md)
## Introduction
@@ -77,7 +79,7 @@ pnpm build
## Change Log
[CHANGELOG](./CHANGELOG.zh_CN.md)
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## How to contribute
@@ -126,14 +128,15 @@ Support modern browsers, not IE
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.5/source/sponsor.png)
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## Contributor
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img src="https://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord

View File

@@ -1,10 +1,12 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp"> </a> <br> <br>
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
**中文** | [English](./README.md) | [日本語](./README.ja-JP.md)
## 简介
@@ -122,10 +124,21 @@ pnpm build
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.5/source/sponsor.png)
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## 更新日志
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## Contributor
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)

View File

@@ -1 +1,3 @@
PORT=5320
ACCESS_TOKEN_SECRET=access_token_secret
REFRESH_TOKEN_SECRET=refresh_token_secret

View File

@@ -2,7 +2,7 @@
## Description
Vben Admin 数据 mock 服务,没有对接任何的数据库,所有数据都是模拟的,用于前端开发时提供数据支持。由于 sqlite 安装需要在本地进行编译,所以这里接口是直接返回的。线上环境不再提供mock集成可自行部署服务或者对接真实数据同步 mock.js等工具有一些限制比如上传文件不行、无法模拟复杂的逻辑等所以这里使用了 真是的后端服务来实现。唯一麻烦的是本地需要同时启动后端服务和前端服务,但是这样可以更好的模拟真实环境。
Vben Admin 数据 mock 服务,没有对接任何的数据库,所有数据都是模拟的,用于前端开发时提供数据支持。线上环境不再提供 mock 集成,可自行部署服务或者对接真实数据,由于 `mock.js` 等工具有一些限制,比如上传文件不行、无法模拟复杂的逻辑等,所以这里使用了真实的后端服务来实现。唯一麻烦的是本地需要同时启动后端服务和前端服务,但是这样可以更好的模拟真实环境。该服务不需要手动启动,已经集成在 vite 插件内,随应用一起启用。
## Running the app

View File

@@ -1,15 +1,14 @@
export default eventHandler((event) => {
const token = getHeader(event, 'Authorization');
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
if (!token) {
setResponseStatus(event, 401);
return useResponseError('UnauthorizedException', 'Unauthorized Exception');
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const username = Buffer.from(token, 'base64').toString('utf8');
const codes =
MOCK_CODES.find((item) => item.username === username)?.codes ?? [];
MOCK_CODES.find((item) => item.username === userinfo.username)?.codes ?? [];
return useResponseSuccess(codes);
});

View File

@@ -1,20 +1,36 @@
import {
clearRefreshTokenCookie,
setRefreshTokenCookie,
} from '~/utils/cookie-utils';
import { generateAccessToken, generateRefreshToken } from '~/utils/jwt-utils';
import { forbiddenResponse } from '~/utils/response';
export default defineEventHandler(async (event) => {
const { password, username } = await readBody(event);
if (!password || !username) {
setResponseStatus(event, 400);
return useResponseError(
'BadRequestException',
'Username and password are required',
);
}
const findUser = MOCK_USERS.find(
(item) => item.username === username && item.password === password,
);
if (!findUser) {
setResponseStatus(event, 403);
return useResponseError('UnauthorizedException', '用户名或密码错误');
clearRefreshTokenCookie(event);
return forbiddenResponse(event);
}
const accessToken = Buffer.from(username).toString('base64');
const accessToken = generateAccessToken(findUser);
const refreshToken = generateRefreshToken(findUser);
setRefreshTokenCookie(event, refreshToken);
return useResponseSuccess({
...findUser,
accessToken,
// TODO: refresh token
refreshToken: accessToken,
});
});

View File

@@ -0,0 +1,15 @@
import {
clearRefreshTokenCookie,
getRefreshTokenFromCookie,
} from '~/utils/cookie-utils';
export default defineEventHandler(async (event) => {
const refreshToken = getRefreshTokenFromCookie(event);
if (!refreshToken) {
return useResponseSuccess('');
}
clearRefreshTokenCookie(event);
return useResponseSuccess('');
});

View File

@@ -0,0 +1,33 @@
import {
clearRefreshTokenCookie,
getRefreshTokenFromCookie,
setRefreshTokenCookie,
} from '~/utils/cookie-utils';
import { verifyRefreshToken } from '~/utils/jwt-utils';
import { forbiddenResponse } from '~/utils/response';
export default defineEventHandler(async (event) => {
const refreshToken = getRefreshTokenFromCookie(event);
if (!refreshToken) {
return forbiddenResponse(event);
}
clearRefreshTokenCookie(event);
const userinfo = verifyRefreshToken(refreshToken);
if (!userinfo) {
return forbiddenResponse(event);
}
const findUser = MOCK_USERS.find(
(item) => item.username === userinfo.username,
);
if (!findUser) {
return forbiddenResponse(event);
}
const accessToken = generateAccessToken(findUser);
setRefreshTokenCookie(event, refreshToken);
return accessToken;
});

View File

@@ -1,14 +1,13 @@
export default eventHandler((event) => {
const token = getHeader(event, 'Authorization');
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
if (!token) {
setResponseStatus(event, 401);
return useResponseError('UnauthorizedException', 'Unauthorized Exception');
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const username = Buffer.from(token, 'base64').toString('utf8');
const menus =
MOCK_MENUS.find((item) => item.username === username)?.menus ?? [];
MOCK_MENUS.find((item) => item.username === userinfo.username)?.menus ?? [];
return useResponseSuccess(menus);
});

View File

@@ -1,14 +1,11 @@
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
export default eventHandler((event) => {
const token = getHeader(event, 'Authorization');
if (!token) {
setResponseStatus(event, 401);
return useResponseError('UnauthorizedException', 'Unauthorized Exception');
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const username = Buffer.from(token, 'base64').toString('utf8');
const user = MOCK_USERS.find((item) => item.username === username);
const { password: _pwd, ...userInfo } = user;
return useResponseSuccess(userInfo);
return useResponseSuccess(userinfo);
});

View File

@@ -1,7 +1,7 @@
import type { NitroErrorHandler } from 'nitropack';
const errorHandler: NitroErrorHandler = function (error, event) {
event.res.end(`[error handler] ${error.stack}`);
event.node.res.end(`[Error Handler] ${error.stack}`);
};
export default errorHandler;

View File

@@ -1,11 +1,4 @@
export default defineEventHandler((event) => {
// setResponseHeaders(event, {
// 'Access-Control-Allow-Credentials': 'true',
// 'Access-Control-Allow-Headers': '*',
// 'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
// 'Access-Control-Allow-Origin': '*',
// 'Access-Control-Expose-Headers': '*',
// });
if (event.method === 'OPTIONS') {
event.node.res.statusCode = 204;
event.node.res.statusMessage = 'No Content.';

View File

@@ -6,10 +6,15 @@
"license": "MIT",
"author": "",
"scripts": {
"start": "nitro dev",
"build": "nitro build"
"build": "nitro build",
"start": "nitro dev"
},
"dependencies": {
"jsonwebtoken": "^9.0.2",
"nitropack": "^2.9.7"
},
"devDependencies": {
"@types/jsonwebtoken": "^9.0.6",
"h3": "^1.12.0"
}
}

View File

@@ -0,0 +1,26 @@
import type { EventHandlerRequest, H3Event } from 'h3';
export function clearRefreshTokenCookie(event: H3Event<EventHandlerRequest>) {
deleteCookie(event, 'jwt', {
httpOnly: true,
sameSite: 'none',
secure: true,
});
}
export function setRefreshTokenCookie(
event: H3Event<EventHandlerRequest>,
refreshToken: string,
) {
setCookie(event, 'jwt', refreshToken, {
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
sameSite: 'none',
secure: true,
});
}
export function getRefreshTokenFromCookie(event: H3Event<EventHandlerRequest>) {
const refreshToken = getCookie(event, 'jwt');
return refreshToken;
}

View File

@@ -0,0 +1,59 @@
import type { EventHandlerRequest, H3Event } from 'h3';
import jwt from 'jsonwebtoken';
import { UserInfo } from './mock-data';
// TODO: Replace with your own secret key
const ACCESS_TOKEN_SECRET = 'access_token_secret';
const REFRESH_TOKEN_SECRET = 'refresh_token_secret';
export interface UserPayload extends UserInfo {
iat: number;
exp: number;
}
export function generateAccessToken(user: UserInfo) {
return jwt.sign(user, ACCESS_TOKEN_SECRET, { expiresIn: '7d' });
}
export function generateRefreshToken(user: UserInfo) {
return jwt.sign(user, REFRESH_TOKEN_SECRET, {
expiresIn: '30d',
});
}
export function verifyAccessToken(
event: H3Event<EventHandlerRequest>,
): null | Omit<UserInfo, 'password'> {
const authHeader = getHeader(event, 'Authorization');
if (!authHeader?.startsWith('Bearer')) {
return null;
}
const token = authHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, ACCESS_TOKEN_SECRET) as UserPayload;
const username = decoded.username;
const user = MOCK_USERS.find((item) => item.username === username);
const { password: _pwd, ...userinfo } = user;
return userinfo;
} catch {
return null;
}
}
export function verifyRefreshToken(
token: string,
): null | Omit<UserInfo, 'password'> {
try {
const decoded = jwt.verify(token, REFRESH_TOKEN_SECRET) as UserPayload;
const username = decoded.username;
const user = MOCK_USERS.find((item) => item.username === username);
const { password: _pwd, ...userinfo } = user;
return userinfo;
} catch {
return null;
}
}

View File

@@ -1,4 +1,12 @@
export const MOCK_USERS = [
export interface UserInfo {
id: number;
password: string;
realName: string;
roles: string[];
username: string;
}
export const MOCK_USERS: UserInfo[] = [
{
id: 0,
password: '123456',

View File

@@ -1,3 +1,5 @@
import type { EventHandlerRequest, H3Event } from 'h3';
export function useResponseSuccess<T = any>(data: T) {
return {
code: 0,
@@ -15,3 +17,13 @@ export function useResponseError(message: string, error: any = null) {
message,
};
}
export function forbiddenResponse(event: H3Event<EventHandlerRequest>) {
setResponseStatus(event, 403);
return useResponseError('ForbiddenException', 'Forbidden Exception');
}
export function unAuthorizedResponse(event: H3Event<EventHandlerRequest>) {
setResponseStatus(event, 401);
return useResponseError('UnauthorizedException', 'Unauthorized Exception');
}

View File

@@ -1,5 +1,5 @@
# 应用标题
VITE_APP_TITLE=Vben Admin
VITE_APP_TITLE=Vben Admin Antd
# 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=vben-web-antd

View File

@@ -1,5 +1,5 @@
# 端口号
VITE_PORT=5555
VITE_PORT=5666
VITE_BASE=/

View File

@@ -14,3 +14,6 @@ VITE_ROUTER_HISTORY=hash
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true

View File

@@ -21,7 +21,7 @@
(function () {
var hm = document.createElement('script');
hm.src =
'https://hm.baidu.com/hm.js?d20a01273820422b6aa2ee41b6c9414d';
'https://hm.baidu.com/hm.js?b38e689f40558f20a9a686d7f6f33edf';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/web-antd",
"version": "5.0.1",
"version": "5.2.0",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -27,24 +27,24 @@
},
"dependencies": {
"@vben/access": "workspace:*",
"@vben/chart-ui": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/constants": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/plugins": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/request": "workspace:*",
"@vben/stores": "workspace:*",
"@vben/styles": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "^10.11.0",
"@vueuse/core": "^11.0.3",
"ant-design-vue": "^4.2.3",
"dayjs": "^1.11.12",
"pinia": "2.2.0",
"vue": "^3.4.36",
"dayjs": "^1.11.13",
"pinia": "2.2.2",
"vue": "^3.4.38",
"vue-router": "^4.4.3"
}
}

View File

@@ -1,4 +1,4 @@
import { requestClient } from '#/api/request';
import { baseRequestClient, requestClient } from '#/api/request';
export namespace AuthApi {
/** 登录接口参数 */
@@ -12,10 +12,14 @@ export namespace AuthApi {
accessToken: string;
desc: string;
realName: string;
refreshToken: string;
userId: string;
username: string;
}
export interface RefreshTokenResult {
data: string;
status: number;
}
}
/**
@@ -25,6 +29,24 @@ export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/**
* 刷新accessToken
*/
export async function refreshTokenApi() {
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
withCredentials: true,
});
}
/**
* 退出登录
*/
export async function logoutApi() {
return baseRequestClient.post('/auth/logout', {
withCredentials: true,
});
}
/**
* 获取用户权限码
*/

View File

@@ -1,2 +1 @@
export * from './core';
export * from './demos';

View File

@@ -1,67 +1,104 @@
/**
* 该文件可自行根据业务逻辑进行调整
*/
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import { RequestClient } from '@vben/request';
import {
authenticateResponseInterceptor,
errorMessageResponseInterceptor,
RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';
import { message } from 'ant-design-vue';
import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core';
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
function createRequestClient(baseURL: string) {
const client = new RequestClient({
baseURL,
// 为每个请求携带 Authorization
makeAuthorization: () => {
return {
// 默认
key: 'Authorization',
tokenHandler: () => {
const accessStore = useAccessStore();
return {
refreshToken: `${accessStore.refreshToken}`,
token: `${accessStore.accessToken}`,
};
},
unAuthorizedHandler: async () => {
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (preferences.app.loginExpiredMode === 'modal') {
accessStore.setLoginExpired(true);
} else {
// 退出登录
await authStore.logout();
}
},
};
},
makeErrorMessage: (msg) => message.error(msg),
makeRequestHeaders: () => {
return {
// 为每个请求携带 Accept-Language
'Accept-Language': preferences.app.locale,
};
},
});
client.addResponseInterceptor<HttpResponse>((response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
/**
* 重新认证逻辑
*/
async function doReAuthenticate() {
console.warn('Access token or refresh token is invalid or expired. ');
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (
preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked
) {
accessStore.setLoginExpired(true);
} else {
await authStore.logout();
}
throw new Error(msg);
}
/**
* 刷新token逻辑
*/
async function doRefreshToken() {
const accessStore = useAccessStore();
const resp = await refreshTokenApi();
const newToken = resp.data;
accessStore.setAccessToken(newToken);
return newToken;
}
function formatToken(token: null | string) {
return token ? `Bearer ${token}` : null;
}
// 请求头处理
client.addRequestInterceptor({
fulfilled: async (config) => {
const accessStore = useAccessStore();
config.headers.Authorization = formatToken(accessStore.accessToken);
config.headers['Accept-Language'] = preferences.app.locale;
return config;
},
});
// response数据解构
client.addResponseInterceptor({
fulfilled: (response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
}
throw new Error(`Error ${status}: ${msg}`);
},
});
// token过期的处理
client.addResponseInterceptor(
authenticateResponseInterceptor({
client,
doReAuthenticate,
doRefreshToken,
enableRefreshToken: preferences.app.enableRefreshToken,
formatToken,
}),
);
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)),
);
return client;
}
export const requestClient = createRequestClient(apiURL);
export const baseRequestClient = new RequestClient({ baseURL: apiURL });

View File

@@ -2,10 +2,9 @@
import type { NotificationItem } from '@vben/layouts';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
import { LOGIN_PATH, VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
import {
BasicLayout,
@@ -14,16 +13,10 @@ import {
UserDropdown,
} from '@vben/layouts';
import { preferences } from '@vben/preferences';
import {
resetAllStores,
storeToRefs,
useAccessStore,
useUserStore,
} from '@vben/stores';
import { storeToRefs, useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
import { $t } from '#/locales';
import { resetRoutes } from '#/router';
import { useAuthStore } from '#/store';
const notifications = ref<NotificationItem[]>([
@@ -100,12 +93,8 @@ const avatar = computed(() => {
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
});
const router = useRouter();
async function handleLogout() {
resetAllStores();
resetRoutes();
await router.replace(LOGIN_PATH);
await authStore.logout(false);
}
function handleNoticeClear() {

View File

@@ -58,7 +58,11 @@ async function loadDayjsLocale(lang: SupportedLanguagesType) {
locale = await import('dayjs/locale/en');
}
}
dayjs.locale(locale);
if (locale) {
dayjs.locale(locale);
} else {
console.error(`Failed to load dayjs locale for ${lang}`);
}
}
/**
@@ -87,4 +91,4 @@ async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
});
}
export { $t, antdLocale, loadMessages, setupI18n };
export { $t, antdLocale, setupI18n };

View File

@@ -2,58 +2,7 @@
"page": {
"demos": {
"title": "Demos",
"access": {
"frontendPermissions": "Frontend Permissions",
"backendPermissions": "Backend Permissions",
"pageAccess": "Page Access",
"buttonControl": "Button Control",
"menuVisible403": "Menu Visible(403)",
"superVisible": "Visible to Super",
"adminVisible": "Visible to Admin",
"userVisible": "Visible to User"
},
"nested": {
"title": "Nested Menu",
"menu1": "Menu 1",
"menu2": "Menu 2",
"menu2_1": "Menu 2-1",
"menu3": "Menu 3",
"menu3_1": "Menu 3-1",
"menu3_2": "Menu 3-2",
"menu3_2_1": "Menu 3-2-1"
},
"outside": {
"title": "External Pages",
"embedded": "Embedded",
"externalLink": "External Link"
},
"badge": {
"title": "Menu Badge",
"dot": "Dot Badge",
"text": "Text Badge",
"color": "Badge Color"
},
"activeIcon": {
"title": "Active Menu Icon",
"children": "Children Active Icon"
},
"fallback": { "title": "Fallback Page" },
"features": {
"title": "Features",
"hideChildrenInMenu": "Hide Menu Children",
"loginExpired": "Login Expired",
"icons": "Icons",
"watermark": "Watermark",
"tabs": "Tabs",
"tabDetail": "Tab Detail Page"
},
"breadcrumb": {
"navigation": "Breadcrumb Navigation",
"lateral": "Lateral Mode",
"lateralDetail": "Lateral Mode Detail",
"level": "Level Mode",
"levelDetail": "Level Mode Detail"
}
"antd": "Ant Design Vue"
}
}
}

View File

@@ -2,60 +2,7 @@
"page": {
"demos": {
"title": "演示",
"access": {
"frontendPermissions": "前端权限",
"backendPermissions": "后端权限",
"pageAccess": "页面访问",
"buttonControl": "按钮控制",
"menuVisible403": "菜单可见(403)",
"superVisible": "Super 可见",
"adminVisible": "Admin 可见",
"userVisible": "User 可见"
},
"nested": {
"title": "嵌套菜单",
"menu1": "菜单 1",
"menu2": "菜单 2",
"menu2_1": "菜单 2-1",
"menu3": "菜单 3",
"menu3_1": "菜单 3-1",
"menu3_2": "菜单 3-2",
"menu3_2_1": "菜单 3-2-1"
},
"outside": {
"title": "外部页面",
"embedded": "内嵌",
"externalLink": "外链"
},
"badge": {
"title": "菜单徽标",
"dot": "点徽标",
"text": "文本徽标",
"color": "徽标颜色"
},
"activeIcon": {
"title": "菜单激活图标",
"children": "子级激活图标"
},
"fallback": {
"title": "缺省页"
},
"features": {
"title": "功能",
"hideChildrenInMenu": "隐藏子菜单",
"loginExpired": "登录过期",
"icons": "图标",
"watermark": "水印",
"tabs": "标签页",
"tabDetail": "标签详情页"
},
"breadcrumb": {
"navigation": "面包屑导航",
"lateral": "平级模式",
"level": "层级模式",
"levelDetail": "层级模式详情",
"lateralDetail": "平级模式详情"
}
"antd": "Ant Design Vue"
}
}
}

View File

@@ -92,10 +92,8 @@ function setupAccessGuard(router: Router) {
return to;
}
const accessRoutes = accessStore.accessRoutes;
// 是否已经生成过动态路由
if (accessRoutes && accessRoutes.length > 0) {
if (accessStore.isAccessChecked) {
return true;
}
@@ -115,10 +113,11 @@ function setupAccessGuard(router: Router) {
// 保存菜单信息和路由信息
accessStore.setAccessMenus(accessibleMenus);
accessStore.setAccessRoutes(accessibleRoutes);
const redirectPath = (from.query.redirect ?? to.path) as string;
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ?? to.fullPath) as string;
return {
path: decodeURIComponent(redirectPath),
...router.resolve(decodeURIComponent(redirectPath)),
replace: true,
};
});

View File

@@ -9,19 +9,19 @@ const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
});
// 有需要可以自行打开注释,并创建文件夹
// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
/** 动态路由 */
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
/** 静态路由列表,访问这些页面可以不需要权限 */
// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
const staticRoutes: RouteRecordRaw[] = [];
/** 外部路由列表,访问这些页面可以不需要Layout可能用于内嵌在别的系统 */
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
const externalRoutes: RouteRecordRaw[] = [];
/** 路由列表,由基本路由+静态路由组成 */
const routes: RouteRecordRaw[] = [
...coreRoutes,
...staticRoutes,
...externalRoutes,
fallbackNotFoundRoute,
];

View File

@@ -1,6 +1,6 @@
import type { RouteRecordRaw } from 'vue-router';
import { BasicLayout, IFrameView } from '#/layouts';
import { BasicLayout } from '#/layouts';
import { $t } from '#/locales';
const routes: RouteRecordRaw[] = [
@@ -15,477 +15,13 @@ const routes: RouteRecordRaw[] = [
name: 'Demos',
path: '/demos',
children: [
// 权限控制
{
meta: {
icon: 'mdi:shield-key-outline',
title: $t('page.demos.access.frontendPermissions'),
title: $t('page.demos.antd'),
},
name: 'AccessDemos',
path: '/demos/access',
children: [
{
name: 'AccessPageControlDemo',
path: '/demos/access/page-control',
component: () => import('#/views/demos/access/index.vue'),
meta: {
icon: 'mdi:page-previous-outline',
title: $t('page.demos.access.pageAccess'),
},
},
{
name: 'AccessButtonControlDemo',
path: '/demos/access/button-control',
component: () => import('#/views/demos/access/button-control.vue'),
meta: {
icon: 'mdi:button-cursor',
title: $t('page.demos.access.buttonControl'),
},
},
{
name: 'AccessMenuVisible403Demo',
path: '/demos/access/menu-visible-403',
component: () =>
import('#/views/demos/access/menu-visible-403.vue'),
meta: {
authority: ['no-body'],
icon: 'mdi:button-cursor',
menuVisibleWithForbidden: true,
title: $t('page.demos.access.menuVisible403'),
},
},
{
name: 'AccessSuperVisibleDemo',
path: '/demos/access/super-visible',
component: () => import('#/views/demos/access/super-visible.vue'),
meta: {
authority: ['super'],
icon: 'mdi:button-cursor',
title: $t('page.demos.access.superVisible'),
},
},
{
name: 'AccessAdminVisibleDemo',
path: '/demos/access/admin-visible',
component: () => import('#/views/demos/access/admin-visible.vue'),
meta: {
authority: ['admin'],
icon: 'mdi:button-cursor',
title: $t('page.demos.access.adminVisible'),
},
},
{
name: 'AccessUserVisibleDemo',
path: '/demos/access/user-visible',
component: () => import('#/views/demos/access/user-visible.vue'),
meta: {
authority: ['user'],
icon: 'mdi:button-cursor',
title: $t('page.demos.access.userVisible'),
},
},
],
},
// 功能
{
meta: {
icon: 'mdi:feature-highlight',
title: $t('page.demos.features.title'),
},
name: 'FeaturesDemos',
path: '/demos/features',
children: [
{
name: 'LoginExpiredDemo',
path: '/demos/features/login-expired',
component: () =>
import('#/views/demos/features/login-expired/index.vue'),
meta: {
icon: 'mdi:encryption-expiration',
title: $t('page.demos.features.loginExpired'),
},
},
{
name: 'IconsDemo',
path: '/demos/features/icons',
component: () => import('#/views/demos/features/icons/index.vue'),
meta: {
title: $t('page.demos.features.icons'),
},
},
{
name: 'WatermarkDemo',
path: '/demos/features/watermark',
component: () =>
import('#/views/demos/features/watermark/index.vue'),
meta: {
title: $t('page.demos.features.watermark'),
},
},
{
name: 'FeatureTabsDemo',
path: '/demos/features/tabs',
component: () => import('#/views/demos/features/tabs/index.vue'),
meta: {
icon: 'lucide:app-window',
title: $t('page.demos.features.tabs'),
},
},
{
name: 'FeatureTabDetailDemo',
path: '/demos/features/tabs/detail/:id',
component: () =>
import('#/views/demos/features/tabs/tab-detail.vue'),
meta: {
activePath: '/demos/features/tabs',
hideInMenu: true,
maxNumOfOpenTab: 3,
title: $t('page.demos.features.tabDetail'),
},
},
{
name: 'HideChildrenInMenuParentDemo',
path: '/demos/features/hide-menu-children',
component: () =>
import('#/views/demos/features/hide-menu-children/parent.vue'),
meta: {
hideChildrenInMenu: true,
icon: 'ic:round-menu',
title: $t('page.demos.features.hideChildrenInMenu'),
},
children: [
{
name: 'HideChildrenInMenuChildrenDemo',
path: '/demos/features/hide-menu-children/children',
component: () =>
import(
'#/views/demos/features/hide-menu-children/children.vue'
),
meta: { title: 'HideChildrenInMenuChildrenDemo' },
},
],
},
],
},
// 面包屑导航
{
name: 'BreadcrumbDemos',
path: '/demos/breadcrumb',
meta: {
icon: 'lucide:navigation',
title: $t('page.demos.breadcrumb.navigation'),
},
children: [
{
name: 'BreadcrumbLateralDemo',
path: '/demos/breadcrumb/lateral',
component: () => import('#/views/demos/breadcrumb/lateral.vue'),
meta: {
icon: 'lucide:navigation',
title: $t('page.demos.breadcrumb.lateral'),
},
},
{
name: 'BreadcrumbLateralDetailDemo',
path: '/demos/breadcrumb/lateral-detail',
component: () =>
import('#/views/demos/breadcrumb/lateral-detail.vue'),
meta: {
activePath: '/demos/breadcrumb/lateral',
hideInMenu: true,
title: $t('page.demos.breadcrumb.lateralDetail'),
},
},
{
name: 'BreadcrumbLevelDemo',
path: '/demos/breadcrumb/level',
meta: {
icon: 'lucide:navigation',
title: $t('page.demos.breadcrumb.level'),
},
children: [
{
name: 'BreadcrumbLevelDetailDemo',
path: '/demos/breadcrumb/level/detail',
component: () =>
import('#/views/demos/breadcrumb/level-detail.vue'),
meta: {
title: $t('page.demos.breadcrumb.levelDetail'),
},
},
],
},
],
},
// 缺省页
{
meta: {
icon: 'mdi:lightbulb-error-outline',
title: $t('page.demos.fallback.title'),
},
name: 'FallbackDemos',
path: '/demos/fallback',
children: [
{
name: 'Fallback403Demo',
path: '/demos/fallback/403',
component: () => import('#/views/_core/fallback/forbidden.vue'),
meta: {
icon: 'mdi:do-not-disturb-alt',
title: '403',
},
},
{
name: 'Fallback404Demo',
path: '/demos/fallback/404',
component: () => import('#/views/_core/fallback/not-found.vue'),
meta: {
icon: 'mdi:table-off',
title: '404',
},
},
{
name: 'Fallback500Demo',
path: '/demos/fallback/500',
component: () =>
import('#/views/_core/fallback/internal-error.vue'),
meta: {
icon: 'mdi:server-network-off',
title: '500',
},
},
{
name: 'FallbackOfflineDemo',
path: '/demos/fallback/offline',
component: () => import('#/views/_core/fallback/offline.vue'),
meta: {
icon: 'mdi:offline',
title: $t('fallback.offline'),
},
},
],
},
// 菜单徽标
{
meta: {
badgeType: 'dot',
badgeVariants: 'destructive',
icon: 'lucide:circle-dot',
title: $t('page.demos.badge.title'),
},
name: 'BadgeDemos',
path: '/demos/badge',
children: [
{
name: 'BadgeDotDemo',
component: () => import('#/views/demos/badge/index.vue'),
path: '/demos/badge/dot',
meta: {
badgeType: 'dot',
icon: 'lucide:square-dot',
title: $t('page.demos.badge.dot'),
},
},
{
name: 'BadgeTextDemo',
component: () => import('#/views/demos/badge/index.vue'),
path: '/demos/badge/text',
meta: {
badge: '10',
icon: 'lucide:square-dot',
title: $t('page.demos.badge.text'),
},
},
{
name: 'BadgeColorDemo',
component: () => import('#/views/demos/badge/index.vue'),
path: '/demos/badge/color',
meta: {
badge: 'Hot',
badgeVariants: 'destructive',
icon: 'lucide:square-dot',
title: $t('page.demos.badge.color'),
},
},
],
},
// 菜单激活图标
{
meta: {
activeIcon: 'fluent-emoji:radioactive',
icon: 'bi:radioactive',
title: $t('page.demos.activeIcon.title'),
},
name: 'ActiveIconDemos',
path: '/demos/active-icon',
children: [
{
name: 'ActiveIconDemo',
component: () => import('#/views/demos/active-icon/index.vue'),
path: '/demos/active-icon/children',
meta: {
activeIcon: 'fluent-emoji:radioactive',
icon: 'bi:radioactive',
title: $t('page.demos.activeIcon.children'),
},
},
],
},
// 外部链接
{
meta: {
icon: 'ic:round-settings-input-composite',
title: $t('page.demos.outside.title'),
},
name: 'OutsideDemos',
path: '/demos/outside',
children: [
{
name: 'IframeDemos',
path: '/demos/outside/iframe',
meta: {
icon: 'mdi:newspaper-variant-outline',
title: $t('page.demos.outside.embedded'),
},
children: [
{
name: 'VueDocumentDemo',
path: '/demos/outside/iframe/vue-document',
component: IFrameView,
meta: {
icon: 'logos:vue',
iframeSrc: 'https://cn.vuejs.org/',
keepAlive: true,
title: 'Vue',
},
},
{
name: 'TailwindcssDemo',
path: '/demos/outside/iframe/tailwindcss',
component: IFrameView,
meta: {
icon: 'devicon:tailwindcss',
iframeSrc: 'https://tailwindcss.com/',
// keepAlive: true,
title: 'Tailwindcss',
},
},
],
},
{
name: 'ExternalLinkDemos',
path: '/demos/outside/external-link',
meta: {
icon: 'mdi:newspaper-variant-multiple-outline',
title: $t('page.demos.outside.externalLink'),
},
children: [
{
name: 'ViteDemo',
path: '/demos/outside/external-link/vite',
component: IFrameView,
meta: {
icon: 'logos:vitejs',
link: 'https://vitejs.dev/',
title: 'Vite',
},
},
{
name: 'VueUseDemo',
path: '/demos/outside/external-link/vue-use',
component: IFrameView,
meta: {
icon: 'logos:vueuse',
link: 'https://vueuse.org',
title: 'VueUse',
},
},
],
},
],
},
// 嵌套菜单
{
meta: {
icon: 'ic:round-menu',
title: $t('page.demos.nested.title'),
},
name: 'NestedDemos',
path: '/demos/nested',
children: [
{
name: 'Menu1Demo',
path: '/demos/nested/menu1',
component: () => import('#/views/demos/nested/menu-1.vue'),
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu1'),
},
},
{
name: 'Menu2Demo',
path: '/demos/nested/menu2',
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu2'),
},
children: [
{
name: 'Menu21Demo',
path: '/demos/nested/menu2/menu2-1',
component: () => import('#/views/demos/nested/menu-2-1.vue'),
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu2_1'),
},
},
],
},
{
name: 'Menu3Demo',
path: '/demos/nested/menu3',
meta: {
icon: 'ic:round-menu',
title: $t('page.demos.nested.menu3'),
},
children: [
{
name: 'Menu31Demo',
path: 'menu3-1',
component: () => import('#/views/demos/nested/menu-3-1.vue'),
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu3_1'),
},
},
{
name: 'Menu32Demo',
path: 'menu3-2',
meta: {
icon: 'ic:round-menu',
title: $t('page.demos.nested.menu3_2'),
},
children: [
{
name: 'Menu321Demo',
path: '/demos/nested/menu3/menu3-2/menu3-2-1',
component: () =>
import('#/views/demos/nested/menu-3-2-1.vue'),
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu3_2_1'),
},
},
],
},
],
},
],
name: 'AntDesignDemos',
path: '/demos/ant-design',
component: () => import('#/views/demos/antd/index.vue'),
},
],
},

View File

@@ -26,7 +26,7 @@ const routes: RouteRecordRaw[] = [
{
name: 'VbenAbout',
path: '/vben-admin/about',
component: () => import('#/views/_core/vben/about/index.vue'),
component: () => import('#/views/_core/about/index.vue'),
meta: {
icon: 'lucide:copyright',
title: $t('page.vben.about'),
@@ -38,8 +38,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'lucide:book-open-text',
iframeSrc: VBEN_DOC_URL,
keepAlive: true,
link: VBEN_DOC_URL,
title: $t('page.vben.document'),
},
},

View File

@@ -10,7 +10,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { notification } from 'ant-design-vue';
import { defineStore } from 'pinia';
import { getAccessCodesApi, getUserInfoApi, loginApi } from '#/api';
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => {
@@ -33,13 +33,11 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { accessToken, refreshToken } = await loginApi(params);
const { accessToken } = await loginApi(params);
// 如果成功获取到 accessToken
if (accessToken) {
// 将 accessToken 存储到 accessStore 中
accessStore.setAccessToken(accessToken);
accessStore.setRefreshToken(refreshToken);
// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
@@ -77,16 +75,19 @@ export const useAuthStore = defineStore('auth', () => {
};
}
async function logout() {
async function logout(redirect: boolean = true) {
await logoutApi();
resetAllStores();
accessStore.setLoginExpired(false);
// 回登陆页带上当前路由地址
await router.replace({
path: LOGIN_PATH,
query: {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
},
query: redirect
? {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
}
: {},
});
}

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -0,0 +1,66 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import { Button, Card, message, notification, Space } from 'ant-design-vue';
type NotificationType = 'error' | 'info' | 'success' | 'warning';
function info() {
message.info('How many roads must a man walk down');
}
function error() {
message.error({
content: 'Once upon a time you dressed so fine',
duration: 2500,
});
}
function warning() {
message.warning('How many roads must a man walk down');
}
function success() {
message.success('Cause you walked hand in hand With another man in my place');
}
function notify(type: NotificationType) {
notification[type]({
duration: 2500,
message: '说点啥呢',
type,
});
}
</script>
<template>
<Page
description="支持多语言,主题功能集成切换等"
title="Ant Design Vue组件使用演示"
>
<Card title="按钮">
<Space>
<Button>Default</Button>
<Button type="primary"> Primary </Button>
<Button> Info </Button>
<Button danger> Error </Button>
</Space>
</Card>
<Card class="mb-5" title="Message">
<Space>
<Button @click="info"> 信息 </Button>
<Button danger @click="error"> 错误 </Button>
<Button @click="warning"> 警告 </Button>
<Button @click="success"> 成功 </Button>
</Space>
</Card>
<Card class="mb-5" title="Notification">
<Space>
<Button @click="notify('info')"> 信息 </Button>
<Button danger @click="notify('error')"> 错误 </Button>
<Button @click="notify('warning')"> 警告 </Button>
<Button @click="notify('success')"> 成功 </Button>
</Space>
</Card>
</Page>
</template>

View File

@@ -1,5 +1,5 @@
# 端口号
VITE_PORT=5666
VITE_PORT=5777
VITE_BASE=/

View File

@@ -14,3 +14,6 @@ VITE_ROUTER_HISTORY=hash
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/web-ele",
"version": "5.0.1",
"version": "5.2.0",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -27,24 +27,24 @@
},
"dependencies": {
"@vben/access": "workspace:*",
"@vben/chart-ui": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/constants": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/plugins": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/request": "workspace:*",
"@vben/stores": "workspace:*",
"@vben/styles": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "^10.11.0",
"dayjs": "^1.11.12",
"element-plus": "^2.7.8",
"pinia": "2.2.0",
"vue": "^3.4.36",
"@vueuse/core": "^11.0.3",
"dayjs": "^1.11.13",
"element-plus": "^2.8.1",
"pinia": "2.2.2",
"vue": "^3.4.38",
"vue-router": "^4.4.3"
},
"devDependencies": {

View File

@@ -1,4 +1,4 @@
import { requestClient } from '#/api/request';
import { baseRequestClient, requestClient } from '#/api/request';
export namespace AuthApi {
/** 登录接口参数 */
@@ -12,10 +12,14 @@ export namespace AuthApi {
accessToken: string;
desc: string;
realName: string;
refreshToken: string;
userId: string;
username: string;
}
export interface RefreshTokenResult {
data: string;
status: number;
}
}
/**
@@ -25,6 +29,24 @@ export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/**
* 刷新accessToken
*/
export async function refreshTokenApi() {
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
withCredentials: true,
});
}
/**
* 退出登录
*/
export async function logoutApi() {
return baseRequestClient.post('/auth/logout', {
withCredentials: true,
});
}
/**
* 获取用户权限码
*/

View File

@@ -1,67 +1,104 @@
/**
* 该文件可自行根据业务逻辑进行调整
*/
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import { RequestClient } from '@vben/request';
import {
authenticateResponseInterceptor,
errorMessageResponseInterceptor,
RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';
import { ElMessage } from 'element-plus';
import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core';
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
function createRequestClient(baseURL: string) {
const client = new RequestClient({
baseURL,
// 为每个请求携带 Authorization
makeAuthorization: () => {
return {
// 默认
key: 'Authorization',
tokenHandler: () => {
const accessStore = useAccessStore();
return {
refreshToken: `${accessStore.refreshToken}`,
token: `${accessStore.accessToken}`,
};
},
unAuthorizedHandler: async () => {
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (preferences.app.loginExpiredMode === 'modal') {
accessStore.setLoginExpired(true);
} else {
// 退出登录
await authStore.logout();
}
},
};
},
makeErrorMessage: (msg) => ElMessage.error(msg),
makeRequestHeaders: () => {
return {
// 为每个请求携带 Accept-Language
'Accept-Language': preferences.app.locale,
};
},
});
client.addResponseInterceptor<HttpResponse>((response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
/**
* 重新认证逻辑
*/
async function doReAuthenticate() {
console.warn('Access token or refresh token is invalid or expired. ');
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (
preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked
) {
accessStore.setLoginExpired(true);
} else {
await authStore.logout();
}
throw new Error(msg);
}
/**
* 刷新token逻辑
*/
async function doRefreshToken() {
const accessStore = useAccessStore();
const resp = await refreshTokenApi();
const newToken = resp.data;
accessStore.setAccessToken(newToken);
return newToken;
}
function formatToken(token: null | string) {
return token ? `Bearer ${token}` : null;
}
// 请求头处理
client.addRequestInterceptor({
fulfilled: async (config) => {
const accessStore = useAccessStore();
config.headers.Authorization = formatToken(accessStore.accessToken);
config.headers['Accept-Language'] = preferences.app.locale;
return config;
},
});
// response数据解构
client.addResponseInterceptor({
fulfilled: (response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
}
throw new Error(`Error ${status}: ${msg}`);
},
});
// token过期的处理
client.addResponseInterceptor(
authenticateResponseInterceptor({
client,
doReAuthenticate,
doRefreshToken,
enableRefreshToken: preferences.app.enableRefreshToken,
formatToken,
}),
);
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => ElMessage.error(msg)),
);
return client;
}
export const requestClient = createRequestClient(apiURL);
export const baseRequestClient = new RequestClient({ baseURL: apiURL });

View File

@@ -3,6 +3,7 @@ import { createApp } from 'vue';
import { registerAccessDirective } from '@vben/access';
import { initStores } from '@vben/stores';
import '@vben/styles';
import '@vben/styles/ele';
import { setupI18n } from '#/locales';

View File

@@ -2,10 +2,9 @@
import type { NotificationItem } from '@vben/layouts';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
import { LOGIN_PATH, VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
import {
BasicLayout,
@@ -14,16 +13,10 @@ import {
UserDropdown,
} from '@vben/layouts';
import { preferences } from '@vben/preferences';
import {
resetAllStores,
storeToRefs,
useAccessStore,
useUserStore,
} from '@vben/stores';
import { storeToRefs, useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
import { $t } from '#/locales';
import { resetRoutes } from '#/router';
import { useAuthStore } from '#/store';
const notifications = ref<NotificationItem[]>([
@@ -100,12 +93,8 @@ const avatar = computed(() => {
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
});
const router = useRouter();
async function handleLogout() {
resetAllStores();
resetRoutes();
await router.replace(LOGIN_PATH);
await authStore.logout(false);
}
function handleNoticeClear() {

View File

@@ -58,7 +58,11 @@ async function loadDayjsLocale(lang: SupportedLanguagesType) {
locale = await import('dayjs/locale/en');
}
}
dayjs.locale(locale);
if (locale) {
dayjs.locale(locale);
} else {
console.error(`Failed to load dayjs locale for ${lang}`);
}
}
/**
@@ -87,4 +91,4 @@ async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
});
}
export { $t, elementLocale, loadMessages, setupI18n };
export { $t, elementLocale, setupI18n };

View File

@@ -92,10 +92,8 @@ function setupAccessGuard(router: Router) {
return to;
}
const accessRoutes = accessStore.accessRoutes;
// 是否已经生成过动态路由
if (accessRoutes && accessRoutes.length > 0) {
if (accessStore.isAccessChecked) {
return true;
}
@@ -115,10 +113,11 @@ function setupAccessGuard(router: Router) {
// 保存菜单信息和路由信息
accessStore.setAccessMenus(accessibleMenus);
accessStore.setAccessRoutes(accessibleRoutes);
const redirectPath = (from.query.redirect ?? to.path) as string;
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ?? to.fullPath) as string;
return {
path: decodeURIComponent(redirectPath),
...router.resolve(decodeURIComponent(redirectPath)),
replace: true,
};
});

View File

@@ -9,19 +9,19 @@ const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
});
// 有需要可以自行打开注释,并创建文件夹
// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
/** 动态路由 */
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
/** 静态路由列表,访问这些页面可以不需要权限 */
// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
const staticRoutes: RouteRecordRaw[] = [];
/** 外部路由列表,访问这些页面可以不需要Layout可能用于内嵌在别的系统 */
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
const externalRoutes: RouteRecordRaw[] = [];
/** 路由列表,由基本路由+静态路由组成 */
const routes: RouteRecordRaw[] = [
...coreRoutes,
...staticRoutes,
...externalRoutes,
fallbackNotFoundRoute,
];

View File

@@ -17,7 +17,6 @@ const routes: RouteRecordRaw[] = [
children: [
{
meta: {
icon: 'mdi:shield-key-outline',
title: $t('page.demos.element-plus'),
},
name: 'NaiveDemos',

View File

@@ -1,11 +1,11 @@
import type { RouteRecordRaw } from 'vue-router';
import {
VBEN_ANT_PREVIEW_URL,
VBEN_DOC_URL,
VBEN_GITHUB_URL,
VBEN_LOGO_URL,
VBEN_NAIVE_PREVIEW_URL,
VBEN_PREVIEW_URL,
} from '@vben/constants';
import { BasicLayout, IFrameView } from '#/layouts';
@@ -26,7 +26,7 @@ const routes: RouteRecordRaw[] = [
{
name: 'VbenAbout',
path: '/vben-admin/about',
component: () => import('#/views/_core/vben/about/index.vue'),
component: () => import('#/views/_core/about/index.vue'),
meta: {
icon: 'lucide:copyright',
title: $t('page.vben.about'),
@@ -38,8 +38,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'lucide:book-open-text',
iframeSrc: VBEN_DOC_URL,
keepAlive: true,
link: VBEN_DOC_URL,
title: $t('page.vben.document'),
},
},
@@ -69,7 +68,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
badgeType: 'dot',
link: VBEN_PREVIEW_URL,
link: VBEN_ANT_PREVIEW_URL,
title: $t('page.vben.antdv'),
},
},

View File

@@ -10,7 +10,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { ElNotification } from 'element-plus';
import { defineStore } from 'pinia';
import { getAccessCodesApi, getUserInfoApi, loginApi } from '#/api';
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => {
@@ -33,13 +33,12 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { accessToken, refreshToken } = await loginApi(params);
const { accessToken } = await loginApi(params);
// 如果成功获取到 accessToken
if (accessToken) {
// 将 accessToken 存储到 accessStore 中
accessStore.setAccessToken(accessToken);
accessStore.setRefreshToken(refreshToken);
// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
@@ -77,16 +76,19 @@ export const useAuthStore = defineStore('auth', () => {
};
}
async function logout() {
async function logout(redirect: boolean = true) {
await logoutApi();
resetAllStores();
accessStore.setLoginExpired(false);
// 回登陆页带上当前路由地址
await router.replace({
path: LOGIN_PATH,
query: {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
},
query: redirect
? {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
}
: {},
});
}

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -1,4 +1,6 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import {
ElButton,
ElCard,
@@ -39,58 +41,38 @@ function notify(type: NotificationType) {
</script>
<template>
<div class="p-5">
<div class="card-box p-5">
<h1 class="text-xl font-semibold">Element Plus组件使用演示</h1>
<div class="text-foreground/80 mt-2">支持多语言主题功能集成切换等</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">按钮</span>
</div>
<div>
<ElSpace>
<ElButton>Default</ElButton>
<ElButton type="primary"> Primary </ElButton>
<ElButton type="info"> Info </ElButton>
<ElButton type="success"> Success </ElButton>
<ElButton type="warning"> Warning </ElButton>
<ElButton type="danger"> Error </ElButton>
</ElSpace>
</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">卡片</span>
</div>
<div>
<ElCard title="卡片"> 卡片内容 </ElCard>
</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">信息 Message </span>
</div>
<div class="flex gap-3">
<Page
description="支持多语言,主题功能集成切换等"
title="Element Plus组件使用演示"
>
<ElCard class="mb-5">
<template #header> 按钮 </template>
<ElSpace>
<ElButton>Default</ElButton>
<ElButton type="primary"> Primary </ElButton>
<ElButton type="info"> Info </ElButton>
<ElButton type="success"> Success </ElButton>
<ElButton type="warning"> Warning </ElButton>
<ElButton type="danger"> Error </ElButton>
</ElSpace>
</ElCard>
<ElCard class="mb-5">
<template #header> Message </template>
<ElSpace>
<ElButton type="info" @click="info"> 信息 </ElButton>
<ElButton type="danger" @click="error"> 错误 </ElButton>
<ElButton type="warning" @click="warning"> 警告 </ElButton>
<ElButton type="success" @click="success"> 成功 </ElButton>
</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">通知 Notification </span>
</div>
<div class="flex gap-3">
</ElSpace>
</ElCard>
<ElCard class="mb-5">
<template #header> Notification </template>
<ElSpace>
<ElButton type="info" @click="notify('info')"> 信息 </ElButton>
<ElButton type="danger" @click="notify('error')"> 错误 </ElButton>
<ElButton type="warning" @click="notify('warning')"> 警告 </ElButton>
<ElButton type="success" @click="notify('success')"> 成功 </ElButton>
</div>
</div>
</div>
</ElSpace>
</ElCard>
</Page>
</template>

View File

@@ -1,5 +1,5 @@
# 端口号
VITE_PORT=5777
VITE_PORT=5888
VITE_BASE=/

View File

@@ -14,3 +14,6 @@ VITE_ROUTER_HISTORY=hash
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/web-naive",
"version": "5.0.1",
"version": "5.2.0",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -27,23 +27,23 @@
},
"dependencies": {
"@vben/access": "workspace:*",
"@vben/chart-ui": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/constants": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/plugins": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/request": "workspace:*",
"@vben/stores": "workspace:*",
"@vben/styles": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "^10.11.0",
"@vueuse/core": "^11.0.3",
"naive-ui": "^2.39.0",
"pinia": "2.2.0",
"vue": "^3.4.36",
"pinia": "2.2.2",
"vue": "^3.4.38",
"vue-router": "^4.4.3"
}
}

View File

@@ -1,4 +1,4 @@
import { requestClient } from '#/api/request';
import { baseRequestClient, requestClient } from '#/api/request';
export namespace AuthApi {
/** 登录接口参数 */
@@ -12,10 +12,14 @@ export namespace AuthApi {
accessToken: string;
desc: string;
realName: string;
refreshToken: string;
userId: string;
username: string;
}
export interface RefreshTokenResult {
data: string;
status: number;
}
}
/**
@@ -25,6 +29,24 @@ export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/**
* 刷新accessToken
*/
export async function refreshTokenApi() {
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
withCredentials: true,
});
}
/**
* 退出登录
*/
export async function logoutApi() {
return baseRequestClient.post('/auth/logout', {
withCredentials: true,
});
}
/**
* 获取用户权限码
*/

View File

@@ -1,66 +1,103 @@
/**
* 该文件可自行根据业务逻辑进行调整
*/
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import { RequestClient } from '@vben/request';
import {
authenticateResponseInterceptor,
errorMessageResponseInterceptor,
RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';
import { message } from '#/naive';
import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core';
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
function createRequestClient(baseURL: string) {
const client = new RequestClient({
baseURL,
// 为每个请求携带 Authorization
makeAuthorization: () => {
return {
// 默认
key: 'Authorization',
tokenHandler: () => {
const accessStore = useAccessStore();
return {
refreshToken: `${accessStore.refreshToken}`,
token: `${accessStore.accessToken}`,
};
},
unAuthorizedHandler: async () => {
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (preferences.app.loginExpiredMode === 'modal') {
accessStore.setLoginExpired(true);
} else {
// 退出登录
await authStore.logout();
}
},
};
},
makeErrorMessage: (msg) => message.error(msg),
makeRequestHeaders: () => {
return {
// 为每个请求携带 Accept-Language
'Accept-Language': preferences.app.locale,
};
},
});
client.addResponseInterceptor<HttpResponse>((response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
/**
* 重新认证逻辑
*/
async function doReAuthenticate() {
console.warn('Access token or refresh token is invalid or expired. ');
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (
preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked
) {
accessStore.setLoginExpired(true);
} else {
await authStore.logout();
}
throw new Error(msg);
}
/**
* 刷新token逻辑
*/
async function doRefreshToken() {
const accessStore = useAccessStore();
const resp = await refreshTokenApi();
const newToken = resp.data;
accessStore.setAccessToken(newToken);
return newToken;
}
function formatToken(token: null | string) {
return token ? `Bearer ${token}` : null;
}
// 请求头处理
client.addRequestInterceptor({
fulfilled: async (config) => {
const accessStore = useAccessStore();
config.headers.Authorization = formatToken(accessStore.accessToken);
config.headers['Accept-Language'] = preferences.app.locale;
return config;
},
});
// response数据解构
client.addResponseInterceptor({
fulfilled: (response) => {
const { data: responseData, status } = response;
const { code, data, message: msg } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return data;
}
throw new Error(`Error ${status}: ${msg}`);
},
});
// token过期的处理
client.addResponseInterceptor(
authenticateResponseInterceptor({
client,
doReAuthenticate,
doRefreshToken,
enableRefreshToken: preferences.app.enableRefreshToken,
formatToken,
}),
);
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)),
);
return client;
}
export const requestClient = createRequestClient(apiURL);
export const baseRequestClient = new RequestClient({ baseURL: apiURL });

View File

@@ -2,10 +2,9 @@
import type { NotificationItem } from '@vben/layouts';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
import { LOGIN_PATH, VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons';
import {
BasicLayout,
@@ -14,16 +13,10 @@ import {
UserDropdown,
} from '@vben/layouts';
import { preferences } from '@vben/preferences';
import {
resetAllStores,
storeToRefs,
useAccessStore,
useUserStore,
} from '@vben/stores';
import { storeToRefs, useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
import { $t } from '#/locales';
import { resetRoutes } from '#/router';
import { useAuthStore } from '#/store';
const notifications = ref<NotificationItem[]>([
@@ -100,12 +93,8 @@ const avatar = computed(() => {
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
});
const router = useRouter();
async function handleLogout() {
resetAllStores();
resetRoutes();
await router.replace(LOGIN_PATH);
await authStore.logout(false);
}
function handleNoticeClear() {

View File

@@ -28,4 +28,4 @@ async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
});
}
export { $t, loadMessages, setupI18n };
export { $t, setupI18n };

View File

@@ -92,13 +92,10 @@ function setupAccessGuard(router: Router) {
return to;
}
const accessRoutes = accessStore.accessRoutes;
// 是否已经生成过动态路由
if (accessRoutes && accessRoutes.length > 0) {
if (accessStore.isAccessChecked) {
return true;
}
// 生成路由表
// 当前登录用户拥有的角色标识列表
const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
@@ -115,10 +112,11 @@ function setupAccessGuard(router: Router) {
// 保存菜单信息和路由信息
accessStore.setAccessMenus(accessibleMenus);
accessStore.setAccessRoutes(accessibleRoutes);
const redirectPath = (from.query.redirect ?? to.path) as string;
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ?? to.fullPath) as string;
return {
path: decodeURIComponent(redirectPath),
...router.resolve(decodeURIComponent(redirectPath)),
replace: true,
};
});

View File

@@ -9,19 +9,19 @@ const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
});
// 有需要可以自行打开注释,并创建文件夹
// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
/** 动态路由 */
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
/** 静态路由列表,访问这些页面可以不需要权限 */
// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
const staticRoutes: RouteRecordRaw[] = [];
/** 外部路由列表,访问这些页面可以不需要Layout可能用于内嵌在别的系统 */
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
const externalRoutes: RouteRecordRaw[] = [];
/** 路由列表,由基本路由+静态路由组成 */
const routes: RouteRecordRaw[] = [
...coreRoutes,
...staticRoutes,
...externalRoutes,
fallbackNotFoundRoute,
];

View File

@@ -17,7 +17,6 @@ const routes: RouteRecordRaw[] = [
children: [
{
meta: {
icon: 'mdi:shield-key-outline',
title: $t('page.demos.naive'),
},
name: 'NaiveDemos',

View File

@@ -1,11 +1,11 @@
import type { RouteRecordRaw } from 'vue-router';
import {
VBEN_ANT_PREVIEW_URL,
VBEN_DOC_URL,
VBEN_ELE_PREVIEW_URL,
VBEN_GITHUB_URL,
VBEN_LOGO_URL,
VBEN_PREVIEW_URL,
} from '@vben/constants';
import { BasicLayout, IFrameView } from '#/layouts';
@@ -26,7 +26,7 @@ const routes: RouteRecordRaw[] = [
{
name: 'VbenAbout',
path: '/vben-admin/about',
component: () => import('#/views/_core/vben/about/index.vue'),
component: () => import('#/views/_core/about/index.vue'),
meta: {
icon: 'lucide:copyright',
title: $t('page.vben.about'),
@@ -38,8 +38,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'lucide:book-open-text',
iframeSrc: VBEN_DOC_URL,
keepAlive: true,
link: VBEN_DOC_URL,
title: $t('page.vben.document'),
},
},
@@ -59,7 +58,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
badgeType: 'dot',
link: VBEN_PREVIEW_URL,
link: VBEN_ANT_PREVIEW_URL,
title: $t('page.vben.antdv'),
},
},

View File

@@ -9,7 +9,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { defineStore } from 'pinia';
import { getAccessCodesApi, getUserInfoApi, loginApi } from '#/api';
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
import { $t } from '#/locales';
import { notification } from '#/naive';
@@ -33,13 +33,12 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { accessToken, refreshToken } = await loginApi(params);
const { accessToken } = await loginApi(params);
// 如果成功获取到 accessToken
if (accessToken) {
// 将 accessToken 存储到 accessStore 中
accessStore.setAccessToken(accessToken);
accessStore.setRefreshToken(refreshToken);
// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
@@ -77,16 +76,19 @@ export const useAuthStore = defineStore('auth', () => {
};
}
async function logout() {
async function logout(redirect: boolean = true) {
await logoutApi();
resetAllStores();
accessStore.setLoginExpired(false);
// 回登陆页带上当前路由地址
await router.replace({
path: LOGIN_PATH,
query: {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
},
query: redirect
? {
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
}
: {},
});
}

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);

View File

@@ -1,7 +1,11 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
import {
EchartsUI,
type EchartsUIType,
useEcharts,
} from '@vben/plugins/echarts';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -13,7 +17,7 @@ onMounted(() => {
containLabel: true,
left: '1%',
right: '1%',
top: '2 %',
top: '2 %',
},
series: [
{

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import type { NotificationType } from 'naive-ui';
import { Page } from '@vben/common-ui';
import { type NotificationType } from 'naive-ui';
import { NButton, NCard, NSpace, useMessage, useNotification } from 'naive-ui';
const notification = useNotification();
@@ -33,59 +34,35 @@ function notify(type: NotificationType) {
</script>
<template>
<div class="p-5">
<div class="card-box p-5">
<h1 class="text-xl font-semibold">naive组件使用演示</h1>
<div class="text-foreground/80 mt-2">支持多语言主题功能集成切换等</div>
</div>
<Page description="支持多语言,主题功能集成切换等" title="naive组件使用演示">
<NCard class="mb-5" title="按钮">
<NSpace>
<NButton>Default</NButton>
<NButton type="tertiary"> Tertiary </NButton>
<NButton type="primary"> Primary </NButton>
<NButton type="info"> Info </NButton>
<NButton type="success"> Success </NButton>
<NButton type="warning"> Warning </NButton>
<NButton type="error"> Error </NButton>
</NSpace>
</NCard>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">按钮</span>
</div>
<div>
<NSpace>
<NButton>Default</NButton>
<NButton type="tertiary"> Tertiary </NButton>
<NButton type="primary"> Primary </NButton>
<NButton type="info"> Info </NButton>
<NButton type="success"> Success </NButton>
<NButton type="warning"> Warning </NButton>
<NButton type="error"> Error </NButton>
</NSpace>
</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">卡片</span>
</div>
<div>
<NCard title="卡片"> 卡片内容 </NCard>
</div>
</div>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">信息 Message </span>
</div>
<div class="flex gap-3">
<NCard class="mb-5" title="Message">
<NSpace>
<NButton type="error" @click="error"> 错误 </NButton>
<NButton type="warning" @click="warning"> 警告 </NButton>
<NButton type="success" @click="success"> 成功 </NButton>
<NButton type="primary" @click="loading"> 加载中 </NButton>
</div>
</div>
</NSpace>
</NCard>
<div class="card-box mt-5 p-5">
<div class="mb-3">
<span class="text-lg font-semibold">通知 Notification </span>
</div>
<div class="flex gap-3">
<NCard class="mb-5" title="Notification">
<NSpace>
<NButton type="error" @click="notify('error')"> 错误 </NButton>
<NButton type="warning" @click="notify('warning')"> 警告 </NButton>
<NButton type="success" @click="notify('success')"> 成功 </NButton>
<NButton type="primary" @click="notify('info')"> 加载中 </NButton>
</div>
</div>
</div>
</NSpace>
</NCard>
</Page>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import { ref } from 'vue';
import { Page } from '@vben/common-ui';
import { NDataTable } from 'naive-ui';
const columns = ref([
@@ -25,7 +27,12 @@ const data = [
</script>
<template>
<NDataTable :columns="columns" :data="data" />
<Page
description="表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。"
title="NDataTable"
>
<NDataTable :columns="columns" :data="data" />
</Page>
</template>
<style scoped></style>

View File

@@ -37,6 +37,7 @@
"astro",
"ui-kit",
"styl",
"vnode",
"nocheck",
"prefixs",
"vitepress",
@@ -53,6 +54,9 @@
"**/*-dist/**",
"**/icons/**",
"pnpm-lock.yaml",
"**/*.log"
"**/*.log",
"**/*.test.ts",
"**/*.spec.ts",
"**/__tests__/**"
]
}

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { computed } from 'vue';
import PreviewGroup from './preview-group.vue';
interface Props {
files?: string;
}
const props = withDefaults(defineProps<Props>(), { files: '() => []' });
const parsedFiles = computed(() => {
try {
return JSON.parse(decodeURIComponent(props.files ?? ''));
} catch {
return [];
}
});
</script>
<template>
<div class="border-border shadow-float relative rounded-xl border">
<div
class="not-prose relative w-full overflow-x-auto rounded-t-lg px-4 py-6"
>
<div class="flex w-full max-w-[700px] px-2">
<slot v-if="parsedFiles.length > 0"></slot>
<div v-else class="text-destructive text-sm">
<span class="bg-destructive text-foreground rounded-sm px-1 py-1">
ERROR:
</span>
The preview directory does not exist. Please check the 'dir'
parameter.
</div>
</div>
</div>
<PreviewGroup v-if="parsedFiles.length > 0" :files="parsedFiles">
<template v-for="file in parsedFiles" #[file]>
<slot :name="file"></slot>
</template>
</PreviewGroup>
</div>
</template>

View File

@@ -0,0 +1 @@
export { default as DemoPreview } from './demo-preview.vue';

View File

@@ -0,0 +1,108 @@
<script setup lang="ts">
import { computed, ref, useSlots } from 'vue';
import { VbenTooltip } from '@vben-core/shadcn-ui';
import { Code } from 'lucide-vue-next';
import {
TabsContent,
TabsIndicator,
TabsList,
TabsRoot,
TabsTrigger,
} from 'radix-vue';
defineOptions({
inheritAttrs: false,
});
const props = withDefaults(
defineProps<{
files?: string[];
}>(),
{ files: () => [] },
);
const open = ref(false);
const slots = useSlots();
const tabs = computed(() => {
return props.files.map((file) => {
return {
component: slots[file],
label: file,
};
});
});
const currentTab = ref('index.vue');
const toggleOpen = () => {
open.value = !open.value;
};
</script>
<template>
<TabsRoot
v-model="currentTab"
class="bg-background-deep border-border overflow-hidden rounded-b-xl border-t"
@update:model-value="open = true"
>
<div class="border-border bg-background flex border-b-2 pr-2">
<div class="flex w-full items-center justify-between text-[13px]">
<TabsList class="relative flex">
<template v-if="open">
<TabsIndicator
class="absolute bottom-0 left-0 h-[2px] w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-[width,transform] duration-300"
>
<div class="size-full bg-[var(--vp-c-indigo-1)]"></div>
</TabsIndicator>
<TabsTrigger
v-for="(tab, index) in tabs"
:key="index"
:value="tab.label"
class="border-box text-foreground px-4 py-3 data-[state=active]:text-[var(--vp-c-indigo-1)]"
tabindex="-1"
>
{{ tab.label }}
</TabsTrigger>
</template>
</TabsList>
<div
:class="{
'py-2': !open,
}"
class="flex items-center"
>
<VbenTooltip side="top">
<template #trigger>
<Code
class="hover:bg-accent size-7 cursor-pointer rounded-full p-1.5"
@click="toggleOpen"
/>
</template>
{{ open ? 'Collapse code' : 'Expand code' }}
</VbenTooltip>
</div>
</div>
</div>
<div
:class="`${open ? 'h-[unset] max-h-[80vh]' : 'h-0'}`"
class="block overflow-y-scroll bg-[var(--vp-code-block-bg)] transition-all duration-300"
>
<TabsContent
v-for="tab in tabs"
:key="tab.label"
:value="tab.label"
as-child
class="rounded-xl"
>
<div class="text-foreground relative rounded-xl">
<component :is="tab.component" class="border-0" />
</div>
</TabsContent>
</div>
</TabsRoot>
</template>

View File

@@ -1,379 +0,0 @@
import type { DefaultTheme, HeadConfig } from 'vitepress';
import { resolve } from 'node:path';
import { type PwaOptions, withPwa } from '@vite-pwa/vitepress';
import { defineConfigWithTheme } from 'vitepress';
import { version } from '../../package.json';
export default withPwa(
defineConfigWithTheme({
description: 'Vben Admin& 企业级管理系统框架',
head: head(),
lang: 'zh',
pwa: pwa(),
// locales: {
// en: {
// label: 'English',
// lang: 'en',
// link: '/en/',
// },
// root: {
// label: '简体中文',
// lang: 'zh-CN',
srcDir: 'src',
// },
themeConfig: {
darkModeSwitchLabel: '主题',
darkModeSwitchTitle: '切换到深色模式',
docFooter: {
next: '下一页',
prev: '上一页',
},
editLink: {
pattern:
'https://github.com/vbenjs/vue-vben-admin/edit/main/docs/:path',
text: '在 GitHub 上编辑此页面',
},
footer: {
copyright: `Copyright © 2020-${new Date().getFullYear()} Vben`,
message: '基于 MIT 许可发布.',
},
i18nRouting: true,
langMenuLabel: '多语言',
lastUpdated: {
formatOptions: {
dateStyle: 'short',
timeStyle: 'medium',
},
text: '最后更新于',
},
lightModeSwitchTitle: '切换到浅色模式',
logo: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp',
nav: nav(),
outline: {
label: '页面导航',
},
returnToTopLabel: '回到顶部',
search: {
options: {
locales: {
zh: {
translations: {
button: {
buttonAriaLabel: '搜索文档',
buttonText: '搜索文档',
},
modal: {
footer: {
navigateText: '切换',
selectText: '选择',
},
noResultsText: '无法找到相关结果',
resetButtonTitle: '清除查询条件',
},
},
},
},
},
provider: 'local',
},
sidebar: {
'/commercial/': { base: '/commercial/', items: sidebarCommercial() },
'/guide/': { base: '/guide/', items: sidebarGuide() },
},
sidebarMenuLabel: '菜单',
siteTitle: 'Vben Admin',
socialLinks: [
{ icon: 'github', link: 'https://github.com/vbenjs/vue-vben-admin' },
],
},
title: 'Vben Admin',
vite: {
build: {
chunkSizeWarningLimit: Infinity,
minify: 'terser',
},
json: {
stringify: true,
},
server: {
fs: {
allow: ['../..'],
},
host: true,
port: 6173,
},
ssr: {
external: ['@vue/repl'],
},
},
}),
);
function nav(): DefaultTheme.NavItem[] {
return [
{
text: '文档',
items: [
{
link: '/guide/introduction/vben',
text: '指南',
// items: [
// {
// link: '/guide/introduction/vben',
// text: '简介',
// },
// {
// link: '/guide/essentials/concept',
// text: '基础',
// },
// {
// link: '/guide/in-depth/layout',
// text: '深入',
// },
// {
// link: '/guide/project/standard',
// text: '工程',
// },
// {
// link: '/guide/other/project-update',
// text: '其他',
// },
// ],
},
{
text: '历史版本',
items: [
{
link: 'https://doc.vvbin.cn',
text: '2.x版本文档',
},
],
},
],
},
{
text: '演示',
items: [
{
text: 'Vben Admin',
items: [
{
link: 'https://www.vben.pro',
text: 'Ant Design Vue 版本(默认)',
},
{
link: 'https://naive.vben.pro',
text: 'Naive 版本',
},
{
link: 'https://ele.vben.pro',
text: 'Element Plus版本',
},
],
},
{
text: '其他',
items: [
{
link: 'https://vben.vvbin.cn',
text: 'Vben Admin 2.x',
},
],
},
],
},
{
text: version,
items: [
{
link: 'https://github.com/vbenjs/vue-vben-admin/releases',
text: '更新日志',
},
{
link: 'https://github.com/orgs/vbenjs/projects/5',
text: '路线图',
},
{
link: 'https://github.com/vbenjs/vue-vben-admin/blob/main/.github/contributing.md',
text: '贡献',
},
],
},
{
link: '/commercial/technical-support',
text: '🦄 技术支持',
},
{
link: '/sponsor/personal',
text: '✨ 赞助',
},
{
link: '/commercial/community',
text: '👨‍👦‍👦 社区交流',
// items: [
// {
// link: 'https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&appChannel=share&inviteCode=22ySzj7pKiw&businessType=9&from=246610&biz=ka&mainSourceId=share&subSourceId=others&jumpsource=shorturl#/pc',
// text: 'QQ频道',
// },
// {
// link: 'https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=mjZmlhgVzzUxvdxllB6C1vHpX8O8QRL0&authKey=DBdFbBwERmfaKY95JvRWqLCJIRGJAmKyZbrpzZ41EKDMZ5SR6MfbjOBaaNRN73fr&noverify=0&group_code=4286109',
// text: 'QQ群',
// },
// {
// link: 'https://discord.gg/VU62jTecad',
// text: 'Discord',
// },
// ],
},
{
link: '/friend-links/',
text: '🤝 友情链接',
},
];
}
function sidebarGuide(): DefaultTheme.SidebarItem[] {
return [
{
collapsed: false,
text: '简介',
items: [
{
link: 'introduction/vben',
text: '关于 Vben Admin',
},
{
link: 'introduction/why',
text: '为什么选择我们?',
},
{ link: 'introduction/quick-start', text: '快速开始' },
],
},
{
text: '基础',
items: [
{ link: 'essentials/concept', text: '基础概念' },
{ link: 'essentials/development', text: '本地开发' },
{ link: 'essentials/route', text: '路由和菜单' },
{ link: 'essentials/settings', text: '配置' },
{ link: 'essentials/icons', text: '图标' },
{ link: 'essentials/styles', text: '样式' },
{ link: 'essentials/external-module', text: '外部模块' },
{ link: 'essentials/build', text: '构建与部署' },
{ link: 'essentials/server', text: '服务端交互与数据Mock' },
],
},
{
text: '深入',
items: [
// { link: 'in-depth/layout', text: '布局' },
{ link: 'in-depth/theme', text: '主题' },
{ link: 'in-depth/access', text: '权限' },
{ link: 'in-depth/locale', text: '国际化' },
{ link: 'in-depth/features', text: '常用功能' },
{ link: 'in-depth/check-updates', text: '检查更新' },
{ link: 'in-depth/loading', text: '全局loading' },
{ link: 'in-depth/ui-framework', text: '组件库切换' },
],
},
{
text: '工程',
items: [
{ link: 'project/standard', text: '规范' },
{ link: 'project/cli', text: 'CLI' },
{ link: 'project/test', text: '单元测试' },
{ link: 'project/tailwindcss', text: 'Tailwind CSS' },
{ link: 'project/changeset', text: 'Changeset' },
{ link: 'project/vite', text: 'Vite Config' },
],
},
{
text: '其他',
items: [
{ link: 'other/project-update', text: '项目更新' },
{ link: 'other/remove-code', text: '移除代码' },
{ link: 'other/faq', text: '常见问题' },
],
},
];
}
function sidebarCommercial(): DefaultTheme.SidebarItem[] {
return [
{
link: 'community',
text: '社区交流',
},
{
link: 'technical-support',
text: '技术支持',
},
{
link: 'customized',
text: '定制开发',
},
];
}
function head(): HeadConfig[] {
return [
['meta', { content: 'Vbenjs Team', name: 'author' }],
[
'meta',
{
content: 'vben, vitejs, vite, shacdn-ui, vue',
name: 'keywords',
},
],
['link', { href: '/favicon.ico', rel: 'icon', type: 'image/svg+xml' }],
[
'meta',
{
content:
'width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no',
name: 'viewport',
},
],
['meta', { content: 'vben admin docs', name: 'keywords' }],
['link', { href: '/favicon.ico', rel: 'icon' }],
// [
// 'script',
// {
// src: 'https://cdn.tailwindcss.com',
// },
// ],
];
}
function pwa(): PwaOptions {
return {
includeManifestIcons: false,
manifest: {
description:
'Vben Admin is a modern admin dashboard template based on Vue 3. ',
icons: [
{
sizes: '192x192',
src: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/pwa-icon-192.png',
type: 'image/png',
},
{
sizes: '512x512',
src: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/pwa-icon-512.png',
type: 'image/png',
},
],
id: '/',
name: 'Vben Admin Doc',
short_name: 'vben_admin_doc',
theme_color: '#ffffff',
},
outDir: resolve(process.cwd(), '.vitepress/dist'),
registerType: 'autoUpdate',
workbox: {
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
},
};
}

Some files were not shown because too many files have changed in this diff Show More