Compare commits

...

79 Commits

Author SHA1 Message Date
vben
46540a7329 chore: release v5.3.2 2024-10-03 15:43:15 +08:00
Vben
13fd0ea16c fix: try to fix the error reported by the stub command in the window system (#4560) 2024-10-03 15:34:29 +08:00
Vben
f7016466ee feat: add examples of asynchronous form verification and verification time (#4559)
* feat: add examples of asynchronous form verification and verification time
2024-10-03 15:15:50 +08:00
Vben
0cd865e211 fix: fixed an error in the form onChange within Naive (#4558)
* fix: fixed an error in the form onChange within Naive

* chore: update
2024-10-03 14:22:18 +08:00
Squall2017
64428b9b11 feat: add form field autofocus configuration (#4550)
* feat: add form field autofocus configuration
2024-10-03 13:10:21 +08:00
LinaBell
aed31a5a4e perf: [antd] default placeholder for input and select components (#4551)
* chore: demo of customizing form layout using tailwind

* perf: default placeholder for input and select components

* chore: update ts type

* chore: extract public methods
2024-10-03 13:04:19 +08:00
dependabot[bot]
b3e196f001 chore(deps-dev): bump the non-breaking-changes group across 1 directory with 3 updates (#4557)
* chore(deps-dev): bump the non-breaking-changes group across 1 directory with 3 updates

Bumps the non-breaking-changes group with 3 updates in the / directory: [turbo](https://github.com/vercel/turborepo), [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) and [rollup](https://github.com/rollup/rollup).


Updates `turbo` from 2.1.2 to 2.1.3
- [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.1.2...v2.1.3)

Updates `vitest` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.2/packages/vitest)

Updates `rollup` from 4.22.5 to 4.24.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.22.5...v4.24.0)

---
updated-dependencies:
- dependency-name: turbo
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vitest
  dependency-type: direct:development
  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
...

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>
2024-10-03 12:54:04 +08:00
LinaBell
b2c117f544 chore: demo of customizing form layout using tailwind (#4549) 2024-09-30 09:47:16 +08:00
vben
01391ee5a1 chore: release v5.3.1 2024-09-29 22:25:20 +08:00
Vben
3572ce1538 fix: when multiple pop-ups exist at the same time, clicking will close all (#4548) 2024-09-29 22:15:43 +08:00
Vben
d1e1256202 chore: disable sorting of non-core folder object fields (#4547)
* chore: disable sorting of non-core folder object fields

* chore: ci error
2024-09-29 22:03:17 +08:00
Squall2017
b7776c5148 fix: fix abnormal display of scroll bar on lock screen page (#4546)
*  fix abnormal display of scroll bar on lock screen page
2024-09-29 21:45:56 +08:00
dependabot[bot]
2d1519eca7 chore(deps): bump the non-breaking-changes group across 1 directory with 4 updates (#4537)
* chore(deps): bump the non-breaking-changes group across 1 directory with 4 updates

Bumps the non-breaking-changes group with 4 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [vue](https://github.com/vuejs/core), [rollup](https://github.com/rollup/rollup) and [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared).


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

Updates `vue` from 3.5.8 to 3.5.10
- [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.5.8...v3.5.10)

Updates `rollup` from 4.22.4 to 4.22.5
- [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.22.4...v4.22.5)

Updates `@vue/shared` from 3.5.8 to 3.5.10
- [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.5.10/packages/shared)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  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: rollup
  dependency-type: direct:development
  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
...

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>
2024-09-28 16:10:26 +08:00
jinmao88
93b5618b52 feat(@vben/stores): export defineStore to support pinia persistence within apps (#4483)
Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
2024-09-28 16:01:04 +08:00
Vben
639d2e1525 feat: add pagination component (#4522)
* feat: add pagination component

* chore: update
2024-09-26 23:09:17 +08:00
Vben
26646d42f7 fix: when modal and drawer exist at the same time, click Close All (#4521) 2024-09-26 22:50:37 +08:00
Vben
17fa8eb93b fix: improve ant design button icon style (#4520) 2024-09-26 22:40:23 +08:00
Vben
8250894a50 fix: improve input browser backfilling style (#4519) 2024-09-26 22:31:20 +08:00
vince
a72b8acaf9 fix: window system clean script execution problems (#4513)
* fix: fix window system clean script execution problems

* fix: lint error

* chore: remove test code
2024-09-26 11:59:19 +08:00
Vben
a46c85d77d chore: update documentation and deps (#4510)
* chore: update docs

* chore: update deps

* chore: update action

* fix: reset after preferences are refreshed

* fix: ci error
2024-09-25 23:09:48 +08:00
Squall2017
fdc5b02c30 feat(form): add merge form functionality (#4495)
* feat: captcha example

* fix: fix lint errors

* chore: event handling and methods

* chore: add accessibility features ARIA labels and roles

* refactor: refactor code structure and improve captcha demo page

* feat: add captcha internationalization

* chore: 适配时间戳国际化展示

* fix: 1. 添加点击位置边界校验,防止点击外部导致x,y误差。2. 演示页面宽度过长添加滚动条。3. 添加hooks

* feat: sync test

* feat: 添加合并表单功能

* fix: 修复上一步不展示问题

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-09-25 18:11:02 +08:00
Netfan
476aa068d7 fix: stripe table style for element plus, fixed: #4501 (#4503) 2024-09-25 17:33:24 +08:00
LinaBell
bb6057cac3 perf: setValues method of the form supports assigning values only to keys that exist in the schema (#4508)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

* feat(@vben-core/form-ui): Default form validation rules applicable to selector components

* fix: Missing the default required label style for components such as select

* fix: the focus style and antd of the input box validation failure should be consistent

* fix: the focus style and antd of the input box validation failure should be consistent

* fix: some antd components failed to verify styles

* perf: setValues method of the form supports assigning values only to keys that exist in the schema

* docs: update form component docs

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-09-25 17:09:38 +08:00
Fifteen
abbbbfb955 fix(docs): fix the selected state of the top navigation bar (#4499)
* fix(@vben/docs): fix the selected state of the top navigation bar

* style(@vben/docs): navigation bar selected item style
2024-09-25 09:53:55 +08:00
handsomeFu
79c87c9f46 chore(@vben/playground): Add new slider captcha element and adjust references (#4490)
Add a new slider captcha action reference (`el6`) to support additional functionality and update related template and event handler to use this new reference.
2024-09-24 14:15:41 +08:00
Vben
f815dcf3ae fix: after deleting the form item, you will also get the form value (#4481)
* fix: after deleting the form item, you will also get the form value
2024-09-23 22:59:58 +08:00
neo.dowithless
1197efea26 fix: wrong style when breadcrumbs display background (#4472) 2024-09-23 14:15:46 +08:00
Vben
2a83f1d666 feat: add playwright e2e testing framework (#4468)
* feat: add playwright e2e testing framework
2024-09-22 21:35:40 +08:00
aonoa
4b3d2d21ed fix: Clear the input box when closing the search (#4467)
Signed-off-by: aonoa <1991849113@qq.com>
2024-09-22 20:38:01 +08:00
vben
31f6cc6416 chore: release v5.3.0 2024-09-22 14:32:23 +08:00
Vben
5ce3a18785 docs: update docs (#4466)
* chore: fixed known issues with form components

* docs: add vben form doc
2024-09-22 14:16:06 +08:00
Vben
dac80703d9 feat: add sliding verification to the login form (#4461) 2024-09-21 21:51:40 +08:00
invalid w
000172e482 chore(@vben/common-ui): add verify component (#4390)
* chore(@vben/common-ui): 增加拖拽校验组件

* chore: 增加样式

* Merge branch 'main' into wangjue-verify-comp

* chore: 封装action组件

* chore: 拆分完成拖拽功能

* chore: 样式调整为tailwindcss语法

* chore: 导出check图标

* chore: 拖动的图标变为@vben/icons的

* chore: 完成插槽功能迁移

* fix: ci error

* chore: 适配暗黑主题

* chore: 国际化

* chore: resolve conflict

* chore: 迁移v2的图片旋转校验组件

* chore: 完善选择校验demo

* chore: 转换为tailwindcss

* chore: 替换为系统的颜色变量

* chore: 使用interface代替组件的props声明

* chore: 调整props

* chore: 优化demo背景

* chore: follow suggest

* chore: rm unnecessary style tag

* chore: update demo

* perf: improve the experience of Captcha components

---------

Co-authored-by: vince <vince292007@gmail.com>
Co-authored-by: Vben <ann.vben@gmail.com>
2024-09-21 20:52:36 +08:00
LinaBell
dbe5b33db6 fix: some antd components failed to verify styles (#4458)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

* feat(@vben-core/form-ui): Default form validation rules applicable to selector components

* fix: Missing the default required label style for components such as select

* fix: the focus style and antd of the input box validation failure should be consistent

* fix: the focus style and antd of the input box validation failure should be consistent

* fix: some antd components failed to verify styles

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-09-21 20:09:43 +08:00
LanceJiang
81a9accafd fix: improve layout boundary issues (#4450) 2024-09-21 14:44:42 +08:00
Vben
bc625ee710 fix: improve global type detection of vue files (#4455) 2024-09-21 13:50:54 +08:00
Vben
d34f1fbf2f fix: improve defineConfig types (#4454) 2024-09-21 13:25:06 +08:00
Vben
60cffb0dec feat: add updateSchema to form api (#4453)
* feat: add updateSchema to form api

* chore: typo

* chore: typo
2024-09-21 11:26:14 +08:00
Vben
68dbe04bef fix: form verification style fails in pop-up window (#4452) 2024-09-21 11:03:35 +08:00
dependabot[bot]
37645f08be chore(deps): bump the non-breaking-changes group with 4 updates (#4451)
* chore(deps): bump the non-breaking-changes group with 4 updates

Bumps the non-breaking-changes group with 4 updates: [vue](https://github.com/vuejs/core), [rollup](https://github.com/rollup/rollup), [eslint](https://github.com/eslint/eslint) and [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared).


Updates `vue` from 3.5.6 to 3.5.7
- [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.5.6...v3.5.7)

Updates `rollup` from 4.22.0 to 4.22.2
- [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.22.0...v4.22.2)

Updates `eslint` from 9.10.0 to 9.11.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.10.0...v9.11.0)

Updates `@vue/shared` from 3.5.6 to 3.5.7
- [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.5.7/packages/shared)

---
updated-dependencies:
- dependency-name: vue
  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-patch
  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: "@vue/shared"
  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-09-21 10:46:38 +08:00
LinaBell
ace942e2df fix: the focus style and antd of the input box validation failure should be consistent (#4446)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

* feat(@vben-core/form-ui): Default form validation rules applicable to selector components

* fix: Missing the default required label style for components such as select

* fix: the focus style and antd of the input box validation failure should be consistent

* fix: the focus style and antd of the input box validation failure should be consistent

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-09-20 22:39:20 +08:00
zhangjian10
f9359ed0f9 fix: update fetch URL to use BASE_URL for version tag retrieval (#4448)
* fix: update fetch URL to use BASE_URL for version tag retrieval

* feat: add configurable update check URL for better flexibility

---------

Co-authored-by: zj <1018zhangjian@gmail.com>
2024-09-20 22:37:30 +08:00
LinaBell
b12ff2d766 fix: missing the default required label style for components such as select (#4444)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

* feat(@vben-core/form-ui): Default form validation rules applicable to selector components

* fix: Missing the default required label style for components such as select
2024-09-20 11:06:44 +08:00
Li Kui
c72747c649 fix: enforce minimum pnpm version 9.5.0 (#4443) 2024-09-20 10:19:08 +08:00
LinaBell
fbd23701de feat: default form validation rules applicable to selector components (#4442)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

* feat(@vben-core/form-ui): Default form validation rules applicable to selector components

---------
2024-09-20 09:46:03 +08:00
zhuizhubf
a634ec3692 fix(@vben/web-ele): fixed some style issues in dark mode (#4436)
* fix(@vben/web-ele): fixed some style issues in dark mode

* fix: lint

---------

Co-authored-by: Vben <ann.vben@gmail.com>
2024-09-19 23:11:41 +08:00
Vben
df48409814 fix: when the api returns 401, the page is refreshed not as expected (#4440) 2024-09-19 23:03:20 +08:00
Vben
4765158510 perf: the request client upload function supports more parameters (#4439) 2024-09-19 22:13:43 +08:00
Vben
161820dbc1 fix: improve the scroll bar flashing when the modal box is opened (#4438) 2024-09-19 21:56:49 +08:00
Vben
56bdb8f606 chore: use pnpm catalog (#4437)
* feat: use pnpm catalog

* fix: lint error
2024-09-19 21:40:54 +08:00
LinaBell
f25783933d fix: hover border style same as antd style when validate error (#4409)
* fix: hover border style same as antd style when validate error

* fix: hover border style same as antd style when validate error

---------
2024-09-19 17:39:26 +08:00
dependabot[bot]
d574fb8b6d chore(deps): bump pinia-plugin-persistedstate (#4428)
Bumps the non-breaking-changes group with 1 update: [pinia-plugin-persistedstate](https://github.com/prazdevs/pinia-plugin-persistedstate).


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

---
updated-dependencies:
- dependency-name: pinia-plugin-persistedstate
  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-09-19 09:57:55 +08:00
Vben
0c73cf8d3f fix: fixed the form component componentProps using the function that did not meet expectations (#4426) 2024-09-18 23:01:40 +08:00
Vben
834cb4c470 fix: the onOpenChange event for the modal component does not work as expected (#4425) 2024-09-18 22:44:46 +08:00
Vben
2c22825546 fix: improve layout boundary processing (#4423) 2024-09-18 22:21:23 +08:00
dependabot[bot]
26d43ef822 chore(deps): bump the non-breaking-changes group across 1 directory with 17 updates (#4419)
Bumps the non-breaking-changes group with 17 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.5.4` | `22.5.5` |
| [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) | `8.14.2` | `8.14.3` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.11` | `3.4.12` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `5.4.5` | `5.4.6` |
| [vue](https://github.com/vuejs/core) | `3.5.5` | `3.5.6` |
| [execa](https://github.com/sindresorhus/execa) | `9.3.1` | `9.4.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.247` | `2.2.249` |
| [postcss](https://github.com/postcss/postcss) | `8.4.45` | `8.4.47` |
| [@jspm/generator](https://github.com/jspm/generator) | `2.3.0` | `2.3.1` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.5.0` | `8.6.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.5.0` | `8.6.0` |
| [@vue/reactivity](https://github.com/vuejs/core/tree/HEAD/packages/reactivity) | `3.5.5` | `3.5.6` |
| [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared) | `3.5.5` | `3.5.6` |
| [@vueuse/core](https://github.com/vueuse/vueuse/tree/HEAD/packages/core) | `11.0.3` | `11.1.0` |
| [@vueuse/integrations](https://github.com/vueuse/vueuse/tree/HEAD/packages/integrations) | `11.0.3` | `11.1.0` |
| [@types/jsonwebtoken](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsonwebtoken) | `9.0.6` | `9.0.7` |
| [publint](https://github.com/bluwy/publint/tree/HEAD/pkg) | `0.2.10` | `0.2.11` |



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

Updates `cspell` from 8.14.2 to 8.14.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.14.3/packages/cspell)

Updates `tailwindcss` from 3.4.11 to 3.4.12
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.12/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.11...v3.4.12)

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

Updates `vue` from 3.5.5 to 3.5.6
- [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.5.5...v3.5.6)

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

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

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

Updates `@jspm/generator` from 2.3.0 to 2.3.1
- [Release notes](https://github.com/jspm/generator/releases)
- [Commits](https://github.com/jspm/generator/compare/2.3.0...2.3.1)

Updates `@typescript-eslint/eslint-plugin` from 8.5.0 to 8.6.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.6.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.5.0 to 8.6.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.6.0/packages/parser)

Updates `@vue/reactivity` from 3.5.5 to 3.5.6
- [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.5.6/packages/reactivity)

Updates `@vue/shared` from 3.5.5 to 3.5.6
- [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.5.6/packages/shared)

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

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

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

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- 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-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-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: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@jspm/generator"
  dependency-type: direct:production
  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: "@vue/reactivity"
  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: "@vueuse/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vueuse/integrations"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@types/jsonwebtoken"
  dependency-type: direct:development
  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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 10:05:13 +08:00
Vben
bfae9626dd perf: display border status color when the form is verified incorrectly (#4407)
* perf: display border status color when the form is verified incorrectly

* chore: adjust the document preview file order
2024-09-14 22:44:21 +08:00
Vben
02c4014ae3 fix: when the form is opened repeatedly, the state is unexpectedly destroyed (#4406) 2024-09-14 22:07:50 +08:00
Vben
c3d0102cda fix: the brand color setting does not take effect (#4405) 2024-09-14 21:35:12 +08:00
Squall2017
38fe6426a2 fix: Improve the problem of inaccurate captcha accuracy (#4401)
* feat: captcha example

* fix: fix lint errors

* chore: event handling and methods

* chore: add accessibility features ARIA labels and roles

* refactor: refactor code structure and improve captcha demo page

* feat: add captcha internationalization

* chore: 适配时间戳国际化展示

* fix: 1. 添加点击位置边界校验,防止点击外部导致x,y误差。2. 演示页面宽度过长添加滚动条。3. 添加hooks

---------
2024-09-14 21:21:16 +08:00
Donny Wang
b8a4fba78c chore: fix ci (#4404) 2024-09-14 17:27:25 +08:00
dependabot[bot]
d99cad35d7 chore(deps): bump the non-breaking-changes group with 5 updates (#4395)
Bumps the non-breaking-changes group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `2.1.0` | `2.1.1` |
| [vue](https://github.com/vuejs/core) | `3.5.4` | `3.5.5` |
| [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) | `3.5.0` | `3.6.0` |
| [@vue/reactivity](https://github.com/vuejs/core/tree/HEAD/packages/reactivity) | `3.5.4` | `3.5.5` |
| [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared) | `3.5.4` | `3.5.5` |


Updates `vitest` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.1/packages/vitest)

Updates `vue` from 3.5.4 to 3.5.5
- [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.5.4...v3.5.5)

Updates `eslint-plugin-perfectionist` from 3.5.0 to 3.6.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.5.0...v3.6.0)

Updates `@vue/reactivity` from 3.5.4 to 3.5.5
- [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.5.5/packages/reactivity)

Updates `@vue/shared` from 3.5.4 to 3.5.5
- [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.5.5/packages/shared)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:development
  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: eslint-plugin-perfectionist
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vue/reactivity"
  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
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-14 10:12:09 +08:00
Squall2017
5ba3a9dec2 refactor: refactor code structure and improve demo page (#4389)
* feat: captcha example

* fix: fix lint errors

* chore: event handling and methods

* chore: add accessibility features ARIA labels and roles

* refactor: refactor code structure and improve captcha demo page

* feat: add captcha internationalization

* chore: 适配时间戳国际化展示

---------

Co-authored-by: vince <vince292007@gmail.com>
2024-09-14 09:53:06 +08:00
Vben
10b90eae5d chore: bump vue-i18n from 9.14.0 to 10.0.1 (#4393) 2024-09-13 22:39:59 +08:00
Vben
29f572abd3 chore: chore(deps): bump pinia-plugin-persistedstate from 3.2.3 to 4.0.1 (#4392) 2024-09-13 22:08:55 +08:00
Vben
d27e5eeef7 fix: improve the dialog and drawer scrollbar experience, fix internal click failure problems and warnings (#4391)
* fix: improve the dialog and drawer scrollbar experience, fix internal click failure problems and warnings

* chore: remove test code
2024-09-13 21:46:56 +08:00
dependabot[bot]
bd6b724aaf chore(deps): bump the non-breaking-changes group with 6 updates (#4382)
Bumps the non-breaking-changes group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [husky](https://github.com/typicode/husky) | `9.1.5` | `9.1.6` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `2.0.5` | `2.1.0` |
| [rollup](https://github.com/rollup/rollup) | `4.21.2` | `4.21.3` |
| [stylelint-scss](https://github.com/stylelint-scss/stylelint-scss) | `6.5.1` | `6.6.0` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.439.0` | `0.441.0` |
| [@tanstack/vue-query](https://github.com/TanStack/query/tree/HEAD/packages/vue-query) | `5.55.4` | `5.56.2` |


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

Updates `vitest` from 2.0.5 to 2.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.0/packages/vitest)

Updates `rollup` from 4.21.2 to 4.21.3
- [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.2...v4.21.3)

Updates `stylelint-scss` from 6.5.1 to 6.6.0
- [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.1...v6.6.0)

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

Updates `@tanstack/vue-query` from 5.55.4 to 5.56.2
- [Release notes](https://github.com/TanStack/query/releases)
- [Commits](https://github.com/TanStack/query/commits/v5.56.2/packages/vue-query)

---
updated-dependencies:
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vitest
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: rollup
  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-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
- dependency-name: "@tanstack/vue-query"
  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-09-13 08:24:11 +08:00
vben
7bcb973d65 fix: ci error 2024-09-12 22:49:33 +08:00
Vben
9e88b8004f fix: try to fix the ci error (#4381) 2024-09-12 22:43:37 +08:00
Vben
76a879d4d8 fix: fixed some style issues (#4379) 2024-09-12 22:03:58 +08:00
dependabot[bot]
537a4b0ecb chore(deps): bump tailwindcss in the non-breaking-changes group (#4369)
Bumps the non-breaking-changes group with 1 update: [tailwindcss](https://github.com/tailwindlabs/tailwindcss).


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

---
updated-dependencies:
- dependency-name: tailwindcss
  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-09-12 10:07:08 +08:00
Vben
855ac02622 fix: select components used in modal pop-ups cannot be selected (#4368)
* fix: select components used in modal pop-ups cannot be selected

* chore: update ci

* chore: update css
2024-09-11 23:10:35 +08:00
Li Kui
61faa1895a fix: vue received a Component that was made a reactive object (#4367) 2024-09-11 22:56:01 +08:00
Li Kui
8f6bf6add3 perf: update menu icons (#4357) 2024-09-11 16:23:24 +08:00
苗大
ceb52aad7f fix: text overflow when text omission component width is lower than maxWidth (#4364) 2024-09-11 16:21:36 +08:00
dependabot[bot]
66c732fdee chore(deps): bump the non-breaking-changes group across 1 directory with 2 updates (#4358)
Bumps the non-breaking-changes group with 2 updates in the / directory: [vue](https://github.com/vuejs/core) and [vue-router](https://github.com/vuejs/router).


Updates `vue` from 3.5.3 to 3.5.4
- [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.5.3...v3.5.4)

Updates `vue-router` from 4.4.3 to 4.4.4
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/compare/v4.4.3...v4.4.4)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vue-router
  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-09-11 15:10:36 +08:00
Li Kui
6e67fb5fe7 fix(@vben/docs): build failed on windows (#4362) 2024-09-11 14:26:42 +08:00
vben
3697f6bc5a chore: release v5.3.0-beta.2 2024-09-10 22:20:51 +08:00
vben
978edb1e02 chore: release v5.3.0-beta.1 [skip ci] 2024-09-10 22:08:26 +08:00
321 changed files with 11131 additions and 4083 deletions

View File

@@ -3,3 +3,5 @@ node_modules
.gitignore .gitignore
*.md *.md
dist dist
.turbo
dist.zip

View File

@@ -1,7 +1,7 @@
name: 🐞 Bug Report name: 🐞 Bug Report
description: Report an issue with Vben Admin to help us make it better. description: Report an issue with Vben Admin to help us make it better.
title: "Bug: " title: 'Bug: '
labels: ["bug: pending triage"] labels: ['bug: pending triage']
body: body:
- type: markdown - type: markdown

View File

@@ -1,6 +1,6 @@
name: 📚 Documentation name: 📚 Documentation
description: Report an issue with Vben Admin Website to help us make it better. description: Report an issue with Vben Admin Website to help us make it better.
title: "Docs: " title: 'Docs: '
labels: [documentation] labels: [documentation]
body: body:
- type: markdown - type: markdown

View File

@@ -1,7 +1,7 @@
name: ✨ New Feature Proposal name: ✨ New Feature Proposal
description: Propose a new feature to be added to Vben Admin description: Propose a new feature to be added to Vben Admin
title: "FEATURE: " title: 'FEATURE: '
labels: ["enhancement: pending triage"] labels: ['enhancement: pending triage']
body: body:
- type: markdown - type: markdown
attributes: attributes:

View File

@@ -1,9 +1,9 @@
name: "Setup Node" name: 'Setup Node'
description: "Setup node and pnpm" description: 'Setup node and pnpm'
runs: runs:
using: "composite" using: 'composite'
steps: steps:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
@@ -12,7 +12,7 @@ runs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: .node-version
cache: "pnpm" cache: 'pnpm'
- name: Get pnpm store directory - name: Get pnpm store directory
shell: bash shell: bash

View File

@@ -1,7 +1,7 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: npm - package-ecosystem: npm
directory: "/" directory: '/'
schedule: schedule:
interval: daily interval: daily
groups: groups:
@@ -9,7 +9,7 @@ updates:
update-types: [minor, patch] update-types: [minor, patch]
- package-ecosystem: github-actions - package-ecosystem: github-actions
directory: "/" directory: '/'
schedule: schedule:
interval: weekly interval: weekly
groups: groups:

View File

@@ -1,7 +1,7 @@
name-template: "v$RESOLVED_VERSION" name-template: 'v$RESOLVED_VERSION'
tag-template: "v$RESOLVED_VERSION" tag-template: 'v$RESOLVED_VERSION'
version-template: $MAJOR.$MINOR.$PATCH version-template: $MAJOR.$MINOR.$PATCH
change-template: "* $TITLE (#$NUMBER) @$AUTHOR" change-template: '* $TITLE (#$NUMBER) @$AUTHOR'
template: | template: |
# What's Changed # What's Changed
@@ -10,52 +10,52 @@ template: |
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
categories: categories:
- title: "🚀 Features" - title: '🚀 Features'
labels: labels:
- "feature" - 'feature'
- title: "🐞 Bug Fixes" - title: '🐞 Bug Fixes'
labels: labels:
- "bug" - 'bug'
- title: "📈 Performance" - title: '📈 Performance'
labels: labels:
- "perf" - 'perf'
- "enhancement" - 'enhancement'
- title: 📝 Documentation - title: 📝 Documentation
labels: labels:
- "documentation" - 'documentation'
- title: 👻 Maintenance - title: 👻 Maintenance
labels: labels:
- "chore" - 'chore'
- "dependencies" - 'dependencies'
# collapse-after: 12 # collapse-after: 12
- title: 🚦 Tests - title: 🚦 Tests
labels: labels:
- "tests" - 'tests'
- title: "Breaking" - title: 'Breaking'
label: "breaking" label: 'breaking'
version-resolver: version-resolver:
major: major:
labels: labels:
- "major" - 'major'
- "breaking" - 'breaking'
minor: minor:
labels: labels:
- "minor" - 'minor'
patch: patch:
labels: labels:
- "feature" - 'feature'
- "patch" - 'patch'
- "bug" - 'bug'
- "maintenance" - 'maintenance'
- "docs" - 'docs'
- "dependencies" - 'dependencies'
- "security" - 'security'
exclude-labels: exclude-labels:
- "skip-changelog" - 'skip-changelog'
- "no-changelog" - 'no-changelog'
- "changelog" - 'changelog'
- "bump versions" - 'bump versions'
- "reverted" - 'reverted'
- "invalid" - 'invalid'

View File

@@ -7,7 +7,7 @@ on:
- main - main
env: env:
HUSKY: "0" HUSKY: '0'
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -19,8 +19,15 @@ permissions:
jobs: jobs:
post-update: post-update:
if: github.repository == 'vbenjs/vue-vben-admin'
# if: ${{ github.actor == 'dependabot[bot]' }} # if: ${{ github.actor == 'dependabot[bot]' }}
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
# - macos-latest
- windows-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -18,7 +18,7 @@ env:
jobs: jobs:
version: version:
if: (github.event.pull_request.merged || github.event_name == 'workflow_dispatch') && github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: (github.event.pull_request.merged || github.event_name == 'workflow_dispatch') && github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
# if: github.repository == 'vbenjs/vue-vben-admin' # if: github.repository == 'vbenjs/vue-vben-admin'
timeout-minutes: 15 timeout-minutes: 15
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -36,7 +36,7 @@ jobs:
uses: changesets/action@v1 uses: changesets/action@v1
with: with:
version: pnpm run version version: pnpm run version
commit: "chore: bump versions" commit: 'chore: bump versions'
title: "chore: bump versions" title: 'chore: bump versions'
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -5,7 +5,7 @@ on:
push: push:
branches: branches:
- main - main
- "releases/*" - 'releases/*'
permissions: permissions:
contents: read contents: read
@@ -17,7 +17,7 @@ env:
jobs: jobs:
test: test:
name: Test name: Test
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@@ -56,7 +56,7 @@ jobs:
lint: lint:
name: Lint name: Lint
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@@ -79,6 +79,7 @@ jobs:
check: check:
name: Check name: Check
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 20 timeout-minutes: 20
strategy: strategy:
@@ -108,8 +109,8 @@ jobs:
ci-ok: ci-ok:
name: CI OK name: CI OK
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && always()
needs: [test, check, lint] needs: [test, check, lint]
env: env:
FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }} FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }}

View File

@@ -9,19 +9,20 @@
# the `language` matrix defined below to confirm you have the correct set of # the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages. # supported CodeQL languages.
# #
name: "CodeQL" name: 'CodeQL'
on: on:
push: push:
branches: ["main"] branches: ['main']
pull_request: pull_request:
branches: ["main"] branches: ['main']
schedule: schedule:
- cron: "35 0 * * 0" - cron: '35 0 * * 0'
jobs: jobs:
analyze: analyze:
name: Analyze (${{ matrix.language }}) name: Analyze (${{ matrix.language }})
if: github.repository == 'vbenjs/vue-vben-admin'
# Runner size impacts CodeQL analysis time. To learn more, please see: # Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql # - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources # - https://gh.io/supported-runners-and-hardware-resources
@@ -90,4 +91,4 @@ jobs:
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v3
with: with:
category: "/language:${{matrix.language}}" category: '/language:${{matrix.language}}'

View File

@@ -8,7 +8,7 @@ on:
jobs: jobs:
deploy-playground-ftp: deploy-playground-ftp:
name: Deploy Push Playground Ftp name: Deploy Push Playground Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -39,7 +39,7 @@ jobs:
deploy-docs-ftp: deploy-docs-ftp:
name: Deploy Push Docs Ftp name: Deploy Push Docs Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -63,7 +63,7 @@ jobs:
deploy-antd-ftp: deploy-antd-ftp:
name: Deploy Push Antd Ftp name: Deploy Push Antd Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -94,7 +94,7 @@ jobs:
deploy-ele-ftp: deploy-ele-ftp:
name: Deploy Push Element Ftp name: Deploy Push Element Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -125,7 +125,7 @@ jobs:
deploy-naive-ftp: deploy-naive-ftp:
name: Deploy Push Naive Ftp name: Deploy Push Naive Ftp
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code

View File

@@ -17,6 +17,7 @@ jobs:
# write permission is required for autolabeler # write permission is required for autolabeler
# otherwise, read permission is required at least # otherwise, read permission is required at least
pull-requests: write pull-requests: write
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: release-drafter/release-drafter@v6 - uses: release-drafter/release-drafter@v6

View File

@@ -3,23 +3,29 @@ name: Issue Close Require
# 触发条件:每天零点 # 触发条件:每天零点
on: on:
workflow_dispatch:
schedule: schedule:
- cron: "0 0 * * *" - cron: '0 0 * * *'
permissions: permissions:
pull-requests: write pull-requests: write
contents: write contents: write
issues: write
jobs: jobs:
close-issues: close-issues:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# 步骤1关闭未活动的 Issues # 关闭未活动的 Issues
- name: Close Inactive Issues - name: Close Inactive Issues
uses: actions-cool/issues-helper@v3 uses: actions/stale@v9
with: with:
actions: "close-issues" # 执行动作:关闭 Issues days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
token: ${{ secrets.GITHUB_TOKEN }} # GitHub Token用于认证 stale-issue-label: needs-reproduction # Label that flags an issue as stale.
labels: "needs reproduction" # 目标标签 only-labels: needs-reproduction # Only process these issues
inactive-day: 3 # 未活动天数阈值 days-before-issue-close: 3
ignore-updates: true
remove-stale-when-updated: false
close-issue-message: This issue was closed because it was open for 3 days without a valid reproduction.
close-issue-label: closed-by-action

View File

@@ -13,33 +13,34 @@ permissions:
jobs: jobs:
reply-labeled: reply-labeled:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: remove enhancement pending - name: remove enhancement pending
if: github.event.label.name == 'enhancement' if: github.event.label.name == 'enhancement'
uses: actions-cool/issues-helper@v3 uses: actions-cool/issues-helper@v3
with: with:
actions: "remove-labels" actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
labels: "enhancement: pending triage" labels: 'enhancement: pending triage'
- name: remove bug pending - name: remove bug pending
if: github.event.label.name == 'bug' if: github.event.label.name == 'bug'
uses: actions-cool/issues-helper@v3 uses: actions-cool/issues-helper@v3
with: with:
actions: "remove-labels" actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
labels: "bug: pending triage" labels: 'bug: pending triage'
- name: needs reproduction - name: needs reproduction
if: github.event.label.name == 'needs reproduction' if: github.event.label.name == 'needs reproduction'
uses: actions-cool/issues-helper@v3 uses: actions-cool/issues-helper@v3
with: with:
actions: "create-comment, remove-labels" actions: 'create-comment, remove-labels'
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
body: | body: |
Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `needs reproduction` will be closed if no activities in 3 days. Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `needs reproduction` will be closed if no activities in 3 days.
labels: "bug: pending triage" labels: 'bug: pending triage'

View File

@@ -2,7 +2,7 @@ name: Lock Threads
on: on:
schedule: schedule:
- cron: "0 0 * * *" - cron: '0 0 * * *'
workflow_dispatch: workflow_dispatch:
permissions: permissions:
@@ -11,13 +11,14 @@ permissions:
jobs: jobs:
action: action:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v5 - uses: dessant/lock-threads@v5
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: "30" issue-inactive-days: '14'
issue-lock-reason: "" issue-lock-reason: ''
pr-inactive-days: "30" pr-inactive-days: '30'
pr-lock-reason: "" pr-lock-reason: ''
process-only: "issues, prs" process-only: 'issues, prs'

View File

@@ -3,10 +3,10 @@ name: Create Release Tag
on: on:
push: push:
tags: tags:
- "v*.*.*" # Push events to matching v*, i.e. v1.0, v20.15.10 - 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10
env: env:
HUSKY: "0" HUSKY: '0'
permissions: permissions:
pull-requests: write pull-requests: write
@@ -15,6 +15,7 @@ permissions:
jobs: jobs:
build: build:
name: Create Release name: Create Release
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:

View File

@@ -9,8 +9,9 @@ on:
jobs: jobs:
main: main:
runs-on: ubuntu-latest
name: Semantic Pull Request name: Semantic Pull Request
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps: steps:
- name: Validate PR title - name: Validate PR title
uses: amannn/action-semantic-pull-request@v5 uses: amannn/action-semantic-pull-request@v5

View File

@@ -1,18 +1,19 @@
name: "Close stale issues" name: 'Close stale issues'
on: on:
schedule: schedule:
- cron: "0 1 * * *" - cron: '0 1 * * *'
jobs: jobs:
stale: stale:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v9
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days" stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
stale-pr-message: "This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days" stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
exempt-issue-labels: "bug,enhancement" exempt-issue-labels: 'bug,enhancement'
days-before-stale: 60 days-before-stale: 60
days-before-close: 7 days-before-close: 7

View File

@@ -3,4 +3,4 @@ ports:
onOpen: open-preview onOpen: open-preview
tasks: tasks:
- init: corepack enable && pnpm install - init: corepack enable && pnpm install
command: pnpm run dev command: pnpm run dev:play

View File

@@ -212,7 +212,6 @@
"*.env": "$(capture).env.*", "*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME", "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", "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*,nginx.conf",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json", "eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json",
"tailwind.config.mjs": "postcss.*" "tailwind.config.mjs": "postcss.*"
}, },

View File

@@ -1,4 +1,4 @@
<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> <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.7/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
@@ -125,11 +125,15 @@ pnpm build
[@Vben](https://github.com/anncwb) [@Vben](https://github.com/anncwb)
## スター歴史
[![Star History Chart](https://api.star-history.com/svg?repos=vbenjs/vue-vben-admin&type=Date)](https://star-history.com/#vbenjs/vue-vben-admin&Date)
## 寄付 ## 寄付
このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます! このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png) ![donate](https://unpkg.com/@vbenjs/static-source@0.1.7/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 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>

View File

@@ -1,4 +1,4 @@
<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> <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.7/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
@@ -124,11 +124,15 @@ Support modern browsers, not IE
[@Vben](https://github.com/anncwb) [@Vben](https://github.com/anncwb)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=vbenjs/vue-vben-admin&type=Date)](https://star-history.com/#vbenjs/vue-vben-admin&Date)
## Donate ## Donate
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support! 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.6/source/sponsor.png) ![donate](https://unpkg.com/@vbenjs/static-source@0.1.7/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 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>

View File

@@ -1,4 +1,4 @@
<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> <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.7/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) [![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
@@ -77,6 +77,10 @@ pnpm dev
pnpm build pnpm build
``` ```
## 更新日志
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## 如何贡献 ## 如何贡献
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。 非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。
@@ -120,18 +124,18 @@ pnpm build
[@Vben](https://github.com/anncwb) [@Vben](https://github.com/anncwb)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=vbenjs/vue-vben-admin&type=Date)](https://star-history.com/#vbenjs/vue-vben-admin&Date)
## 捐赠 ## 捐赠
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持! 如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png) ![donate](https://unpkg.com/@vbenjs/static-source@0.1.7/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 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 ## Contributor
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors"> <a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">

View File

@@ -10,11 +10,11 @@
"start": "nitro dev" "start": "nitro dev"
}, },
"dependencies": { "dependencies": {
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "catalog:",
"nitropack": "^2.9.7" "nitropack": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"@types/jsonwebtoken": "^9.0.6", "@types/jsonwebtoken": "catalog:",
"h3": "^1.12.0" "h3": "catalog:"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-antd", "name": "@vben/web-antd",
"version": "5.2.2", "version": "5.3.2",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {
@@ -40,11 +40,11 @@
"@vben/styles": "workspace:*", "@vben/styles": "workspace:*",
"@vben/types": "workspace:*", "@vben/types": "workspace:*",
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "^11.0.3", "@vueuse/core": "catalog:",
"ant-design-vue": "^4.2.3", "ant-design-vue": "catalog:",
"dayjs": "^1.11.13", "dayjs": "catalog:",
"pinia": "2.2.2", "pinia": "catalog:",
"vue": "^3.5.4", "vue": "catalog:",
"vue-router": "^4.4.3" "vue-router": "catalog:"
} }
} }

View File

@@ -4,6 +4,7 @@ import type {
VbenFormProps, VbenFormProps,
} from '@vben/common-ui'; } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue'; import { h } from 'vue';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
@@ -27,13 +28,13 @@ import {
Select, Select,
Space, Space,
Switch, Switch,
Textarea,
TimePicker, TimePicker,
TreeSelect, TreeSelect,
Upload, Upload,
} from 'ant-design-vue'; } from 'ant-design-vue';
// 业务表单组件适配 // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
export type FormComponentType = export type FormComponentType =
| 'AutoComplete' | 'AutoComplete'
| 'Checkbox' | 'Checkbox'
@@ -51,11 +52,22 @@ export type FormComponentType =
| 'Select' | 'Select'
| 'Space' | 'Space'
| 'Switch' | 'Switch'
| 'Textarea'
| 'TimePicker' | 'TimePicker'
| 'TreeSelect' | 'TreeSelect'
| 'Upload' | 'Upload'
| BaseFormComponentType; | BaseFormComponentType;
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
) => {
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
const placeholder = props?.placeholder || $t(`placeholder.${type}`);
return h(component, { ...props, ...attrs, placeholder }, slots);
};
};
// 初始化表单组件并注册到form组件内部 // 初始化表单组件并注册到form组件内部
setupVbenForm<FormComponentType>({ setupVbenForm<FormComponentType>({
components: { components: {
@@ -72,23 +84,27 @@ setupVbenForm<FormComponentType>({
return h(Button, { ...props, attrs, type: 'primary' }, slots); return h(Button, { ...props, attrs, type: 'primary' }, slots);
}, },
Divider, Divider,
Input, Input: withDefaultPlaceholder(Input, 'input'),
InputNumber, InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword, InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
Mentions, Mentions: withDefaultPlaceholder(Mentions, 'input'),
Radio, Radio,
RadioGroup, RadioGroup,
RangePicker, RangePicker,
Rate, Rate,
Select, Select: withDefaultPlaceholder(Select, 'select'),
Space, Space,
Switch, Switch,
Textarea: withDefaultPlaceholder(Textarea, 'input'),
TimePicker, TimePicker,
TreeSelect, TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
Upload, Upload,
}, },
config: { config: {
// ant design vue组件库默认都是 v-model:value
baseModelPropName: 'value', baseModelPropName: 'value',
// 一些组件是 v-model:checked 或者 v-model:fileList
modelPropNameMap: { modelPropNameMap: {
Checkbox: 'checked', Checkbox: 'checked',
Radio: 'checked', Radio: 'checked',
@@ -97,12 +113,20 @@ setupVbenForm<FormComponentType>({
}, },
}, },
defineRules: { defineRules: {
// 输入项目必填国际化适配
required: (value, _params, ctx) => { required: (value, _params, ctx) => {
if ((!value && value !== 0) || value.length === 0) { if (value === undefined || value === null || value.length === 0) {
return $t('formRules.required', [ctx.label]); return $t('formRules.required', [ctx.label]);
} }
return true; return true;
}, },
// 选择项目必填国际化适配
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('formRules.selectRequired', [ctx.label]);
}
return true;
},
}, },
}); });

View File

@@ -10,10 +10,6 @@ export namespace AuthApi {
/** 登录接口返回值 */ /** 登录接口返回值 */
export interface LoginResult { export interface LoginResult {
accessToken: string; accessToken: string;
desc: string;
realName: string;
userId: string;
username: string;
} }
export interface RefreshTokenResult { export interface RefreshTokenResult {

View File

@@ -1,6 +1,8 @@
/** /**
* 该文件可自行根据业务逻辑进行调整 * 该文件可自行根据业务逻辑进行调整
*/ */
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
@@ -68,7 +70,7 @@ function createRequestClient(baseURL: string) {
}); });
// response数据解构 // response数据解构
client.addResponseInterceptor({ client.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => { fulfilled: (response) => {
const { data: responseData, status } = response; const { data: responseData, status } = response;
@@ -93,7 +95,10 @@ function createRequestClient(baseURL: string) {
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor( client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)), errorMessageResponseInterceptor((msg: string, _error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
message.error(msg);
}),
); );
return client; return client;

View File

@@ -19,7 +19,12 @@ const router = createRouter({
: createWebHistory(import.meta.env.VITE_BASE), : createWebHistory(import.meta.env.VITE_BASE),
// 应该添加到路由的初始路由列表。 // 应该添加到路由的初始路由列表。
routes, routes,
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: (to, _from, savedPosition) => {
if (savedPosition) {
return savedPosition;
}
return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 };
},
// 是否应该禁止尾部斜杠。 // 是否应该禁止尾部斜杠。
// strict: true, // strict: true,
}); });

View File

@@ -29,6 +29,7 @@ const routes: RouteRecordRaw[] = [
path: '/workspace', path: '/workspace',
component: () => import('#/views/dashboard/workspace/index.vue'), component: () => import('#/views/dashboard/workspace/index.vue'),
meta: { meta: {
icon: 'carbon:workspace',
title: $t('page.dashboard.workspace'), title: $t('page.dashboard.workspace'),
}, },
}, },

View File

@@ -58,6 +58,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: 'logos:naiveui',
link: VBEN_NAIVE_PREVIEW_URL, link: VBEN_NAIVE_PREVIEW_URL,
title: $t('page.vben.naive-ui'), title: $t('page.vben.naive-ui'),
}, },
@@ -68,6 +69,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: 'logos:element',
link: VBEN_ELE_PREVIEW_URL, link: VBEN_ELE_PREVIEW_URL,
title: $t('page.vben.element-plus'), title: $t('page.vben.element-plus'),
}, },

View File

@@ -76,7 +76,11 @@ export const useAuthStore = defineStore('auth', () => {
} }
async function logout(redirect: boolean = true) { async function logout(redirect: boolean = true) {
try {
await logoutApi(); await logoutApi();
} catch {
// 不做任何处理
}
resetAllStores(); resetAllStores();
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);

View File

@@ -2,9 +2,9 @@
import type { VbenFormSchema } from '@vben/common-ui'; import type { VbenFormSchema } from '@vben/common-ui';
import type { BasicOption } from '@vben/types'; import type { BasicOption } from '@vben/types';
import { computed } from 'vue'; import { computed, markRaw } from 'vue';
import { AuthenticationLogin, z } from '@vben/common-ui'; import { AuthenticationLogin, SliderCaptcha, z } from '@vben/common-ui';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
@@ -15,15 +15,15 @@ const authStore = useAuthStore();
const MOCK_USER_OPTIONS: BasicOption[] = [ const MOCK_USER_OPTIONS: BasicOption[] = [
{ {
label: '超级管理员', label: 'Super',
value: 'vben', value: 'vben',
}, },
{ {
label: '管理员', label: 'Admin',
value: 'admin', value: 'admin',
}, },
{ {
label: '用户', label: 'User',
value: 'jack', value: 'jack',
}, },
]; ];
@@ -78,6 +78,13 @@ const formSchema = computed((): VbenFormSchema[] => {
label: $t('authentication.password'), label: $t('authentication.password'),
rules: z.string().min(1, { message: $t('authentication.passwordTip') }), rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
}, },
{
component: markRaw(SliderCaptcha),
fieldName: 'captcha',
rules: z.boolean().refine((value) => value, {
message: $t('authentication.verifyRequiredTip'),
}),
},
]; ];
}); });
</script> </script>

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-ele", "name": "@vben/web-ele",
"version": "5.2.2", "version": "5.3.2",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {
@@ -40,14 +40,14 @@
"@vben/styles": "workspace:*", "@vben/styles": "workspace:*",
"@vben/types": "workspace:*", "@vben/types": "workspace:*",
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "^11.0.3", "@vueuse/core": "catalog:",
"dayjs": "^1.11.13", "dayjs": "catalog:",
"element-plus": "^2.8.2", "element-plus": "catalog:",
"pinia": "2.2.2", "pinia": "catalog:",
"vue": "^3.5.4", "vue": "catalog:",
"vue-router": "^4.4.3" "vue-router": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"unplugin-element-plus": "^0.8.0" "unplugin-element-plus": "catalog:"
} }
} }

View File

@@ -4,6 +4,7 @@ import type {
VbenFormProps, VbenFormProps,
} from '@vben/common-ui'; } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue'; import { h } from 'vue';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
@@ -42,6 +43,16 @@ export type FormComponentType =
| 'Upload' | 'Upload'
| BaseFormComponentType; | BaseFormComponentType;
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
) => {
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
const placeholder = props?.placeholder || $t(`placeholder.${type}`);
return h(component, { ...props, ...attrs, placeholder }, slots);
};
};
// 初始化表单组件并注册到form组件内部 // 初始化表单组件并注册到form组件内部
setupVbenForm<FormComponentType>({ setupVbenForm<FormComponentType>({
components: { components: {
@@ -56,14 +67,14 @@ setupVbenForm<FormComponentType>({
return h(ElButton, { ...props, attrs, type: 'primary' }, slots); return h(ElButton, { ...props, attrs, type: 'primary' }, slots);
}, },
Divider: ElDivider, Divider: ElDivider,
Input: ElInput, Input: withDefaultPlaceholder(ElInput, 'input'),
InputNumber: ElInputNumber, InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
RadioGroup: ElRadioGroup, RadioGroup: ElRadioGroup,
Select: ElSelect, Select: withDefaultPlaceholder(ElSelect, 'select'),
Space: ElSpace, Space: ElSpace,
Switch: ElSwitch, Switch: ElSwitch,
TimePicker: ElTimePicker, TimePicker: ElTimePicker,
TreeSelect: ElTreeSelect, TreeSelect: withDefaultPlaceholder(ElTreeSelect, 'select'),
Upload: ElUpload, Upload: ElUpload,
}, },
config: { config: {
@@ -73,11 +84,17 @@ setupVbenForm<FormComponentType>({
}, },
defineRules: { defineRules: {
required: (value, _params, ctx) => { required: (value, _params, ctx) => {
if ((!value && value !== 0) || value.length === 0) { if (value === undefined || value === null || value.length === 0) {
return $t('formRules.required', [ctx.label]); return $t('formRules.required', [ctx.label]);
} }
return true; return true;
}, },
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('formRules.selectRequired', [ctx.label]);
}
return true;
},
}, },
}); });

View File

@@ -10,10 +10,6 @@ export namespace AuthApi {
/** 登录接口返回值 */ /** 登录接口返回值 */
export interface LoginResult { export interface LoginResult {
accessToken: string; accessToken: string;
desc: string;
realName: string;
userId: string;
username: string;
} }
export interface RefreshTokenResult { export interface RefreshTokenResult {

View File

@@ -1,6 +1,8 @@
/** /**
* 该文件可自行根据业务逻辑进行调整 * 该文件可自行根据业务逻辑进行调整
*/ */
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
@@ -68,7 +70,7 @@ function createRequestClient(baseURL: string) {
}); });
// response数据解构 // response数据解构
client.addResponseInterceptor({ client.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => { fulfilled: (response) => {
const { data: responseData, status } = response; const { data: responseData, status } = response;
@@ -93,7 +95,10 @@ function createRequestClient(baseURL: string) {
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor( client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => ElMessage.error(msg)), errorMessageResponseInterceptor((msg: string, _error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
ElMessage.error(msg);
}),
); );
return client; return client;

View File

@@ -19,7 +19,12 @@ const router = createRouter({
: createWebHistory(import.meta.env.VITE_BASE), : createWebHistory(import.meta.env.VITE_BASE),
// 应该添加到路由的初始路由列表。 // 应该添加到路由的初始路由列表。
routes, routes,
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: (to, _from, savedPosition) => {
if (savedPosition) {
return savedPosition;
}
return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 };
},
// 是否应该禁止尾部斜杠。 // 是否应该禁止尾部斜杠。
// strict: true, // strict: true,
}); });

View File

@@ -29,6 +29,7 @@ const routes: RouteRecordRaw[] = [
path: '/workspace', path: '/workspace',
component: () => import('#/views/dashboard/workspace/index.vue'), component: () => import('#/views/dashboard/workspace/index.vue'),
meta: { meta: {
icon: 'carbon:workspace',
title: $t('page.dashboard.workspace'), title: $t('page.dashboard.workspace'),
}, },
}, },

View File

@@ -7,6 +7,7 @@ import {
VBEN_LOGO_URL, VBEN_LOGO_URL,
VBEN_NAIVE_PREVIEW_URL, VBEN_NAIVE_PREVIEW_URL,
} from '@vben/constants'; } from '@vben/constants';
import { SvgAntdvLogoIcon } from '@vben/icons';
import { BasicLayout, IFrameView } from '#/layouts'; import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales'; import { $t } from '#/locales';
@@ -58,6 +59,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: 'logos:naiveui',
link: VBEN_NAIVE_PREVIEW_URL, link: VBEN_NAIVE_PREVIEW_URL,
title: $t('page.vben.naive-ui'), title: $t('page.vben.naive-ui'),
}, },
@@ -68,6 +70,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: SvgAntdvLogoIcon,
link: VBEN_ANT_PREVIEW_URL, link: VBEN_ANT_PREVIEW_URL,
title: $t('page.vben.antdv'), title: $t('page.vben.antdv'),
}, },

View File

@@ -77,7 +77,11 @@ export const useAuthStore = defineStore('auth', () => {
} }
async function logout(redirect: boolean = true) { async function logout(redirect: boolean = true) {
try {
await logoutApi(); await logoutApi();
} catch {
// 不做任何处理
}
resetAllStores(); resetAllStores();
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);

View File

@@ -2,9 +2,9 @@
import type { VbenFormSchema } from '@vben/common-ui'; import type { VbenFormSchema } from '@vben/common-ui';
import type { BasicOption } from '@vben/types'; import type { BasicOption } from '@vben/types';
import { computed } from 'vue'; import { computed, markRaw } from 'vue';
import { AuthenticationLogin, z } from '@vben/common-ui'; import { AuthenticationLogin, SliderCaptcha, z } from '@vben/common-ui';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
@@ -15,15 +15,15 @@ const authStore = useAuthStore();
const MOCK_USER_OPTIONS: BasicOption[] = [ const MOCK_USER_OPTIONS: BasicOption[] = [
{ {
label: '超级管理员', label: 'Super',
value: 'vben', value: 'vben',
}, },
{ {
label: '管理员', label: 'Admin',
value: 'admin', value: 'admin',
}, },
{ {
label: '用户', label: 'User',
value: 'jack', value: 'jack',
}, },
]; ];
@@ -78,6 +78,13 @@ const formSchema = computed((): VbenFormSchema[] => {
label: $t('authentication.password'), label: $t('authentication.password'),
rules: z.string().min(1, { message: $t('authentication.passwordTip') }), rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
}, },
{
component: markRaw(SliderCaptcha),
fieldName: 'captcha',
rules: z.boolean().refine((value) => value, {
message: $t('authentication.verifyRequiredTip'),
}),
},
]; ];
}); });
</script> </script>

View File

@@ -7,6 +7,7 @@ import {
ElMessage, ElMessage,
ElNotification, ElNotification,
ElSpace, ElSpace,
ElTable,
} from 'element-plus'; } from 'element-plus';
type NotificationType = 'error' | 'info' | 'success' | 'warning'; type NotificationType = 'error' | 'info' | 'success' | 'warning';
@@ -38,6 +39,14 @@ function notify(type: NotificationType) {
type, type,
}); });
} }
const tableData = [
{ prop1: '1', prop2: 'A' },
{ prop1: '2', prop2: 'B' },
{ prop1: '3', prop2: 'C' },
{ prop1: '4', prop2: 'D' },
{ prop1: '5', prop2: 'E' },
{ prop1: '6', prop2: 'F' },
];
</script> </script>
<template> <template>
@@ -74,5 +83,11 @@ function notify(type: NotificationType) {
<ElButton type="success" @click="notify('success')"> 成功 </ElButton> <ElButton type="success" @click="notify('success')"> 成功 </ElButton>
</ElSpace> </ElSpace>
</ElCard> </ElCard>
<ElCard class="mb-5">
<ElTable :data="tableData" stripe>
<ElTable.TableColumn label="测试列1" prop="prop1" />
<ElTable.TableColumn label="测试列2" prop="prop2" />
</ElTable>
</ElCard>
</Page> </Page>
</template> </template>

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-naive", "name": "@vben/web-naive",
"version": "5.2.2", "version": "5.3.2",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {
@@ -40,10 +40,10 @@
"@vben/styles": "workspace:*", "@vben/styles": "workspace:*",
"@vben/types": "workspace:*", "@vben/types": "workspace:*",
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "^11.0.3", "@vueuse/core": "catalog:",
"naive-ui": "^2.39.0", "naive-ui": "catalog:",
"pinia": "2.2.2", "pinia": "catalog:",
"vue": "^3.5.4", "vue": "catalog:",
"vue-router": "^4.4.3" "vue-router": "catalog:"
} }
} }

View File

@@ -4,6 +4,7 @@ import type {
VbenFormProps, VbenFormProps,
} from '@vben/common-ui'; } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue'; import { h } from 'vue';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
@@ -43,6 +44,16 @@ export type FormComponentType =
| 'Upload' | 'Upload'
| BaseFormComponentType; | BaseFormComponentType;
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
) => {
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
const placeholder = props?.placeholder || $t(`placeholder.${type}`);
return h(component, { ...props, ...attrs, placeholder }, slots);
};
};
// 初始化表单组件并注册到form组件内部 // 初始化表单组件并注册到form组件内部
setupVbenForm<FormComponentType>({ setupVbenForm<FormComponentType>({
components: { components: {
@@ -62,17 +73,18 @@ setupVbenForm<FormComponentType>({
); );
}, },
Divider: NDivider, Divider: NDivider,
Input: NInput, Input: withDefaultPlaceholder(NInput, 'input'),
InputNumber: NInputNumber, InputNumber: withDefaultPlaceholder(NInputNumber, 'input'),
RadioGroup: NRadioGroup, RadioGroup: NRadioGroup,
Select: NSelect, Select: withDefaultPlaceholder(NSelect, 'select'),
Space: NSpace, Space: NSpace,
Switch: NSwitch, Switch: NSwitch,
TimePicker: NTimePicker, TimePicker: NTimePicker,
TreeSelect: NTreeSelect, TreeSelect: withDefaultPlaceholder(NTreeSelect, 'select'),
Upload: NUpload, Upload: NUpload,
}, },
config: { config: {
disabledOnChangeListener: true,
baseModelPropName: 'value', baseModelPropName: 'value',
modelPropNameMap: { modelPropNameMap: {
Checkbox: 'checked', Checkbox: 'checked',
@@ -82,11 +94,17 @@ setupVbenForm<FormComponentType>({
}, },
defineRules: { defineRules: {
required: (value, _params, ctx) => { required: (value, _params, ctx) => {
if ((!value && value !== 0) || value.length === 0) { if (value === undefined || value === null || value.length === 0) {
return $t('formRules.required', [ctx.label]); return $t('formRules.required', [ctx.label]);
} }
return true; return true;
}, },
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('formRules.selectRequired', [ctx.label]);
}
return true;
},
}, },
}); });

View File

@@ -1 +1,2 @@
export * from './form'; export * from './form';
export * from './naive';

View File

@@ -10,10 +10,6 @@ export namespace AuthApi {
/** 登录接口返回值 */ /** 登录接口返回值 */
export interface LoginResult { export interface LoginResult {
accessToken: string; accessToken: string;
desc: string;
realName: string;
userId: string;
username: string;
} }
export interface RefreshTokenResult { export interface RefreshTokenResult {

View File

@@ -1,6 +1,8 @@
/** /**
* 该文件可自行根据业务逻辑进行调整 * 该文件可自行根据业务逻辑进行调整
*/ */
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
@@ -10,7 +12,7 @@ import {
} from '@vben/request'; } from '@vben/request';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
import { message } from '#/naive'; import { message } from '#/adapter';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core'; import { refreshTokenApi } from './core';
@@ -67,7 +69,7 @@ function createRequestClient(baseURL: string) {
}); });
// response数据解构 // response数据解构
client.addResponseInterceptor({ client.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => { fulfilled: (response) => {
const { data: responseData, status } = response; const { data: responseData, status } = response;
@@ -92,7 +94,10 @@ function createRequestClient(baseURL: string) {
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor( client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)), errorMessageResponseInterceptor((msg: string, _error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
message.error(msg);
}),
); );
return client; return client;

View File

@@ -6,10 +6,10 @@ import type {
import { generateAccessible } from '@vben/access'; import { generateAccessible } from '@vben/access';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { message } from '#/adapter';
import { getAllMenusApi } from '#/api'; import { getAllMenusApi } from '#/api';
import { BasicLayout, IFrameView } from '#/layouts'; import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { message } from '#/naive';
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue'); const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');

View File

@@ -19,7 +19,12 @@ const router = createRouter({
: createWebHistory(import.meta.env.VITE_BASE), : createWebHistory(import.meta.env.VITE_BASE),
// 应该添加到路由的初始路由列表。 // 应该添加到路由的初始路由列表。
routes, routes,
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: (to, _from, savedPosition) => {
if (savedPosition) {
return savedPosition;
}
return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 };
},
// 是否应该禁止尾部斜杠。 // 是否应该禁止尾部斜杠。
// strict: true, // strict: true,
}); });

View File

@@ -29,6 +29,7 @@ const routes: RouteRecordRaw[] = [
path: '/workspace', path: '/workspace',
component: () => import('#/views/dashboard/workspace/index.vue'), component: () => import('#/views/dashboard/workspace/index.vue'),
meta: { meta: {
icon: 'carbon:workspace',
title: $t('page.dashboard.workspace'), title: $t('page.dashboard.workspace'),
}, },
}, },

View File

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

View File

@@ -7,6 +7,7 @@ import {
VBEN_GITHUB_URL, VBEN_GITHUB_URL,
VBEN_LOGO_URL, VBEN_LOGO_URL,
} from '@vben/constants'; } from '@vben/constants';
import { SvgAntdvLogoIcon } from '@vben/icons';
import { BasicLayout, IFrameView } from '#/layouts'; import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales'; import { $t } from '#/locales';
@@ -58,6 +59,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: SvgAntdvLogoIcon,
link: VBEN_ANT_PREVIEW_URL, link: VBEN_ANT_PREVIEW_URL,
title: $t('page.vben.antdv'), title: $t('page.vben.antdv'),
}, },
@@ -68,6 +70,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView, component: IFrameView,
meta: { meta: {
badgeType: 'dot', badgeType: 'dot',
icon: 'logos:element',
link: VBEN_ELE_PREVIEW_URL, link: VBEN_ELE_PREVIEW_URL,
title: $t('page.vben.element-plus'), title: $t('page.vben.element-plus'),
}, },

View File

@@ -9,9 +9,9 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { notification } from '#/adapter';
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api'; import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { notification } from '#/naive';
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
const accessStore = useAccessStore(); const accessStore = useAccessStore();
@@ -77,7 +77,11 @@ export const useAuthStore = defineStore('auth', () => {
} }
async function logout(redirect: boolean = true) { async function logout(redirect: boolean = true) {
try {
await logoutApi(); await logoutApi();
} catch {
// 不做任何处理
}
resetAllStores(); resetAllStores();
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);

View File

@@ -2,9 +2,9 @@
import type { VbenFormSchema } from '@vben/common-ui'; import type { VbenFormSchema } from '@vben/common-ui';
import type { BasicOption } from '@vben/types'; import type { BasicOption } from '@vben/types';
import { computed } from 'vue'; import { computed, markRaw } from 'vue';
import { AuthenticationLogin, z } from '@vben/common-ui'; import { AuthenticationLogin, SliderCaptcha, z } from '@vben/common-ui';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
@@ -15,15 +15,15 @@ const authStore = useAuthStore();
const MOCK_USER_OPTIONS: BasicOption[] = [ const MOCK_USER_OPTIONS: BasicOption[] = [
{ {
label: '超级管理员', label: 'Super',
value: 'vben', value: 'vben',
}, },
{ {
label: '管理员', label: 'Admin',
value: 'admin', value: 'admin',
}, },
{ {
label: '用户', label: 'User',
value: 'jack', value: 'jack',
}, },
]; ];
@@ -78,6 +78,13 @@ const formSchema = computed((): VbenFormSchema[] => {
label: $t('authentication.password'), label: $t('authentication.password'),
rules: z.string().min(1, { message: $t('authentication.passwordTip') }), rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
}, },
{
component: markRaw(SliderCaptcha),
fieldName: 'captcha',
rules: z.boolean().refine((value) => value, {
message: $t('authentication.verifyRequiredTip'),
}),
},
]; ];
}); });
</script> </script>

View File

@@ -46,7 +46,10 @@
"vite", "vite",
"echarts", "echarts",
"sortablejs", "sortablejs",
"etag" "etag",
"naiveui",
"uicons",
"iconoir"
], ],
"ignorePaths": [ "ignorePaths": [
"**/node_modules/**", "**/node_modules/**",

View File

@@ -24,6 +24,7 @@ const parsedFiles = computed(() => {
class="not-prose relative w-full overflow-x-auto rounded-t-lg px-4 py-6" 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"> <div class="flex w-full max-w-[700px] px-2">
<ClientOnly>
<slot v-if="parsedFiles.length > 0"></slot> <slot v-if="parsedFiles.length > 0"></slot>
<div v-else class="text-destructive text-sm"> <div v-else class="text-destructive text-sm">
<span class="bg-destructive text-foreground rounded-sm px-1 py-1"> <span class="bg-destructive text-foreground rounded-sm px-1 py-1">
@@ -32,6 +33,7 @@ const parsedFiles = computed(() => {
The preview directory does not exist. Please check the 'dir' The preview directory does not exist. Please check the 'dir'
parameter. parameter.
</div> </div>
</ClientOnly>
</div> </div>
</div> </div>
<PreviewGroup v-if="parsedFiles.length > 0" :files="parsedFiles"> <PreviewGroup v-if="parsedFiles.length > 0" :files="parsedFiles">

View File

@@ -133,12 +133,19 @@ function sidebarCommercial(): DefaultTheme.SidebarItem[] {
function nav(): DefaultTheme.NavItem[] { function nav(): DefaultTheme.NavItem[] {
return [ return [
{ {
activeMatch: '^/en/(guide|components)/',
text: 'Doc', text: 'Doc',
items: [ items: [
{ {
activeMatch: '^/en/guide/',
link: '/en/guide/introduction/vben', link: '/en/guide/introduction/vben',
text: 'Guide', text: 'Guide',
}, },
// {
// activeMatch: '^/en/components/',
// link: '/en/components/introduction',
// text: 'Components',
// },
{ {
text: 'Historical Versions', text: 'Historical Versions',
items: [ items: [

View File

@@ -47,7 +47,10 @@ export const demoPreviewPlugin = (md: MarkdownRenderer) => {
const regex = /<DemoPreview[^>]*\sdir="([^"]*)"/g; const regex = /<DemoPreview[^>]*\sdir="([^"]*)"/g;
// Iterate through the Markdown content and replace the pattern // Iterate through the Markdown content and replace the pattern
state.src = state.src.replaceAll(regex, (_match, dir) => { state.src = state.src.replaceAll(regex, (_match, dir) => {
const componentDir = join(process.cwd(), 'src', dir); const componentDir = join(process.cwd(), 'src', dir).replaceAll(
'\\',
'/',
);
let childFiles: string[] = []; let childFiles: string[] = [];
let dirExists = true; let dirExists = true;
@@ -80,7 +83,12 @@ export const demoPreviewPlugin = (md: MarkdownRenderer) => {
if (!state.tokens[index]) { if (!state.tokens[index]) {
return ''; return '';
} }
const firstString = 'index.vue';
childFiles = childFiles.sort((a, b) => {
if (a === firstString) return -1;
if (b === firstString) return 1;
return a.localeCompare(b, 'en', { sensitivity: 'base' });
});
state.tokens[index].content = state.tokens[index].content =
`<DemoPreview files="${encodeURIComponent(JSON.stringify(childFiles))}" ><${ComponentName}/> `<DemoPreview files="${encodeURIComponent(JSON.stringify(childFiles))}" ><${ComponentName}/>
`; `;

View File

@@ -11,6 +11,10 @@ import {
} from '@nolebase/vitepress-plugin-git-changelog/vite'; } from '@nolebase/vitepress-plugin-git-changelog/vite';
import tailwind from 'tailwindcss'; import tailwind from 'tailwindcss';
import { defineConfig, postcssIsolateStyles } from 'vitepress'; import { defineConfig, postcssIsolateStyles } from 'vitepress';
import {
groupIconMdPlugin,
groupIconVitePlugin,
} from 'vitepress-plugin-group-icons';
import { demoPreviewPlugin } from './plugins/demo-preview'; import { demoPreviewPlugin } from './plugins/demo-preview';
import { search as zhSearch } from './zh.mts'; import { search as zhSearch } from './zh.mts';
@@ -21,13 +25,14 @@ export const shared = defineConfig({
markdown: { markdown: {
preConfig(md) { preConfig(md) {
md.use(demoPreviewPlugin); md.use(demoPreviewPlugin);
md.use(groupIconMdPlugin);
}, },
}, },
pwa: pwa(), pwa: pwa(),
srcDir: 'src', srcDir: 'src',
themeConfig: { themeConfig: {
i18nRouting: true, i18nRouting: true,
logo: 'https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp', logo: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
search: { search: {
options: { options: {
locales: { locales: {
@@ -79,6 +84,7 @@ export const shared = defineConfig({
}), }),
GitChangelogMarkdownSection(), GitChangelogMarkdownSection(),
viteArchiverPlugin({ outputDir: '.vitepress' }), viteArchiverPlugin({ outputDir: '.vitepress' }),
groupIconVitePlugin(),
], ],
server: { server: {
fs: { fs: {
@@ -132,12 +138,12 @@ function pwa(): PwaOptions {
icons: [ icons: [
{ {
sizes: '192x192', sizes: '192x192',
src: 'https://unpkg.com/@vbenjs/static-source@0.1.6/source/pwa-icon-192.png', src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-192.png',
type: 'image/png', type: 'image/png',
}, },
{ {
sizes: '512x512', sizes: '512x512',
src: 'https://unpkg.com/@vbenjs/static-source@0.1.6/source/pwa-icon-512.png', src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-512.png',
type: 'image/png', type: 'image/png',
}, },
], ],

View File

@@ -154,15 +154,19 @@ function sidebarComponents(): DefaultTheme.SidebarItem[] {
items: [ items: [
{ {
link: 'common-ui/vben-modal', link: 'common-ui/vben-modal',
text: 'Vben Modal 模态框', text: 'Modal 模态框',
}, },
{ {
link: 'common-ui/vben-drawer', link: 'common-ui/vben-drawer',
text: 'Vben Drawer 抽屉', text: 'Drawer 抽屉',
}, },
{ {
link: 'common-ui/vben-form', link: 'common-ui/vben-form',
text: 'Vben Form 表单', text: 'Form 表单',
},
{
link: 'common-ui/vben-count-to-animator',
text: 'CountToAnimator 数字动画',
}, },
], ],
}, },
@@ -172,13 +176,16 @@ function sidebarComponents(): DefaultTheme.SidebarItem[] {
function nav(): DefaultTheme.NavItem[] { function nav(): DefaultTheme.NavItem[] {
return [ return [
{ {
activeMatch: '^/(guide|components)/',
text: '文档', text: '文档',
items: [ items: [
{ {
activeMatch: '^/guide/',
link: '/guide/introduction/vben', link: '/guide/introduction/vben',
text: '指南', text: '指南',
}, },
{ {
activeMatch: '^/components/',
link: '/components/introduction', link: '/components/introduction',
text: '组件', text: '组件',
}, },

View File

@@ -1,30 +1,92 @@
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, watch } from 'vue'; import {
computed,
nextTick,
onBeforeUnmount,
onMounted,
ref,
watch,
} from 'vue';
// import { useAntdDesignTokens } from '@vben/hooks';
// import { initPreferences } from '@vben/preferences';
import { ConfigProvider, theme } from 'ant-design-vue';
import mediumZoom from 'medium-zoom'; import mediumZoom from 'medium-zoom';
import { useRoute } from 'vitepress'; import { useRoute } from 'vitepress';
import DefaultTheme from 'vitepress/theme'; import DefaultTheme from 'vitepress/theme';
const { Layout } = DefaultTheme; const { Layout } = DefaultTheme;
const route = useRoute(); const route = useRoute();
// const { tokens } = useAntdDesignTokens();
const initZoom = () => { const initZoom = () => {
// mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); // mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' });
mediumZoom('.VPContent img', { background: 'var(--vp-c-bg)' }); mediumZoom('.VPContent img', { background: 'var(--vp-c-bg)' });
}; };
const isDark = ref(true);
watch( watch(
() => route.path, () => route.path,
() => nextTick(() => initZoom()), () => nextTick(() => initZoom()),
); );
// initPreferences({
// namespace: 'docs',
// });
onMounted(() => { onMounted(() => {
initZoom(); initZoom();
}); });
// 使用该函数
const observer = watchDarkModeChange((dark) => {
isDark.value = dark;
});
onBeforeUnmount(() => {
observer?.disconnect();
});
function watchDarkModeChange(callback: (isDark: boolean) => void) {
if (typeof window === 'undefined') {
return;
}
const htmlElement = document.documentElement;
const observer = new MutationObserver(() => {
const isDark = htmlElement.classList.contains('dark');
callback(isDark);
});
observer.observe(htmlElement, {
attributeFilter: ['class'],
attributes: true,
});
const initialIsDark = htmlElement.classList.contains('dark');
callback(initialIsDark);
return observer;
}
const tokenTheme = computed(() => {
const algorithm = isDark.value
? [theme.darkAlgorithm]
: [theme.defaultAlgorithm];
return {
algorithm,
// token: tokens,
};
});
</script> </script>
<template> <template>
<ConfigProvider :theme="tokenTheme">
<Layout /> <Layout />
</ConfigProvider>
</template> </template>
<style> <style>

View File

@@ -11,6 +11,7 @@ import { initHmPlugin } from './plugins/hm';
import './styles'; import './styles';
import 'virtual:group-icons.css';
import '@nolebase/vitepress-plugin-git-changelog/client/style.css'; import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
export default { export default {

View File

@@ -5,3 +5,18 @@ html.dark {
.dark .VPContent { .dark .VPContent {
/* background-color: #14161a; */ /* background-color: #14161a; */
} }
.form-valid-error p {
margin: 0;
}
/* 顶部导航栏选中项样式 */
.VPNavBarMenuLink,
.VPNavBarMenuGroup {
border-bottom: 1px solid transparent;
}
.VPNavBarMenuLink.active,
.VPNavBarMenuGroup.active {
border-bottom-color: var(--vp-c-brand-1);
}

View File

@@ -1,25 +1,33 @@
{ {
"name": "@vben/docs", "name": "@vben/docs",
"version": "5.2.2", "version": "5.3.2",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "vitepress build", "build": "vitepress build",
"dev": "vitepress dev", "dev": "vitepress dev",
"docs:preview": "vitepress preview" "docs:preview": "vitepress preview"
}, },
"imports": {
"#/*": "./src/_env/*"
},
"dependencies": { "dependencies": {
"@vben-core/shadcn-ui": "workspace:*", "@vben-core/shadcn-ui": "workspace:*",
"@vben/common-ui": "workspace:*", "@vben/common-ui": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/styles": "workspace:*", "@vben/styles": "workspace:*",
"lucide-vue-next": "^0.439.0", "ant-design-vue": "catalog:",
"medium-zoom": "^1.1.0", "lucide-vue-next": "catalog:",
"radix-vue": "^1.9.5" "medium-zoom": "catalog:",
"radix-vue": "catalog:",
"vitepress-plugin-group-icons": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"@nolebase/vitepress-plugin-git-changelog": "^2.5.0", "@nolebase/vitepress-plugin-git-changelog": "catalog:",
"@vben/vite-config": "workspace:*", "@vben/vite-config": "workspace:*",
"@vite-pwa/vitepress": "^0.5.3", "@vite-pwa/vitepress": "catalog:",
"vitepress": "^1.3.4", "vitepress": "catalog:",
"vue": "^3.5.4" "vue": "catalog:"
} }
} }

View File

@@ -0,0 +1,127 @@
import type {
BaseFormComponentType,
VbenFormSchema as FormSchema,
VbenFormProps,
} from '@vben/common-ui';
import { h } from 'vue';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
AutoComplete,
Button,
Checkbox,
CheckboxGroup,
DatePicker,
Divider,
Input,
InputNumber,
InputPassword,
Mentions,
Radio,
RadioGroup,
RangePicker,
Rate,
Select,
Space,
Switch,
Textarea,
TimePicker,
TreeSelect,
Upload,
} from 'ant-design-vue';
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
export type FormComponentType =
| 'AutoComplete'
| 'Checkbox'
| 'CheckboxGroup'
| 'DatePicker'
| 'Divider'
| 'Input'
| 'InputNumber'
| 'InputPassword'
| 'Mentions'
| 'Radio'
| 'RadioGroup'
| 'RangePicker'
| 'Rate'
| 'Select'
| 'Space'
| 'Switch'
| 'Textarea'
| 'TimePicker'
| 'TreeSelect'
| 'Upload'
| BaseFormComponentType;
// 初始化表单组件并注册到form组件内部
setupVbenForm<FormComponentType>({
components: {
AutoComplete,
Checkbox,
CheckboxGroup,
DatePicker,
// 自定义默认的重置按钮
DefaultResetActionButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'default' }, slots);
},
// 自定义默认的提交按钮
DefaultSubmitActionButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'primary' }, slots);
},
Divider,
Input,
InputNumber,
InputPassword,
Mentions,
Radio,
RadioGroup,
RangePicker,
Rate,
Select,
Space,
Switch,
Textarea,
TimePicker,
TreeSelect,
Upload,
},
config: {
// ant design vue组件库默认都是 v-model:value
baseModelPropName: 'value',
// 一些组件是 v-model:checked 或者 v-model:fileList
modelPropNameMap: {
Checkbox: 'checked',
Radio: 'checked',
Switch: 'checked',
Upload: 'fileList',
},
},
defineRules: {
// 输入项目必填国际化适配
required: (value, _params, ctx) => {
if (value === undefined || value === null || value.length === 0) {
return $t('formRules.required', [ctx.label]);
}
return true;
},
// 选择项目必填国际化适配
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('formRules.selectRequired', [ctx.label]);
}
return true;
},
},
});
const useVbenForm = useForm<FormComponentType>;
export { useVbenForm, z };
export type VbenFormSchema = FormSchema<FormComponentType>;
export type { VbenFormProps };

View File

@@ -0,0 +1 @@
export * from './form';

View File

@@ -10,16 +10,18 @@
免费QQ群人数上限200将会不定期清理。推荐加入QQ频道进行交流 免费QQ群人数上限200将会不定期清理。推荐加入QQ频道进行交流
:::
## 微信群 ## 微信群
作者主要通过微信群提供帮助,如果你有问题,可以通过以下方式加入微信群。
通过微信联系作者,注明加群来意:
::: tip ::: tip
因为微信群人数有限制,加微信群前,你可以通过[赞助](../sponsor/personal.md)任意金额,主动发送截图给作者,备注`加入微信群`即可。 因为微信群人数有限制,加微信群前,你可以通过[赞助](../sponsor/personal.md)任意金额,主动发送截图给作者,备注`加入微信群`即可。
::: :::
作者主要通过微信群提供帮助,如果你有问题,可以通过以下方式加入微信群。 <img src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/wechat.jpg" style="width: 300px;"/>
通过微信联系作者,注明加群来意:
<img src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/wechat.jpg" style="width: 300px;"/>

View File

@@ -7,6 +7,6 @@
- 通过邮箱联系开发者: [ann.vben@gmail.com](mailto:ann.vben@gmail.com) - 通过邮箱联系开发者: [ann.vben@gmail.com](mailto:ann.vben@gmail.com)
- 通过微信联系开发者: - 通过微信联系开发者:
<img src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/wechat.jpg" style="width: 300px;"/> <img src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/wechat.jpg" style="width: 300px;"/>
我们会在第一时间回复您,定制费用根据需求而定。 我们会在第一时间回复您,定制费用根据需求而定。

View File

@@ -0,0 +1,52 @@
---
outline: deep
---
# Vben CountToAnimator 数字动画
框架提供的数字动画组件,支持数字动画效果。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 基础用法
通过 `start-val``end-val`设置数字动画的开始值和结束值, 持续时间`3000`ms。
<DemoPreview dir="demos/vben-count-to-animator/basic" />
## 自定义前缀及分隔符
通过 `prefix``separator` 设置数字动画的前缀和分隔符。
<DemoPreview dir="demos/vben-count-to-animator/custom" />
### Props
| 属性名 | 描述 | 类型 | 默认值 |
| ---------- | -------------- | --------- | -------- |
| startVal | 起始值 | `number` | `0` |
| endVal | 结束值 | `number` | `2021` |
| duration | 动画持续时间 | `number` | `1500` |
| autoplay | 自动执行 | `boolean` | `true` |
| prefix | 前缀 | `string` | - |
| suffix | 后缀 | `string` | - |
| separator | 分隔符 | `string` | `,` |
| color | 字体颜色 | `string` | - |
| useEasing | 是否开启动画 | `boolean` | `true` |
| transition | 动画效果 | `string` | `linear` |
| decimals | 保留小数点位数 | `number` | `0` |
### Methods
以下事件,只有在 `useVbenModal({onCancel:()=>{}})` 中传入才会生效。
| 事件名 | 描述 | 类型 |
| ------ | ------------ | ---------- |
| start | 开始执行动画 | `()=>void` |
| reset | 重置 | `()=>void` |

View File

@@ -6,6 +6,14 @@ outline: deep
框架提供的抽屉组件,支持`自动高度``loading`等功能。 框架提供的抽屉组件,支持`自动高度``loading`等功能。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 基础用法 ## 基础用法
使用 `useVbenDrawer` 创建最基础的模态框。 使用 `useVbenDrawer` 创建最基础的模态框。

View File

@@ -4,8 +4,453 @@ outline: deep
# Vben Form 表单 # Vben Form 表单
框架提供的表单组件,可适配 `Element Plus``Ant Design Vue``Naive`UI 框架。 框架提供的表单组件,可适配 `Element Plus``Ant Design Vue``Naive UI`框架。
# 使用 > 如果文档内没有参数说明,可以尝试在在线示例内寻找
TODO ::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 适配器
表单底层使用 [vee-validate](https://vee-validate.logaretm.com/v4/) 进行表单验证,所以你可以使用 `vee-validate` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
### 适配器说明
每个应用都有不同的 UI 框架,所以在应用的 `src/adapter/form` 内部,你可以根据自己的需求,进行组件适配。下面是 `Ant Design Vue` 的适配器示例代码,可根据注释查看说明:
::: details ant design 适配器
```ts
import type {
BaseFormComponentType,
VbenFormSchema as FormSchema,
VbenFormProps,
} from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
AutoComplete,
Button,
Checkbox,
CheckboxGroup,
DatePicker,
Divider,
Input,
InputNumber,
InputPassword,
Mentions,
Radio,
RadioGroup,
RangePicker,
Rate,
Select,
Space,
Switch,
Textarea,
TimePicker,
TreeSelect,
Upload,
} from 'ant-design-vue';
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
export type FormComponentType =
| 'AutoComplete'
| 'Checkbox'
| 'CheckboxGroup'
| 'DatePicker'
| 'Divider'
| 'Input'
| 'InputNumber'
| 'InputPassword'
| 'Mentions'
| 'Radio'
| 'RadioGroup'
| 'RangePicker'
| 'Rate'
| 'Select'
| 'Space'
| 'Switch'
| 'Textarea'
| 'TimePicker'
| 'TreeSelect'
| 'Upload'
| BaseFormComponentType;
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
) => {
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
const placeholder = props?.placeholder || $t(`placeholder.${type}`);
return h(component, { ...props, ...attrs, placeholder }, slots);
};
};
// 初始化表单组件并注册到form组件内部
setupVbenForm<FormComponentType>({
components: {
AutoComplete,
Checkbox,
CheckboxGroup,
DatePicker,
// 自定义默认的重置按钮
DefaultResetActionButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'default' }, slots);
},
// 自定义默认的提交按钮
DefaultSubmitActionButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'primary' }, slots);
},
Divider,
Input: withDefaultPlaceholder(Input, 'input'),
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
Mentions: withDefaultPlaceholder(Mentions, 'input'),
Radio,
RadioGroup,
RangePicker,
Rate,
Select: withDefaultPlaceholder(Select, 'select'),
Space,
Switch,
Textarea: withDefaultPlaceholder(Textarea, 'input'),
TimePicker,
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
Upload,
},
config: {
// 是否禁用onChange事件监听naive ui组件库默认不需要监听onChange事件否则会在控制台报错
disabledOnChangeListener: true,
// ant design vue组件库默认都是 v-model:value
baseModelPropName: 'value',
// 一些组件是 v-model:checked 或者 v-model:fileList
modelPropNameMap: {
Checkbox: 'checked',
Radio: 'checked',
Switch: 'checked',
Upload: 'fileList',
},
},
defineRules: {
// 输入项目必填国际化适配
required: (value, _params, ctx) => {
if (value === undefined || value === null || value.length === 0) {
return $t('formRules.required', [ctx.label]);
}
return true;
},
// 选择项目必填国际化适配
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('formRules.selectRequired', [ctx.label]);
}
return true;
},
},
});
const useVbenForm = useForm<FormComponentType>;
export { useVbenForm, z };
export type VbenFormSchema = FormSchema<FormComponentType>;
export type { VbenFormProps };
```
:::
## 基础用法
::: tip README
下方示例代码中的,存在一些国际化、主题色未适配问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
:::
使用 `useVbenForm` 创建最基础的表单。
<DemoPreview dir="demos/vben-form/basic" />
## 查询表单
查询表单是一种特殊的表单,用于查询数据。查询表单不会触发表单验证,只会触发查询事件。
<DemoPreview dir="demos/vben-form/query" />
## 表单校验
表单校验是一个非常重要的功能,可以通过 `rules` 属性进行校验。
<DemoPreview dir="demos/vben-form/rules" />
## 表单联动
表单联动是一个非常常见的功能,可以通过 `dependencies` 属性进行联动。
_注意_ 需要指定 `dependencies``triggerFields` 属性,设置由谁的改动来触发,以便表单组件能够正确的联动。
<DemoPreview dir="demos/vben-form/dynamic" />
## 自定义组件
如果你的业务组件库没有提供某个组件,你可以自行封装一个组件,然后加到表单内部。
<DemoPreview dir="demos/vben-form/custom" />
## 操作
一些常见的表单操作。
<DemoPreview dir="demos/vben-form/api" />
## API
`useVbenForm` 返回一个数组,第一个元素是表单组件,第二个元素是表单的方法。
```vue
<script setup lang="ts">
import { useVbenForm } from '#/adapter';
// Form 为弹窗组件
// formApi 为弹窗的方法
const [Form, formApi] = useVbenForm({
// 属性
// 事件
});
</script>
<template>
<Form />
</template>
```
### FormApi
useVbenForm 返回的第二个参数,是一个对象,包含了一些表单的方法。
| 方法名 | 描述 | 类型 |
| --- | --- | --- |
| submitForm | 提交表单 | `(e:Event)=>Promise<Record<string,any>>` |
| resetForm | 重置表单 | `()=>Promise<void>` |
| setValues | 设置表单值, 默认会过滤不在schema中定义的field, 可通过filterFields形参关闭过滤 | `(fields: Record<string, any>, filterFields?: boolean, shouldValidate?: boolean) => Promise<void>` |
| getValues | 获取表单值 | `(fields:Record<string, any>,shouldValidate: boolean = false)=>Promise<void>` |
| validate | 表单校验 | `()=>Promise<void>` |
| resetValidate | 重置表单校验 | `()=>Promise<void>` |
| updateSchema | 更新formSchema | `(schema:FormSchema[])=>void` |
| setFieldValue | 设置字段值 | `(field: string, value: any, shouldValidate?: boolean)=>Promise<void>` |
| setState | 设置组件状态props | `(stateOrFn:\| ((prev: VbenFormProps) => Partial<VbenFormProps>)\| Partial<VbenFormProps>)=>Promise<void>` |
| getState | 获取组件状态props | `()=>Promise<VbenFormProps>` |
| form | 表单对象实例,可以操作表单,见 [useForm](https://vee-validate.logaretm.com/v4/api/use-form/) | - |
## Props
所有属性都可以传入 `useVbenForm` 的第一个参数中。
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| layout | 表单项布局 | `'horizontal' \| 'vertical'` | `horizontal` |
| showCollapseButton | 是否显示折叠按钮 | `boolean` | `false` |
| wrapperClass | 表单的布局基于tailwindcss | `any` | - |
| actionWrapperClass | 表单操作区域class | `any` | - |
| handleReset | 表单重置回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
| handleSubmit | 表单提交回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
| resetButtonOptions | 重置按钮组件参数 | `ActionButtonOptions` | - |
| submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - |
| showDefaultActions | 是否显示默认操作按钮 | `boolean` | `true` |
| collapsed | 是否折叠,在`是否展开在showCollapseButton=true`时生效 | `boolean` | `false` |
| collapsedRows | 折叠时保持的行数 | `number` | `1` |
| commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - |
| schema | 表单项的每一项配置 | `FormSchema` | - |
### TS 类型说明
::: details ActionButtonOptions
```ts
export interface ActionButtonOptions {
/** 样式 */
class?: any;
/** 是否禁用 */
disabled?: boolean;
/** 是否加载中 */
loading?: boolean;
/** 按钮大小 */
size?: ButtonVariantSize;
/** 按钮类型 */
variant?: ButtonVariants;
/** 是否显示 */
show?: boolean;
/** 按钮文本 */
text?: string;
}
```
:::
::: details FormCommonConfig
```ts
export interface FormCommonConfig {
/**
* 所有表单项的props
*/
componentProps?: ComponentProps;
/**
* 所有表单项的控件样式
*/
controlClass?: string;
/**
* 所有表单项的禁用状态
* @default false
*/
disabled?: boolean;
/**
* 所有表单项的控件样式
* @default {}
*/
formFieldProps?: Partial<typeof Field>;
/**
* 所有表单项的栅格布局
* @default ""
*/
formItemClass?: string;
/**
* 隐藏所有表单项label
* @default false
*/
hideLabel?: boolean;
/**
* 是否隐藏必填标记
* @default false
*/
hideRequiredMark?: boolean;
/**
* 所有表单项的label样式
* @default ""
*/
labelClass?: string;
/**
* 所有表单项的label宽度
*/
labelWidth?: number;
/**
* 所有表单项的wrapper样式
*/
wrapperClass?: string;
}
```
:::
::: details FormSchema
```ts
export interface FormSchema<
T extends BaseFormComponentType = BaseFormComponentType,
> extends FormCommonConfig {
/** 组件 */
component: Component | T;
/** 组件参数 */
componentProps?: ComponentProps;
/** 默认值 */
defaultValue?: any;
/** 依赖 */
dependencies?: FormItemDependencies;
/** 描述 */
description?: string;
/** 字段名 */
fieldName: string;
/** 帮助信息 */
help?: string;
/** 表单项 */
label?: string;
// 自定义组件内部渲染
renderComponentContent?: RenderComponentContentType;
/** 字段规则 */
rules?: FormSchemaRuleType;
/** 后缀 */
suffix?: CustomRenderType;
}
```
:::
### 表单联动
表单联动需要通过 schema 内的 `dependencies` 属性进行联动,允许您添加字段之间的依赖项,以根据其他字段的值控制字段。
```ts
dependencies: {
// 只有当 name 字段的值变化时,才会触发联动
triggerFields: ['name'],
// 动态判断当前字段是否需要显示,不显示则直接销毁
if(values,formApi){},
// 动态判断当前字段是否需要显示不显示用css隐藏
show(values,formApi){},
// 动态判断当前字段是否需要禁用
disabled(values,formApi){},
// 字段变更时,都会触发该函数
trigger(values,formApi){},
// 动态rules
rules(values,formApi){},
// 动态必填
required(values,formApi){},
// 动态组件参数
componentProps(values,formApi){},
}
```
### 表单校验
表单联动需要通过 schema 内的 `rules` 属性进行配置。
rules的值可以是一个字符串也可以是一个zod的schema。
#### 字符串
```ts
// 表示字段必填默认会根据适配器的required进行国际化
{
rules: 'required';
}
// 表示字段必填默认会根据适配器的required进行国际化用于下拉选择之类
{
rules: 'selectRequired';
}
```
#### zod
rules也支持 zod 的 schema可以进行更复杂的校验zod 的使用请查看 [zod文档](https://zod.dev/)。
```ts
import { z } from '#/adapter';
// 基础类型
{
rules: z.string().min(1, { message: '请输入字符串' });
}
// 可选,并且携带默认值
{
rules: z.string().default('默认值').optional(),
}
// 复杂校验
{
z.string().min(1, { message: "请输入" })
.refine((value) => value === "123", {
message: "值必须为123",
});
}
```

View File

@@ -6,6 +6,14 @@ outline: deep
框架提供的模态框组件,支持`拖拽``全屏``自动高度``loading`等功能。 框架提供的模态框组件,支持`拖拽``全屏``自动高度``loading`等功能。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 基础用法 ## 基础用法
使用 `useVbenModal` 创建最基础的模态框。 使用 `useVbenModal` 创建最基础的模态框。

View File

@@ -2,7 +2,7 @@
::: info README ::: info README
该文档介绍的是框架组件的使用方法、属性、事件等。如果你觉得组件封装的不好,或者不符合你的需求,可以直接使用原生组件,或者自己封装一个组件,不需要拘泥于框架提供的组件。我们只是提供了一些常用的组件,方便你快速开发。是否使用,取决于你的需求。 该文档介绍的是框架组件的使用方法、属性、事件等。如果你觉得现有组件封装不够理想,或者不完全符合你的需求,可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由
::: :::

View File

@@ -0,0 +1,6 @@
<script lang="ts" setup>
import { VbenCountToAnimator } from '@vben/common-ui';
</script>
<template>
<VbenCountToAnimator :duration="3000" :end-val="30000" :start-val="1" />
</template>

View File

@@ -0,0 +1,12 @@
<script lang="ts" setup>
import { VbenCountToAnimator } from '@vben/common-ui';
</script>
<template>
<VbenCountToAnimator
:duration="3000"
:end-val="2000000"
:start-val="1"
prefix="$"
separator="/"
/>
</template>

View File

@@ -0,0 +1,236 @@
<script lang="ts" setup>
import { Button, message, Space } from 'ant-design-vue';
import { useVbenForm } from '#/adapter';
const [BaseForm, formApi] = useVbenForm({
// 所有表单项共用,可单独在表单内覆盖
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
},
// 使用 tailwindcss grid布局
// 提交函数
handleSubmit: onSubmit,
// 垂直布局label和input在不同行值为vertical
layout: 'horizontal',
// 水平布局label和input在同一行
schema: [
{
// 组件需要在 #/adapter.ts内注册并加上类型
component: 'Input',
// 对应组件的参数
componentProps: {
placeholder: '请输入用户名',
},
// 字段名
fieldName: 'field1',
// 界面显示的label
label: 'field1',
},
{
component: 'Select',
componentProps: {
allowClear: true,
filterOption: true,
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
placeholder: '请选择',
showSearch: true,
},
fieldName: 'fieldOptions',
label: '下拉选',
},
],
wrapperClass: 'grid-cols-1 md:grid-cols-2',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
function handleClick(
action:
| 'batchAddSchema'
| 'batchDeleteSchema'
| 'disabled'
| 'hiddenAction'
| 'hiddenResetButton'
| 'hiddenSubmitButton'
| 'labelWidth'
| 'resetDisabled'
| 'resetLabelWidth'
| 'showAction'
| 'showResetButton'
| 'showSubmitButton'
| 'updateActionAlign'
| 'updateResetButton'
| 'updateSchema'
| 'updateSubmitButton',
) {
switch (action) {
case 'updateSchema': {
formApi.updateSchema([
{
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
{
label: '选项3',
value: '3',
},
],
},
fieldName: 'fieldOptions',
},
]);
message.success('字段 `fieldOptions` 下拉选项更新成功。');
break;
}
case 'labelWidth': {
formApi.setState({
commonConfig: {
labelWidth: 150,
},
});
break;
}
case 'resetLabelWidth': {
formApi.setState({
commonConfig: {
labelWidth: 100,
},
});
break;
}
case 'disabled': {
formApi.setState({ commonConfig: { disabled: true } });
break;
}
case 'resetDisabled': {
formApi.setState({ commonConfig: { disabled: false } });
break;
}
case 'hiddenAction': {
formApi.setState({ showDefaultActions: false });
break;
}
case 'showAction': {
formApi.setState({ showDefaultActions: true });
break;
}
case 'hiddenResetButton': {
formApi.setState({ resetButtonOptions: { show: false } });
break;
}
case 'showResetButton': {
formApi.setState({ resetButtonOptions: { show: true } });
break;
}
case 'hiddenSubmitButton': {
formApi.setState({ submitButtonOptions: { show: false } });
break;
}
case 'showSubmitButton': {
formApi.setState({ submitButtonOptions: { show: true } });
break;
}
case 'updateResetButton': {
formApi.setState({
resetButtonOptions: { disabled: true },
});
break;
}
case 'updateSubmitButton': {
formApi.setState({
submitButtonOptions: { loading: true },
});
break;
}
case 'updateActionAlign': {
formApi.setState({
// 可以自行调整class
actionWrapperClass: 'text-center',
});
break;
}
case 'batchAddSchema': {
formApi.setState((prev) => {
const currentSchema = prev?.schema ?? [];
const newSchema = [];
for (let i = 0; i < 2; i++) {
newSchema.push({
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: `field${i}${Date.now()}`,
label: `field+`,
});
}
return {
schema: [...currentSchema, ...newSchema],
};
});
break;
}
case 'batchDeleteSchema': {
formApi.setState((prev) => {
const currentSchema = prev?.schema ?? [];
return {
schema: currentSchema.slice(0, -2),
};
});
break;
}
}
}
</script>
<template>
<div>
<Space class="mb-5 flex-wrap">
<Button @click="handleClick('updateSchema')">updateSchema</Button>
<Button @click="handleClick('labelWidth')">更改labelWidth</Button>
<Button @click="handleClick('resetLabelWidth')">还原labelWidth</Button>
<Button @click="handleClick('disabled')">禁用表单</Button>
<Button @click="handleClick('resetDisabled')">解除禁用</Button>
<Button @click="handleClick('hiddenAction')">隐藏操作按钮</Button>
<Button @click="handleClick('showAction')">显示操作按钮</Button>
<Button @click="handleClick('hiddenResetButton')">隐藏重置按钮</Button>
<Button @click="handleClick('showResetButton')">显示重置按钮</Button>
<Button @click="handleClick('hiddenSubmitButton')">隐藏提交按钮</Button>
<Button @click="handleClick('showSubmitButton')">显示提交按钮</Button>
<Button @click="handleClick('updateResetButton')">修改重置按钮</Button>
<Button @click="handleClick('updateSubmitButton')">修改提交按钮</Button>
<Button @click="handleClick('updateActionAlign')">
调整操作按钮位置
</Button>
<Button @click="handleClick('batchAddSchema')"> 批量添加表单项 </Button>
<Button @click="handleClick('batchDeleteSchema')">
批量删除表单项
</Button>
</Space>
<BaseForm />
</div>
</template>

View File

@@ -0,0 +1,231 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter';
const [BaseForm] = useVbenForm({
// 所有表单项共用,可单独在表单内覆盖
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
},
// 提交函数
handleSubmit: onSubmit,
// 垂直布局label和input在不同行值为vertical
// 水平布局label和input在同一行
layout: 'horizontal',
schema: [
{
// 组件需要在 #/adapter.ts内注册并加上类型
component: 'Input',
// 对应组件的参数
componentProps: {
placeholder: '请输入用户名',
},
// 字段名
fieldName: 'username',
// 界面显示的label
label: '字符串',
},
{
component: 'InputPassword',
componentProps: {
placeholder: '请输入密码',
},
fieldName: 'password',
label: '密码',
},
{
component: 'InputNumber',
componentProps: {
placeholder: '请输入',
},
fieldName: 'number',
label: '数字(带后缀)',
suffix: () => '¥',
},
{
component: 'Select',
componentProps: {
allowClear: true,
filterOption: true,
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
placeholder: '请选择',
showSearch: true,
},
fieldName: 'options',
label: '下拉选',
},
{
component: 'RadioGroup',
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
fieldName: 'radioGroup',
label: '单选组',
},
{
component: 'Radio',
fieldName: 'radio',
label: '',
renderComponentContent: () => {
return {
default: () => ['Radio'],
};
},
},
{
component: 'CheckboxGroup',
componentProps: {
name: 'cname',
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
fieldName: 'checkboxGroup',
label: '多选组',
},
{
component: 'Checkbox',
fieldName: 'checkbox',
label: '',
renderComponentContent: () => {
return {
default: () => ['我已阅读并同意'],
};
},
},
{
component: 'Mentions',
componentProps: {
options: [
{
label: 'afc163',
value: 'afc163',
},
{
label: 'zombieJ',
value: 'zombieJ',
},
],
placeholder: '请输入',
},
fieldName: 'mentions',
label: '提及',
},
{
component: 'Rate',
fieldName: 'rate',
label: '评分',
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'switch',
label: '开关',
},
{
component: 'DatePicker',
fieldName: 'datePicker',
label: '日期选择框',
},
{
component: 'RangePicker',
fieldName: 'rangePicker',
label: '范围选择器',
},
{
component: 'TimePicker',
fieldName: 'timePicker',
label: '时间选择框',
},
{
component: 'TreeSelect',
componentProps: {
allowClear: true,
placeholder: '请选择',
showSearch: true,
treeData: [
{
label: 'root 1',
value: 'root 1',
children: [
{
label: 'parent 1',
value: 'parent 1',
children: [
{
label: 'parent 1-0',
value: 'parent 1-0',
children: [
{
label: 'my leaf',
value: 'leaf1',
},
{
label: 'your leaf',
value: 'leaf2',
},
],
},
{
label: 'parent 1-1',
value: 'parent 1-1',
},
],
},
{
label: 'parent 2',
value: 'parent 2',
},
],
},
],
treeNodeFilterProp: 'label',
},
fieldName: 'treeSelect',
label: '树选择',
},
],
wrapperClass: 'grid-cols-1',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
</script>
<template>
<BaseForm />
</template>

View File

@@ -0,0 +1,68 @@
<script lang="ts" setup>
import { h } from 'vue';
import { Input, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter';
const [Form] = useVbenForm({
// 所有表单项共用,可单独在表单内覆盖
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
labelClass: 'w-2/6',
},
// 提交函数
handleSubmit: onSubmit,
// 垂直布局label和input在不同行值为vertical
// 水平布局label和input在同一行
layout: 'horizontal',
schema: [
{
// 组件需要在 #/adapter.ts内注册并加上类型
component: 'Input',
fieldName: 'field',
label: '自定义后缀',
suffix: () => h('span', { class: 'text-red-600' }, '元'),
},
{
component: 'Input',
fieldName: 'field1',
label: '自定义组件slot',
renderComponentContent: () => ({
prefix: () => 'prefix',
suffix: () => 'suffix',
}),
},
{
component: h(Input, { placeholder: '请输入' }),
fieldName: 'field2',
label: '自定义组件',
rules: 'required',
},
{
component: 'Input',
fieldName: 'field3',
label: '自定义组件(slot)',
rules: 'required',
},
],
wrapperClass: 'grid-cols-1',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
</script>
<template>
<Form>
<template #field3="slotProps">
<Input placeholder="请输入" v-bind="slotProps" />
</template>
</Form>
</template>

View File

@@ -0,0 +1,168 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter';
const [Form] = useVbenForm({
// 提交函数
handleSubmit: onSubmit,
schema: [
{
component: 'Input',
defaultValue: 'hidden value',
dependencies: {
show: false,
// 随意一个字段改变时,都会触发
triggerFields: ['field1Switch'],
},
fieldName: 'hiddenField',
label: '隐藏字段',
},
{
component: 'Switch',
defaultValue: true,
fieldName: 'field1Switch',
help: '通过Dom控制销毁',
label: '显示字段1',
},
{
component: 'Switch',
defaultValue: true,
fieldName: 'field2Switch',
help: '通过css控制隐藏',
label: '显示字段2',
},
{
component: 'Switch',
fieldName: 'field3Switch',
label: '禁用字段3',
},
{
component: 'Switch',
fieldName: 'field4Switch',
label: '字段4必填',
},
{
component: 'Input',
dependencies: {
if(values) {
return !!values.field1Switch;
},
// 只有指定的字段改变时,才会触发
triggerFields: ['field1Switch'],
},
// 字段名
fieldName: 'field1',
// 界面显示的label
label: '字段1',
},
{
component: 'Input',
dependencies: {
show(values) {
return !!values.field2Switch;
},
triggerFields: ['field2Switch'],
},
fieldName: 'field2',
label: '字段2',
},
{
component: 'Input',
dependencies: {
disabled(values) {
return !!values.field3Switch;
},
triggerFields: ['field3Switch'],
},
fieldName: 'field3',
label: '字段3',
},
{
component: 'Input',
dependencies: {
required(values) {
return !!values.field4Switch;
},
triggerFields: ['field4Switch'],
},
fieldName: 'field4',
label: '字段4',
},
{
component: 'Input',
dependencies: {
rules(values) {
if (values.field1 === '123') {
return 'required';
}
return null;
},
triggerFields: ['field1'],
},
fieldName: 'field5',
help: '当字段1的值为`123`时,必填',
label: '动态rules',
},
{
component: 'Select',
componentProps: {
allowClear: true,
class: 'w-full',
filterOption: true,
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
placeholder: '请选择',
showSearch: true,
},
dependencies: {
componentProps(values) {
if (values.field2 === '123') {
return {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
{
label: '选项3',
value: '3',
},
],
};
}
return {};
},
triggerFields: ['field2'],
},
fieldName: 'field6',
help: '当字段2的值为`123`时,更改下拉选项',
label: '动态配置',
},
],
// 大屏一行显示3个中屏一行显示2个小屏一行显示1个
wrapperClass: 'grid-cols-1 md:grid-cols-2',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
</script>
<template>
<Form />
</template>

View File

@@ -0,0 +1,94 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter';
const [QueryForm] = useVbenForm({
// 默认展开
collapsed: false,
// 所有表单项共用,可单独在表单内覆盖
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
},
// 提交函数
handleSubmit: onSubmit,
// 垂直布局label和input在不同行值为vertical
// 水平布局label和input在同一行
layout: 'horizontal',
schema: [
{
// 组件需要在 #/adapter.ts内注册并加上类型
component: 'Input',
// 对应组件的参数
componentProps: {
placeholder: '请输入用户名',
},
// 字段名
fieldName: 'username',
// 界面显示的label
label: '字符串',
},
{
component: 'InputPassword',
componentProps: {
placeholder: '请输入密码',
},
fieldName: 'password',
label: '密码',
},
{
component: 'InputNumber',
componentProps: {
placeholder: '请输入',
},
fieldName: 'number',
label: '数字(带后缀)',
suffix: () => '¥',
},
{
component: 'Select',
componentProps: {
allowClear: true,
filterOption: true,
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
placeholder: '请选择',
showSearch: true,
},
fieldName: 'options',
label: '下拉选',
},
{
component: 'DatePicker',
fieldName: 'datePicker',
label: '日期选择框',
},
],
// 是否可展开
showCollapseButton: true,
submitButtonOptions: {
text: '查询',
},
wrapperClass: 'grid-cols-1 md:grid-cols-2',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
</script>
<template>
<QueryForm />
</template>

View File

@@ -0,0 +1,189 @@
<script lang="ts" setup>
import { message } from 'ant-design-vue';
import { useVbenForm, z } from '#/adapter';
const [Form] = useVbenForm({
// 所有表单项共用,可单独在表单内覆盖
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
},
// 提交函数
handleSubmit: onSubmit,
// 垂直布局label和input在不同行值为vertical
// 水平布局label和input在同一行
layout: 'horizontal',
schema: [
{
// 组件需要在 #/adapter.ts内注册并加上类型
component: 'Input',
// 对应组件的参数
componentProps: {
placeholder: '请输入',
},
// 字段名
fieldName: 'field1',
// 界面显示的label
label: '字段1',
rules: 'required',
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
defaultValue: '默认值',
fieldName: 'field2',
label: '默认值(必填)',
rules: 'required',
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'field3',
label: '默认值(非必填)',
rules: z.string().default('默认值').optional(),
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'field31',
label: '自定义信息',
rules: z.string().min(1, { message: '最少输入1个字符' }),
},
{
component: 'Input',
// 对应组件的参数
componentProps: {
placeholder: '请输入',
},
// 字段名
fieldName: 'field4',
// 界面显示的label
label: '邮箱',
rules: z.string().email('请输入正确的邮箱'),
},
{
component: 'InputNumber',
componentProps: {
placeholder: '请输入',
},
fieldName: 'number',
label: '数字',
rules: 'required',
},
{
component: 'Select',
componentProps: {
allowClear: true,
filterOption: true,
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
placeholder: '请选择',
showSearch: true,
},
defaultValue: undefined,
fieldName: 'options',
label: '下拉选',
rules: 'selectRequired',
},
{
component: 'RadioGroup',
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
fieldName: 'radioGroup',
label: '单选组',
rules: 'selectRequired',
},
{
component: 'CheckboxGroup',
componentProps: {
name: 'cname',
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
fieldName: 'checkboxGroup',
label: '多选组',
rules: 'selectRequired',
},
{
component: 'Checkbox',
fieldName: 'checkbox',
label: '',
renderComponentContent: () => {
return {
default: () => ['我已阅读并同意'],
};
},
rules: 'selectRequired',
},
{
component: 'DatePicker',
defaultValue: undefined,
fieldName: 'datePicker',
label: '日期选择框',
rules: 'selectRequired',
},
{
component: 'RangePicker',
defaultValue: undefined,
fieldName: 'rangePicker',
label: '区间选择框',
rules: 'selectRequired',
},
{
component: 'InputPassword',
componentProps: {
placeholder: '请输入',
},
fieldName: 'password',
label: '密码',
rules: 'required',
},
],
wrapperClass: 'grid-cols-1',
});
function onSubmit(values: Record<string, any>) {
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
}
</script>
<template>
<Form />
</template>

View File

@@ -46,8 +46,6 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
```json ```json
{ {
"scripts": { "scripts": {
// Install dependencies
"bootstrap": "pnpm install",
// Build the project // Build the project
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build", "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
// Build the project with analysis // Build the project with analysis
@@ -77,7 +75,7 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
// Check types // Check types
"check:type": "turbo run typecheck", "check:type": "turbo run typecheck",
// Clean the project (delete node_modules, dist, .turbo, etc.) // Clean the project (delete node_modules, dist, .turbo, etc.)
"clean": "vsh clean", "clean": "node ./scripts/clean.mjs",
// Commit code // Commit code
"commit": "czg", "commit": "czg",
// Start the project (by default, the dev scripts of all packages in the entire repository will run) // Start the project (by default, the dev scripts of all packages in the entire repository will run)
@@ -97,7 +95,7 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
// Lint code // Lint code
"lint": "vsh lint", "lint": "vsh lint",
// After installing dependencies, execute the stub script for all packages // After installing dependencies, execute the stub script for all packages
"postinstall": "turbo run stub", "postinstall": "pnpm -r run stub --if-present",
// Only allow using pnpm // Only allow using pnpm
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
// Install husky // Install husky
@@ -107,9 +105,9 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
// Package specification check // Package specification check
"publint": "vsh publint", "publint": "vsh publint",
// Delete all node_modules, yarn.lock, package.lock.json, and reinstall dependencies // Delete all node_modules, yarn.lock, package.lock.json, and reinstall dependencies
"reinstall": "pnpm clean --del-lock && pnpm bootstrap", "reinstall": "pnpm clean --del-lock && pnpm install",
// Run vitest unit tests // Run vitest unit tests
"test:unit": "vitest", "test:unit": "vitest run --dom",
// Update project dependencies // Update project dependencies
"update:deps": " pnpm update --latest --recursive", "update:deps": " pnpm update --latest --recursive",
// Changeset generation and versioning // Changeset generation and versioning

View File

@@ -163,6 +163,8 @@ The `src/api/request.ts` within the application can be configured according to t
/** /**
* This file can be adjusted according to business logic * This file can be adjusted according to business logic
*/ */
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
@@ -227,7 +229,7 @@ function createRequestClient(baseURL: string) {
}); });
// Deal Response Data // Deal Response Data
client.addResponseInterceptor({ client.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => { fulfilled: (response) => {
const { data: responseData, status } = response; const { data: responseData, status } = response;
@@ -253,7 +255,10 @@ function createRequestClient(baseURL: string) {
// Generic error handling; if none of the above error handling logic is triggered, it will fall back to this. // Generic error handling; if none of the above error handling logic is triggered, it will fall back to this.
client.addResponseInterceptor( client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)), errorMessageResponseInterceptor((msg: string, _error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
message.error(msg);
}),
); );
return client; return client;

View File

@@ -163,7 +163,7 @@ const defaultPreferences: Preferences = {
compact: false, compact: false,
contentCompact: 'wide', contentCompact: 'wide',
defaultAvatar: defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.6/source/avatar-v1.webp', 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
dynamicTitle: true, dynamicTitle: true,
enableCheckUpdates: true, enableCheckUpdates: true,
enablePreferences: true, enablePreferences: true,
@@ -202,7 +202,7 @@ const defaultPreferences: Preferences = {
}, },
logo: { logo: {
enable: true, enable: true,
source: 'https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp', source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
}, },
navigation: { navigation: {
accordion: true, accordion: true,

View File

@@ -37,8 +37,6 @@ If you want to adjust the content of the login form, you can configure the `Auth
```vue ```vue
<AuthenticationLogin <AuthenticationLogin
:loading="authStore.loginLoading" :loading="authStore.loginLoading"
password-placeholder="123456"
username-placeholder="vben"
@submit="authStore.authLogin" @submit="authStore.authLogin"
/> />
``` ```

View File

@@ -42,23 +42,6 @@ Check the dependency situation of the entire project and output `unused dependen
pnpm vsh check-dep pnpm vsh check-dep
``` ```
### vsh clean
Delete the project's `node_modules`, `dist`, `.turbo` directories, etc., to clean the project.
#### Usage
```bash
pnpm vsh clean
```
#### Options
| Option | Description |
| --- | --- |
| `-r,--recursive` | Recursively delete the entire project, default `true` |
| `--del-lock` | Whether to delete the `pnpm-lock.yaml` file, default `true` |
### vsh lint ### vsh lint
Lint checks the project to see if the code in the project conforms to standards. Lint checks the project to see if the code in the project conforms to standards.

View File

@@ -8,7 +8,7 @@ hero:
text: Enterprise-Level Management System Framework text: Enterprise-Level Management System Framework
tagline: Fully Upgraded, Ready to Use, Simple and Efficient tagline: Fully Upgraded, Ready to Use, Simple and Efficient
image: image:
src: https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp src: https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp
alt: Vben Admin alt: Vben Admin
actions: actions:
- theme: brand - theme: brand

View File

@@ -9,7 +9,7 @@
- 通过邮箱联系作者: [ann.vben@gmail.com](mailto:ann.vben@gmail.com) - 通过邮箱联系作者: [ann.vben@gmail.com](mailto:ann.vben@gmail.com)
- 通过微信联系作者: - 通过微信联系作者:
<img src="https://unpkg.com/@vbenjs/static-source@0.1.6/source/wechat.jpg" style="width: 300px;"/> <img src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/wechat.jpg" style="width: 300px;"/>
### 提供资料 ### 提供资料
@@ -22,6 +22,6 @@
- 名称Vben Admin - 名称Vben Admin
- 链接https://www.vben.pro - 链接https://www.vben.pro
- 描述Vben Admin 企业级开箱即用的中后台前端解决方案 - 描述Vben Admin 企业级开箱即用的中后台前端解决方案
- Logohttps://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp - Logohttps://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp
我们将定期的检查友情链接,如果发现您的网站已经删除了我们的友情链接以及链接地址是否正确。 我们将定期的检查友情链接,如果发现您的网站已经删除了我们的友情链接以及链接地址是否正确。

View File

@@ -46,8 +46,6 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
```json ```json
{ {
"scripts": { "scripts": {
// 安装依赖
"bootstrap": "pnpm install",
// 构建项目 // 构建项目
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build", "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
// 构建项目并分析 // 构建项目并分析
@@ -77,7 +75,7 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
// 检查类型 // 检查类型
"check:type": "turbo run typecheck", "check:type": "turbo run typecheck",
// 清理项目删除node_modules、dist、.turbo等目录 // 清理项目删除node_modules、dist、.turbo等目录
"clean": "vsh clean", "clean": "node ./scripts/clean.mjs",
// 提交代码 // 提交代码
"commit": "czg", "commit": "czg",
// 启动项目默认会运行整个仓库所有包的dev脚本 // 启动项目默认会运行整个仓库所有包的dev脚本
@@ -97,7 +95,7 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
// lint 代码 // lint 代码
"lint": "vsh lint", "lint": "vsh lint",
// 依赖安装完成之后执行所有包的stub脚本 // 依赖安装完成之后执行所有包的stub脚本
"postinstall": "turbo run stub", "postinstall": "pnpm -r run stub --if-present",
// 只允许使用pnpm // 只允许使用pnpm
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
// husky的安装 // husky的安装
@@ -107,9 +105,9 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
// 包规范检查 // 包规范检查
"publint": "vsh publint", "publint": "vsh publint",
// 删除所有的node_modules、yarn.lock、package.lock.json重新安装依赖 // 删除所有的node_modules、yarn.lock、package.lock.json重新安装依赖
"reinstall": "pnpm clean --del-lock && pnpm bootstrap", "reinstall": "pnpm clean --del-lock && pnpm install",
// 运行 vitest 单元测试 // 运行 vitest 单元测试
"test:unit": "vitest", "test:unit": "vitest run --dom",
// 更新项目依赖 // 更新项目依赖
"update:deps": " pnpm update --latest --recursive", "update:deps": " pnpm update --latest --recursive",
// changeset生成提交集 // changeset生成提交集

View File

@@ -163,6 +163,8 @@ export async function deleteUserApi(user: UserInfo) {
/** /**
* 该文件可自行根据业务逻辑进行调整 * 该文件可自行根据业务逻辑进行调整
*/ */
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
@@ -230,7 +232,7 @@ function createRequestClient(baseURL: string) {
}); });
// response数据解构 // response数据解构
client.addResponseInterceptor({ client.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => { fulfilled: (response) => {
const { data: responseData, status } = response; const { data: responseData, status } = response;
@@ -256,7 +258,10 @@ function createRequestClient(baseURL: string) {
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里 // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor( client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)), errorMessageResponseInterceptor((msg: string, _error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
message.error(msg);
}),
); );
return client; return client;

View File

@@ -185,7 +185,7 @@ const defaultPreferences: Preferences = {
compact: false, compact: false,
contentCompact: 'wide', contentCompact: 'wide',
defaultAvatar: defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.6/source/avatar-v1.webp', 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
dynamicTitle: true, dynamicTitle: true,
enableCheckUpdates: true, enableCheckUpdates: true,
enablePreferences: true, enablePreferences: true,
@@ -224,7 +224,7 @@ const defaultPreferences: Preferences = {
}, },
logo: { logo: {
enable: true, enable: true,
source: 'https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp', source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
}, },
navigation: { navigation: {
accordion: true, accordion: true,

View File

@@ -1,10 +1,14 @@
---
outline: deep
---
# 登录 # 登录
本文介绍如何去改造自己的应用程序登录页。 本文介绍如何去改造自己的应用程序登录页以及如何快速的对接登录页面接口
## 登录页面调整 ## 登录页面调整
如果你想调整登录页面的标题、描述和图标以及工具栏,你可以通过配置 `AuthPageLayout` 组件的 `props` 参数来实现。 如果你想调整登录页面的标题、描述和图标以及工具栏,你可以通过配置 `AuthPageLayout` 组件的参数来实现。
![login](/guide/login.png) ![login](/guide/login.png)
@@ -30,8 +34,6 @@
```vue ```vue
<AuthenticationLogin <AuthenticationLogin
:loading="authStore.loginLoading" :loading="authStore.loginLoading"
password-placeholder="123456"
username-placeholder="vben"
@submit="authStore.authLogin" @submit="authStore.authLogin"
/> />
``` ```
@@ -108,8 +110,111 @@
::: :::
::: tip ::: tip Note
如果这些配置不能满足你的需求,你可以自行实现登录表单及相关登录逻辑。 如果这些配置不能满足你的需求,你可以自行实现登录表单及相关登录逻辑或者给我们提交 `PR`
::: :::
## 接口对接流程
这里将会快速的介绍如何快速对接自己的后端。
### 前置条件
- 首先文档用的后端服务,接口返回的格式统一如下:
```ts
interface HttpResponse<T = any> {
/**
* 0 表示成功 其他表示失败
* 0 means success, others means fail
*/
code: number;
data: T;
message: string;
}
```
如果你不符合这个格式,你需要先阅读 [服务端交互](../essentials/server.md) 文档,改造你的`request.ts`配置。
- 其次你需要在先将本地代理地址改为你的真实后端地址,你可以在应用下的 `vite.config.mts` 内配置:
```ts
import { defineConfig } from '@vben/vite-config';
export default defineConfig(async () => {
return {
vite: {
server: {
proxy: {
'/api': {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
// 这里改为你的真实接口地址
target: 'http://localhost:5320/api',
ws: true,
},
},
},
},
};
});
```
### 登录接口
为了能正常登录,你的后端最少需要提供 `2-3` 个接口:
- 登录接口
接口地址可在应用下的 `src/api/core/auth` 内修改,以下为默认接口地址:
```ts
/**
* 登录
*/
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/** 只需要保证登录接口返回值有 `accessToken` 字段即可 */
export interface LoginResult {
accessToken: string;
}
```
- 获取用户信息接口
接口地址可在应用下的 `src/api/core/user` 内修改,以下为默认接口地址:
```ts
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/info');
}
/** 只需要保证登录接口返回值有以下字段即可,多的字段可以自行使用 */
export interface UserInfo {
roles: string[];
realName: string;
}
```
- 获取权限码 (可选)
这个接口用于获取用户的权限码,权限码是用于控制用户的权限的,接口地址可在应用下的 `src/api/core/auth` 内修改,以下为默认接口地址:
```ts
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}
```
如果你不需要这个权限,你只需要把代码改为返回一个空数组即可。
```ts {2}
export async function getAccessCodesApi() {
// 这里返回一个空数组即可
return [];
}
```

View File

@@ -30,12 +30,12 @@ git -v
::: code-group ::: code-group
```bash [GitHub] ```sh [GitHub]
# clone 代码 # clone 代码
git clone https://github.com/vbenjs/vue-vben-admin.git git clone https://github.com/vbenjs/vue-vben-admin.git
``` ```
```bash [Gitee] ```sh [Gitee]
# clone 代码 # clone 代码
# Gitee 的代码可能不是最新的 # Gitee 的代码可能不是最新的
git clone https://gitee.com/annsion/vue-vben-admin.git git clone https://gitee.com/annsion/vue-vben-admin.git

View File

@@ -1,3 +1,7 @@
---
outline: deep
---
# 精简版本 # 精简版本
`5.0` 版本开始,我们不再提供精简的仓库或者分支。我们的目标是提供一个更加一致的开发体验,同时减少维护成本。在这里,我们将如何介绍自己的项目,如何去精简以及移除不需要的功能。 `5.0` 版本开始,我们不再提供精简的仓库或者分支。我们的目标是提供一个更加一致的开发体验,同时减少维护成本。在这里,我们将如何介绍自己的项目,如何去精简以及移除不需要的功能。
@@ -65,3 +69,26 @@ pnpm install
} }
} }
``` ```
## 其他
如果你想更进一步精简,你可以删除参考一下文件或者文件夹的作用,判断自己是否需要,不需要删除即可:
- `.changeset` 文件夹用于管理版本变更
- `.github` 文件夹用于存放 GitHub 的配置文件
- `.vscode` 文件夹用于存放 VSCode 的配置文件,如果你使用其他编辑器,可以删除
- `./scripts/deploy` 文件夹用于存放部署脚本如果你不需要docker部署可以删除
## 应用精简
当你确定了某个应用,你还可以进一步精简:
### 删除不需要的路由及页面
- 在应用的 `src/router/routes` 文件中,你可以删除不需要的路由。其中 `core` 文件夹内,如果只需要登录和忘记密码,你可以删除其他路由,如忘记密码、注册等。路由删除后,你可以删除对应的页面文件,在 `src/views/_core` 文件夹中。
- 在应用的 `src/router/routes` 文件中,你可以按需求删除不需要的路由,如`demos``vben` 目录等。路由删除后,你可以删除对应的页面文件,在 `src/views` 文件夹中。
### 删除不需要的组件
- 在应用的 `packages/effects/common-ui/src/ui` 文件夹中,你可以删除不需要的组件,如`about``dashboard` 目录等。删除之前请先确保你的路由中没有引用到这些组件。

View File

@@ -42,16 +42,6 @@ pnpm vsh check-circular
pnpm vsh check-dep pnpm vsh check-dep
``` ```
### vsh clean
删除项目的`node_modules``dist``.turbo`等目录,清理项目。
#### 用法
```bash
pnpm vsh clean
```
#### 选项 #### 选项
| 选项 | 说明 | | 选项 | 说明 |

View File

@@ -8,7 +8,7 @@ hero:
text: 企业级管理系统框架 text: 企业级管理系统框架
tagline: 全新升级,开箱即用,简单高效 tagline: 全新升级,开箱即用,简单高效
image: image:
src: https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp src: https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp
alt: Vben Admin alt: Vben Admin
actions: actions:
- theme: brand - theme: brand

View File

@@ -2,7 +2,7 @@
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持! 如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
![](https://unpkg.com/@vbenjs/static-source@0.1.6/source/sponsor.png) ![](https://unpkg.com/@vbenjs/static-source@0.1.7/source/sponsor.png)
您的赞助将帮助我们: 您的赞助将帮助我们:

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