38 Commits

Author SHA1 Message Date
dap
89dd4b8131 chore: version update 2025-04-30 11:26:57 +08:00
dap
a10a981fab Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev 2025-04-30 11:13:25 +08:00
Jin Mao
20c15f352f perf: page componet supports custom height offset for flexible content height … (#6081)
* perf: Page supports custom height offset for flexible content height control.

允许通过 height 属性调整页面内容高度计算。修改了 Page 组件以支持自定义高度偏移量,用于更灵活的内容高度控制。

* chore: typo

* perf(page): replace height with heightOffset for flexible content sizing

The `height` prop was replaced with `heightOffset` to better describe its purpose when used with `autoContentHeight`. The new prop allows custom offset values (in pixels) to adjust content area sizing, with clearer documentation.
2025-04-29 18:15:12 +08:00
Netfan
8aa7dabeff fix: calculation for collapsing search form is incorrect while initially hidden (#6068)
* 修复当默认隐藏搜索表单时,折叠位置的计算不正确的问题
2025-04-28 23:20:33 +08:00
vben
78c7c1589a chore: update readme.md 2025-04-28 23:11:34 +08:00
Vben
dd833ca56b chore: update dependencies and documentation, optimize build toolchain (#6060)
* chore: update packageManager version to pnpm@10.9.0 for compatibility improvements

* chore: Update dependent versions and configurations to improve compatibility and stability

- Update Node version to 22.1.0
- Updated pnpm version to 10.10.0
- Fixed syntax error in prettier command in lintstagedrc
- Update dependent versions in pnpm-lock.yaml to ensure consistency
- Update format and content in README documents to improve readability

* fix: lint error
2025-04-28 23:08:05 +08:00
vem
681c1dc267 fix: Update existing route index to prevent 404 on user switch (#6003)
Co-authored-by: tars-macmini <vem@qq.com>
2025-04-28 18:19:47 +08:00
Netfan
4545422ee0 fix: lock state will not change overflow style in drawer and modal (#6067)
* Modal和Drawer的锁定状态不再修改overflow样式
2025-04-28 17:02:54 +08:00
dap
5f26f5662e Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev 2025-04-28 13:19:57 +08:00
Gahotx
ca94ca906f fix: add rounded corners to project and quick nav items (#5296) 2025-04-27 22:50:42 +08:00
Vben
76de450c71 chore: update dependency version for improved stability and compatibility (#6023)
* chore: update dependency version for improved stability and compatibility

* fix: optimize clearPoints function in useCaptchaPoints hook to improve performance

* fix: make several props optional in various components for better flexibility
2025-04-27 22:06:49 +08:00
Trivikram Kamat
dd2b1ed580 fix: install corepack from npm (#5905)
* fix: install corepack from npm

* docs: install corepack from npm
2025-04-27 22:03:35 +08:00
ming4762
baec89f896 perf: resolve duplicate component names (#6039) 2025-04-27 22:02:38 +08:00
vben
7c7051a11e chore: release v5.5.5 2025-04-27 21:45:10 +08:00
Netfan
aa27a2f7a1 feat: encrypt the privacy data when it is persisted (#6056)
* 对私密数据持久化时执行加密
* 将锁屏密码合并到accessStore中进行加密
2025-04-27 20:59:10 +08:00
Jin Mao
9ee6d06d50 docs: add deepWiki doc link (#6057) 2025-04-27 20:54:07 +08:00
ming4762
0cc1cb5a7b perf: improve destroyOnClose for VbenDrawer&VbenModal (#6051)
* fix: fix that the default value of modal destroyOnClose does not take effect

* perf: improve destroyOnClose for VbenDrawer
2025-04-27 11:26:50 +08:00
dap
e662681ce2 fix: 拖拽上传在单文件时的样式 2025-04-27 09:57:16 +08:00
Netfan
0a9fc4e02d fix: title of search button in vxeTable toolbar (#6046)
* 修改vxeTable工具栏里的搜索按钮的提示文案
2025-04-26 01:08:41 +08:00
Netfan
be840460d8 feat: vbenSelect support prop allowClear (#6043) 2025-04-25 23:37:03 +08:00
Netfan
cb45987fe2 docs: update example (#6036)
* 跟进后端菜单逻辑的修改,现已无需传递basicLayout布局
2025-04-25 11:44:47 +08:00
panda7
5ffd7db8e0 fix: the initial value echo for the check-button-group (#6029)
Co-authored-by: sqchen <9110848@qq.com>
2025-04-25 08:35:03 +08:00
Netfan
14377705e7 fix: alert confirm state in beforeClose callback (#6019) 2025-04-23 12:20:52 +08:00
dap
23503778d4 chore: 去除vxe的锁定 2025-04-22 17:56:22 +08:00
dap
f54fab0bae Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev 2025-04-22 17:55:44 +08:00
pangyajun123
b985ff0584 fix: vxe-table theme token follow primary color (#6007) 2025-04-21 19:15:05 +08:00
dap
eff2f2a0b1 Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev 2025-04-20 09:14:37 +08:00
dap
664fa800cd chore: 搜定vxe版本 2025-04-20 09:13:08 +08:00
dap
5dc4448c01 docs: changelog 2025-04-20 09:06:32 +08:00
dap
ccfe992779 chore: 暂时锁定vxe版本(样式问题) 2025-04-20 09:05:57 +08:00
dap
583504495d feat: 对模板的说明... 2025-04-20 08:53:50 +08:00
dap
7fb4bf3431 fix: 工作流list展示在开启缩放会有误差导致触底逻辑不会触发 2025-04-20 08:42:19 +08:00
wyc001122
b148b8ec92 fix: fix geader menu activation path (#5997)
Co-authored-by: 王泳超 <wangyongchao@testor.com.cn>
2025-04-19 14:35:33 +08:00
Netfan
79de6bcbf7 fix: alert send wrong confirm state to beforeClose (#5991)
* 修复alert在按下Esc或者点击遮罩关闭时,可能发送错误的isConfirm状态
2025-04-17 22:23:05 +08:00
Netfan
14bd6dd25d fix: destroyOnClose works within connectedComponent (#5989)
* 修复destroyOnClose没能销毁connectedComponent自身的问题
2025-04-17 20:25:49 +08:00
dap
9b577261e2 chore: vite6.3.1已经修复开发/打包问题 解除版本锁定 2025-04-17 14:21:47 +08:00
PIPEDREA_WZJ
7f269e0d69 Update tailwindcss.md (#5602)
tailwindcss最新的版本已经是v4.x,vben中使用的是3.x的tailwindcss。在未进行兼容前,会出现运行失败的问题
2025-04-17 14:01:39 +08:00
yuh
4baec83db5 feat: add examples: form-upload (#5955)
* feat: add examples: form-upload

* fix: upload: accept and label

* fix: upload: 设置表单值、图片预览
2025-04-17 14:00:46 +08:00
127 changed files with 1453 additions and 631 deletions

View File

@@ -2,5 +2,5 @@ ports:
- port: 5555 - port: 5555
onOpen: open-preview onOpen: open-preview
tasks: tasks:
- init: corepack enable && pnpm install - init: npm i -g corepack && pnpm install
command: pnpm run dev:play command: pnpm run dev:play

View File

@@ -1 +1 @@
20.14.0 22.1.0

View File

@@ -14,7 +14,7 @@
"editor.tabSize": 2, "editor.tabSize": 2,
"editor.detectIndentation": false, "editor.detectIndentation": false,
"editor.cursorBlinking": "expand", "editor.cursorBlinking": "expand",
"editor.largeFileOptimizations": false, "editor.largeFileOptimizations": true,
"editor.accessibilitySupport": "off", "editor.accessibilitySupport": "off",
"editor.cursorSmoothCaretAnimation": "on", "editor.cursorSmoothCaretAnimation": "on",
"editor.guides.bracketPairs": "active", "editor.guides.bracketPairs": "active",
@@ -91,6 +91,7 @@
"**/bower_components": true, "**/bower_components": true,
"**/.turbo": true, "**/.turbo": true,
"**/.idea": true, "**/.idea": true,
"**/.vitepress": true,
"**/tmp": true, "**/tmp": true,
"**/.git": true, "**/.git": true,
"**/.svn": true, "**/.svn": true,
@@ -113,6 +114,8 @@
"**/yarn.lock": true "**/yarn.lock": true
}, },
"typescript.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"],
// search // search
"search.searchEditor.singleClickBehaviour": "peekDefinition", "search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false, "search.followSymlinks": false,

View File

@@ -1,3 +1,13 @@
# 1.3.3
**BUG FIX**
- 工作流list展示在开启缩放会有误差导致触底逻辑不会触发
**OTHER**
- 代码生成预览对模板的提示...(下载都懒得点一下吗)
# 1.3.2 # 1.3.2
**REFACTOR** **REFACTOR**

View File

@@ -1,4 +1,9 @@
<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> <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)
@@ -15,27 +20,27 @@ Vue Vben Adminは、最新の`vue3`、`vite`、`TypeScript`などの主流技術
## アップグレード通知 ## アップグレード通知
これは最新バージョン5.0であり、以前のバージョンとは互換性がありません。新しいプロジェクトを開始する場合は、最新バージョンを使用することをお勧めします。古いバージョンを表示したい場合は、[v2ブランチ](https://github.com/vbenjs/vue-vben-admin/tree/v2)を使用してください。 これは最新バージョン `5.0` であり、以前のバージョンとは互換性がありません。新しいプロジェクトを開始する場合は、最新バージョンを使用することをお勧めします。古いバージョンを表示したい場合は、[v2ブランチ](https://github.com/vbenjs/vue-vben-admin/tree/v2)を使用してください。
## 特徴 ## 特徴
- **最新技術スタック**: Vue 3やViteなどの最先端フロントエンド技術で開発 - **最新技術スタック**Vue 3やViteなどの最先端フロントエンド技術で開発
- **TypeScript**: アプリケーション規模のJavaScriptのための言語 - **TypeScript**アプリケーション規模のJavaScriptのための言語
- **テーマ**: 複数のテーマカラーが利用可能で、カスタマイズオプションも豊富 - **テーマ**複数のテーマカラーが利用可能で、カスタマイズオプションも豊富
- **国際化**: 完全な内蔵国際化サポート - **国際化**完全な内蔵国際化サポート
- **権限管理**: 動的ルートベースの権限生成ソリューションを内蔵 - **権限管理**動的ルートベースの権限生成ソリューションを内蔵
## プレビュー ## プレビュー
- [Vben Admin](https://vben.pro/) - フルバージョンの中国語サイト - [Vben Admin](https://vben.pro/) - フルバージョンの中国語サイト
テストアカウント: vben/123456 テストアカウントvben/123456
<p align="center"> <div align="center">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p> </div>
### Gitpodを使用 ### Gitpodを使用
@@ -49,30 +54,27 @@ GitpodGitHub用の無料オンライン開発環境でプロジェクト
## インストールと使用 ## インストールと使用
- プロジェクトコードを取得 1. プロジェクトコードを取得
```bash ```bash
git clone https://github.com/vbenjs/vue-vben-admin.git git clone https://github.com/vbenjs/vue-vben-admin.git
``` ```
- 依存関係のインストール 2. 依存関係のインストール
```bash ```bash
cd vue-vben-admin cd vue-vben-admin
npm i -g corepack
corepack enable
pnpm install pnpm install
``` ```
- 実行 3. 実行
```bash ```bash
pnpm dev pnpm dev
``` ```
- ビルド 4. ビルド
```bash ```bash
pnpm build pnpm build
@@ -86,17 +88,17 @@ pnpm build
ご参加をお待ちしております![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を送信してください。
**Pull Request:** **Pull Request プロセス:**
1. コードをフォーク 1. コードをフォーク
2. 自分のブランチを作成: `git checkout -b feat/xxxx` 2. 自分のブランチを作成`git checkout -b feat/xxxx`
3. 変更をコミット: `git commit -am 'feat(function): add xxxxx'` 3. 変更をコミット`git commit -am 'feat(function): add xxxxx'`
4. ブランチをプッシュ: `git push origin feat/xxxx` 4. ブランチをプッシュ`git push origin feat/xxxx`
5. `pull request`を送信 5. `pull request`を送信
## Git貢献提出規則 ## Git貢献提出規則
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 規則 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)) 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 規則 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` 新機能の追加 - `feat` 新機能の追加
- `fix` 問題/バグの修正 - `fix` 問題/バグの修正
@@ -109,7 +111,6 @@ pnpm build
- `chore` 依存関係の更新/スキャフォールディング設定の変更など - `chore` 依存関係の更新/スキャフォールディング設定の変更など
- `ci` 継続的インテグレーション - `ci` 継続的インテグレーション
- `types` 型定義ファイルの変更 - `types` 型定義ファイルの変更
- `wip` 開発中
## ブラウザサポート ## ブラウザサポート
@@ -117,9 +118,9 @@ pnpm build
モダンブラウザをサポートし、IEはサポートしません モダンブラウザをサポートし、IEはサポートしません
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: | | :-: | :-: | :-: | :-: |
| サポートしない | 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン | | 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン |
## メンテナー ## メンテナー
@@ -140,8 +141,7 @@ pnpm build
## 貢献者 ## 貢献者
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors"> <a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors" <img alt="Contributors" src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a> </a>
## Discord ## Discord

View File

@@ -1,4 +1,9 @@
<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> <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)
@@ -17,7 +22,7 @@ Vue Vben Admin is a free and open source middle and back-end template. Using the
This is the latest version, 5.0, and it is not compatible with previous versions. If you are starting a new project, it is recommended to use the latest version. If you wish to view the old version, please use the [v2 branch](https://github.com/vbenjs/vue-vben-admin/tree/v2). This is the latest version, 5.0, and it is not compatible with previous versions. If you are starting a new project, it is recommended to use the latest version. If you wish to view the old version, please use the [v2 branch](https://github.com/vbenjs/vue-vben-admin/tree/v2).
## Feature ## Features
- **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite - **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite
- **TypeScript**: A language for application-scale JavaScript - **TypeScript**: A language for application-scale JavaScript
@@ -31,11 +36,11 @@ This is the latest version, 5.0, and it is not compatible with previous versions
Test Account: vben/123456 Test Account: vben/123456
<p align="center"> <div align="center">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png"> <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p> </div>
### Use Gitpod ### Use Gitpod
@@ -47,31 +52,29 @@ Open the project in Gitpod (free online dev environment for GitHub) and start co
[Document](https://doc.vben.pro/) [Document](https://doc.vben.pro/)
## Install and use ## Install and Use
- Get the project code 1. Get the project code
```bash ```bash
git clone https://github.com/vbenjs/vue-vben-admin.git git clone https://github.com/vbenjs/vue-vben-admin.git
``` ```
- Installation dependencies 2. Install dependencies
```bash ```bash
cd vue-vben-admin cd vue-vben-admin
npm i -g corepack
corepack enable
pnpm install pnpm install
``` ```
- run 3. Run
```bash ```bash
pnpm dev pnpm dev
``` ```
- build 4. Build
```bash ```bash
pnpm build pnpm build
@@ -81,21 +84,21 @@ pnpm build
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases) [CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## How to contribute ## How to Contribute
You are very welcome to join[Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) Or submit a Pull Request You are very welcome to join! [Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) or submit a Pull Request.
**Pull Request:** **Pull Request Process:**
1. Fork code! 1. Fork the code
2. Create your own branch: `git checkout -b feat/xxxx` 2. Create your branch: `git checkout -b feat/xxxx`
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'` 3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
4. Push your branch: `git push origin feat/xxxx` 4. Push your branch: `git push origin feat/xxxx`
5. submit`pull request` 5. Submit `pull request`
## Git Contribution submission specification ## Git Contribution Submission Specification
- reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)) Reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` Add new features - `feat` Add new features
- `fix` Fix the problem/BUG - `fix` Fix the problem/BUG
@@ -108,17 +111,16 @@ You are very welcome to join[Raise an issue](https://github.com/anncwb/vue-vb
- `chore` Dependency update/scaffolding configuration modification etc. - `chore` Dependency update/scaffolding configuration modification etc.
- `ci` Continuous integration - `ci` Continuous integration
- `types` Type definition file changes - `types` Type definition file changes
- `wip` In development
## Browser support ## Browser Support
The `Chrome 80+` browser is recommended for local development The `Chrome 80+` browser is recommended for local development
Support modern browsers, not IE Support modern browsers, not IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: | | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## Maintainer ## Maintainer
@@ -136,11 +138,10 @@ If you think this project is helpful to you, you can help the author buy a cup o
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aee;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: #408aee;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## Contributor ## Contributors
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors"> <a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors" <img alt="Contributors" src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a> </a>
## Discord ## Discord

View File

@@ -76,7 +76,7 @@ admin 账号: admin admin123
git clone https://gitee.com/dapppp/ruoyi-plus-vben5.git git clone https://gitee.com/dapppp/ruoyi-plus-vben5.git
``` ```
- 安装依赖 2. 安装依赖
```bash ```bash
cd ruoyi-plus-vben5 cd ruoyi-plus-vben5
@@ -150,7 +150,7 @@ VITE_GLOB_WEBSOCKET_ENABLE=false
pnpm dev:antd pnpm dev:antd
``` ```
- 打包 4. 打包
```bash ```bash
pnpm build:antd pnpm build:antd
@@ -164,7 +164,7 @@ pnpm build:antd
## Git 贡献提交规范 ## Git 贡献提交规范
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)) 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` 增加新功能 - `feat` 增加新功能
- `fix` 修复问题/BUG - `fix` 修复问题/BUG
@@ -186,7 +186,7 @@ pnpm build:antd
本地开发推荐使用`Chrome` 最新版本浏览器 本地开发推荐使用`Chrome` 最新版本浏览器
支持现代浏览器, 不支持 IE 支持现代浏览器不支持 IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: | | :-: | :-: | :-: | :-: | :-: |

View File

@@ -0,0 +1,13 @@
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
return useResponseSuccess({
url: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
});
// return useResponseError("test")
});

View File

@@ -7,6 +7,7 @@ export default defineEventHandler(() => {
<li><a href="/api/menu">/api/menu/all</a></li> <li><a href="/api/menu">/api/menu/all</a></li>
<li><a href="/api/auth/codes">/api/auth/codes</a></li> <li><a href="/api/auth/codes">/api/auth/codes</a></li>
<li><a href="/api/auth/login">/api/auth/login</a></li> <li><a href="/api/auth/login">/api/auth/login</a></li>
<li><a href="/api/upload">/api/upload</a></li>
</ul> </ul>
`; `;
}); });

View File

@@ -3,3 +3,6 @@ VITE_APP_TITLE=Plus Admin
# 应用命名空间用于缓存、store等功能的前缀确保隔离 # 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=vben-web-antd VITE_APP_NAMESPACE=vben-web-antd
# 对store进行加密的密钥在将store持久化到localStorage时会使用该密钥进行加密
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-antd", "name": "@vben/web-antd",
"version": "1.3.2", "version": "1.3.3",
"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": {

View File

@@ -87,8 +87,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {}, componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false,
name: component.name, name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => { setup: (props: any, { attrs, expose, slots }) => {
const placeholder = const placeholder =
props?.placeholder || props?.placeholder ||
@@ -162,20 +162,34 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载 // 如果你的组件体积比较大,可以使用异步加载
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiSelect',
},
'select',
{
component: Select, component: Select,
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
visibleEvent: 'onDropdownVisibleChange', visibleEvent: 'onDropdownVisibleChange',
modelPropName: 'value', modelPropName: 'value',
}), },
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { ),
ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: TreeSelect, component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' }, fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon', loadingSlot: 'suffixIcon',
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'treeData', optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange', visibleEvent: 'onVisibleChange',
}), },
),
AutoComplete, AutoComplete,
Checkbox, Checkbox,
CheckboxGroup, CheckboxGroup,

View File

@@ -98,7 +98,7 @@ Upload.Dragger只会影响样式
{{ $t('component.upload.upload') }} {{ $t('component.upload.upload') }}
</a-button> </a-button>
</div> </div>
<div v-if="enableDragUpload && innerFileList?.length < maxCount"> <div v-if="enableDragUpload">
<p class="ant-upload-drag-icon"> <p class="ant-upload-drag-icon">
<InboxOutlined /> <InboxOutlined />
</p> </p>

View File

@@ -20,7 +20,7 @@ import {
} from '@vben/icons'; } from '@vben/icons';
import { useClipboard } from '@vueuse/core'; import { useClipboard } from '@vueuse/core';
import { Skeleton, Tree } from 'ant-design-vue'; import { Alert, Skeleton, Tree } from 'ant-design-vue';
import { previewCode } from '#/api/tool/gen'; import { previewCode } from '#/api/tool/gen';
@@ -185,6 +185,11 @@ const { copy } = useClipboard({ legacy: true });
</div> </div>
</template> </template>
</Tree> </Tree>
<Alert
class="mt-2"
show-icon
message="👆显示的名称为模板的文件名,非最终下载文件名..."
/>
</div> </div>
<CodeMirror <CodeMirror
v-model="codeContent" v-model="codeContent"

View File

@@ -28,6 +28,7 @@ import { categoryTree } from '#/api/workflow/category';
import { pageByAllTaskFinish, pageByAllTaskWait } from '#/api/workflow/task'; import { pageByAllTaskFinish, pageByAllTaskWait } from '#/api/workflow/task';
import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components'; import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components';
import { bottomOffset } from './constant';
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE; const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
@@ -140,7 +141,9 @@ const handleScroll = debounce(async (e: Event) => {
// e.target.scrollHeight 是元素的总高度。 // e.target.scrollHeight 是元素的总高度。
const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement; const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isBottom = scrollTop + clientHeight >= scrollHeight; const isBottom = scrollTop + clientHeight >= scrollHeight - bottomOffset;
console.log('scrollTop + clientHeight', scrollTop + clientHeight);
console.log('scrollHeight', scrollHeight);
// 滚动到底部且没有加载完成 // 滚动到底部且没有加载完成
if (isBottom && !isLoadComplete.value) { if (isBottom && !isLoadComplete.value) {

View File

@@ -0,0 +1,7 @@
/**
* 底部偏移量
* 在缩放时会差大概0.5px 导致触底逻辑不会触发
* 在这里设置手动补偿
* @see https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IC28RE#note_40175381
*/
export const bottomOffset = 2;

View File

@@ -24,6 +24,7 @@ import { cloneDeep, debounce } from 'lodash-es';
import { pageByCurrent } from '#/api/workflow/instance'; import { pageByCurrent } from '#/api/workflow/instance';
import { ApprovalCard, ApprovalPanel } from '../components'; import { ApprovalCard, ApprovalPanel } from '../components';
import { bottomOffset } from './constant';
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE; const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
@@ -95,7 +96,7 @@ const handleScroll = debounce(async (e: Event) => {
// e.target.scrollHeight 是元素的总高度。 // e.target.scrollHeight 是元素的总高度。
const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement; const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isBottom = scrollTop + clientHeight >= scrollHeight; const isBottom = scrollTop + clientHeight >= scrollHeight - bottomOffset;
// 滚动到底部且没有加载完成 // 滚动到底部且没有加载完成
if (isBottom && !isLoadComplete.value) { if (isBottom && !isLoadComplete.value) {

View File

@@ -26,6 +26,7 @@ import { categoryTree } from '#/api/workflow/category';
import { pageByTaskCopy } from '#/api/workflow/task'; import { pageByTaskCopy } from '#/api/workflow/task';
import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components'; import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components';
import { bottomOffset } from './constant';
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE; const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
@@ -99,7 +100,7 @@ const handleScroll = debounce(async (e: Event) => {
// e.target.scrollHeight 是元素的总高度。 // e.target.scrollHeight 是元素的总高度。
const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement; const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isBottom = scrollTop + clientHeight >= scrollHeight; const isBottom = scrollTop + clientHeight >= scrollHeight - bottomOffset;
// 滚动到底部且没有加载完成 // 滚动到底部且没有加载完成
if (isBottom && !isLoadComplete.value) { if (isBottom && !isLoadComplete.value) {

View File

@@ -26,6 +26,7 @@ import { categoryTree } from '#/api/workflow/category';
import { pageByTaskFinish } from '#/api/workflow/task'; import { pageByTaskFinish } from '#/api/workflow/task';
import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components'; import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components';
import { bottomOffset } from './constant';
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE; const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
@@ -99,7 +100,7 @@ const handleScroll = debounce(async (e: Event) => {
// e.target.scrollHeight 是元素的总高度。 // e.target.scrollHeight 是元素的总高度。
const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement; const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isBottom = scrollTop + clientHeight >= scrollHeight; const isBottom = scrollTop + clientHeight >= scrollHeight - bottomOffset;
// 滚动到底部且没有加载完成 // 滚动到底部且没有加载完成
if (isBottom && !isLoadComplete.value) { if (isBottom && !isLoadComplete.value) {

View File

@@ -27,6 +27,7 @@ import { categoryTree } from '#/api/workflow/category';
import { pageByTaskWait } from '#/api/workflow/task'; import { pageByTaskWait } from '#/api/workflow/task';
import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components'; import { ApprovalCard, ApprovalPanel, CopyComponent } from '../components';
import { bottomOffset } from './constant';
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE; const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
@@ -100,7 +101,7 @@ const handleScroll = debounce(async (e: Event) => {
// e.target.scrollHeight 是元素的总高度。 // e.target.scrollHeight 是元素的总高度。
const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement; const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isBottom = scrollTop + clientHeight >= scrollHeight; const isBottom = scrollTop + clientHeight >= scrollHeight - bottomOffset;
// 滚动到底部且没有加载完成 // 滚动到底部且没有加载完成
if (isBottom && !isLoadComplete.value) { if (isBottom && !isLoadComplete.value) {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/docs", "name": "@vben/docs",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "vitepress build", "build": "vitepress build",

View File

@@ -59,7 +59,7 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda
::: info 注意 ::: info 注意
- `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。另外,如果设置了`destroyOnClose`内部Modal及其子组件会在被关闭后<b>完全销毁</b>
- 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性如默认隐藏全屏按钮修改默认ZIndex等。 - 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性如默认隐藏全屏按钮修改默认ZIndex等。
::: :::

View File

@@ -58,7 +58,7 @@ Open a terminal in your code directory and execute the following commands:
cd vue-vben-admin cd vue-vben-admin
# Enable the project-specified version of pnpm # Enable the project-specified version of pnpm
corepack enable npm i -g corepack
# Install dependencies # Install dependencies
pnpm install pnpm install

View File

@@ -114,8 +114,6 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
```ts ```ts
const dashboardMenus = [ const dashboardMenus = [
{ {
// 这里固定写死 BasicLayout不可更改
component: 'BasicLayout',
meta: { meta: {
order: -1, order: -1,
title: 'page.dashboard.title', title: 'page.dashboard.title',
@@ -144,6 +142,16 @@ const dashboardMenus = [
}, },
], ],
}, },
{
name: 'Test',
path: '/test',
component: '/test/index',
meta: {
title: 'page.test',
// 部分特殊页面如果不需要基础布局页面顶部和侧边栏可将noBasicLayout设置为true
noBasicLayout: true,
},
},
]; ];
``` ```

View File

@@ -58,7 +58,7 @@ git clone https://gitee.com/annsion/vue-vben-admin.git
cd vue-vben-admin cd vue-vben-admin
# 使用项目指定的pnpm版本进行依赖安装 # 使用项目指定的pnpm版本进行依赖安装
corepack enable npm i -g corepack
# 安装依赖 # 安装依赖
pnpm install pnpm install

View File

@@ -11,3 +11,7 @@
当前只有对应的包下面存在 `tailwind.config.mjs` 文件才会启用 tailwindcss 的编译,否则不会启用 tailwindcss。如果你是纯粹的 SDK 包,不需要使用 tailwindcss可以不用创建 `tailwind.config.mjs` 文件。 当前只有对应的包下面存在 `tailwind.config.mjs` 文件才会启用 tailwindcss 的编译,否则不会启用 tailwindcss。如果你是纯粹的 SDK 包,不需要使用 tailwindcss可以不用创建 `tailwind.config.mjs` 文件。
::: :::
## 提示
`tailwindcss`已至v4.x版本使用方法与`tailwindcss: ^3.4.17`有差异v4.0无法与v3.x版本兼容在开发前请确认`package.json`中的`tailwindcss`版本。

View File

@@ -20,6 +20,9 @@ hero:
- theme: alt - theme: alt
text: 在 GitHub 查看 text: 在 GitHub 查看
link: https://github.com/vbenjs/vue-vben-admin link: https://github.com/vbenjs/vue-vben-admin
- theme: alt
text: DeepWiki 文档
link: https://deepwiki.com/vbenjs/vue-vben-admin
features: features:
- icon: 🚀 - icon: 🚀

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/commitlint-config", "name": "@vben/commitlint-config",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -10,7 +10,15 @@ export async function vue(): Promise<Linter.Config[]> {
interopDefault(import('@typescript-eslint/parser')), interopDefault(import('@typescript-eslint/parser')),
] as const); ] as const);
const flatEssential = pluginVue.configs?.['flat/essential'] || [];
const flatStronglyRecommended =
pluginVue.configs?.['flat/strongly-recommended'] || [];
const flatRecommended = pluginVue.configs?.['flat/recommended'] || [];
return [ return [
...flatEssential,
...flatStronglyRecommended,
...flatRecommended,
{ {
files: ['**/*.vue'], files: ['**/*.vue'],
languageOptions: { languageOptions: {
@@ -43,12 +51,9 @@ export async function vue(): Promise<Linter.Config[]> {
plugins: { plugins: {
vue: pluginVue, vue: pluginVue,
}, },
processor: pluginVue.processors['.vue'], processor: pluginVue.processors?.['.vue'],
rules: { rules: {
...pluginVue.configs.base.rules, ...pluginVue.configs?.base?.rules,
...pluginVue.configs['vue3-essential'].rules,
...pluginVue.configs['vue3-strongly-recommended'].rules,
...pluginVue.configs['vue3-recommended'].rules,
'vue/attribute-hyphenation': [ 'vue/attribute-hyphenation': [
'error', 'error',
@@ -131,7 +136,6 @@ export async function vue(): Promise<Linter.Config[]> {
'vue/require-default-prop': 'error', 'vue/require-default-prop': 'error',
'vue/require-explicit-emits': 'error', 'vue/require-explicit-emits': 'error',
'vue/require-prop-types': 'off', 'vue/require-prop-types': 'off',
'vue/script-setup-uses-vars': 'error',
'vue/singleline-html-element-content-newline': 'off', 'vue/singleline-html-element-content-newline': 'off',
'vue/space-infix-ops': 'error', 'vue/space-infix-ops': 'error',
'vue/space-unary-ops': ['error', { nonwords: false, words: true }], 'vue/space-unary-ops': ['error', { nonwords: false, words: true }],

View File

@@ -43,6 +43,7 @@ export default {
'stylelint-scss', 'stylelint-scss',
], ],
rules: { rules: {
'at-rule-no-deprecated': null,
'at-rule-no-unknown': [ 'at-rule-no-unknown': [
true, true,
{ {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/stylelint-config", "name": "@vben/stylelint-config",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/node-utils", "name": "@vben/node-utils",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/tailwind-config", "name": "@vben/tailwind-config",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/tsconfig", "name": "@vben/tsconfig",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/vite-config", "name": "@vben/vite-config",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@@ -3,149 +3,328 @@ import type { ConfigEnv, PluginOption, UserConfig } from 'vite';
import type { PluginOptions } from 'vite-plugin-dts'; import type { PluginOptions } from 'vite-plugin-dts';
import type { Options as PwaPluginOptions } from 'vite-plugin-pwa'; import type { Options as PwaPluginOptions } from 'vite-plugin-pwa';
/**
* ImportMap 配置接口
* @description 用于配置模块导入映射,支持自定义导入路径和范围
* @example
* ```typescript
* {
* imports: {
* 'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js'
* },
* scopes: {
* 'https://site.com/': {
* 'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js'
* }
* }
* }
* ```
*/
interface IImportMap { interface IImportMap {
/** 模块导入映射 */
imports?: Record<string, string>; imports?: Record<string, string>;
/** 作用域特定的导入映射 */
scopes?: { scopes?: {
[scope: string]: Record<string, string>; [scope: string]: Record<string, string>;
}; };
} }
/**
* 打印插件配置选项
* @description 用于配置控制台打印信息
*/
interface PrintPluginOptions { interface PrintPluginOptions {
/** /**
* 打印的数据 * 打印的数据映射
* @description 键值对形式的数据,将在控制台打印
* @example
* ```typescript
* {
* 'App Version': '1.0.0',
* 'Build Time': '2024-01-01'
* }
* ```
*/ */
infoMap?: Record<string, string | undefined>; infoMap?: Record<string, string | undefined>;
} }
/**
* Nitro Mock 插件配置选项
* @description 用于配置 Nitro Mock 服务器的行为
*/
interface NitroMockPluginOptions { interface NitroMockPluginOptions {
/** /**
* mock server 包名 * Mock 服务器包名
* @default '@vbenjs/nitro-mock'
*/ */
mockServerPackage?: string; mockServerPackage?: string;
/** /**
* mock 服务端口 * Mock 服务端口
* @default 3000
*/ */
port?: number; port?: number;
/** /**
* mock 日志是否打印 * 是否打印 Mock 日志
* @default false
*/ */
verbose?: boolean; verbose?: boolean;
} }
/**
* 归档插件配置选项
* @description 用于配置构建产物的压缩归档
*/
interface ArchiverPluginOptions { interface ArchiverPluginOptions {
/** /**
* 输出文件名 * 输出文件名
* @default dist * @default 'dist'
*/ */
name?: string; name?: string;
/** /**
* 输出目录 * 输出目录
* @default . * @default '.'
*/ */
outputDir?: string; outputDir?: string;
} }
/** /**
* importmap 插件配置 * ImportMap 插件配置
* @description 用于配置模块的 CDN 导入
*/ */
interface ImportmapPluginOptions { interface ImportmapPluginOptions {
/** /**
* CDN 供应商 * CDN 供应商
* @default jspm.io * @default 'jspm.io'
* @description 支持 esm.sh 和 jspm.io 两种 CDN 供应商
*/ */
defaultProvider?: 'esm.sh' | 'jspm.io'; defaultProvider?: 'esm.sh' | 'jspm.io';
/** importmap 配置 */ /**
* ImportMap 配置数组
* @description 配置需要从 CDN 导入的包
* @example
* ```typescript
* [
* { name: 'vue' },
* { name: 'pinia', range: '^2.0.0' }
* ]
* ```
*/
importmap?: Array<{ name: string; range?: string }>; importmap?: Array<{ name: string; range?: string }>;
/** 手动配置importmap */ /**
* 手动配置 ImportMap
* @description 自定义 ImportMap 配置
*/
inputMap?: IImportMap; inputMap?: IImportMap;
} }
/** /**
* 用于判断是否需要加载插件 * 条件插件配置
* @description 用于根据条件动态加载插件
*/ */
interface ConditionPlugin { interface ConditionPlugin {
// 判断条件 /**
* 判断条件
* @description 当条件为 true 时加载插件
*/
condition?: boolean; condition?: boolean;
// 插件对象 /**
* 插件对象
* @description 返回插件数组或 Promise
*/
plugins: () => PluginOption[] | PromiseLike<PluginOption[]>; plugins: () => PluginOption[] | PromiseLike<PluginOption[]>;
} }
/**
* 通用插件配置选项
* @description 所有插件共用的基础配置
*/
interface CommonPluginOptions { interface CommonPluginOptions {
/** 是否开启devtools */ /**
* 是否开启开发工具
* @default false
*/
devtools?: boolean; devtools?: boolean;
/** 环境变量 */ /**
* 环境变量
* @description 自定义环境变量
*/
env?: Record<string, any>; env?: Record<string, any>;
/** 是否注入metadata */ /**
* 是否注入元数据
* @default true
*/
injectMetadata?: boolean; injectMetadata?: boolean;
/** 是否构建模式 */ /**
* 是否为构建模式
* @default false
*/
isBuild?: boolean; isBuild?: boolean;
/** 构建模式 */ /**
* 构建模式
* @default 'development'
*/
mode?: string; mode?: string;
/** 开启依赖分析 */ /**
* 是否开启依赖分析
* @default false
* @description 使用 rollup-plugin-visualizer 分析依赖
*/
visualizer?: boolean | PluginVisualizerOptions; visualizer?: boolean | PluginVisualizerOptions;
} }
/**
* 应用插件配置选项
* @description 用于配置应用构建时的插件选项
*/
interface ApplicationPluginOptions extends CommonPluginOptions { interface ApplicationPluginOptions extends CommonPluginOptions {
/** 开启后会在打包dist同级生成dist.zip */ /**
* 是否开启压缩归档
* @default false
* @description 开启后会在打包目录生成 zip 文件
*/
archiver?: boolean; archiver?: boolean;
/** 压缩归档插件配置 */ /**
* 压缩归档插件配置
* @description 配置压缩归档的行为
*/
archiverPluginOptions?: ArchiverPluginOptions; archiverPluginOptions?: ArchiverPluginOptions;
/** 开启 gzip|brotli 压缩 */ /**
* 是否开启压缩
* @default false
* @description 支持 gzip 和 brotli 压缩
*/
compress?: boolean; compress?: boolean;
/** 压缩类型 */ /**
* 压缩类型
* @default ['gzip']
* @description 可选的压缩类型
*/
compressTypes?: ('brotli' | 'gzip')[]; compressTypes?: ('brotli' | 'gzip')[];
/** 在构建的时候抽离配置文件 */ /**
* 是否抽离配置文件
* @default false
* @description 在构建时抽离配置文件
*/
extraAppConfig?: boolean; extraAppConfig?: boolean;
/** 是否开启html插件 */ /**
* 是否开启 HTML 插件
* @default true
*/
html?: boolean; html?: boolean;
/** 是否开启i18n */ /**
* 是否开启国际化
* @default false
*/
i18n?: boolean; i18n?: boolean;
/** 是否开启 importmap CDN */ /**
* 是否开启 ImportMap CDN
* @default false
*/
importmap?: boolean; importmap?: boolean;
/** importmap 插件配置 */ /**
* ImportMap 插件配置
*/
importmapOptions?: ImportmapPluginOptions; importmapOptions?: ImportmapPluginOptions;
/** 是否注入app loading */ /**
* 是否注入应用加载动画
* @default true
*/
injectAppLoading?: boolean; injectAppLoading?: boolean;
/** 是否注入全局scss */ /**
* 是否注入全局 SCSS
* @default true
*/
injectGlobalScss?: boolean; injectGlobalScss?: boolean;
/** 是否注入版权信息 */ /**
* 是否注入版权信息
* @default true
*/
license?: boolean; license?: boolean;
/** 是否开启nitro mock */ /**
* 是否开启 Nitro Mock
* @default false
*/
nitroMock?: boolean; nitroMock?: boolean;
/** nitro mock 插件配置 */ /**
* Nitro Mock 插件配置
*/
nitroMockOptions?: NitroMockPluginOptions; nitroMockOptions?: NitroMockPluginOptions;
/** 开启控制台自定义打印 */ /**
* 是否开启控制台打印
* @default false
*/
print?: boolean; print?: boolean;
/** 打印插件配置 */ /**
* 打印插件配置
*/
printInfoMap?: PrintPluginOptions['infoMap']; printInfoMap?: PrintPluginOptions['infoMap'];
/** 是否开启pwa */ /**
* 是否开启 PWA
* @default false
*/
pwa?: boolean; pwa?: boolean;
/** pwa 插件配置 */ /**
* PWA 插件配置
*/
pwaOptions?: Partial<PwaPluginOptions>; pwaOptions?: Partial<PwaPluginOptions>;
/** 是否开启vxe-table懒加载 */ /**
* 是否开启 VXE Table 懒加载
* @default false
*/
vxeTableLazyImport?: boolean; vxeTableLazyImport?: boolean;
} }
/**
* 库插件配置选项
* @description 用于配置库构建时的插件选项
*/
interface LibraryPluginOptions extends CommonPluginOptions { interface LibraryPluginOptions extends CommonPluginOptions {
/** 开启 dts 输出 */ /**
* 是否开启 DTS 输出
* @default true
* @description 生成 TypeScript 类型声明文件
*/
dts?: boolean | PluginOptions; dts?: boolean | PluginOptions;
} }
/**
* 应用配置选项类型
*/
type ApplicationOptions = ApplicationPluginOptions; type ApplicationOptions = ApplicationPluginOptions;
/**
* 库配置选项类型
*/
type LibraryOptions = LibraryPluginOptions; type LibraryOptions = LibraryPluginOptions;
/**
* 应用配置定义函数类型
* @description 用于定义应用构建配置
*/
type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{ type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{
/** 应用插件配置 */
application?: ApplicationOptions; application?: ApplicationOptions;
/** Vite 配置 */
vite?: UserConfig; vite?: UserConfig;
}>; }>;
/**
* 库配置定义函数类型
* @description 用于定义库构建配置
*/
type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{ type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{
/** 库插件配置 */
library?: LibraryOptions; library?: LibraryOptions;
/** Vite 配置 */
vite?: UserConfig; vite?: UserConfig;
}>; }>;
/**
* 配置定义类型
* @description 应用或库的配置定义
*/
type DefineConfig = DefineApplicationOptions | DefineLibraryOptions; type DefineConfig = DefineApplicationOptions | DefineLibraryOptions;
export type { export type {

View File

@@ -1,6 +1,6 @@
{ {
"name": "vben-admin-monorepo", "name": "vben-admin-monorepo",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"keywords": [ "keywords": [
"monorepo", "monorepo",
@@ -96,7 +96,7 @@
"node": ">=20.10.0", "node": ">=20.10.0",
"pnpm": ">=9.12.0" "pnpm": ">=9.12.0"
}, },
"packageManager": "pnpm@9.15.9", "packageManager": "pnpm@10.10.0",
"pnpm": { "pnpm": {
"peerDependencyRules": { "peerDependencyRules": {
"allowedVersions": { "allowedVersions": {
@@ -107,7 +107,7 @@
"@ast-grep/napi": "catalog:", "@ast-grep/napi": "catalog:",
"@ctrl/tinycolor": "catalog:", "@ctrl/tinycolor": "catalog:",
"clsx": "catalog:", "clsx": "catalog:",
"esbuild": "0.24.0", "esbuild": "0.25.3",
"pinia": "catalog:", "pinia": "catalog:",
"vue": "catalog:" "vue": "catalog:"
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/design", "name": "@vben-core/design",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/icons", "name": "@vben-core/icons",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/shared", "name": "@vben-core/shared",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line vue/prefer-import-from-vue
import { isFunction, isObject, isString } from '@vue/shared'; import { isFunction, isObject, isString } from '@vue/shared';
/** /**

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/typings", "name": "@vben-core/typings",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/composables", "name": "@vben-core/composables",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/preferences", "name": "@vben-core/preferences",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/form-ui", "name": "@vben-core/form-ui",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -2,13 +2,18 @@ import type { FormRenderProps } from '../types';
import { computed, nextTick, onMounted, ref, useTemplateRef, watch } from 'vue'; import { computed, nextTick, onMounted, ref, useTemplateRef, watch } from 'vue';
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'; import {
breakpointsTailwind,
useBreakpoints,
useElementVisibility,
} from '@vueuse/core';
/** /**
* 动态计算行数 * 动态计算行数
*/ */
export function useExpandable(props: FormRenderProps) { export function useExpandable(props: FormRenderProps) {
const wrapperRef = useTemplateRef<HTMLElement>('wrapperRef'); const wrapperRef = useTemplateRef<HTMLElement>('wrapperRef');
const isVisible = useElementVisibility(wrapperRef);
const rowMapping = ref<Record<number, number>>({}); const rowMapping = ref<Record<number, number>>({});
// 是否已经计算过一次 // 是否已经计算过一次
const isCalculated = ref(false); const isCalculated = ref(false);
@@ -31,6 +36,7 @@ export function useExpandable(props: FormRenderProps) {
() => props.showCollapseButton, () => props.showCollapseButton,
() => breakpoints.active().value, () => breakpoints.active().value,
() => props.schema?.length, () => props.schema?.length,
() => isVisible.value,
], ],
async ([val]) => { async ([val]) => {
if (val) { if (val) {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/layout-ui", "name": "@vben-core/layout-ui",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/menu-ui", "name": "@vben-core/menu-ui",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -10,7 +10,7 @@ import { VbenIcon } from '@vben-core/shadcn-ui';
import { useMenuContext } from '../hooks'; import { useMenuContext } from '../hooks';
interface Props extends MenuItemProps { interface Props extends MenuItemProps {
isMenuMore: boolean; isMenuMore?: boolean;
isTopLevelMenuSubmenu: boolean; isTopLevelMenuSubmenu: boolean;
level?: number; level?: number;
} }

View File

@@ -47,6 +47,10 @@ function onAlertClosed() {
isConfirm.value = false; isConfirm.value = false;
} }
function onEscapeKeyDown() {
isConfirm.value = false;
}
const getIconRender = computed(() => { const getIconRender = computed(() => {
let iconRender: Component | null = null; let iconRender: Component | null = null;
if (props.icon) { if (props.icon) {
@@ -91,14 +95,13 @@ const getIconRender = computed(() => {
}); });
function doCancel() { function doCancel() {
isConfirm.value = false; handleCancel();
handleOpenChange(false); handleOpenChange(false);
} }
function doConfirm() { function doConfirm() {
isConfirm.value = true; handleConfirm();
handleOpenChange(false); handleOpenChange(false);
emits('confirm');
} }
provideAlertContext({ provideAlertContext({
@@ -117,7 +120,7 @@ function handleCancel() {
const loading = ref(false); const loading = ref(false);
async function handleOpenChange(val: boolean) { async function handleOpenChange(val: boolean) {
await nextTick(); await nextTick(); // 等待标记isConfirm状态
if (!val && props.beforeClose) { if (!val && props.beforeClose) {
loading.value = true; loading.value = true;
try { try {
@@ -141,6 +144,7 @@ async function handleOpenChange(val: boolean) {
:overlay-blur="overlayBlur" :overlay-blur="overlayBlur"
@opened="emits('opened')" @opened="emits('opened')"
@closed="onAlertClosed" @closed="onAlertClosed"
@escape-key-down="onEscapeKeyDown"
:class=" :class="
cn( cn(
containerClass, containerClass,

View File

@@ -52,6 +52,10 @@ export interface DrawerProps {
* 弹窗描述 * 弹窗描述
*/ */
description?: string; description?: string;
/**
* 在关闭时销毁抽屉
*/
destroyOnClose?: boolean;
/** /**
* 是否显示底部 * 是否显示底部
* @default true * @default true
@@ -143,10 +147,6 @@ export interface DrawerApiOptions extends DrawerState {
* 独立的抽屉组件 * 独立的抽屉组件
*/ */
connectedComponent?: Component; connectedComponent?: Component;
/**
* 在关闭时销毁抽屉。仅在使用 connectedComponent 时有效
*/
destroyOnClose?: boolean;
/** /**
* 关闭前的回调,返回 false 可以阻止关闭 * 关闭前的回调,返回 false 可以阻止关闭
* @returns * @returns

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { DrawerProps, ExtendedDrawerApi } from './drawer'; import type { DrawerProps, ExtendedDrawerApi } from './drawer';
import { computed, provide, ref, useId, watch } from 'vue'; import { computed, provide, ref, unref, useId, watch } from 'vue';
import { import {
useIsMobile, useIsMobile,
@@ -35,6 +35,7 @@ interface Props extends DrawerProps {
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
appendToMain: false, appendToMain: false,
closeIconPlacement: 'right', closeIconPlacement: 'right',
destroyOnClose: true,
drawerApi: undefined, drawerApi: undefined,
submitting: false, submitting: false,
zIndex: 1000, zIndex: 1000,
@@ -63,6 +64,7 @@ const {
confirmText, confirmText,
contentClass, contentClass,
description, description,
destroyOnClose,
footer: showFooter, footer: showFooter,
footerClass, footerClass,
header: showHeader, header: showHeader,
@@ -80,17 +82,17 @@ const {
zIndex, zIndex,
} = usePriorityValues(props, state); } = usePriorityValues(props, state);
watch( // watch(
() => showLoading.value, // () => showLoading.value,
(v) => { // (v) => {
if (v && wrapperRef.value) { // if (v && wrapperRef.value) {
wrapperRef.value.scrollTo({ // wrapperRef.value.scrollTo({
// behavior: 'smooth', // // behavior: 'smooth',
top: 0, // top: 0,
}); // });
} // }
}, // },
); // );
function interactOutside(e: Event) { function interactOutside(e: Event) {
if (!closeOnClickModal.value || submitting.value) { if (!closeOnClickModal.value || submitting.value) {
@@ -131,6 +133,29 @@ const getAppendTo = computed(() => {
? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div` ? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div`
: undefined; : undefined;
}); });
/**
* destroyOnClose功能完善
*/
// 是否打开过
const hasOpened = ref(false);
const isClosed = ref(true);
watch(
() => state?.value?.isOpen,
(value) => {
isClosed.value = false;
if (value && !unref(hasOpened)) {
hasOpened.value = true;
}
},
);
function handleClosed() {
isClosed.value = true;
props.drawerApi?.onClosed();
}
const getForceMount = computed(() => {
return !unref(destroyOnClose) && unref(hasOpened);
});
</script> </script>
<template> <template>
<Sheet <Sheet
@@ -144,15 +169,17 @@ const getAppendTo = computed(() => {
cn('flex w-[520px] flex-col', drawerClass, { cn('flex w-[520px] flex-col', drawerClass, {
'!w-full': isMobile || placement === 'bottom' || placement === 'top', '!w-full': isMobile || placement === 'bottom' || placement === 'top',
'max-h-[100vh]': placement === 'bottom' || placement === 'top', 'max-h-[100vh]': placement === 'bottom' || placement === 'top',
hidden: isClosed,
}) })
" "
:modal="modal" :modal="modal"
:open="state?.isOpen" :open="state?.isOpen"
:side="placement" :side="placement"
:z-index="zIndex" :z-index="zIndex"
:force-mount="getForceMount"
:overlay-blur="overlayBlur" :overlay-blur="overlayBlur"
@close-auto-focus="handleFocusOutside" @close-auto-focus="handleFocusOutside"
@closed="() => drawerApi?.onClosed()" @closed="handleClosed"
@escape-key-down="escapeKeyDown" @escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside" @focus-outside="handleFocusOutside"
@interact-outside="interactOutside" @interact-outside="interactOutside"
@@ -239,19 +266,13 @@ const getAppendTo = computed(() => {
ref="wrapperRef" ref="wrapperRef"
:class=" :class="
cn('relative flex-1 overflow-y-auto p-3', contentClass, { cn('relative flex-1 overflow-y-auto p-3', contentClass, {
'overflow-hidden': showLoading, 'pointer-events-none': showLoading || submitting,
}) })
" "
> >
<VbenLoading
v-if="showLoading || submitting"
class="size-full"
spinning
/>
<slot></slot> <slot></slot>
</div> </div>
<VbenLoading v-if="showLoading || submitting" spinning />
<SheetFooter <SheetFooter
v-if="showFooter" v-if="showFooter"
:class=" :class="

View File

@@ -21,7 +21,9 @@ import VbenDrawer from './drawer.vue';
const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT'); const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT');
const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {}; const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {
destroyOnClose: true,
};
export function setDefaultDrawerProps(props: Partial<DrawerProps>) { export function setDefaultDrawerProps(props: Partial<DrawerProps>) {
Object.assign(DEFAULT_DRAWER_PROPS, props); Object.assign(DEFAULT_DRAWER_PROPS, props);

View File

@@ -123,17 +123,17 @@ watch(
{ immediate: true }, { immediate: true },
); );
watch( // watch(
() => [showLoading.value, submitting.value], // () => [showLoading.value, submitting.value],
([l, s]) => { // ([l, s]) => {
if ((s || l) && wrapperRef.value) { // if ((s || l) && wrapperRef.value) {
wrapperRef.value.scrollTo({ // wrapperRef.value.scrollTo({
// behavior: 'smooth', // // behavior: 'smooth',
top: 0, // top: 0,
}); // });
} // }
}, // },
); // );
function handleFullscreen() { function handleFullscreen() {
props.modalApi?.setState((prev) => { props.modalApi?.setState((prev) => {
@@ -274,18 +274,13 @@ function handleClosed() {
ref="wrapperRef" ref="wrapperRef"
:class=" :class="
cn('relative min-h-40 flex-1 overflow-y-auto p-3', contentClass, { cn('relative min-h-40 flex-1 overflow-y-auto p-3', contentClass, {
'overflow-hidden': showLoading || submitting, 'pointer-events-none': showLoading || submitting,
}) })
" "
> >
<VbenLoading
v-if="showLoading || submitting"
class="size-full h-auto min-h-full"
spinning
/>
<slot></slot> <slot></slot>
</div> </div>
<VbenLoading v-if="showLoading || submitting" spinning />
<VbenIconButton <VbenIconButton
v-if="fullscreenButton" v-if="fullscreenButton"
class="hover:bg-accent hover:text-accent-foreground text-foreground/80 flex-center absolute right-10 top-3 hidden size-6 rounded-full px-1 text-lg opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none sm:block" class="hover:bg-accent hover:text-accent-foreground text-foreground/80 flex-center absolute right-10 top-3 hidden size-6 rounded-full px-1 text-lg opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none sm:block"

View File

@@ -1,6 +1,14 @@
import type { ExtendedModalApi, ModalApiOptions, ModalProps } from './modal'; import type { ExtendedModalApi, ModalApiOptions, ModalProps } from './modal';
import { defineComponent, h, inject, nextTick, provide, reactive } from 'vue'; import {
defineComponent,
h,
inject,
nextTick,
provide,
reactive,
ref,
} from 'vue';
import { useStore } from '@vben-core/shared/store'; import { useStore } from '@vben-core/shared/store';
@@ -9,7 +17,9 @@ import VbenModal from './modal.vue';
const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT'); const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT');
const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {}; const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {
destroyOnClose: true,
};
export function setDefaultModalProps(props: Partial<ModalProps>) { export function setDefaultModalProps(props: Partial<ModalProps>) {
Object.assign(DEFAULT_MODAL_PROPS, props); Object.assign(DEFAULT_MODAL_PROPS, props);
@@ -24,6 +34,7 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
const { connectedComponent } = options; const { connectedComponent } = options;
if (connectedComponent) { if (connectedComponent) {
const extendedApi = reactive({}); const extendedApi = reactive({});
const isModalReady = ref(true);
const Modal = defineComponent( const Modal = defineComponent(
(props: TParentModalProps, { attrs, slots }) => { (props: TParentModalProps, { attrs, slots }) => {
provide(USER_MODAL_INJECT_KEY, { provide(USER_MODAL_INJECT_KEY, {
@@ -33,6 +44,11 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
Object.setPrototypeOf(extendedApi, api); Object.setPrototypeOf(extendedApi, api);
}, },
options, options,
async reCreateModal() {
isModalReady.value = false;
await nextTick();
isModalReady.value = true;
},
}); });
checkProps(extendedApi as ExtendedModalApi, { checkProps(extendedApi as ExtendedModalApi, {
...props, ...props,
@@ -41,7 +57,7 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
}); });
return () => return () =>
h( h(
connectedComponent, isModalReady.value ? connectedComponent : 'div',
{ {
...props, ...props,
...attrs, ...attrs,
@@ -70,6 +86,13 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
injectData.options?.onOpenChange?.(isOpen); injectData.options?.onOpenChange?.(isOpen);
}; };
mergedOptions.onClosed = () => {
options.onClosed?.();
if (mergedOptions.destroyOnClose) {
injectData.reCreateModal?.();
}
};
const api = new ModalApi(mergedOptions); const api = new ModalApi(mergedOptions);
const extendedApi: ExtendedModalApi = api as never; const extendedApi: ExtendedModalApi = api as never;

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/shadcn-ui", "name": "@vben-core/shadcn-ui",
"version": "5.5.4", "version": "5.5.5",
"#main": "./dist/index.mjs", "#main": "./dist/index.mjs",
"#module": "./dist/index.mjs", "#module": "./dist/index.mjs",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",

View File

@@ -41,7 +41,6 @@ watch(
innerValue.value.length > 0 ? innerValue.value[0] : undefined; innerValue.value.length > 0 ? innerValue.value[0] : undefined;
} }
}, },
{ immediate: true },
); );
watch( watch(
@@ -60,7 +59,7 @@ watch(
innerValue.value = val === undefined ? [] : [val as ValueType]; innerValue.value = val === undefined ? [] : [val as ValueType];
} }
}, },
{ deep: true }, { deep: true, immediate: true },
); );
async function onBtnClick(value: ValueType) { async function onBtnClick(value: ValueType) {

View File

@@ -10,7 +10,7 @@ import TabsIndicator from './tabs-indicator.vue';
interface Props { interface Props {
defaultValue?: string; defaultValue?: string;
tabs: SegmentedItem[]; tabs?: SegmentedItem[];
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {

View File

@@ -1,4 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { CircleX } from '@vben-core/icons';
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -8,6 +10,7 @@ import {
} from '../../ui'; } from '../../ui';
interface Props { interface Props {
allowClear?: boolean;
class?: any; class?: any;
// 弹出层的类名 // 弹出层的类名
contentClass?: any; contentClass?: any;
@@ -15,12 +18,27 @@ interface Props {
placeholder?: string; placeholder?: string;
} }
const props = defineProps<Props>(); const props = withDefaults(defineProps<Props>(), {
allowClear: false,
});
const modelValue = defineModel<string>();
function handleClear() {
modelValue.value = undefined;
}
</script> </script>
<template> <template>
<Select> <Select v-model="modelValue">
<SelectTrigger :class="props.class"> <SelectTrigger :class="props.class" class="flex w-full items-center">
<SelectValue :placeholder="placeholder" /> <SelectValue class="flex-auto text-left" :placeholder="placeholder" />
<CircleX
@pointerdown.stop
@click.stop.prevent="handleClear"
v-if="allowClear && modelValue"
data-clear-button
class="mr-1 size-4 cursor-pointer opacity-50 hover:opacity-100"
/>
</SelectTrigger> </SelectTrigger>
<SelectContent :class="props.contentClass"> <SelectContent :class="props.contentClass">
<template v-for="item in options" :key="item.value"> <template v-for="item in options" :key="item.value">

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben-core/tabs-ui", "name": "@vben-core/tabs-ui",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/constants", "name": "@vben/constants",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/access", "name": "@vben/access",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -50,7 +50,15 @@ async function generateAccessible(
delete route.component; delete route.component;
} }
// 根据router name判断如果路由已经存在则不再添加 // 根据router name判断如果路由已经存在则不再添加
if (!names?.includes(route.name)) { if (names?.includes(route.name)) {
// 找到已存在的路由索引并更新不更新会造成切换用户时一级目录未更新homePath 在二级目录导致的404问题
const index = root.children?.findIndex(
(item) => item.name === route.name,
);
if (index !== undefined && index !== -1 && root.children) {
root.children[index] = route;
}
} else {
root.children?.push(route); root.children?.push(route);
} }
} else { } else {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/common-ui", "name": "@vben/common-ui",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -9,7 +9,7 @@ export function useCaptchaPoints() {
} }
function clearPoints() { function clearPoints() {
points.splice(0, points.length); points.splice(0);
} }
return { return {
addPoint, addPoint,

View File

@@ -65,7 +65,7 @@
&.jv-string { &.jv-string {
color: hsl(var(--primary)); color: hsl(var(--primary));
word-break: break-word; overflow-wrap: break-word;
white-space: normal; white-space: normal;
} }
} }

View File

@@ -3,15 +3,17 @@ import type { StyleValue } from 'vue';
import type { PageProps } from './types'; import type { PageProps } from './types';
import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue';
import { CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT } from '@vben-core/shared/constants'; import { CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT } from '@vben-core/shared/constants';
import { cn } from '@vben-core/shared/utils'; import { cn } from '@vben-core/shared/utils';
import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue';
defineOptions({ defineOptions({
name: 'Page', name: 'Page',
}); });
const { autoContentHeight = false } = defineProps<PageProps>(); const { autoContentHeight = false, heightOffset = 0 } =
defineProps<PageProps>();
const headerHeight = ref(0); const headerHeight = ref(0);
const footerHeight = ref(0); const footerHeight = ref(0);
@@ -23,7 +25,7 @@ const footerRef = useTemplateRef<HTMLDivElement>('footerRef');
const contentStyle = computed<StyleValue>(() => { const contentStyle = computed<StyleValue>(() => {
if (autoContentHeight) { if (autoContentHeight) {
return { return {
height: `calc(var(${CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT}) - ${headerHeight.value}px)`, height: `calc(var(${CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT}) - ${headerHeight.value}px - ${typeof heightOffset === 'number' ? `${heightOffset}px` : heightOffset})`,
overflowY: shouldAutoHeight.value ? 'auto' : 'unset', overflowY: shouldAutoHeight.value ? 'auto' : 'unset',
}; };
} }

View File

@@ -8,4 +8,10 @@ export interface PageProps {
autoContentHeight?: boolean; autoContentHeight?: boolean;
headerClass?: string; headerClass?: string;
footerClass?: string; footerClass?: string;
/**
* Custom height offset value (in pixels) to adjust content area sizing
* when used with autoContentHeight
* @default 0
*/
heightOffset?: number;
} }

View File

@@ -3,18 +3,20 @@ import type { VbenFormSchema } from '@vben-core/form-ui';
import type { AuthenticationProps, LoginAndRegisterParams } from './types'; import type { AuthenticationProps, LoginAndRegisterParams } from './types';
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useVbenForm } from '@vben-core/form-ui'; import { useVbenForm } from '@vben-core/form-ui';
import { VbenButton, VbenCheckbox } from '@vben-core/shadcn-ui'; import { VbenButton, VbenCheckbox } from '@vben-core/shadcn-ui';
import { cloneDeep } from '@vben-core/shared/utils'; import { cloneDeep } from '@vben-core/shared/utils';
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import Title from './auth-title.vue'; import Title from './auth-title.vue';
import ThirdPartyLogin from './third-party-login.vue'; import ThirdPartyLogin from './third-party-login.vue';
interface Props extends AuthenticationProps { interface Props extends AuthenticationProps {
formSchema: VbenFormSchema[]; formSchema?: VbenFormSchema[];
} }
defineOptions({ defineOptions({

View File

@@ -1,17 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Recordable } from '@vben/types'; import type { Recordable } from '@vben/types';
import type { VbenFormSchema } from '@vben-core/form-ui'; import type { VbenFormSchema } from '@vben-core/form-ui';
import { $t } from '@vben/locales';
import { useVbenForm } from '@vben-core/form-ui';
import { VbenButton } from '@vben-core/shadcn-ui';
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { useVbenForm } from '@vben-core/form-ui';
import { VbenButton } from '@vben-core/shadcn-ui';
import Title from './auth-title.vue'; import Title from './auth-title.vue';
interface Props { interface Props {
formSchema: VbenFormSchema[]; formSchema?: VbenFormSchema[];
/** /**
* @zh_CN 是否处于加载处理状态 * @zh_CN 是否处于加载处理状态
*/ */

View File

@@ -6,7 +6,7 @@ import { computed } from 'vue';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@vben-core/shadcn-ui'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@vben-core/shadcn-ui';
interface Props { interface Props {
tabs: TabOption[]; tabs?: TabOption[];
} }
defineOptions({ defineOptions({

View File

@@ -12,7 +12,7 @@ import {
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
items: AnalysisOverviewItem[]; items?: AnalysisOverviewItem[];
} }
defineOptions({ defineOptions({

View File

@@ -10,7 +10,7 @@ import {
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
items: WorkbenchProjectItem[]; items?: WorkbenchProjectItem[];
title: string; title: string;
} }
@@ -37,6 +37,8 @@ defineEmits(['click']);
'border-r-0': index % 3 === 2, 'border-r-0': index % 3 === 2,
'border-b-0': index < 3, 'border-b-0': index < 3,
'pb-4': index > 2, 'pb-4': index > 2,
'rounded-bl-xl': index === items.length - 3,
'rounded-br-xl': index === items.length - 1,
}" }"
class="border-border group w-full cursor-pointer border-r border-t p-4 transition-all hover:shadow-xl md:w-1/2 lg:w-1/3" class="border-border group w-full cursor-pointer border-r border-t p-4 transition-all hover:shadow-xl md:w-1/2 lg:w-1/3"
> >

View File

@@ -10,7 +10,7 @@ import {
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
items: WorkbenchQuickNavItem[]; items?: WorkbenchQuickNavItem[];
title: string; title: string;
} }
@@ -35,8 +35,10 @@ defineEmits(['click']);
<div <div
:class="{ :class="{
'border-r-0': index % 3 === 2, 'border-r-0': index % 3 === 2,
'pb-4': index > 2,
'border-b-0': index < 3, 'border-b-0': index < 3,
'pb-4': index > 2,
'rounded-bl-xl': index === items.length - 3,
'rounded-br-xl': index === items.length - 1,
}" }"
class="flex-col-center border-border group w-1/3 cursor-pointer border-r border-t py-8 hover:shadow-xl" class="flex-col-center border-border group w-1/3 cursor-pointer border-r border-t py-8 hover:shadow-xl"
@click="$emit('click', item)" @click="$emit('click', item)"

View File

@@ -10,7 +10,7 @@ import {
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
items: WorkbenchTodoItem[]; items?: WorkbenchTodoItem[];
title: string; title: string;
} }

View File

@@ -10,7 +10,7 @@ import {
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
items: WorkbenchTrendItem[]; items?: WorkbenchTrendItem[];
title: string; title: string;
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/hooks", "name": "@vben/hooks",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/layouts", "name": "@vben/layouts",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,8 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
interface Props { interface Props {
companyName: string; companyName?: string;
companySiteLink?: string; companySiteLink?: string;
date: string; date?: string;
icp?: string; icp?: string;
icpLink?: string; icpLink?: string;
} }

View File

@@ -12,7 +12,7 @@ import {
updatePreferences, updatePreferences,
usePreferences, usePreferences,
} from '@vben/preferences'; } from '@vben/preferences';
import { useLockStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
import { cloneDeep, mapTree } from '@vben/utils'; import { cloneDeep, mapTree } from '@vben/utils';
import { VbenAdminLayout } from '@vben-core/layout-ui'; import { VbenAdminLayout } from '@vben-core/layout-ui';
@@ -49,7 +49,7 @@ const {
sidebarCollapsed, sidebarCollapsed,
theme, theme,
} = usePreferences(); } = usePreferences();
const lockStore = useLockStore(); const accessStore = useAccessStore();
const { refresh } = useRefresh(); const { refresh } = useRefresh();
const sidebarTheme = computed(() => { const sidebarTheme = computed(() => {
@@ -356,7 +356,7 @@ const headerSlots = computed(() => {
/> />
<Transition v-if="preferences.widget.lockScreen" name="slide-up"> <Transition v-if="preferences.widget.lockScreen" name="slide-up">
<slot v-if="lockStore.isLockScreen" name="lock-screen"></slot> <slot v-if="accessStore.isLockScreen" name="lock-screen"></slot>
</Transition> </Transition>
<template v-if="preferencesButtonPosition.fixed"> <template v-if="preferencesButtonPosition.fixed">

View File

@@ -1,15 +1,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { MenuRecordRaw } from '@vben/types'; import type { MenuRecordRaw } from '@vben/types';
import type { MenuProps } from '@vben-core/menu-ui'; import type { MenuProps } from '@vben-core/menu-ui';
import { Menu } from '@vben-core/menu-ui';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { Menu } from '@vben-core/menu-ui';
import { useNavigation } from './use-navigation'; import { useNavigation } from './use-navigation';
interface Props extends MenuProps { interface Props extends MenuProps {
collapse?: boolean; collapse?: boolean;
menus: MenuRecordRaw[]; menus?: MenuRecordRaw[];
} }
withDefaults(defineProps<Props>(), { withDefaults(defineProps<Props>(), {

View File

@@ -1,11 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { MenuRecordRaw } from '@vben/types'; import type { MenuRecordRaw } from '@vben/types';
import type { MenuProps } from '@vben-core/menu-ui'; import type { MenuProps } from '@vben-core/menu-ui';
import { Menu } from '@vben-core/menu-ui'; import { Menu } from '@vben-core/menu-ui';
interface Props extends MenuProps { interface Props extends MenuProps {
menus: MenuRecordRaw[]; menus?: MenuRecordRaw[];
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {

View File

@@ -74,7 +74,7 @@ function useMixedMenu() {
*/ */
const headerActive = computed(() => { const headerActive = computed(() => {
if (!needSplit.value) { if (!needSplit.value) {
return route.path; return route.meta?.activePath ?? route.path;
} }
return rootMenuPath.value; return rootMenuPath.value;
}); });

View File

@@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { MenuRecordRaw } from '@vben/types'; import type { MenuRecordRaw } from '@vben/types';
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { import {
ArrowDown, ArrowDown,
ArrowUp, ArrowUp,
@@ -10,9 +12,10 @@ import {
} from '@vben/icons'; } from '@vben/icons';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { isWindowsOs } from '@vben/utils'; import { isWindowsOs } from '@vben/utils';
import { useVbenModal } from '@vben-core/popup-ui'; import { useVbenModal } from '@vben-core/popup-ui';
import { useMagicKeys, whenever } from '@vueuse/core'; import { useMagicKeys, whenever } from '@vueuse/core';
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import SearchPanel from './search-panel.vue'; import SearchPanel from './search-panel.vue';
@@ -21,7 +24,7 @@ defineOptions({
}); });
const props = withDefaults( const props = withDefaults(
defineProps<{ enableShortcutKey?: boolean; menus: MenuRecordRaw[] }>(), defineProps<{ enableShortcutKey?: boolean; menus?: MenuRecordRaw[] }>(),
{ {
enableShortcutKey: true, enableShortcutKey: true,
menus: () => [], menus: () => [],

View File

@@ -1,21 +1,24 @@
<script setup lang="ts"> <script setup lang="ts">
import type { MenuRecordRaw } from '@vben/types'; import type { MenuRecordRaw } from '@vben/types';
import { nextTick, onMounted, ref, shallowRef, watch } from 'vue';
import { useRouter } from 'vue-router';
import { SearchX, X } from '@vben/icons'; import { SearchX, X } from '@vben/icons';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { mapTree, traverseTreeValues, uniqueByField } from '@vben/utils'; import { mapTree, traverseTreeValues, uniqueByField } from '@vben/utils';
import { VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui'; import { VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
import { isHttpUrl } from '@vben-core/shared/utils'; import { isHttpUrl } from '@vben-core/shared/utils';
import { onKeyStroke, useLocalStorage, useThrottleFn } from '@vueuse/core'; import { onKeyStroke, useLocalStorage, useThrottleFn } from '@vueuse/core';
import { nextTick, onMounted, ref, shallowRef, watch } from 'vue';
import { useRouter } from 'vue-router';
defineOptions({ defineOptions({
name: 'SearchPanel', name: 'SearchPanel',
}); });
const props = withDefaults( const props = withDefaults(
defineProps<{ keyword: string; menus: MenuRecordRaw[] }>(), defineProps<{ keyword?: string; menus?: MenuRecordRaw[] }>(),
{ {
keyword: '', keyword: '',
menus: () => [], menus: () => [],

View File

@@ -1,12 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive, ref } from 'vue';
import { LockKeyhole } from '@vben/icons'; import { LockKeyhole } from '@vben/icons';
import { $t, useI18n } from '@vben/locales'; import { $t, useI18n } from '@vben/locales';
import { storeToRefs, useLockStore } from '@vben/stores'; import { storeToRefs, useAccessStore } from '@vben/stores';
import { useScrollLock } from '@vben-core/composables'; import { useScrollLock } from '@vben-core/composables';
import { useVbenForm, z } from '@vben-core/form-ui'; import { useVbenForm, z } from '@vben-core/form-ui';
import { VbenAvatar, VbenButton } from '@vben-core/shadcn-ui'; import { VbenAvatar, VbenButton } from '@vben-core/shadcn-ui';
import { useDateFormat, useNow } from '@vueuse/core'; import { useDateFormat, useNow } from '@vueuse/core';
import { computed, reactive, ref } from 'vue';
interface Props { interface Props {
avatar?: string; avatar?: string;
@@ -23,7 +26,7 @@ withDefaults(defineProps<Props>(), {
defineEmits<{ toLogin: [] }>(); defineEmits<{ toLogin: [] }>();
const { locale } = useI18n(); const { locale } = useI18n();
const lockStore = useLockStore(); const accessStore = useAccessStore();
const now = useNow(); const now = useNow();
const meridiem = useDateFormat(now, 'A'); const meridiem = useDateFormat(now, 'A');
@@ -32,7 +35,7 @@ const minute = useDateFormat(now, 'mm');
const date = useDateFormat(now, 'YYYY-MM-DD dddd', { locales: locale.value }); const date = useDateFormat(now, 'YYYY-MM-DD dddd', { locales: locale.value });
const showUnlockForm = ref(false); const showUnlockForm = ref(false);
const { lockScreenPassword } = storeToRefs(lockStore); const { lockScreenPassword } = storeToRefs(accessStore);
const [Form, { form, validate }] = useVbenForm( const [Form, { form, validate }] = useVbenForm(
reactive({ reactive({
@@ -63,7 +66,7 @@ async function handleSubmit() {
const { valid } = await validate(); const { valid } = await validate();
if (valid) { if (valid) {
if (validPass.value) { if (validPass.value) {
lockStore.unlockScreen(); accessStore.unlockScreen();
} else { } else {
form.setFieldError('password', $t('authentication.passwordErrorTip')); form.setFieldError('password', $t('authentication.passwordErrorTip'));
} }

View File

@@ -14,7 +14,7 @@ defineOptions({
withDefaults( withDefaults(
defineProps<{ defineProps<{
disabled?: boolean; disabled?: boolean;
items: SelectOption[]; items?: SelectOption[];
multiple?: boolean; multiple?: boolean;
onBtnClick?: (value: string) => void; onBtnClick?: (value: string) => void;
placeholder?: string; placeholder?: string;

View File

@@ -7,7 +7,7 @@ defineOptions({
name: 'PreferenceToggleItem', name: 'PreferenceToggleItem',
}); });
withDefaults(defineProps<{ disabled?: boolean; items: SelectOption[] }>(), { withDefaults(defineProps<{ disabled?: boolean; items?: SelectOption[] }>(), {
disabled: false, disabled: false,
items: () => [], items: () => [],
}); });

View File

@@ -1,13 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import type { AnyFunction } from '@vben/types';
import type { Component } from 'vue'; import type { Component } from 'vue';
import type { AnyFunction } from '@vben/types';
import { computed, useTemplateRef, watch } from 'vue';
import { useHoverToggle } from '@vben/hooks'; import { useHoverToggle } from '@vben/hooks';
import { LockKeyhole, LogOut } from '@vben/icons'; import { LockKeyhole, LogOut } from '@vben/icons';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { preferences, usePreferences } from '@vben/preferences'; import { preferences, usePreferences } from '@vben/preferences';
import { useLockStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
import { isWindowsOs } from '@vben/utils'; import { isWindowsOs } from '@vben/utils';
import { useVbenModal } from '@vben-core/popup-ui'; import { useVbenModal } from '@vben-core/popup-ui';
import { import {
Badge, Badge,
@@ -21,8 +25,8 @@ import {
VbenAvatar, VbenAvatar,
VbenIcon, VbenIcon,
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
import { useMagicKeys, whenever } from '@vueuse/core'; import { useMagicKeys, whenever } from '@vueuse/core';
import { computed, useTemplateRef, watch } from 'vue';
import { LockScreenModal } from '../lock-screen'; import { LockScreenModal } from '../lock-screen';
@@ -78,7 +82,7 @@ const emit = defineEmits<{ logout: [] }>();
const { globalLockScreenShortcutKey, globalLogoutShortcutKey } = const { globalLockScreenShortcutKey, globalLogoutShortcutKey } =
usePreferences(); usePreferences();
const lockStore = useLockStore(); const accessStore = useAccessStore();
const [LockModal, lockModalApi] = useVbenModal({ const [LockModal, lockModalApi] = useVbenModal({
connectedComponent: LockScreenModal, connectedComponent: LockScreenModal,
}); });
@@ -129,7 +133,7 @@ function handleOpenLock() {
function handleSubmitLock(lockScreenPassword: string) { function handleSubmitLock(lockScreenPassword: string) {
lockModalApi.close(); lockModalApi.close();
lockStore.lockScreen(lockScreenPassword); accessStore.lockScreen(lockScreenPassword);
} }
function handleLogout() { function handleLogout() {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/plugins", "name": "@vben/plugins",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -45,13 +45,12 @@
); );
--vxe-ui-table-row-current-background-color: hsl(var(--accent)); --vxe-ui-table-row-current-background-color: hsl(var(--accent));
--vxe-ui-table-row-hover-current-background-color: hsl(var(--accent-hover)); --vxe-ui-table-row-hover-current-background-color: hsl(var(--accent-hover));
--vxe-ui-font-primary-tinge-color: hsl(var(--primary));
--vxe-ui-font-primary-lighten-color: hsl(var(--primary) / 60%);
--vxe-ui-font-primary-darken-color: hsl(var(--primary));
/* --vxe-ui-table-fixed-scrolling-box-shadow-color: rgb(0 0 0 / 80%); */ /* --vxe-ui-table-fixed-scrolling-box-shadow-color: rgb(0 0 0 / 80%); */
/** 右上角toolbar按钮色/翻页主题色保持一致 */
--vxe-ui-font-primary-lighten-color: hsl(var(--primary-500));
--vxe-ui-font-primary-darken-color: hsl(var(--primary-600));
height: auto !important; height: auto !important;
} }

View File

@@ -24,8 +24,8 @@ export function useVbenVxeGrid(options: VxeGridProps) {
return () => h(VxeGrid, { ...props, ...attrs, api: extendedApi }, slots); return () => h(VxeGrid, { ...props, ...attrs, api: extendedApi }, slots);
}, },
{ {
inheritAttrs: false,
name: 'VbenVxeGrid', name: 'VbenVxeGrid',
inheritAttrs: false,
}, },
); );
// Add reactivity support // Add reactivity support

View File

@@ -150,7 +150,9 @@ const toolbarOptions = computed(() => {
icon: 'vxe-icon-search', icon: 'vxe-icon-search',
circle: true, circle: true,
status: showSearchForm.value ? 'primary' : undefined, status: showSearchForm.value ? 'primary' : undefined,
title: $t('common.search'), title: showSearchForm.value
? $t('common.hideSearchPanel')
: $t('common.showSearchPanel'),
}; };
// 将搜索按钮合并到用户配置的toolbarConfig.tools中 // 将搜索按钮合并到用户配置的toolbarConfig.tools中
const toolbarConfig: VxeGridPropTypes.ToolbarConfig = { const toolbarConfig: VxeGridPropTypes.ToolbarConfig = {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/request", "name": "@vben/request",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/icons", "name": "@vben/icons",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/locales", "name": "@vben/locales",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -18,5 +18,7 @@
"delete": "Delete", "delete": "Delete",
"create": "Create", "create": "Create",
"yes": "Yes", "yes": "Yes",
"no": "No" "no": "No",
"showSearchPanel": "Show search panel",
"hideSearchPanel": "Hide search panel"
} }

View File

@@ -18,5 +18,7 @@
"delete": "删除", "delete": "删除",
"create": "新增", "create": "新增",
"yes": "是", "yes": "是",
"no": "否" "no": "否",
"showSearchPanel": "显示搜索面板",
"hideSearchPanel": "隐藏搜索面板"
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/preferences", "name": "@vben/preferences",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/stores", "name": "@vben/stores",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {
@@ -25,6 +25,7 @@
"@vben-core/typings": "workspace:*", "@vben-core/typings": "workspace:*",
"pinia": "catalog:", "pinia": "catalog:",
"pinia-plugin-persistedstate": "catalog:", "pinia-plugin-persistedstate": "catalog:",
"secure-ls": "catalog:",
"vue": "catalog:", "vue": "catalog:",
"vue-router": "catalog:" "vue-router": "catalog:"
} }

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