Compare commits

..

83 Commits

Author SHA1 Message Date
Netfan
67071326a1 chore: update electron dependence 2025-05-19 09:55:56 +08:00
Netfan
30387b94a2 feat: electron support 2025-05-19 09:55:51 +08:00
afe1
643f25347b perf: stub unbuild params (#6210) 2025-05-19 09:54:31 +08:00
wyc001122
49a739ffc6 fix: in mixed layout mode, the sidebar does not display when the first child node is an external link (#6219)
Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-19 09:54:30 +08:00
ming4762
128e749702 perf: perf the control logic of Tab (#6220)
* perf: perf the control logic of Tab

* 每个标签页Tab使用唯一的key来控制关闭打开等逻辑
* 统一函数获取tab的key
* 通过3种方式设置tab key:1、使用router query参数pageKey 2、使用路由meta参数fullPathKey设置使用fullPath或path作为key
* 单个路由可以打开多个标签页
* 如果设置fullPathKey为false,则query变更不会打开新的标签(这很实用)

* perf: perf the control logic of Tab

* perf: perf the control logic of Tab

* 测试用例适配

* perf: perf the control logic of Tab

* 解决AI提示的警告
2025-05-19 09:54:30 +08:00
wyc001122
c91fd146b8 fix(@vben-core/shadcn-ui): fix disabled functionality not working in VbenTree component (#6205)
* fix(@vben-core/shadcn-ui): fix disabled functionality not working in VbenTree component

* fix(@vben-core/shadcn-ui): add cursor-not-allowed className when disabled and disable onfocus

---------

Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-05-19 09:54:29 +08:00
afe1
74874a88a6 fix: css style (#6176) 2025-05-19 09:54:28 +08:00
panda7
f0f890c583 fix: the mobile terminal can wrap lines and expand slot attributes (#6165)
Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-05-19 09:54:27 +08:00
XiaoHetitu
ea48a01d8f feat(tabs): 支持计算属性作为标签标题,解决 #6170 的问题 (#6163)
* feat(tabs): 支持动态函数作为标签标题

修改 `setTabTitle` 和 `tabsView` 逻辑,允许传入函数作为标签标题,以便动态生成标题内容

* feat(tabbar): 添加动态设置标签页标题功能

允许设置静态字符串或动态函数作为标签标题,支持根据状态或语言变化动态更新标题

* refactor(tabs): 移除冗余的newTabTitle2变量并优化标题设置逻辑

移除tabs组件中冗余的newTabTitle2变量,直接使用newTabTitle作为标题来源。同时,优化use-tabs和tabbar模块的标题设置逻辑,支持ComputedRef作为动态标题,提升代码简洁性和可维护性。

---------

Co-authored-by: yuanwj <ywj6792341@qq.com>
2025-05-19 09:54:26 +08:00
chewenye
9311c658a1 types: 导出authentication组件的type,自定义toolbarList时类型使用ToolbarType (#6158)
Co-authored-by: 车文烨 <chewy@china-lehua.com>
2025-05-19 09:54:25 +08:00
Netfan
12151d9742 fix: refresh command of tabbar issue, fixed: #6162 (#6169) 2025-05-19 09:54:25 +08:00
anyup
de655af23b feat: support to refresh the tab page by route name (#6153)
Co-authored-by: anyup <anyupxing@163.com>
2025-05-19 09:54:24 +08:00
afe1
6fe909bfba fix: delete useless code (#6143) 2025-05-19 09:54:23 +08:00
wyc001122
899a99535f docs(@vben/docs): update settings doc (#6128)
Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-19 09:54:22 +08:00
zyf0624
29bdf2d13b fix: tsconfig moduleResolution (#6122)
Co-authored-by: pzzyf <2279948211@qq.com>
2025-05-19 09:54:22 +08:00
Netfan
4f633c1a9a fix: missing argument for getPopupContainer 2025-05-19 09:54:21 +08:00
Leeson
b2951b2975 fix: delete Popconfirm being obscured by fixed columns (#6118)
* fix: delete Popconfirm being obscured by fixed columns

* fix: opened popConfirm will prevent the table from scrolling

---------

Co-authored-by: Netfan <netfan@foxmail.com>
2025-05-19 09:54:20 +08:00
vben
d9f8722c27 chore: release v5.5.6 2025-05-19 09:54:19 +08:00
Jin Mao
1539fc738c fix: handle undefined children in generate-menus (#6117)
When children is undefined, use empty array as fallback to prevent potential runtime errors. This matches the behavior when hideChildrenInMenu is true.
2025-05-19 09:54:19 +08:00
LinaBell
200859fc7e fix: when keepAlive is enabled, returning directly through browser buttons/gestures will not close pop ups (#6113) 2025-05-19 09:54:18 +08:00
ming4762
36fb6b2222 fix: fix IconPicker props warning (#6108)
Invalid prop: type check failed for prop "onUpdate:value". Expected Function, got Array
2025-05-19 09:54:17 +08:00
vben
3304d54546 chore: remove prepare script from package.json 2025-05-19 09:54:16 +08:00
vben
ca57d223b4 chore: update prepare script in package.json to remove lefthook installation 2025-05-19 09:54:15 +08:00
Vben
0fa587c246 feat(project): migrate from husky and lint-staged to lefthook (#6104) 2025-05-19 09:54:11 +08:00
Vben
4fd2fee782 feat: support smooth auto-scroll to active menu item (#6102) 2025-05-19 09:54:00 +08:00
Vben
c4a4ca5232 chore: close eslint object sorting (#6101) 2025-05-19 09:53:59 +08:00
aonoa
73db7f3ef5 refactor: modify the default homepage path loaded from the preference… (#6099)
* refactor: modify the default homepage path loaded from the preferences.ts

Signed-off-by: aonoa <1991849113@qq.com>

* refactor: modify the default homepage path loaded from the preferences.ts

Signed-off-by: aonoa <1991849113@qq.com>

---------

Signed-off-by: aonoa <1991849113@qq.com>
2025-05-19 09:53:58 +08:00
Netfan
aef2134b60 fix: add triggerClass binding to PopoverTrigger and update icon-picker styles (#6095)
* Popover支持设置trigger的样式
* 修正icon-picker的input值更新
2025-05-19 09:53:58 +08:00
Netfan
f920895b8c fix: add missing translation for preferences drawer (#6094) 2025-05-19 09:53:57 +08:00
Netfan
10257e3611 fix: destroyOnClose incorrect default value, fixed #6092 (#6093) 2025-05-19 09:53:56 +08:00
ming4762
a88a2c8afa fix: fix LoginExpiredModal in some cases, message may be obscured (#6086) 2025-05-19 09:53:56 +08:00
Netfan
d92697e7f7 fix: show validation message as tooltip in compact form (#6087)
* 紧凑模式表单的校验消息将显示为一个tooltip
2025-05-19 09:53:55 +08:00
Jin Mao
e34285a51e 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-05-19 09:53:54 +08:00
Netfan
721b5f3d3e fix: calculation for collapsing search form is incorrect while initially hidden (#6068)
* 修复当默认隐藏搜索表单时,折叠位置的计算不正确的问题
2025-05-19 09:53:53 +08:00
vben
5e694b3194 chore: update readme.md 2025-05-19 09:53:52 +08:00
Vben
bf5e697c42 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-05-19 09:53:46 +08:00
vem
9437e97ce4 fix: Update existing route index to prevent 404 on user switch (#6003)
Co-authored-by: tars-macmini <vem@qq.com>
2025-05-19 09:51:07 +08:00
Netfan
77c09b4ddf fix: lock state will not change overflow style in drawer and modal (#6067)
* Modal和Drawer的锁定状态不再修改overflow样式
2025-05-19 09:51:06 +08:00
Gahotx
70d07c683a fix: add rounded corners to project and quick nav items (#5296) 2025-05-19 09:51:05 +08:00
Vben
e840905934 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-05-19 09:50:59 +08:00
Trivikram Kamat
8b192d05fd fix: install corepack from npm (#5905)
* fix: install corepack from npm

* docs: install corepack from npm
2025-05-19 09:50:36 +08:00
ming4762
9f910c3486 perf: resolve duplicate component names (#6039) 2025-05-19 09:50:35 +08:00
vben
25b0822afd chore: release v5.5.5 2025-05-19 09:50:34 +08:00
Netfan
8292024fc7 feat: encrypt the privacy data when it is persisted (#6056)
* 对私密数据持久化时执行加密
* 将锁屏密码合并到accessStore中进行加密
2025-05-19 09:50:26 +08:00
Jin Mao
9a0e813143 docs: add deepWiki doc link (#6057) 2025-05-19 09:50:13 +08:00
ming4762
1a73329691 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-05-19 09:50:12 +08:00
Netfan
ab161444fc fix: title of search button in vxeTable toolbar (#6046)
* 修改vxeTable工具栏里的搜索按钮的提示文案
2025-05-19 09:50:12 +08:00
Netfan
0243e68fbe feat: vbenSelect support prop allowClear (#6043) 2025-05-19 09:50:11 +08:00
Netfan
54c0d4ed83 docs: update example (#6036)
* 跟进后端菜单逻辑的修改,现已无需传递basicLayout布局
2025-05-19 09:50:10 +08:00
panda7
e320311128 fix: the initial value echo for the check-button-group (#6029)
Co-authored-by: sqchen <9110848@qq.com>
2025-05-19 09:50:09 +08:00
Netfan
1faa52335c fix: alert confirm state in beforeClose callback (#6019) 2025-05-19 09:50:09 +08:00
pangyajun123
9ff600657b fix: vxe-table theme token follow primary color (#6007) 2025-05-19 09:50:08 +08:00
wyc001122
d14527a292 fix: fix geader menu activation path (#5997)
Co-authored-by: 王泳超 <wangyongchao@testor.com.cn>
2025-05-19 09:50:07 +08:00
Netfan
eb70c48d14 fix: alert send wrong confirm state to beforeClose (#5991)
* 修复alert在按下Esc或者点击遮罩关闭时,可能发送错误的isConfirm状态
2025-05-19 09:50:06 +08:00
Netfan
302de1deaf fix: destroyOnClose works within connectedComponent (#5989)
* 修复destroyOnClose没能销毁connectedComponent自身的问题
2025-05-19 09:50:06 +08:00
PIPEDREA_WZJ
ea0c2ad58b Update tailwindcss.md (#5602)
tailwindcss最新的版本已经是v4.x,vben中使用的是3.x的tailwindcss。在未进行兼容前,会出现运行失败的问题
2025-05-19 09:50:05 +08:00
yuh
678646b4ba feat: add examples: form-upload (#5955)
* feat: add examples: form-upload

* fix: upload: accept and label

* fix: upload: 设置表单值、图片预览
2025-05-19 09:50:04 +08:00
Netfan
a4da6dedf8 fix: fixed arguments of callbacks in formApi (#5970)
* 修复 `handleValuesChange` 传递的参数不是处理后的表单值的问题

* 修复 `handleReset` 未能传递正确参数的问题
2025-05-19 09:50:04 +08:00
Netfan
332a8be29c feat: pass fieldsChanged into the handleValuesChange callback function (#5968)
* fieldsChanged(已被改变值的字段名)将传入handleValuesChange回调函数
2025-05-19 09:50:03 +08:00
ming4762
357ae0e565 perf: improve destroyOnClose for VbenModal (#5964) 2025-05-19 09:50:02 +08:00
LinaBell
fe2310300c perf: beforeClose of drawer support promise (#5932)
* perf: the beforeClose function of drawer is consistent with that of modal

* refactor: drawer test update
2025-05-19 09:50:01 +08:00
zhouda1fu
7e99c62abf fix: missing await in department form(#5967) 2025-05-19 09:50:01 +08:00
Netfan
a3b2d5c2e1 docs: update alert and apiComponent docs (#5961) 2025-05-19 09:50:00 +08:00
wyc001122
39f9c6a3f4 fix: determine if scrollbar has been totally scrolled (#5934)
* 修复在系统屏幕缩放比例不为100%的情况下,滚动组件对是否已滚动到边界的判断可能不正确的问题
2025-05-19 09:49:59 +08:00
ming4762
48c616ea81 fix: modal closing animation (#5960) 2025-05-19 09:49:58 +08:00
ming4762
06e279c917 feat: modal&drawer support center-footer slot (#5956) 2025-05-19 09:49:58 +08:00
lztb
ff65b061ef feat: vben-form添加arrayToStringFields属性 (#5957)
* feat: vben-form添加arrayToStringFields属性

* feat: 修改handleArrayToStringFields和handleStringToArrayFields中嵌套数组格式的处理不一致

---------

Co-authored-by: 米山 <17726957223@189.cn>
2025-05-19 09:49:57 +08:00
Netfan
b8f145aa7f feat: add more expose methods for apiComponent (#5958)
* 为ApiComponent组件添加getOptions和getValue导出方法。
2025-05-19 09:49:56 +08:00
Netfan
091596eda8 feat: add useAlertContext for Alert component (#5947)
* 新增Alert的子组件中获取弹窗上下文的能力
2025-05-19 09:49:55 +08:00
Netfan
17b0111424 fix: table actions in fixed column (#5945) 2025-05-19 09:49:55 +08:00
Netfan
6e5ddb6d25 feat: alert support customize footer (#5940)
* Alert组件支持自定义footer
2025-05-19 09:49:54 +08:00
Netfan
46a10959c8 fix: long navigation menu can be scrolled (#5939)
* 修复超长的导航菜单无法纵向滚动的问题
2025-05-19 09:49:53 +08:00
ming4762
382df99988 perf: improve destroyOnClose for VbenModal (#5935)
* perf: 优化Vben Modal destroyOnClose,解决destroyOnClose=false,Modal依旧会被销毁的问题

影响范围(重要):destroyOnClose默认为true,这会导致所有的modal都会默认渲染到body
radix-vue Dialog组件默认会销毁挂载的组件,所以即使destroyOnClose=false,Modal依旧会被销毁的问题
对于一些大表单重复渲染导致卡顿,ApiComponent也会频繁的加载数据

* fix: modal closing animation

---------

Co-authored-by: Netfan <netfan@foxmail.com>
2025-05-19 09:49:52 +08:00
ming4762
d00b6bb83e perf: improve autoSelect of ApiComponent (#5936)
* fix: 修复autoSelect不生效的问题,props.valueField已经被omit了

* feat: ApiComponent autoSelect支持使用函数,可以满足灵活性要求更高的场景
2025-05-19 09:49:51 +08:00
Netfan
82a05e3b3a feat: api-component support autoSelect prop (#5931)
* feat: api-component support autoSelect prop

* docs: add version requirement
2025-05-19 09:49:51 +08:00
Netfan
d3d1e1616c docs: docs modal z-index fixed, update alert docs (#5930) 2025-05-19 09:49:50 +08:00
Netfan
a4682a7116 fix: alert animation (#5927) 2025-05-19 09:49:49 +08:00
Netfan
a8935aaf8c fix: builtin color change throttled in preference drawer (#5924)
修复偏好设置中的自定义主题色拖动选择颜色时页面会明显卡顿的问题
2025-05-19 09:49:48 +08:00
Netfan
a6b480fb8f fix: theme mode follow the system only auto (#5923)
* 修复主题在未设置为auto时,仍然会跟随系统主题变化的问题。
2025-05-19 09:49:48 +08:00
Netfan
a87fa3ffbe fix: alert action button focus, fixed #5921 (#5922)
* 修复Alert组件的按钮焦点切换问题
2025-05-19 09:49:47 +08:00
zhang
d450df946c chore: 导出框架自带的组件,方便独立页面使用 (#5876) 2025-05-19 09:49:46 +08:00
Netfan
20f902ed2c feat: electron control buttons 2025-04-09 04:05:27 +08:00
Netfan
7536be5e49 feat: electron support 2025-04-09 01:24:15 +08:00
193 changed files with 8283 additions and 4042 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@ dist-ssr
dist.zip
dist.tar
dist.war
dist-electron
.nitro
.output
*-dist.zip

View File

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

View File

@@ -1,6 +0,0 @@
echo Start running commit-msg hook...
# Check whether the git commit information is standardized
pnpm exec commitlint --edit "$1"
echo Run commit-msg hook done.

View File

@@ -1,3 +0,0 @@
# 每次 git pull 之后, 安装依赖
pnpm install

View File

@@ -1,7 +0,0 @@
# update `.vscode/vben-admin.code-workspace` file
pnpm vsh code-workspace --auto-commit
# Format and submit code according to lintstagedrc.js configuration
pnpm exec lint-staged
echo Run pre-commit hook done.

View File

@@ -1,20 +0,0 @@
export default {
'*.md': ['prettier --cache --ignore-unknown --write'],
'*.vue': [
'prettier --write',
'eslint --cache --fix',
'stylelint --fix --allow-empty-input',
],
'*.{js,jsx,ts,tsx}': [
'prettier --cache --ignore-unknown --write',
'eslint --cache --fix',
],
'*.{scss,less,styl,html,vue,css}': [
'prettier --cache --ignore-unknown --write',
'stylelint --fix --allow-empty-input',
],
'package.json': ['prettier --cache --write'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
'prettier --cache --write--parser json',
],
};

View File

@@ -1 +1 @@
20.14.0
22.1.0

3
.npmrc
View File

@@ -1,4 +1,7 @@
registry = "https://registry.npmmirror.com"
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
public-hoist-pattern[]=lefthook
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
public-hoist-pattern[]=husky
public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier

View File

@@ -14,7 +14,7 @@
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.cursorBlinking": "expand",
"editor.largeFileOptimizations": false,
"editor.largeFileOptimizations": true,
"editor.accessibilitySupport": "off",
"editor.cursorSmoothCaretAnimation": "on",
"editor.guides.bracketPairs": "active",
@@ -91,6 +91,7 @@
"**/bower_components": true,
"**/.turbo": true,
"**/.idea": true,
"**/.vitepress": true,
"**/tmp": true,
"**/.git": true,
"**/.svn": true,
@@ -112,6 +113,8 @@
"**/yarn.lock": true
},
"typescript.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"],
// search
"search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false,
@@ -216,7 +219,7 @@
"*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml",
"tailwind.config.mjs": "postcss.*"
},
"commentTranslate.hover.enabled": false,

View File

@@ -1,8 +1,13 @@
<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)
<h1>Vue Vben Admin</h1>
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
@@ -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などの最先端フロントエンド技術で開発
- **TypeScript**: アプリケーション規模のJavaScriptのための言語
- **テーマ**: 複数のテーマカラーが利用可能で、カスタマイズオプションも豊富
- **国際化**: 完全な内蔵国際化サポート
- **権限管理**: 動的ルートベースの権限生成ソリューションを内蔵
- **最新技術スタック**Vue 3やViteなどの最先端フロントエンド技術で開発
- **TypeScript**アプリケーション規模のJavaScriptのための言語
- **テーマ**複数のテーマカラーが利用可能で、カスタマイズオプションも豊富
- **国際化**完全な内蔵国際化サポート
- **権限管理**動的ルートベースの権限生成ソリューションを内蔵
## プレビュー
- [Vben Admin](https://vben.pro/) - フルバージョンの中国語サイト
テストアカウント: vben/123456
テストアカウントvben/123456
<p 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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p>
<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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</div>
### Gitpodを使用
@@ -49,30 +54,27 @@ GitpodGitHub用の無料オンライン開発環境でプロジェクト
## インストールと使用
- プロジェクトコードを取得
1. プロジェクトコードを取得
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
- 依存関係のインストール
2. 依存関係のインストール
```bash
cd vue-vben-admin
corepack enable
npm i -g corepack
pnpm install
```
- 実行
3. 実行
```bash
pnpm dev
```
- ビルド
4. ビルド
```bash
pnpm build
@@ -86,40 +88,39 @@ pnpm build
ご参加をお待ちしております![Issueを提出](https://github.com/anncwb/vue-vben-admin/issues/new/choose)するか、Pull Requestを送信してください。
**Pull Request:**
**Pull Request プロセス:**
1. コードをフォーク
2. 自分のブランチを作成: `git checkout -b feat/xxxx`
3. 変更をコミット: `git commit -am 'feat(function): add xxxxx'`
4. ブランチをプッシュ: `git push origin feat/xxxx`
1. コードをフォーク
2. 自分のブランチを作成`git checkout -b feat/xxxx`
3. 変更をコミット`git commit -am 'feat(function): add xxxxx'`
4. ブランチをプッシュ`git push origin feat/xxxx`
5. `pull request`を送信
## 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` 新機能の追加
- `fix` 問題/バグの修正
- `style` コードスタイルに関連し、実行結果に影響しない
- `perf` 最適化/パフォーマンス向上
- `refactor` リファクタリング
- `revert` 変更の取り消し
- `test` テスト関連
- `docs` ドキュメント/注釈
- `chore` 依存関係の更新/スキャフォールディング設定の変更など
- `ci` 継続的インテグレーション
- `types` 型定義ファイルの変更
- `wip` 開発中
- `feat` 新機能の追加
- `fix` 問題/バグの修正
- `style` コードスタイルに関連し、実行結果に影響しない
- `perf` 最適化/パフォーマンス向上
- `refactor` リファクタリング
- `revert` 変更の取り消し
- `test` テスト関連
- `docs` ドキュメント/注釈
- `chore` 依存関係の更新/スキャフォールディング設定の変更など
- `ci` 継続的インテグレーション
- `types` 型定義ファイルの変更
## ブラウザサポート
ローカル開発には`Chrome 80+`ブラウザを推奨します
ローカル開発には `Chrome 80+` ブラウザを推奨します
モダンブラウザをサポートし、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 |
| :-: | :-: | :-: | :-: | :-: |
| サポートしない | 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン |
| [<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バージョン |
## メンテナー
@@ -140,8 +141,7 @@ pnpm build
## 貢献者
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
<img alt="Contributors" src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord

View File

@@ -1,8 +1,13 @@
<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)
<h1>Vue Vben Admin</h1>
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
@@ -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).
## Feature
## Features
- **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite
- **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
<p 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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p>
<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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</div>
### 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/)
## Install and use
## Install and Use
- Get the project code
1. Get the project code
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
- Installation dependencies
2. Install dependencies
```bash
cd vue-vben-admin
corepack enable
npm i -g corepack
pnpm install
```
- run
3. Run
```bash
pnpm dev
```
- build
4. Build
```bash
pnpm build
@@ -81,44 +84,43 @@ pnpm build
[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!
2. Create your own branch: `git checkout -b feat/xxxx`
1. Fork the code
2. Create your branch: `git checkout -b feat/xxxx`
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
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
- `fix` Fix the problem/BUG
- `style` The code style is related and does not affect the running result
- `perf` Optimization/performance improvement
- `refactor` Refactor
- `revert` Undo edit
- `test` Test related
- `docs` Documentation/notes
- `chore` Dependency update/scaffolding configuration modification etc.
- `ci` Continuous integration
- `types` Type definition file changes
- `wip` In development
- `feat` Add new features
- `fix` Fix the problem/BUG
- `style` The code style is related and does not affect the running result
- `perf` Optimization/performance improvement
- `refactor` Refactor
- `revert` Undo edit
- `test` Test related
- `docs` Documentation/notes
- `chore` Dependency update/scaffolding configuration modification etc.
- `ci` Continuous integration
- `types` Type definition file changes
## Browser support
## Browser Support
The `Chrome 80+` browser is recommended for local development
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 |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| [<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 |
| :-: | :-: | :-: | :-: |
| last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 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>
## Contributor
## Contributors
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
<img alt="Contributors" src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord

View File

@@ -1,8 +1,13 @@
<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)
<h1>Vue Vben Admin</h1>
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
@@ -15,31 +20,31 @@ Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的
## 升级提示
该版本为最新版本`5.0`, 与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
该版本为最新版本 `5.0`与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
## 特性
- **最新技术栈**:使用 Vue3/vite 等前端前沿技术开发
- **TypeScript**: 应用程序级 JavaScript 的语言
- **TypeScript**应用程序级 JavaScript 的语言
- **主题**:提供多套主题色彩,可配置自定义主题
- **国际化**:内置完善的国际化方案
- **权限** 内置完善的动态路由权限生成方案
- **权限**内置完善的动态路由权限生成方案
## 预览
- [Vben Admin](https://vben.pro/) - 完整版中文站点
测试账号: vben/123456
测试账号vben/123456
<p 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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p>
<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/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</div>
### 使用 Gitpod
在 Gitpod适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
在 Gitpod适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
@@ -49,29 +54,27 @@ Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的
## 安装使用
- 获取项目代码
1. 获取项目代码
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
- 安装依赖
2. 安装依赖
```bash
cd vue-vben-admin
corepack enable
npm i -g corepack
pnpm install
```
- 运行
3. 运行
```bash
pnpm dev
```
- 打包
4. 打包
```bash
pnpm build
@@ -85,68 +88,66 @@ pnpm build
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。
**Pull Request:**
**Pull Request 流程:**
1. Fork 代码!
2. 创建自己的分支: `git checkout -b feature/xxxx`
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
4. 推送您的分支: `git push origin feature/xxxx`
5. 提交`pull request`
1. Fork 代码
2. 创建自己的分支`git checkout -b feature/xxxx`
3. 提交你的修改`git commit -am 'feat(function): add xxxxx'`
4. 推送您的分支`git push origin feature/xxxx`
5. 提交 `pull request`
## 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` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `ci` 持续集成
- `types` 类型定义文件更改
## 浏览器支持
本地开发推荐使用`Chrome 80+` 浏览器
本地开发推荐使用 `Chrome 80+` 浏览器
支持现代浏览器, 不支持 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 |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| [<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 |
| :-: | :-: | :-: | :-: |
| last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 维护者
[@Vben](https://github.com/anncwb)
## Star History
## Star 历史
[![Star History Chart](https://api.star-history.com/svg?repos=vbenjs/vue-vben-admin&type=Date)](https://star-history.com/#vbenjs/vue-vben-admin&Date)
## 捐赠
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持
![donate](https://unpkg.com/@vbenjs/static-source@0.1.7/source/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## Contributor
## 贡献者
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img alt="Contributors"
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
<img alt="Contributors" src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
</a>
## Discord
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
## License
## 许可证
[MIT © Vben-2020](./LICENSE)

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import type { Router } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { startProgress, stopProgress } from '@vben/utils';
@@ -18,7 +18,7 @@ function setupCommonGuard(router: Router) {
// 记录已经加载的页面
const loadedPaths = new Set<string>();
router.beforeEach(async (to) => {
router.beforeEach((to) => {
to.meta.loaded = loadedPaths.has(to.path);
// 页面加载进度条
@@ -56,7 +56,7 @@ function setupAccessGuard(router: Router) {
return decodeURIComponent(
(to.query?.redirect as string) ||
userStore.userInfo?.homePath ||
DEFAULT_HOME_PATH,
preferences.app.defaultHomePath,
);
}
return true;
@@ -75,7 +75,7 @@ function setupAccessGuard(router: Router) {
path: LOGIN_PATH,
// 如不需要,直接删除 query
query:
to.fullPath === DEFAULT_HOME_PATH
to.fullPath === preferences.app.defaultHomePath
? {}
: { redirect: encodeURIComponent(to.fullPath) },
// 携带当前跳转的页面,登录后重新跳转该页面
@@ -108,8 +108,8 @@ function setupAccessGuard(router: Router) {
accessStore.setAccessRoutes(accessibleRoutes);
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ??
(to.path === DEFAULT_HOME_PATH
? userInfo.homePath || DEFAULT_HOME_PATH
(to.path === preferences.app.defaultHomePath
? userInfo.homePath || preferences.app.defaultHomePath
: to.fullPath)) as string;
return {

View File

@@ -1,6 +1,7 @@
import type { RouteRecordRaw } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { $t } from '#/locales';
@@ -34,7 +35,7 @@ const coreRoutes: RouteRecordRaw[] = [
},
name: 'Root',
path: '/',
redirect: DEFAULT_HOME_PATH,
redirect: preferences.app.defaultHomePath,
children: [],
},
{

View File

@@ -3,7 +3,8 @@ import type { Recordable, UserInfo } from '@vben/types';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { notification } from 'ant-design-vue';
@@ -54,7 +55,9 @@ export const useAuthStore = defineStore('auth', () => {
} else {
onSuccess
? await onSuccess?.()
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
: await router.push(
userInfo.homePath || preferences.app.defaultHomePath,
);
}
if (userInfo?.realName) {

View File

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

View File

@@ -130,8 +130,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {},
) => {
return defineComponent({
inheritAttrs: false,
name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => {
const placeholder =
props?.placeholder ||
@@ -184,19 +184,33 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载
// Button: () =>
// import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: ElSelectV2,
loadingSlot: 'loading',
visibleEvent: 'onVisibleChange',
}),
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: ElTreeSelect,
props: { label: 'label', children: 'children' },
nodeKey: 'value',
loadingSlot: 'loading',
optionsPropName: 'data',
visibleEvent: 'onVisibleChange',
}),
ApiSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiSelect',
},
'select',
{
component: ElSelectV2,
loadingSlot: 'loading',
visibleEvent: 'onVisibleChange',
},
),
ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: ElTreeSelect,
props: { label: 'label', children: 'children' },
nodeKey: 'value',
loadingSlot: 'loading',
optionsPropName: 'data',
visibleEvent: 'onVisibleChange',
},
),
Checkbox: ElCheckbox,
CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot;

View File

@@ -1,6 +1,6 @@
import type { Router } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { startProgress, stopProgress } from '@vben/utils';
@@ -18,7 +18,7 @@ function setupCommonGuard(router: Router) {
// 记录已经加载的页面
const loadedPaths = new Set<string>();
router.beforeEach(async (to) => {
router.beforeEach((to) => {
to.meta.loaded = loadedPaths.has(to.path);
// 页面加载进度条
@@ -56,7 +56,7 @@ function setupAccessGuard(router: Router) {
return decodeURIComponent(
(to.query?.redirect as string) ||
userStore.userInfo?.homePath ||
DEFAULT_HOME_PATH,
preferences.app.defaultHomePath,
);
}
return true;
@@ -75,7 +75,7 @@ function setupAccessGuard(router: Router) {
path: LOGIN_PATH,
// 如不需要,直接删除 query
query:
to.fullPath === DEFAULT_HOME_PATH
to.fullPath === preferences.app.defaultHomePath
? {}
: { redirect: encodeURIComponent(to.fullPath) },
// 携带当前跳转的页面,登录后重新跳转该页面
@@ -108,8 +108,8 @@ function setupAccessGuard(router: Router) {
accessStore.setAccessRoutes(accessibleRoutes);
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ??
(to.path === DEFAULT_HOME_PATH
? userInfo.homePath || DEFAULT_HOME_PATH
(to.path === preferences.app.defaultHomePath
? userInfo.homePath || preferences.app.defaultHomePath
: to.fullPath)) as string;
return {

View File

@@ -1,6 +1,7 @@
import type { RouteRecordRaw } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { $t } from '#/locales';
@@ -34,7 +35,7 @@ const coreRoutes: RouteRecordRaw[] = [
},
name: 'Root',
path: '/',
redirect: DEFAULT_HOME_PATH,
redirect: preferences.app.defaultHomePath,
children: [],
},
{

View File

@@ -3,7 +3,8 @@ import type { Recordable, UserInfo } from '@vben/types';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { ElNotification } from 'element-plus';
@@ -55,7 +56,9 @@ export const useAuthStore = defineStore('auth', () => {
} else {
onSuccess
? await onSuccess?.()
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
: await router.push(
userInfo.homePath || preferences.app.defaultHomePath,
);
}
if (userInfo?.realName) {

View File

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

View File

@@ -76,8 +76,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {},
) => {
return defineComponent({
inheritAttrs: false,
name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => {
const placeholder =
props?.placeholder ||
@@ -131,19 +131,33 @@ async function initComponentAdapter() {
// Button: () =>
// import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: NSelect,
modelPropName: 'value',
}),
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: NTreeSelect,
nodeKey: 'value',
loadingSlot: 'arrow',
keyField: 'value',
modelPropName: 'value',
optionsPropName: 'options',
visibleEvent: 'onVisibleChange',
}),
ApiSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiSelect',
},
'select',
{
component: NSelect,
modelPropName: 'value',
},
),
ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: NTreeSelect,
nodeKey: 'value',
loadingSlot: 'arrow',
keyField: 'value',
modelPropName: 'value',
optionsPropName: 'options',
visibleEvent: 'onVisibleChange',
},
),
Checkbox: NCheckbox,
CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot;

View File

@@ -1,6 +1,6 @@
import type { Router } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { startProgress, stopProgress } from '@vben/utils';
@@ -18,7 +18,7 @@ function setupCommonGuard(router: Router) {
// 记录已经加载的页面
const loadedPaths = new Set<string>();
router.beforeEach(async (to) => {
router.beforeEach((to) => {
to.meta.loaded = loadedPaths.has(to.path);
// 页面加载进度条
@@ -56,7 +56,7 @@ function setupAccessGuard(router: Router) {
return decodeURIComponent(
(to.query?.redirect as string) ||
userStore.userInfo?.homePath ||
DEFAULT_HOME_PATH,
preferences.app.defaultHomePath,
);
}
return true;
@@ -75,7 +75,7 @@ function setupAccessGuard(router: Router) {
path: LOGIN_PATH,
// 如不需要,直接删除 query
query:
to.fullPath === DEFAULT_HOME_PATH
to.fullPath === preferences.app.defaultHomePath
? {}
: { redirect: encodeURIComponent(to.fullPath) },
// 携带当前跳转的页面,登录后重新跳转该页面
@@ -107,8 +107,8 @@ function setupAccessGuard(router: Router) {
accessStore.setAccessRoutes(accessibleRoutes);
accessStore.setIsAccessChecked(true);
const redirectPath = (from.query.redirect ??
(to.path === DEFAULT_HOME_PATH
? userInfo.homePath || DEFAULT_HOME_PATH
(to.path === preferences.app.defaultHomePath
? userInfo.homePath || preferences.app.defaultHomePath
: to.fullPath)) as string;
return {

View File

@@ -1,6 +1,7 @@
import type { RouteRecordRaw } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { $t } from '#/locales';
@@ -34,7 +35,7 @@ const coreRoutes: RouteRecordRaw[] = [
},
name: 'Root',
path: '/',
redirect: DEFAULT_HOME_PATH,
redirect: preferences.app.defaultHomePath,
children: [],
},
{

View File

@@ -3,7 +3,8 @@ import type { Recordable, UserInfo } from '@vben/types';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { defineStore } from 'pinia';
@@ -55,7 +56,9 @@ export const useAuthStore = defineStore('auth', () => {
} else {
onSuccess
? await onSuccess?.()
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
: await router.push(
userInfo.homePath || preferences.app.defaultHomePath,
);
}
if (userInfo?.realName) {

View File

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

View File

@@ -78,7 +78,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
| --- | --- | --- | --- |
| appendToMain | 是否挂载到内容区域默认挂载到body | `boolean` | `false` |
| connectedComponent | 连接另一个Modal组件 | `Component` | - |
| destroyOnClose | 关闭时销毁`connectedComponent` | `boolean` | `false` |
| destroyOnClose | 关闭时销毁 | `boolean` | `false` |
| title | 标题 | `string\|slot` | - |
| titleTooltip | 标题提示信息 | `string\|slot` | - |
| description | 描述信息 | `string\|slot` | - |

View File

@@ -98,8 +98,8 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
"postinstall": "pnpm -r run stub --if-present",
// Only allow using pnpm
"preinstall": "npx only-allow pnpm",
// Install husky
"prepare": "is-ci || husky",
// Install lefthook
"prepare": "is-ci || lefthook install",
// Preview the application
"preview": "turbo-run preview",
// Package specification check

View File

@@ -60,6 +60,29 @@ VITE_INJECT_APP_LOADING=true
VITE_ARCHIVER=true
```
```bash [.env.production]
# Public Path for Resources, must start and end with /
VITE_BASE=/
# API URL
VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
# Whether to enable compression, can be set to none, brotli, gzip
VITE_COMPRESS=gzip
# Whether to enable PWA
VITE_PWA=false
# vue-router mode
VITE_ROUTER_HISTORY=hash
# Whether to inject global loading
VITE_INJECT_APP_LOADING=true
# Whether to generate dist.zip after packaging
VITE_ARCHIVER=true
```
:::
## Dynamic Configuration in Production Environment
@@ -142,6 +165,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
/**
* @description Project configuration file
* Only a part of the configuration in the project needs to be covered, and unnecessary configurations do not need to be covered. The default configuration will be automatically used
* !!! Please clear the cache after changing the configuration, otherwise it may not take effect
*/
export const overridesPreferences = defineOverridesPreferences({
// overrides
@@ -164,6 +188,7 @@ const defaultPreferences: Preferences = {
contentCompact: 'wide',
defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
defaultHomePath: '/analytics',
dynamicTitle: true,
enableCheckUpdates: true,
enablePreferences: true,
@@ -171,7 +196,7 @@ const defaultPreferences: Preferences = {
isMobile: false,
layout: 'sidebar-nav',
locale: 'zh-CN',
loginExpiredMode: 'modal',
loginExpiredMode: 'page',
name: 'Vben Admin',
preferencesButtonPosition: 'auto',
watermark: false,
@@ -190,14 +215,16 @@ const defaultPreferences: Preferences = {
enable: true,
icp: '',
icpLink: '',
settingShow: true,
},
footer: {
enable: true,
enable: false,
fixed: false,
},
header: {
enable: true,
hidden: false,
menuAlign: 'start',
mode: 'fixed',
},
logo: {
@@ -219,23 +246,28 @@ const defaultPreferences: Preferences = {
sidebar: {
autoActivateChild: false,
collapsed: false,
collapsedButton: true,
collapsedShowTitle: false,
enable: true,
expandOnHover: true,
extraCollapse: true,
extraCollapse: false,
fixedButton: true,
hidden: false,
width: 230,
width: 224,
},
tabbar: {
draggable: true,
enable: true,
height: 36,
height: 38,
keepAlive: true,
maxCount: 0,
middleClickToClose: false,
persist: true,
showIcon: true,
showMaximize: true,
showMore: true,
styleType: 'chrome',
wheelable: true,
},
theme: {
builtinType: 'default',
@@ -246,7 +278,7 @@ const defaultPreferences: Preferences = {
mode: 'dark',
radius: '0.5',
semiDarkHeader: false,
semiDarkSidebar: true,
semiDarkSidebar: false,
},
transition: {
enable: true,
@@ -260,9 +292,9 @@ const defaultPreferences: Preferences = {
languageToggle: true,
lockScreen: true,
notification: true,
refresh: true,
sidebarToggle: true,
themeToggle: true,
refresh: true,
},
};
```
@@ -289,6 +321,8 @@ interface AppPreferences {
contentCompact: ContentCompactType;
// /** Default application avatar */
defaultAvatar: string;
/** Default homepage path */
defaultHomePath: string;
// /** Enable dynamic title */
dynamicTitle: boolean;
/** Whether to enable update checks */
@@ -342,6 +376,8 @@ interface CopyrightPreferences {
icp: string;
/** Link to the ICP */
icpLink: string;
/** Whether to show in settings panel */
settingShow?: boolean;
}
interface FooterPreferences {
@@ -356,6 +392,8 @@ interface HeaderPreferences {
enable: boolean;
/** Whether the header is hidden, css-hidden */
hidden: boolean;
/** Header menu alignment */
menuAlign: LayoutHeaderMenuAlignType;
/** Header display mode */
mode: LayoutHeaderModeType;
}
@@ -376,8 +414,12 @@ interface NavigationPreferences {
styleType: NavigationStyleType;
}
interface SidebarPreferences {
/** Automatically activate child menu when clicking on directory */
autoActivateChild: boolean;
/** Whether the sidebar is collapsed */
collapsed: boolean;
/** Whether the sidebar collapse button is visible */
collapsedButton: boolean;
/** Whether to show title when sidebar is collapsed */
collapsedShowTitle: boolean;
/** Whether the sidebar is visible */
@@ -386,6 +428,8 @@ interface SidebarPreferences {
expandOnHover: boolean;
/** Whether the sidebar extension area is collapsed */
extraCollapse: boolean;
/** Whether the sidebar fixed button is visible */
fixedButton: boolean;
/** Whether the sidebar is hidden - css */
hidden: boolean;
/** Sidebar width */
@@ -414,6 +458,10 @@ interface TabbarPreferences {
height: number;
/** Whether tab caching is enabled */
keepAlive: boolean;
/** Maximum number of tabs */
maxCount: number;
/** Whether to close tab when middle-clicked */
middleClickToClose: boolean;
/** Whether tabs are persistent */
persist: boolean;
/** Whether icons in multiple tabs are enabled */
@@ -424,6 +472,8 @@ interface TabbarPreferences {
showMore: boolean;
/** Tab style */
styleType: TabsStyleType;
/** Whether mouse wheel response is enabled */
wheelable: boolean;
}
interface ThemePreferences {
/** Built-in theme name */
@@ -511,5 +561,6 @@ interface Preferences {
- The `overridesPreferences` method only needs to override a part of the configurations in the project. There's no need to override configurations that are not needed; they will automatically use the default settings.
- Any configuration item can be overridden. You just need to override it within the `overridesPreferences` method. Do not modify the default configuration file.
- Please clear the cache after changing the configuration, otherwise it may not take effect.
:::

View File

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

View File

@@ -18,7 +18,7 @@ If you encounter a problem, you can start looking from the following aspects:
## Dependency Issues
In a `Monorepo` project, it is necessary to develop the habit of executing `pnpm install` every time you `git pull` the code, as new dependency packages are often added. The project has already configured automatic execution of `pnpm install` in `.husky/git-merge`, but sometimes there might be issues. If it does not execute automatically, it is recommended to execute it manually once.
In a `Monorepo` project, it's important to get into the habit of running `pnpm install` after every `git pull` because new dependencies are often added. The project has configured automatic execution of `pnpm install` in `lefthook.yml`, but sometimes there might be issues. If it does not execute automatically, it is recommended to execute it manually once.
## About Cache Update Issues

View File

@@ -33,8 +33,8 @@ The project integrates the following code verification tools:
- [Prettier](https://prettier.io/) for code formatting
- [Commitlint](https://commitlint.js.org/) for checking the standard of git commit messages
- [Publint](https://publint.dev/) for checking the standard of npm packages
- [Lint Staged](https://github.com/lint-staged/lint-staged) for running code verification before git commits
- [Cspell](https://cspell.org/) for checking spelling errors
- [lefthook](https://github.com/evilmartians/lefthook) for managing Git hooks, automatically running code checks and formatting before commits
## ESLint
@@ -148,18 +148,66 @@ The cspell configuration file is `cspell.json`, which can be modified according
Git hooks are generally combined with various lints to check code style during git commits. If the check fails, the commit will not proceed. Developers need to modify and resubmit.
### husky
### lefthook
One issue is that the check will verify all code, but we only want to check the code we are committing. This is where husky comes in.
One issue is that the check will verify all code, but we only want to check the code we are committing. This is where lefthook comes in.
The most effective solution is to perform Lint checks locally before committing. A common practice is to use husky or pre-commit to perform a Lint check before local submission.
The most effective solution is to perform Lint checks locally before committing. A common practice is to use lefthook to perform a Lint check before local submission.
The project defines corresponding hooks inside `.husky`.
The project defines corresponding hooks inside `lefthook.yml`:
#### How to Disable Husky
- `pre-commit`: Runs before commit, used for code formatting and checking
If you want to disable Husky, simply delete the .husky directory.
- `code-workspace`: Updates VSCode workspace configuration
- `lint-md`: Formats Markdown files
- `lint-vue`: Formats and checks Vue files
- `lint-js`: Formats and checks JavaScript/TypeScript files
- `lint-style`: Formats and checks style files
- `lint-package`: Formats package.json
- `lint-json`: Formats other JSON files
### lint-staged
- `post-merge`: Runs after merge, used for automatic dependency installation
Used for automatically fixing style issues of committed files. Its configuration file is `.lintstagedrc.mjs`, which can be modified according to project needs.
- `install`: Runs `pnpm install` to install new dependencies
- `commit-msg`: Runs during commit, used for checking commit message format
- `commitlint`: Uses commitlint to check commit messages
#### How to Disable lefthook
If you want to disable lefthook, there are two ways:
::: code-group
```bash [Temporary disable]
git commit -m 'feat: add home page' --no-verify
```
```bash [Permanent disable]
# Simply delete the lefthook.yml file
rm lefthook.yml
```
:::
#### How to Modify lefthook Configuration
If you want to modify lefthook's configuration, you can edit the `lefthook.yml` file. For example:
```yaml
pre-commit:
parallel: true # Execute tasks in parallel
jobs:
- name: lint-js
run: pnpm prettier --cache --ignore-unknown --write {staged_files}
glob: '*.{js,jsx,ts,tsx}'
```
Where:
- `parallel`: Whether to execute tasks in parallel
- `jobs`: Defines the list of tasks to execute
- `name`: Task name
- `run`: Command to execute
- `glob`: File pattern to match
- `{staged_files}`: Represents the list of staged files

View File

@@ -98,8 +98,8 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
"postinstall": "pnpm -r run stub --if-present",
// 只允许使用pnpm
"preinstall": "npx only-allow pnpm",
// husky的安装
"prepare": "is-ci || husky",
// lefthook的安装
"prepare": "is-ci || lefthook install",
// 预览应用
"preview": "turbo-run preview",
// 包规范检查

View File

@@ -339,6 +339,10 @@ interface RouteMeta {
| 'success'
| 'warning'
| string;
/**
* 路由的完整路径作为key默认true
*/
fullPathKey?: boolean;
/**
* 当前路由的子级在菜单中不展现
* @default false
@@ -502,6 +506,13 @@ interface RouteMeta {
用于配置页面的徽标颜色。
### fullPathKey
- 类型:`boolean`
- 默认值:`true`
是否将路由的完整路径作为tab key默认true
### activePath
- 类型:`string`
@@ -602,3 +613,32 @@ const { refresh } = useRefresh();
refresh();
</script>
```
## 标签页与路由控制
在某些场景下需要单个路由打开多个标签页或者修改路由的query不打开新的标签页
每个标签页Tab使用唯一的key标识设置Tab key有三种方式优先级由高到低
- 使用路由query参数pageKey
```vue
<script setup lang="ts">
import { useRouter } from 'vue-router';
// 跳转路由
const router = useRouter();
router.push({
path: 'path',
query: {
pageKey: 'key',
},
});
```
- 路由的完整路径作为key
`meta` 属性中的 `fullPathKey`不为false则使用路由`fullPath`作为key
- 路由的path作为key
`meta` 属性中的 `fullPathKey`为false则使用路由`path`作为key

View File

@@ -187,6 +187,7 @@ const defaultPreferences: Preferences = {
contentCompact: 'wide',
defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
defaultHomePath: '/analytics',
dynamicTitle: true,
enableCheckUpdates: true,
enablePreferences: true,
@@ -194,7 +195,7 @@ const defaultPreferences: Preferences = {
isMobile: false,
layout: 'sidebar-nav',
locale: 'zh-CN',
loginExpiredMode: 'modal',
loginExpiredMode: 'page',
name: 'Vben Admin',
preferencesButtonPosition: 'auto',
watermark: false,
@@ -213,14 +214,16 @@ const defaultPreferences: Preferences = {
enable: true,
icp: '',
icpLink: '',
settingShow: true,
},
footer: {
enable: true,
enable: false,
fixed: false,
},
header: {
enable: true,
hidden: false,
menuAlign: 'start',
mode: 'fixed',
},
logo: {
@@ -242,23 +245,28 @@ const defaultPreferences: Preferences = {
sidebar: {
autoActivateChild: false,
collapsed: false,
collapsedButton: true,
collapsedShowTitle: false,
enable: true,
expandOnHover: true,
extraCollapse: true,
extraCollapse: false,
fixedButton: true,
hidden: false,
width: 230,
width: 224,
},
tabbar: {
draggable: true,
enable: true,
height: 36,
height: 38,
keepAlive: true,
maxCount: 0,
middleClickToClose: false,
persist: true,
showIcon: true,
showMaximize: true,
showMore: true,
styleType: 'chrome',
wheelable: true,
},
theme: {
builtinType: 'default',
@@ -269,7 +277,7 @@ const defaultPreferences: Preferences = {
mode: 'dark',
radius: '0.5',
semiDarkHeader: false,
semiDarkSidebar: true,
semiDarkSidebar: false,
},
transition: {
enable: true,
@@ -312,6 +320,8 @@ interface AppPreferences {
contentCompact: ContentCompactType;
// /** 应用默认头像 */
defaultAvatar: string;
/** 默认首页地址 */
defaultHomePath: string;
// /** 开启动态标题 */
dynamicTitle: boolean;
/** 是否开启检查更新 */
@@ -366,6 +376,8 @@ interface CopyrightPreferences {
icp: string;
/** 备案号链接 */
icpLink: string;
/** 设置面板是否显示*/
settingShow?: boolean;
}
interface FooterPreferences {
@@ -380,6 +392,8 @@ interface HeaderPreferences {
enable: boolean;
/** 顶栏是否隐藏,css-隐藏 */
hidden: boolean;
/** 顶栏菜单位置 */
menuAlign: LayoutHeaderMenuAlignType;
/** header显示模式 */
mode: LayoutHeaderModeType;
}
@@ -401,8 +415,12 @@ interface NavigationPreferences {
}
interface SidebarPreferences {
/** 点击目录时自动激活子菜单 */
autoActivateChild: boolean;
/** 侧边栏是否折叠 */
collapsed: boolean;
/** 侧边栏折叠按钮是否可见 */
collapsedButton: boolean;
/** 侧边栏折叠时是否显示title */
collapsedShowTitle: boolean;
/** 侧边栏是否可见 */
@@ -411,6 +429,8 @@ interface SidebarPreferences {
expandOnHover: boolean;
/** 侧边栏扩展区域是否折叠 */
extraCollapse: boolean;
/** 侧边栏固定按钮是否可见 */
fixedButton: boolean;
/** 侧边栏是否隐藏 - css */
hidden: boolean;
/** 侧边栏宽度 */
@@ -439,6 +459,10 @@ interface TabbarPreferences {
height: number;
/** 开启标签页缓存功能 */
keepAlive: boolean;
/** 限制最大数量 */
maxCount: number;
/** 是否点击中键时关闭标签 */
middleClickToClose: boolean;
/** 是否持久化标签 */
persist: boolean;
/** 是否开启多标签页图标 */
@@ -449,6 +473,8 @@ interface TabbarPreferences {
showMore: boolean;
/** 标签页风格 */
styleType: TabsStyleType;
/** 是否开启鼠标滚轮响应 */
wheelable: boolean;
}
interface ThemePreferences {

View File

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

View File

@@ -18,7 +18,7 @@
## 依赖问题
`Monorepo` 项目下,需要养成每次 `git pull`代码都要执行`pnpm install`的习惯,因为经常会有新的依赖包加入,项目在`.husky/git-merge`已经配置了自动执行`pnpm install`,但是有时候会出现问题,如果没有自动执行,建议手动执行一次。
`Monorepo` 项目下,需要养成每次 `git pull`代码都要执行`pnpm install`的习惯,因为经常会有新的依赖包加入,项目在`lefthook.yml`已经配置了自动执行`pnpm install`,但是有时候会出现问题,如果没有自动执行,建议手动执行一次。
## 关于缓存更新问题

View File

@@ -33,8 +33,8 @@
- [Prettier](https://prettier.io/) 用于代码格式化
- [Commitlint](https://commitlint.js.org/) 用于检查 git 提交信息的规范
- [Publint](https://publint.dev/) 用于检查 npm 包的规范
- [Lint Staged](https://github.com/lint-staged/lint-staged) 用于在 git 提交前运行代码校验
- [Cspell](https://cspell.org/) 用于检查拼写错误
- [lefthook](https://github.com/evilmartians/lefthook) 用于管理 Git hooks在提交前自动运行代码校验和格式化
## ESLint
@@ -148,18 +148,66 @@ cspell 配置文件为 `cspell.json`,可以根据项目需求进行修改。
git hook 一般结合各种 lint在 git 提交代码的时候进行代码风格校验,如果校验没通过,则不会进行提交。需要开发者自行修改后再次进行提交
### husky
### lefthook
有一个问题就是校验会校验全部代码,但是我们只想校验我们自己提交的代码,这个时候就可以使用 husky
有一个问题就是校验会校验全部代码,但是我们只想校验我们自己提交的代码,这个时候就可以使用 lefthook
最有效的解决方案就是将 Lint 校验放到本地,常见做法是使用 husky 或者 pre-commit 在本地提交之前先做一次 Lint 校验。
最有效的解决方案就是将 Lint 校验放到本地,常见做法是使用 lefthook 在本地提交之前先做一次 Lint 校验。
项目在 `.husky` 内部定义了相应的 hooks
项目在 `lefthook.yml` 内部定义了相应的 hooks
#### 如何关闭 Husky
- `pre-commit`: 在提交前运行,用于代码格式化和检查
如果你想关闭 Husky直接删除 `.husky` 目录即可。
- `code-workspace`: 更新 VSCode 工作区配置
- `lint-md`: 格式化 Markdown 文件
- `lint-vue`: 格式化并检查 Vue 文件
- `lint-js`: 格式化并检查 JavaScript/TypeScript 文件
- `lint-style`: 格式化并检查样式文件
- `lint-package`: 格式化 package.json
- `lint-json`: 格式化其他 JSON 文件
### lint-staged
- `post-merge`: 在合并后运行,用于自动安装依赖
用于自动修复提交文件风格问题,其配置文件为 `.lintstagedrc.mjs`,可以根据项目需求进行修改。
- `install`: 运行 `pnpm install` 安装新依赖
- `commit-msg`: 在提交时运行,用于检查提交信息格式
- `commitlint`: 使用 commitlint 检查提交信息
#### 如何关闭 lefthook
如果你想关闭 lefthook有两种方式
::: code-group
```bash [临时关闭]
git commit -m 'feat: add home page' --no-verify
```
```bash [永久关闭]
# 删除 lefthook.yml 文件即可
rm lefthook.yml
```
:::
#### 如何修改 lefthook 配置
如果你想修改 lefthook 的配置,可以编辑 `lefthook.yml` 文件。例如:
```yaml
pre-commit:
parallel: true # 并行执行任务
jobs:
- name: lint-js
run: pnpm prettier --cache --ignore-unknown --write {staged_files}
glob: '*.{js,jsx,ts,tsx}'
```
其中:
- `parallel`: 是否并行执行任务
- `jobs`: 定义要执行的任务列表
- `name`: 任务名称
- `run`: 要执行的命令
- `glob`: 匹配的文件模式
- `{staged_files}`: 表示暂存的文件列表

View File

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

View File

@@ -70,7 +70,7 @@ export async function perfectionist(): Promise<Linter.Config[]> {
},
],
'perfectionist/sort-objects': [
'error',
'off',
{
customGroups: {
items: 'items',

View File

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

View File

@@ -28,6 +28,13 @@ const customConfig: Linter.Config[] = [
'perfectionist/sort-objects': 'off',
},
},
{
files: ['**/**.vue'],
ignores: restrictedImportIgnores,
rules: {
'perfectionist/sort-objects': 'off',
},
},
{
// apps内部的一些基础规则
files: ['apps/**/**'],

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/tailwind-config",
"version": "5.5.5",
"version": "5.5.6",
"private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
@@ -12,7 +12,7 @@
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild"
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"

View File

@@ -1,6 +1,9 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"compilerOptions": {
"moduleResolution": "bundler"
},
"include": ["src"],
"exclude": ["node_modules"]
}

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/vite-config",
"version": "5.5.5",
"version": "5.5.6",
"private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
@@ -47,12 +47,15 @@
"@vitejs/plugin-vue-jsx": "catalog:",
"dayjs": "catalog:",
"dotenv": "catalog:",
"electron": "catalog:",
"rollup": "catalog:",
"rollup-plugin-visualizer": "catalog:",
"sass": "catalog:",
"vite": "catalog:",
"vite-plugin-compression": "catalog:",
"vite-plugin-dts": "catalog:",
"vite-plugin-electron": "catalog:",
"vite-plugin-electron-renderer": "catalog:",
"vite-plugin-html": "catalog:",
"vite-plugin-lazy-import": "catalog:"
}

View File

@@ -0,0 +1,40 @@
import type { PluginOption } from 'vite';
import type { CommonPluginOptions } from '../typing';
import fs from 'node:fs';
import electron from 'vite-plugin-electron/simple';
export const viteElectronPlugin = (
options: CommonPluginOptions,
): PluginOption => {
fs.rmSync('dist-electron', { force: true, recursive: true });
const isServe = !options.isBuild;
const isBuild = options.isBuild;
const sourcemap = isServe || !!process.env.VSCODE_DEBUG;
return electron({
main: {
entry: 'electron/main.ts',
vite: {
build: {
minify: isBuild,
outDir: 'dist-electron/main',
sourcemap,
},
},
},
preload: {
input: 'electron/preload.ts',
vite: {
build: {
minify: isBuild,
outDir: 'dist-electron/preload',
sourcemap: sourcemap ? 'inline' : undefined, // #332
},
},
},
renderer: {},
});
};

View File

@@ -18,6 +18,7 @@ import { VitePWA } from 'vite-plugin-pwa';
import viteVueDevTools from 'vite-plugin-vue-devtools';
import { viteArchiverPlugin } from './archiver';
import { viteElectronPlugin } from './electron';
import { viteExtraAppConfigPlugin } from './extra-app-config';
import { viteImportMapPlugin } from './importmap';
import { viteInjectAppLoadingPlugin } from './inject-app-loading';
@@ -97,6 +98,7 @@ async function loadApplicationPlugins(
archiverPluginOptions,
compress,
compressTypes,
electron,
extraAppConfig,
html,
i18n,
@@ -213,6 +215,10 @@ async function loadApplicationPlugins(
return [await viteArchiverPlugin(archiverPluginOptions)];
},
},
{
condition: electron,
plugins: () => [viteElectronPlugin(commonOptions)],
},
]);
}

View File

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

76
lefthook.yml Normal file
View File

@@ -0,0 +1,76 @@
# EXAMPLE USAGE:
#
# Refer for explanation to following link:
# https://lefthook.dev/configuration/
#
# pre-push:
# jobs:
# - name: packages audit
# tags:
# - frontend
# - security
# run: yarn audit
#
# - name: gems audit
# tags:
# - backend
# - security
# run: bundle audit
#
# pre-commit:
# parallel: true
# jobs:
# - run: yarn eslint {staged_files}
# glob: "*.{js,ts,jsx,tsx}"
#
# - name: rubocop
# glob: "*.rb"
# exclude:
# - config/application.rb
# - config/routes.rb
# run: bundle exec rubocop --force-exclusion {all_files}
#
# - name: govet
# files: git ls-files -m
# glob: "*.go"
# run: go vet {files}
#
# - script: "hello.js"
# runner: node
#
# - script: "hello.go"
# runner: go run
pre-commit:
parallel: true
commands:
code-workspace:
run: pnpm vsh code-workspace --auto-commit
lint-md:
run: pnpm prettier --cache --ignore-unknown --write {staged_files}
glob: '*.md'
lint-vue:
run: pnpm prettier --write {staged_files} && pnpm eslint --cache --fix {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files}
glob: '*.vue'
lint-js:
run: pnpm prettier --cache --ignore-unknown --write {staged_files} && pnpm eslint --cache --fix {staged_files}
glob: '*.{js,jsx,ts,tsx}'
lint-style:
run: pnpm prettier --cache --ignore-unknown --write {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files}
glob: '*.{scss,less,styl,html,vue,css}'
lint-package:
run: pnpm prettier --cache --write {staged_files}
glob: 'package.json'
lint-json:
run: pnpm prettier --cache --write --parser json {staged_files}
glob: '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}'
post-merge:
commands:
install:
run: pnpm install
commit-msg:
commands:
commitlint:
run: pnpm exec commitlint --edit $1

View File

@@ -1,6 +1,6 @@
{
"name": "vben-admin-monorepo",
"version": "5.5.5",
"version": "5.5.6",
"private": true,
"keywords": [
"monorepo",
@@ -51,14 +51,14 @@
"lint": "vsh lint",
"postinstall": "pnpm -r run stub --if-present",
"preinstall": "npx only-allow pnpm",
"prepare": "is-ci || husky",
"preview": "turbo-run preview",
"publint": "vsh publint",
"reinstall": "pnpm clean --del-lock && pnpm install",
"test:unit": "vitest run --dom",
"test:e2e": "turbo run test:e2e",
"update:deps": "npx taze -r -w",
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile",
"catalog": "pnpx codemod pnpm/catalog"
},
"devDependencies": {
"@changesets/changelog-github": "catalog:",
@@ -81,9 +81,8 @@
"cross-env": "catalog:",
"cspell": "catalog:",
"happy-dom": "catalog:",
"husky": "catalog:",
"is-ci": "catalog:",
"lint-staged": "catalog:",
"lefthook": "catalog:",
"playwright": "catalog:",
"rimraf": "catalog:",
"tailwindcss": "catalog:",
@@ -99,7 +98,7 @@
"node": ">=20.10.0",
"pnpm": ">=9.12.0"
},
"packageManager": "pnpm@9.15.9",
"packageManager": "pnpm@10.10.0",
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
@@ -110,7 +109,7 @@
"@ast-grep/napi": "catalog:",
"@ctrl/tinycolor": "catalog:",
"clsx": "catalog:",
"esbuild": "0.24.0",
"esbuild": "0.25.3",
"pinia": "catalog:",
"vue": "catalog:"
},

View File

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

View File

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

View File

@@ -45,6 +45,7 @@ export {
Menu,
Minimize,
Minimize2,
Minus,
MoonStar,
Palette,
PanelLeft,
@@ -58,6 +59,8 @@ export {
Settings,
Shrink,
Square,
SquareArrowDownLeft,
SquareArrowUpRight,
SquareCheckBig,
SquareMinus,
Sun,

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/shared",
"version": "5.5.5",
"version": "5.5.6",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -98,6 +98,8 @@
"@types/lodash.get": "catalog:",
"@types/lodash.isequal": "catalog:",
"@types/lodash.set": "catalog:",
"@types/nprogress": "catalog:"
"@types/nprogress": "catalog:",
"@vben-core/typings": "workspace:*",
"electron": "catalog:"
}
}

View File

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

View File

@@ -28,10 +28,11 @@ function openWindow(url: string, options: OpenWindowOptions = {}): void {
* @param path
*/
function openRouteInNewWindow(path: string) {
const { hash, origin } = location;
// const { hash, origin } = location;
const fullPath = path.startsWith('/') ? path : `/${path}`;
const url = `${origin}${hash ? '/#' : ''}${fullPath}`;
openWindow(url, { target: '_blank' });
// const url = `${origin}${hash ? '/#' : ''}${fullPath}`;
// openWindow(url, { target: '_blank' });
window.ipcRenderer.invoke('open-win', fullPath);
}
export { openRouteInNewWindow, openWindow };

View File

@@ -1,6 +1,9 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/library.json",
"compilerOptions": {
"types": ["@vben-core/typings/electron"]
},
"include": ["src"],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,27 @@
import type { IpcRendererEvent } from 'electron';
export type IpcRendererInvoke =
| 'app-close'
| 'app-maximize'
| 'app-minimize'
| 'is-maximized'
| 'open-win';
declare global {
interface Window {
ipcRenderer: {
invoke: (channel: IpcRendererInvoke, ...args: any[]) => Promise<any>;
off: (
channel: string,
listener: (event: IpcRendererEvent, ...args: any[]) => void,
) => void;
on: (
channel: string,
listener: (event: IpcRendererEvent, ...args: any[]) => void,
) => void;
send: (channel: string, data: any) => Promise<any>;
};
}
}
export {};

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/typings",
"version": "5.5.5",
"version": "5.5.6",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -27,6 +27,9 @@
},
"./vue-router": {
"types": "./vue-router.d.ts"
},
"./electron": {
"types": "./electron.d.ts"
}
},
"publishConfig": {

View File

@@ -1,3 +1,8 @@
import type { RouteLocationNormalized } from 'vue-router';
export type TabDefinition = RouteLocationNormalized;
export interface TabDefinition extends RouteLocationNormalized {
/**
* 标签页的key
*/
key?: string;
}

View File

@@ -43,6 +43,10 @@ interface RouteMeta {
| 'success'
| 'warning'
| string;
/**
* 路由的完整路径作为key默认true
*/
fullPathKey?: boolean;
/**
* 当前路由的子级在菜单中不展现
* @default false

View File

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

View File

@@ -11,6 +11,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
"compact": false,
"contentCompact": "wide",
"defaultAvatar": "https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp",
"defaultHomePath": "/analytics",
"dynamicTitle": true,
"enableCheckUpdates": true,
"enablePreferences": true,

View File

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

View File

@@ -11,6 +11,7 @@ const defaultPreferences: Preferences = {
contentCompact: 'wide',
defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
defaultHomePath: '/analytics',
dynamicTitle: true,
enableCheckUpdates: true,
enablePreferences: true,

View File

@@ -35,6 +35,8 @@ interface AppPreferences {
contentCompact: ContentCompactType;
// /** 应用默认头像 */
defaultAvatar: string;
/** 默认首页地址 */
defaultHomePath: string;
// /** 开启动态标题 */
dynamicTitle: boolean;
/** 是否开启检查更新 */

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/form-ui",
"version": "5.5.5",
"version": "5.5.6",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -38,6 +38,7 @@
},
"dependencies": {
"@vben-core/composables": "workspace:*",
"@vben-core/icons": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",

View File

@@ -2,13 +2,18 @@ import type { FormRenderProps } from '../types';
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) {
const wrapperRef = useTemplateRef<HTMLElement>('wrapperRef');
const isVisible = useElementVisibility(wrapperRef);
const rowMapping = ref<Record<number, number>>({});
// 是否已经计算过一次
const isCalculated = ref(false);
@@ -31,6 +36,7 @@ export function useExpandable(props: FormRenderProps) {
() => props.showCollapseButton,
() => breakpoints.active().value,
() => props.schema?.length,
() => isVisible.value,
],
async ([val]) => {
if (val) {

View File

@@ -5,6 +5,7 @@ import type { FormSchema, MaybeComponentProps } from '../types';
import { computed, nextTick, onUnmounted, useTemplateRef, watch } from 'vue';
import { CircleAlert } from '@vben-core/icons';
import {
FormControl,
FormDescription,
@@ -12,6 +13,7 @@ import {
FormItem,
FormMessage,
VbenRenderContent,
VbenTooltip,
} from '@vben-core/shadcn-ui';
import { cn, isFunction, isObject, isString } from '@vben-core/shared/utils';
@@ -354,6 +356,24 @@ onUnmounted(() => {
</template>
<!-- <slot></slot> -->
</component>
<VbenTooltip
v-if="compact && isInValid"
:delay-duration="300"
side="left"
>
<template #trigger>
<slot name="trigger">
<CircleAlert
:class="
cn(
'text-foreground/80 hover:text-foreground inline-flex size-5 cursor-pointer',
)
"
/>
</slot>
</template>
<FormMessage />
</VbenTooltip>
</slot>
</FormControl>
<!-- 自定义后缀 -->
@@ -365,7 +385,7 @@ onUnmounted(() => {
</FormDescription>
</div>
<Transition name="slide-up">
<Transition name="slide-up" v-if="!compact">
<FormMessage class="absolute bottom-1" />
</Transition>
</div>

View File

@@ -31,8 +31,8 @@ export function useVbenForm<
h(VbenUseForm, { ...props, ...attrs, formApi: extendedApi }, slots);
},
{
inheritAttrs: false,
name: 'VbenUseForm',
inheritAttrs: false,
},
);
// Add reactivity support

View File

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

View File

@@ -64,7 +64,7 @@ const logoStyle = computed((): CSSProperties => {
<header
:class="theme"
:style="style"
class="border-border bg-header top-0 flex w-full flex-[0_0_auto] items-center border-b pl-2 transition-[margin-top] duration-200"
class="app-header border-border bg-header top-0 flex w-full flex-[0_0_auto] items-center border-b pl-2 transition-[margin-top] duration-200"
>
<div v-if="slots.logo" :style="logoStyle">
<slot name="logo"></slot>
@@ -75,3 +75,17 @@ const logoStyle = computed((): CSSProperties => {
<slot></slot>
</header>
</template>
<style lang="scss" scoped>
.bg-header {
app-region: drag;
user-select: none;
:deep(.cursor-pointer),
:deep(.vben-sub-menu),
:deep(.vben-menu-item),
:deep(button),
:deep(a) {
app-region: no-drag;
}
}
</style>

View File

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

View File

@@ -31,6 +31,7 @@ import {
createSubMenuContext,
useMenuStyle,
} from '../hooks';
import { useMenuScroll } from '../hooks/use-menu-scroll';
import { flattedChildren } from '../utils';
import SubMenu from './sub-menu.vue';
@@ -44,6 +45,7 @@ const props = withDefaults(defineProps<Props>(), {
mode: 'vertical',
rounded: true,
theme: 'dark',
scrollToActive: false,
});
const emit = defineEmits<{
@@ -206,15 +208,19 @@ function handleResize() {
isFirstTimeRender = false;
}
function getActivePaths() {
const activeItem = activePath.value && items.value[activePath.value];
const enableScroll = computed(
() => props.scrollToActive && props.mode === 'vertical' && !props.collapse,
);
if (!activeItem || props.mode === 'horizontal' || props.collapse) {
return [];
}
const { scrollToActiveItem } = useMenuScroll(activePath, {
enable: enableScroll,
delay: 320,
});
return activeItem.parentPaths;
}
// 监听 activePath 变化,自动滚动到激活项
watch(activePath, () => {
scrollToActiveItem();
});
// 默认展开菜单
function initMenu() {
@@ -318,6 +324,16 @@ function removeSubMenu(subMenu: MenuItemRegistered) {
function removeMenuItem(item: MenuItemRegistered) {
Reflect.deleteProperty(items.value, item.path);
}
function getActivePaths() {
const activeItem = activePath.value && items.value[activePath.value];
if (!activeItem || props.mode === 'horizontal' || props.collapse) {
return [];
}
return activeItem.parentPaths;
}
</script>
<template>
<ul
@@ -374,10 +390,10 @@ $namespace: vben;
var(--menu-item-margin-x);
font-size: var(--menu-font-size);
color: var(--menu-item-color);
text-decoration: none;
white-space: nowrap;
list-style: none;
text-decoration: none;
cursor: pointer;
list-style: none;
background: var(--menu-item-background-color);
border: none;
border-radius: var(--menu-item-radius);
@@ -701,8 +717,8 @@ $namespace: vben;
width: var(--menu-item-icon-size);
height: var(--menu-item-icon-size);
margin-right: 8px;
text-align: center;
vertical-align: middle;
text-align: center;
}
}

View File

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

View File

@@ -0,0 +1,46 @@
import type { Ref } from 'vue';
import { watch } from 'vue';
import { useDebounceFn } from '@vueuse/core';
interface UseMenuScrollOptions {
delay?: number;
enable?: boolean | Ref<boolean>;
}
export function useMenuScroll(
activePath: Ref<string | undefined>,
options: UseMenuScrollOptions = {},
) {
const { enable = true, delay = 320 } = options;
function scrollToActiveItem() {
const isEnabled = typeof enable === 'boolean' ? enable : enable.value;
if (!isEnabled) return;
const activeElement = document.querySelector(
`aside li[role=menuitem].is-active`,
);
if (activeElement) {
activeElement.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center',
});
}
}
const debouncedScroll = useDebounceFn(scrollToActiveItem, delay);
watch(activePath, () => {
const isEnabled = typeof enable === 'boolean' ? enable : enable.value;
if (!isEnabled) return;
debouncedScroll();
});
return {
scrollToActiveItem,
};
}

View File

@@ -18,15 +18,9 @@ defineOptions({
const props = withDefaults(defineProps<Props>(), {
collapse: false,
// theme: 'dark',
});
const forward = useForwardProps(props);
// const emit = defineEmits<{
// 'update:openKeys': [key: Key[]];
// 'update:selectedKeys': [key: Key[]];
// }>();
</script>
<template>

View File

@@ -42,6 +42,12 @@ interface MenuProps {
*/
rounded?: boolean;
/**
* @zh_CN 是否自动滚动到激活的菜单项
* @default false
*/
scrollToActive?: boolean;
/**
* @zh_CN 菜单主题
* @default dark

View File

@@ -35,7 +35,7 @@ interface Props extends DrawerProps {
const props = withDefaults(defineProps<Props>(), {
appendToMain: false,
closeIconPlacement: 'right',
destroyOnClose: true,
destroyOnClose: false,
drawerApi: undefined,
submitting: false,
zIndex: 1000,
@@ -82,17 +82,17 @@ const {
zIndex,
} = usePriorityValues(props, state);
watch(
() => showLoading.value,
(v) => {
if (v && wrapperRef.value) {
wrapperRef.value.scrollTo({
// behavior: 'smooth',
top: 0,
});
}
},
);
// watch(
// () => showLoading.value,
// (v) => {
// if (v && wrapperRef.value) {
// wrapperRef.value.scrollTo({
// // behavior: 'smooth',
// top: 0,
// });
// }
// },
// );
function interactOutside(e: Event) {
if (!closeOnClickModal.value || submitting.value) {
@@ -266,19 +266,13 @@ const getForceMount = computed(() => {
ref="wrapperRef"
:class="
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>
</div>
<VbenLoading v-if="showLoading || submitting" spinning />
<SheetFooter
v-if="showFooter"
:class="

View File

@@ -9,6 +9,7 @@ import {
h,
inject,
nextTick,
onDeactivated,
provide,
reactive,
ref,
@@ -21,9 +22,7 @@ import VbenDrawer from './drawer.vue';
const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT');
const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {
destroyOnClose: true,
};
const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {};
export function setDefaultDrawerProps(props: Partial<DrawerProps>) {
Object.assign(DEFAULT_DRAWER_PROPS, props);
@@ -66,11 +65,20 @@ export function useVbenDrawer<
slots,
);
},
// eslint-disable-next-line vue/one-component-per-file
{
inheritAttrs: false,
name: 'VbenParentDrawer',
inheritAttrs: false,
},
);
/**
* 在开启keepAlive情况下 直接通过浏览器按钮/手势等返回 不会关闭弹窗
*/
onDeactivated(() => {
(extendedApi as ExtendedDrawerApi)?.close?.();
});
return [Drawer, extendedApi as ExtendedDrawerApi] as const;
}
@@ -107,9 +115,10 @@ export function useVbenDrawer<
return () =>
h(VbenDrawer, { ...props, ...attrs, drawerApi: extendedApi }, slots);
},
// eslint-disable-next-line vue/one-component-per-file
{
inheritAttrs: false,
name: 'VbenDrawer',
inheritAttrs: false,
},
);
injectData.extendApi?.(extendedApi);

View File

@@ -34,7 +34,7 @@ interface Props extends ModalProps {
const props = withDefaults(defineProps<Props>(), {
appendToMain: false,
destroyOnClose: true,
destroyOnClose: false,
modalApi: undefined,
});
@@ -123,17 +123,17 @@ watch(
{ immediate: true },
);
watch(
() => [showLoading.value, submitting.value],
([l, s]) => {
if ((s || l) && wrapperRef.value) {
wrapperRef.value.scrollTo({
// behavior: 'smooth',
top: 0,
});
}
},
);
// watch(
// () => [showLoading.value, submitting.value],
// ([l, s]) => {
// if ((s || l) && wrapperRef.value) {
// wrapperRef.value.scrollTo({
// // behavior: 'smooth',
// top: 0,
// });
// }
// },
// );
function handleFullscreen() {
props.modalApi?.setState((prev) => {
@@ -274,18 +274,13 @@ function handleClosed() {
ref="wrapperRef"
:class="
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>
</div>
<VbenLoading v-if="showLoading || submitting" spinning />
<VbenIconButton
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"

View File

@@ -5,6 +5,7 @@ import {
h,
inject,
nextTick,
onDeactivated,
provide,
reactive,
ref,
@@ -17,9 +18,7 @@ import VbenModal from './modal.vue';
const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT');
const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {
destroyOnClose: true,
};
const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {};
export function setDefaultModalProps(props: Partial<ModalProps>) {
Object.assign(DEFAULT_MODAL_PROPS, props);
@@ -65,11 +64,20 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
slots,
);
},
// eslint-disable-next-line vue/one-component-per-file
{
inheritAttrs: false,
name: 'VbenParentModal',
inheritAttrs: false,
},
);
/**
* 在开启keepAlive情况下 直接通过浏览器按钮/手势等返回 不会关闭弹窗
*/
onDeactivated(() => {
(extendedApi as ExtendedModalApi)?.close?.();
});
return [Modal, extendedApi as ExtendedModalApi] as const;
}
@@ -114,9 +122,10 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
slots,
);
},
// eslint-disable-next-line vue/one-component-per-file
{
inheritAttrs: false,
name: 'VbenModal',
inheritAttrs: false,
},
);
injectData.extendApi?.(extendedApi);

View File

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

View File

@@ -36,7 +36,7 @@ export interface VbenButtonGroupProps
btnClass?: any;
gap?: number;
multiple?: boolean;
options?: { label: CustomRenderType; value: ValueType }[];
options?: { [key: string]: any; label: CustomRenderType; value: ValueType }[];
showIcon?: boolean;
size?: 'large' | 'middle' | 'small';
}

View File

@@ -119,7 +119,7 @@ async function onBtnClick(value: ValueType) {
<CircleCheckBig v-else-if="innerValue.includes(btn.value)" />
<Circle v-else />
</div>
<slot name="option" :label="btn.label" :value="btn.value">
<slot name="option" :label="btn.label" :value="btn.value" :data="btn">
<VbenRenderContent :content="btn.label" />
</slot>
</Button>
@@ -127,6 +127,9 @@ async function onBtnClick(value: ValueType) {
</template>
<style lang="scss" scoped>
.vben-check-button-group {
display: flex;
flex-wrap: wrap;
&:deep(.size-large) button {
.icon-wrapper {
margin-right: 0.3rem;
@@ -159,5 +162,16 @@ async function onBtnClick(value: ValueType) {
}
}
}
&.no-gap > :deep(button):nth-of-type(1) {
border-right-width: 0;
}
&.no-gap {
:deep(button + button) {
margin-right: -1px;
border-left-width: 1px;
}
}
}
</style>

View File

@@ -21,6 +21,7 @@ interface Props extends PopoverRootProps {
class?: ClassType;
contentClass?: ClassType;
contentProps?: PopoverContentProps;
triggerClass?: ClassType;
}
const props = withDefaults(defineProps<Props>(), {});
@@ -32,6 +33,7 @@ const delegatedProps = computed(() => {
class: _cls,
contentClass: _,
contentProps: _cProps,
triggerClass: _tClass,
...delegated
} = props;
@@ -43,7 +45,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<template>
<PopoverRoot v-bind="forwarded">
<PopoverTrigger>
<PopoverTrigger :class="triggerClass">
<slot name="trigger"></slot>
<PopoverContent

View File

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

View File

@@ -224,15 +224,20 @@ defineExpose({
:class="
cn('cursor-pointer', getNodeClass?.(item), {
'data-[selected]:bg-accent': !multiple,
'cursor-not-allowed': disabled,
})
"
v-bind="
Object.assign(item.bind, {
onfocus: disabled ? 'this.blur()' : undefined,
})
"
v-bind="item.bind"
@select="
(event) => {
if (event.detail.originalEvent.type === 'click') {
event.preventDefault();
}
onSelect(item, event.detail.isSelected);
!disabled && onSelect(item, event.detail.isSelected);
}
"
@toggle="
@@ -240,7 +245,7 @@ defineExpose({
if (event.detail.originalEvent.type === 'click') {
event.preventDefault();
}
onToggle(item);
!disabled && onToggle(item);
}
"
class="tree-node focus:ring-grass8 my-0.5 flex items-center rounded px-2 py-1 outline-none focus:ring-2"
@@ -262,10 +267,11 @@ defineExpose({
<Checkbox
v-if="multiple"
:checked="isSelected"
:disabled="disabled"
:indeterminate="isIndeterminate"
@click="
() => {
handleSelect();
!disabled && handleSelect();
// onSelect(item, !isSelected);
}
"
@@ -276,7 +282,7 @@ defineExpose({
(_event) => {
// $event.stopPropagation();
// $event.preventDefault();
handleSelect();
!disabled && handleSelect();
// onSelect(item, !isSelected);
}
"

View File

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

View File

@@ -12,7 +12,6 @@ interface Props extends TabsProps {}
defineOptions({
name: 'VbenTabsChrome',
// eslint-disable-next-line perfectionist/sort-objects
inheritAttrs: false,
});
@@ -41,14 +40,14 @@ const style = computed(() => {
const tabsView = computed(() => {
return props.tabs.map((tab) => {
const { fullPath, meta, name, path } = tab || {};
const { fullPath, meta, name, path, key } = tab || {};
const { affixTab, icon, newTabTitle, tabClosable, title } = meta || {};
return {
affixTab: !!affixTab,
closable: Reflect.has(meta, 'tabClosable') ? !!tabClosable : true,
fullPath,
icon: icon as string,
key: fullPath || path,
key,
meta,
name,
path,

View File

@@ -12,7 +12,7 @@ interface Props extends TabsProps {}
defineOptions({
name: 'VbenTabs',
// eslint-disable-next-line perfectionist/sort-objects
inheritAttrs: false,
});
const props = withDefaults(defineProps<Props>(), {
@@ -47,14 +47,14 @@ const typeWithClass = computed(() => {
const tabsView = computed(() => {
return props.tabs.map((tab) => {
const { fullPath, meta, name, path } = tab || {};
const { fullPath, meta, name, path, key } = tab || {};
const { affixTab, icon, newTabTitle, tabClosable, title } = meta || {};
return {
affixTab: !!affixTab,
closable: Reflect.has(meta, 'tabClosable') ? !!tabClosable : true,
fullPath,
icon: icon as string,
key: fullPath || path,
key,
meta,
name,
path,

View File

@@ -15,5 +15,5 @@ pnpm add @vben/constants
### 使用
```ts
import { DEFAULT_HOME_PATH } from '@vben/constants';
import { LOGIN_PATH } from '@vben/constants';
```

View File

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

View File

@@ -3,11 +3,6 @@
*/
export const LOGIN_PATH = '/auth/login';
/**
* @zh_CN 默认首页地址
*/
export const DEFAULT_HOME_PATH = '/analytics';
export interface LanguageOption {
label: string;
value: 'en-US' | 'zh-CN';

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