Compare commits

...

919 Commits

Author SHA1 Message Date
982bd9cd1b 初始化
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
缺陷:主题配色需要优化整体的同风格
2026-08-14 23:23:58 +08:00
27135f4ae6 初始化
缺陷:主题配色需要优化整体的同风格
2026-08-14 23:19:06 +08:00
李琦
318aeab092 AI代码生成工具、个人中心 2026-08-13 19:04:28 +08:00
李琦
c45bcde94d AI代码生成工具、个人中心 2026-08-11 09:39:29 +08:00
李琦
cbbbe4ab7a AI代码生成工具、个人中心 2026-08-10 18:32:33 +08:00
李琦
e8f30a1275 AI代码生成工具 2026-08-10 15:51:04 +08:00
李琦
089fa2f3eb 更新规则和uipro 2026-08-10 14:42:27 +08:00
李琦
f676b763ee 更新规则和uipro 2026-08-10 13:58:01 +08:00
李琦
5b7da38aeb 更新规则和uipro 2026-08-10 13:45:52 +08:00
李琦
7895909a0c Merge remote-tracking branch 'vben/main'
# Conflicts:
#	README.md
#	apps/web-antd/src/adapter/component/index.ts
#	apps/web-antd/src/layouts/basic.vue
#	apps/web-antd/src/router/routes/modules/demos.ts
#	apps/web-antd/src/views/demos/antd/index.vue
#	package.json
#	pnpm-lock.yaml
2026-08-10 13:28:08 +08:00
JyQAQ
e8d35a7471 fix(@vben/styles): 修复弹窗内 tooltip 层级被遮挡问题 (#8240)
将 antd-tooltip 的 z-index 提升至 2001,避免在 Modal/弹窗等高 z-index 容器内的 tooltip 被遮挡
2026-08-07 06:08:20 +08:00
yshbyy
f038166681 chore: 更新.gitattributes文件配置 (#8178)
git 不支持 Shell 的花括号展开语法
2026-08-07 05:16:35 +08:00
dependabot[bot]
88cc837f6a build(deps): bump actions/stale from 10 to 11 (#8227)
Bumps [actions/stale](https://github.com/actions/stale) from 10 to 11.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v10...v11)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: '11'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 05:15:36 +08:00
金毛88
82d790a6ab Merge branch 'fork/dream-weave/fix/popup-route-reentry' 2026-08-07 05:14:52 +08:00
金毛88
9c3ba53990 Merge branch 'fork/ming4762/fix-transition-20260805' 2026-08-07 05:11:42 +08:00
金毛88
cb707c8c78 Merge branch 'fork/LayHuts/fix/lint-format' 2026-08-07 05:09:58 +08:00
Dream
98761dce98 fix(@vben-core/popup-ui): stabilize content popups across routes
Mount in-content drawers and modals to the persistent main content element.

Initialize drawer open state when mounted after the API opens.

Fixes vbenjs/vue-vben-admin#8210
2026-08-06 10:17:14 +08:00
zhongming4762
d3dc081b5d perf: 优化路由动画切换 1、切换出现双页面问题 2、切换出现横向和纵向滚动条问题 2026-08-05 19:14:12 +08:00
layhuts
2c1e643ab9 fix: 调整lint执行顺序
使用核心 no-nested-ternary 规则替代 Unicorn 自动修复,避免嵌套三元表达式被错误加括号
调整 oxlint、oxfmt、eslint 和 stylelint 的执行顺序,保证commit与format流程一致
2026-08-05 11:10:21 +08:00
Dream
0a47dc8a3d fix(@vben/playground): reset popup form state 2026-08-05 10:24:28 +08:00
Dream
d0c8c887fd docs: document typed popup data contracts 2026-08-05 09:54:01 +08:00
Dream
f16c780c2b refactor(@vben/web-naive): type modal shared data 2026-08-05 09:52:28 +08:00
Dream
ebe0eadee4 feat(@vben/playground): add typed popup data examples 2026-08-05 09:50:55 +08:00
Dream
3cbb1e8411 refactor(@vben/playground): type popup data consumers 2026-08-05 09:48:27 +08:00
Dream
21d9132703 feat(@vben-core/popup-ui)!: add typed popup data contracts
Bind shared data to modal and drawer APIs and infer it from exposed connected components.

BREAKING CHANGE: getData<T>() is replaced by getData().
Shared data defaults to unknown, and an unset payload returns undefined instead
of an empty object.
2026-08-05 09:46:37 +08:00
dream-weave
9f5b1cd9fb fix(@vben-core/form-ui)!: group field slot component props (#8215)
* refactor(@vben-core/form-ui)!: group field slot component props

* fix(@vben-core/form-ui): stabilize grouped field slot bindings

Resolve function-based common component props with field context.

Preserve internal model and event bindings when custom field slots spread componentProps.

Add regression coverage for array contexts, disabled precedence, and stale binding isolation.

* feat(@vben/vite-config): warn about field slot migration

Print the temporary field-slot migration warning when the development server starts.

Inject the same message into the browser console and keep the plugin serve-only.

* docs(@vben/docs): document field slot migration

Place the breaking field-slot notice at the start of both form documents.

Explain old and new bindings, development warnings, and planned notice removal.

* feat(@vben/playground): extend custom form example

Add a switchable input and select field to demonstrate schema component updates.

Update the composite phone field to emit new tuple values so validation observes changes.
2026-07-31 18:13:49 +08:00
dream-weave
32495e40b2 fix(@vben-core/popup-ui): rebind popup api after HMR (#8217)
* fix(@vben-core/popup-ui): rebind popup api after hmr

* fix(@vben-core/popup-ui): preserve options after remount
2026-07-31 06:13:10 +08:00
dream-weave
cb52807b27 fix(@vben-core/form-ui): correct field slot props (#8216) 2026-07-31 06:07:52 +08:00
MistyMoon
418c16e093 fix(@vben/locales): 修复锁屏弹窗按钮文案歧义 (#8211)
锁屏设置弹窗(lock-screen-modal)的确认按钮作用是输入密码后锁定屏幕,
但按钮文案 i18n key `ui.widgets.lockScreen.screenButton` 原值为「解锁」/「Unlock」,
与弹窗标题「锁定屏幕」及实际动作矛盾,存在歧义。

- zh-CN: 「解锁」->「锁定」
- en-US: 「Unlock」->「Lock」

(同段另有 `unlock` key 值「点击解锁」,用于已锁定后的全屏解锁界面,语义正确,保持不变)
2026-07-30 07:12:08 +08:00
JyQAQ
b04d728249 fix(@vben-core/form-ui): 兼容 zod v4 的 ZodArray,避免误用 unwrap() 丢失数组外壳导致数组校验失败 (#8207) 2026-07-28 15:50:15 +08:00
JyQAQ
44483db9af fix(project): 修复弹窗中表单上传组件预览图片层级问题 (#8205)
将 PreviewGroupComponent 的 hidden class 替换为通过 classes.popup.root
设置更高 z-index,避免在弹窗内被遮挡
2026-07-27 22:37:33 +08:00
layhuts
fbf0cebf4b style: 优化 vxe-table 类型组织结构,将 viewed-row 功能域相关类型进行模块化拆分,由全局类型声明调整为功能目录内聚管理,避免公共 types 文件持续膨胀。 (#8204) 2026-07-27 22:36:04 +08:00
金毛88
98344dfcec Merge branch 'fork/dream-weave/fix-layout-scroll-container' 2026-07-25 20:37:20 +08:00
Dream
6d5ccc7ac8 fix(@vben/layouts): scope hash targets to layout 2026-07-24 17:32:51 +08:00
Dream
b9c6d56f74 fix(@vben/layouts): restore internal scroll navigation 2026-07-24 16:58:39 +08:00
Dream
aaf0da582c fix(@vben-core/layout-ui): stabilize internal layout scrolling 2026-07-24 16:57:32 +08:00
Dream
9a5d052fa5 fix(@vben-core/composables): lock layout scroll container 2026-07-24 16:56:35 +08:00
Dream
baea741432 feat(@vben-core/shared): add layout scroll helpers 2026-07-24 16:55:36 +08:00
xingyu4j
33f4522bff fix: 补充 i18n 缺失的英文 2026-07-24 15:26:08 +08:00
xingyu4j
cb6b0a8872 fix: constrain popper content to available viewport width 2026-07-24 15:21:07 +08:00
xingyu4j
57e2a54219 fix: add missing Symbol descriptions 2026-07-24 15:17:55 +08:00
xingyu4j
4db254cd21 fix: Tailwindcss v4 new variable shorthand syntax 2026-07-24 15:07:17 +08:00
xingyu4j
255a76d79a feat: canonical tailwind class 2026-07-24 15:04:10 +08:00
dream-weave
dcdbfe5dfc fix(@vben-core/form-ui): restore lock screen form submission (#8195)
* fix(@vben-core/form-ui): avoid stale form context access

* fix(@vben/playground): constrain date range codec fields

* test(@vben-core/form-ui): harden benchmark fixtures

* docs(@vben/docs): document form runtime and benchmarks

* fix(@vben/docs): 明确 getValues/submit 返回值及 submit 参数类型
2026-07-24 10:05:27 +08:00
xingyu
0542b509ca chore: bump versions (#8192) 2026-07-23 20:41:13 +08:00
金毛88
eaf585d03a Merge branch 'fork/dream-weave/update-zod' 2026-07-23 20:35:00 +08:00
xingyu4j
0a45cb41fb fix: 添加 StyleProvider 以支持 Tailwind 样式覆盖;移除 InputNumber 组件的宽度样式,优化组件适配;antdv 暂不支持 2026-07-23 17:50:22 +08:00
Dream
517a42ec05 perf(@vben-core/form-ui): benchmark form hot paths 2026-07-23 17:47:57 +08:00
Dream
bacfdf5e42 perf(@vben-core/form-ui): optimize array field updates 2026-07-23 17:47:57 +08:00
Dream
2e69c3fefc fix(@vben/playground): address form codec edge cases 2026-07-23 17:47:57 +08:00
Dream
43b78da024 refactor(@vben/playground): share date range codecs 2026-07-23 17:47:57 +08:00
Dream
decbed20bc fix(@vben-core/form-ui): harden codec value boundaries 2026-07-23 17:47:57 +08:00
Dream
1ac5ac3e82 fix(@vben-core/form-ui): preserve array field focus 2026-07-23 17:47:57 +08:00
zhb410181
8d5a419c50 Merge branch 'vbenjs:main' into main 2026-07-23 15:25:16 +08:00
xingyu
2d82505330 fix: dropdown menu responsiveness and improve dialog handling (#8187)
* fix: 修复用户下拉框小部件菜单行点击无响应及弹框闪退

- 主题/时区/全屏/通知菜单行补充 @select 处理器,点击行任意位置即可触发
- 时区设置弹框宿主移出 DropdownMenu(showButton 模式),修复弹框随下拉框关闭而闪退
- 通知组件暴露 toggle 供下拉框调用
- 偏好设置小部件文案精简,positionMap 顺序调整

* feat: draggable-list.vue 直接复用 SelectItem,用法和 tabbar.vue 完全一致
2026-07-23 15:14:25 +08:00
dream-weave
98dea92225 feat(@vben-core/form-ui): add typed form value codecs (#8189)
* feat(@vben-core/form-ui): add typed form value codecs

* test(@vben-core/form-ui): cover codec value boundaries

* refactor(project): propagate form codec generics

* feat(@vben/plugins): propagate form codecs through vxe grids

* refactor(@vben/playground): migrate form codec examples

* refactor(@vben/playground): migrate query forms to codecs

* docs(@vben/docs): document form value codecs
2026-07-23 15:09:31 +08:00
hiss
e6a23479ee fix: 修复锁定屏幕和退出登录小部件,位置在 user-dropdown 时,使用快捷键唤出两个模态窗 2026-07-23 14:44:32 +08:00
zhb410181
294e9f2966 Merge branch 'vbenjs:main' into main 2026-07-23 13:44:17 +08:00
Harold Zhang
f43de252b5 fix: fixed the icon defect which cause to langauge button can not be clicked (#8184) 2026-07-23 12:20:38 +08:00
zhb410181
ebc0f23e64 Merge branch 'vbenjs:main' into main 2026-07-22 20:35:55 +08:00
dream-weave
28757fb9c8 refactor(@vben-core/form-ui): migrate to Zod 4 and TanStack Form (#8176)
* build(@vben-core/form-ui): update form validation dependencies

* refactor(@vben-core/form-ui): replace vee-validate with TanStack Form

* test(@vben-core/form-ui): cover TanStack Form migration

* docs(@vben/docs): document Zod 4 form migration

* refactor(project): update form adapters

* refactor(project): migrate application form consumers

* refactor(@vben/playground): migrate form examples

* docs(@vben/docs): fix validate return type and required rule empty check in form docs

* fix(@vben-core/form-ui): resolve oxlint and eslint errors

- rewrite nested ternary expressions as if/else in form-field-array.vue and form-runtime.ts
- sort @tanstack/vue-form before @vben-core/composables in package.json

* chore: fix merge artifacts and formatting

- move dependencies before devDependencies in root package.json
- update preferences snapshot for widget positioning fields
- format form-array demo README

* refactor(@vben-core/form-ui): optimize form runtime and value flow

- add fine-grained field selectors and atomic dependency resolution
- expose raw and formatted value snapshots with focused regression coverage

* fix(@vben/layouts): dispose sortable instance on unmount

* docs(@vben/docs): document form runtime API changes

- list added, changed, removed, and deprecated form APIs
- document atomic dependencies and raw versus formatted values
2026-07-22 19:47:07 +08:00
zhb410181
81f69d797d Merge branch 'vbenjs:main' into main 2026-07-22 18:06:57 +08:00
xingyu
6b6708bcf2 fix: 修复点击退出图标确认后不能退出 && 图标排序等数组字段需顺序敏感比较 (#8179)
* chore: 调整 sortablejs 的位置,只在用到的模块引入

* fix: non-null assertion lint error

* fix: 修复点击退出图标确认后不能退出

* fix: 图标排序等数组字段需顺序敏感比较

* feat: 配置中增加 refresh 并统一位置
2026-07-22 17:44:10 +08:00
zhb410181
5c1d31f680 Merge branch 'vbenjs:main' into main 2026-07-22 14:59:16 +08:00
金毛88
899910547f Merge branch 'fork/xingyu4j/deps' 2026-07-22 09:55:03 +08:00
金毛88
70a1d0a2e0 Merge branch 'fork/maoxuner/fix/system-menu-form' 2026-07-21 23:05:33 +08:00
MistyMoon
24eb67224d fix: message/notification demos not auto-dismissing due to wrong duration unit (#8168)
duration was written as 2500 (intended as ms), but ant-design-vue's
message/notification duration is in seconds, so it was interpreted as
2500s (~41min), making the popups appear to never close.
Changed to 2.5 with a comment documenting the unit.

Closes #8144
2026-07-21 22:57:17 +08:00
Jin Mao
e4e25028b5 Merge branch 'main' into fix/system-menu-form 2026-07-21 22:53:06 +08:00
金毛88
ef27b4e349 Merge branch 'fork/maoxuner/fix/lang-doc' 2026-07-21 22:48:41 +08:00
金毛88
b21563a89b feat: 顶栏与用户下拉框按钮样式统一与 tooltip 修复
- 修复 VbenTooltip 的 :content prop 类型错误,改用默认插槽
- 修复 VbenIconButton 的 onClick prop 支持数组合并
- VbenFullScreen 新增 tooltip prop,支持直接设置提示
- 统一顶栏与用户下拉框所有按钮样式,使用 VbenIconButton 包装
- 移除 i18n 中多余的"启用"字样(全局搜索/语言切换)
- 修复 VbenPopover PopoverTrigger 嵌套 button 导致 tooltip 不显示

Co-Authored-By: AtomCode (GLM-5.2) <noreply@atomgit.com>
2026-07-21 22:36:42 +08:00
zhb410181
d06451cdb7 Merge branch 'vbenjs:main' into main 2026-07-21 16:31:51 +08:00
xingyu4j
5318774efe fix: 优化命令执行逻辑,使用串行执行以提高错误可见性 2026-07-20 18:50:49 +08:00
xingyu4j
68a2717a26 fix: test error 2026-07-20 18:48:20 +08:00
xingyu4j
0a2c01e453 fix: 添加 oxlint 禁用注释以避免嵌套三元运算符警告 2026-07-20 18:45:38 +08:00
xingyu4j
b330f08ef4 fix: lint 2026-07-20 18:36:48 +08:00
xingyu4j
6676d962e9 fix: 修复Vben用户信息中的 homePath 属性定义 2026-07-20 18:36:37 +08:00
xingyu4j
dd8307dfe5 chore: update dependencies and refactor command execution 2026-07-20 18:36:09 +08:00
xingyu4j
d0c327e037 chore: update pnpm v11.15.1 2026-07-20 17:40:54 +08:00
xingyu4j
901a147abb Merge branch 'main' of https://github.com/xingyu4j/vue-vben-admin into deps 2026-07-20 17:39:20 +08:00
陆伯言
86e68bdde3 docs: 同步后端接入文档示例菜单地址
提升示例菜单数据的整体一致性,避免多处信息不一致的情况
2026-07-20 01:03:58 +08:00
陆伯言
054deae3bb fix: 菜单组件mock数据与实际保持一致 2026-07-20 01:03:58 +08:00
陆伯言
772286fb73 fix: 路由地址不强制以斜杠开头
兼容新dashboard路由配置
2026-07-20 00:46:27 +08:00
陆伯言
5936ff2e0f fix: 系统菜单管理上级菜单无法显示名称的问题
antdv-next TreeSelect组件没有title插槽
2026-07-20 00:20:00 +08:00
金毛88
f840d235ef feat: 偏好设置小部件支持位置选择与拖拽排序
- 顶栏各小部件按钮支持选择位置(header/user-dropdown/none),偏好设置按钮额外保留 auto/fixed 智能兜底,移动端/全屏内容模式下自动切 fixed 浮动保命,避免偏好入口死锁
- draggable-list.vue 的 listRef 未在模板绑定,Sortable 永不初始化导致小部件无法拖拽;加 ref 绑定与 data-key 让 onEnd 从 DOM 读真实新顺序
- preferences.ts 的 updatePreferences 用 defu(merge) 合并数组,对 widget.order 是 concat 语义,每次拖拽触发更新都会把当前 order 追加一次,localStorage 里膨胀到上百条;改用 mergeWithArrayOverride 整体替换,加载缓存时 sanitizeCachedArray 去重已存在的脏数据
- preferences 按钮之前在 widget.order 里因 labelMap 未登记显示成裸字符串,且 widgetChecks 缺 refresh 导致刷新按钮不按 order 渲染;统一 preferences 与其它 widget 的拖拽排序与位置 select,refresh 补进 rightSlots.widgetChecks 并补模板渲染
- 补 sortablejs 依赖、WidgetPreferences.order 类型字段、preferences-drawer.vue 的 widgetOrder 绑定
2026-07-19 21:34:11 +08:00
陆伯言
930597c605 docs: 更新新增语言包的说明
closed #8160
2026-07-19 02:27:09 +08:00
陆伯言
41c20a43af docs: 更正语言使用示例,确保可用
使用可用的语言配置
修复computed变量使用语法错误

closed #8159
2026-07-19 01:22:00 +08:00
陆伯言
fe65d548be docs: 修复英文语言文件路径错误
closed #8158
2026-07-19 01:17:22 +08:00
金毛88
0cd87c170f feat: 顶栏按钮支持位置选择(header/user-dropdown/none)
为顶栏所有部件按钮添加独立的位置配置,支持在顶栏、用户下拉菜单、不显示
三种选项间切换,每个按钮可独立设置。

- 新增 7 个位置偏好字段:globalSearchButtonPosition、
  themeToggleButtonPosition、languageToggleButtonPosition、
  fullscreenButtonPosition、notificationButtonPosition、
  refreshButtonPosition、timezoneButtonPosition
- 合并 lockScreenButtonPosition、logoutButtonPosition
- header.vue 按位置条件过滤按钮显示
- user-dropdown.vue 新增对应菜单项,支持在用户下拉菜单中显示
- 偏好设置界面仅保留位置选择器(不再需要独立的开关)
- 更新中英文国际化文案

Co-Authored-By: AtomCode (deepseek-v4-flash) <noreply@atomgit.com>
2026-07-18 22:46:31 +08:00
金毛88
b71ebbd673 Merge remote-tracking branch 'pr-8019-temp/main' 2026-07-18 19:21:36 +08:00
金毛88
31d3bd18f3 Merge branch 'fork/LayHuts/feature/form-field-arry' 2026-07-18 19:18:14 +08:00
Jin Mao
eae6771554 Merge branch 'main' into feature/fix_defects_router 2026-07-18 03:54:49 +08:00
JyQAQ
8ac66a96bc fix: 修复弹窗中使用裁剪图片会出现层级问题 (#8156)
* fix(@vben/playground): 弹窗中使用裁剪图片会出现层级问题

* fix(project): 修复弹窗中裁剪图片在 web-antd 与 web-antdv-next 的层级问题
2026-07-17 15:17:37 +08:00
zhb410181
822cec0f5c Merge branch 'vbenjs:main' into main 2026-07-16 13:13:38 +08:00
Guillermo Sagar
6910c691f7 修复动画导致的白屏Bug (#8148)
首次页面加载正常,但是当通过页面点击切换路由的时候白屏,无法正常渲染子页面

 Vue Transition + KeepAlive 空白页 bug**: `<Transition mode="out-in">` + 条件渲染会导致路由切换空白页。`mode="out-in"` 要求旧元素完成 leave 动画后新元素才进入,但路由切换时条件渲染可能在动画前就移除了旧元素,导致 `<Transition>` 永远等待一个不存在的元素 → 死锁。**解决方案**: 移除 `mode="out-in"`(保留 Transition 动画),或在 `apps/web-antd/src/preferences.ts` 设置 `transition: { enable: false }` 关闭动画走 `v-else` 分支。
2026-07-16 09:35:25 +08:00
zhb410181
71c30d3e18 Merge branch 'vbenjs:main' into main 2026-07-14 14:07:09 +08:00
Harold Zhang
263d8e5b52 Merge branch 'main' into feature/fix_defects_router 2026-07-14 09:47:34 +08:00
Harold Zhang
b79b82ecf0 feat: fixed the preference will hide all other button theme/timezone/lanague etc (#8147) 2026-07-13 21:31:06 +08:00
xingyu4j
91a2e80be8 fix: 优化代码格式,合并类型声明 2026-07-13 18:30:19 +08:00
xingyu4j
819ddd4ebb fix(style): 添加no-invalid-position-declaration规则到stylelint配置 2026-07-13 18:29:30 +08:00
xingyu4j
bb6403d513 chore: update deps 2026-07-13 18:29:01 +08:00
xingyu4j
45c3776ffd chore: update pnpm v11.12.0 2026-07-13 18:27:57 +08:00
zhb410181
1d23cd707c Merge branch 'vbenjs:main' into main 2026-07-13 11:22:06 +08:00
Harold Zhang
6eb79b8ef0 Merge branch 'main' into feature/fix_defects_router 2026-07-13 08:59:16 +08:00
zouawen
8b7c245bc7 fix: 修复首选项导航栏宽度问题 (#8136) 2026-07-11 11:43:47 +08:00
Harold Zhang
e416de3290 fix: fixed defects of router 2026-07-10 10:15:40 +08:00
zhb410181
398b445d35 Merge branch 'vbenjs:main' into main 2026-07-09 15:41:03 +08:00
luoqiz
14d03a1c2d fix: 统一BasicUserInfo (#8133) 2026-07-09 13:23:29 +08:00
zhb410181
9769c11de5 fix(style): 修复偏好设置功能tab栏宽度未自适应问题 (#8132) 2026-07-09 13:23:08 +08:00
hiss
cae47e8c7f fix(style): 修复偏好设置功能tab栏宽度未自适应问题 2026-07-08 16:42:04 +08:00
陆伯言
88918aad10 docs: fix typo of env demo (#8129)
closed #8125
2026-07-08 08:38:06 +08:00
陆伯言
75c3a7214b docs: update default home path perferences (#8121)
closed #8117
2026-07-07 21:41:51 +08:00
陆伯言
71bcabd118 docs: update nitro mock server url (#8119)
closed 8113
2026-07-03 17:12:43 +08:00
dream-weave
81619b6090 fix(lint): align eslint and oxlint rules (#8118)
* docs: 路由文档示例代码同步路由组织新规范

* fix(lint): align eslint and oxlint rules

* fix(lint): avoid control character regex
2026-07-03 17:12:13 +08:00
dream-weave
77468ce9a6 docs: 路由文档示例代码同步路由组织新规范 (#8114) 2026-07-02 18:35:54 +08:00
Evan
8779c00670 fix: 修复homePath的路径 (#8110)
* fix: 修复homePath的路径

* fix: 单元测试数据

* chore: 单元测试快照数据

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2026-07-01 17:31:37 +08:00
金毛88
61f1b53325 fix: 修改默认首页,以适配router重构 2026-07-01 17:02:55 +08:00
layhuts
c56bb7d320 docs: 更新文档 2026-07-01 15:07:56 +08:00
金毛88
1490a93f47 Merge branch 'fork/bnuephjx/refactor/router-redirect' 2026-07-01 13:31:27 +08:00
金毛88
e50296e3c5 Merge branch 'fork/zouawen/main' 2026-07-01 13:06:42 +08:00
陆伯言
5da38ccded fix: 调整mock默认路由 (#8108)
* fix: 调整mock默认路由

1. starting改为running 语义更明确
2. API地址修复
3. 列表顺序调整,登录接口靠前

* docs: 替换axios调用示例

原先/api/user接口地址不对,且是受认证保护的接口,响应异常容易造成误解
2026-07-01 13:02:44 +08:00
layhuts
20b69fa480 revert: 撤销修改 2026-07-01 11:49:27 +08:00
layhuts
fdf2abb702 refactor: 修改form-field-array支持dependencies 2026-07-01 11:08:35 +08:00
layhuts
9d36b34c4c docs: 修复错误的注释说明 2026-07-01 09:52:51 +08:00
dependabot[bot]
9b356d731d build(deps): bump actions/checkout from 6 to 7 (#8080)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 22:42:58 +08:00
Evan
18e2bbf969 Merge branch 'main' into refactor/router-redirect 2026-06-30 22:23:54 +08:00
layhuts
14bb94245c feat: 新增logo铺满显示和是否显示text配置 (#8102)
* feat: 新增logo铺满显示和是否显示text配置

* feat: logo.enable=false时隐藏logo区域占位;设置logoMode、showText为必填。

* style: 修复注释问题

* fix: 删除多余属性
2026-06-30 21:50:45 +08:00
Evan
feb0265744 Merge branch 'main' into refactor/router-redirect 2026-06-30 14:26:23 +08:00
xueyitt
7182405d24 fix: 修复弹框自定义宽度 class 被默认 max-w 覆盖的问题 (#8100)
将 modalClass 参数移至 cn() 末尾,确保用户通过 class 传入的宽度样式
优先于内置默认的 max-w-[calc(100vw-20px)] 生效,使 业务使用Modal 上的自定义的max-w-[50%] 等方式能正确控制弹框宽度。
2026-06-30 14:24:18 +08:00
陆伯言
d7d6d2e337 fix: lint issue from a8c3729 (#8098) 2026-06-30 14:23:52 +08:00
Harold Zhang
31c31b914b feat: fix check error (#8094) 2026-06-30 14:23:27 +08:00
Evan
f00a881295 refactor(@vben/access): 重构路由的重定向逻辑
@vben-core/shared
@vben/playground
@vben/backend-mock
@vben/web-antd
@vben/web-antdv-next
@vben/web-ele
@vben/naive
@vben/tdesign
2026-06-30 13:36:37 +08:00
zoumingjun
5ed867eb95 feat: 优化禁用的开关组件也可以查看help帮助信息 2026-06-30 09:39:32 +08:00
zoumingjun
ae5bd3afc5 feat: 首选项导航栏选项标题过长时显示省略号,且增加聚焦时文字提示 2026-06-30 09:37:28 +08:00
vben
a8c3729850 feat: add ICP filing number to copyright across app 2026-06-24 10:04:10 +08:00
gotounix
794edd419e fix: add includes in mock tsconfig (#8085) 2026-06-23 21:47:08 +08:00
layhuts
9a284ee385 style: 处理modal设置class="md:w-5/12"格式时Fullscreen时无法最大化问题 (#8084) 2026-06-23 21:46:43 +08:00
gotounix
e031457271 fix: add missing imports (#8082) 2026-06-23 21:46:19 +08:00
金毛88
0931599f96 chore: update deps 2026-06-21 14:48:51 +08:00
xingyu4j
dc3865f778 fix: 优化 lint 执行策略并修复 pre-commit 依赖解析
- vsh lint 按硬件自适应:CPU<=4 核串行(汇总错误),>4 核并行;
  CPU>4 且空闲内存>8GB 时 oxfmt/oxlint 默认线程数提升至 4,否则维持 2
- lefthook pre-commit 改为串行执行,避免与 check:type 并行导致低配机资源飙升
- pre-commit 仅对暂存文件 lint 并自动修复回填(stage_fixed)
- lint 命令统一加 pnpm exec 前缀,修复 lefthook 经 sh 调用时
  oxlint 找不到 workspace 局部依赖(eslint-plugin-eslint-comments)的问题
2026-06-18 16:35:27 +08:00
yshbyy
45399d0299 fix(@vben-core/shadcn-ui): 补全 ScrollArea onScroll 滚动事件透传 (#8069) 2026-06-18 16:10:21 +08:00
xingyu
dc3466d77a refactor: 将 unicorn / TypeScript 规则迁移至 oxlint,并完善 oxfmt 配置 (#8067)
* chore: update deps

* chore: update archiver v8

* fix: 还原 vue/html-closing-bracket-newline

* feat: 增加默认配置和配置注释

* feat: 增加oxlint默认插件配置和注释

* refactor: remove unicorn ESLint configuration and update dependencies

- Deleted the unicorn ESLint configuration file from the lint-configs package.
- Removed unicorn configuration from the main index file.
- Updated oxlint-config to include a comprehensive set of unicorn rules.
- Adjusted preferences and vxe-table files to disable specific unicorn rules.
- Removed references to eslint-plugin-unicorn from pnpm-lock.yaml and pnpm-workspace.yaml.

* refactor: 移除 eslint 的 @typescript-eslint/eslint-plugin 依赖,将 TypeScript 配置迁移到 oxlint

* feat: open typeAware

* fix: mac 和linux下报错
2026-06-18 16:10:01 +08:00
金毛88
65885ea74b chore: update lockfile 2026-06-16 16:47:33 +08:00
金毛88
769791351f chore: update deps && lint 2026-06-16 16:25:21 +08:00
金毛88
741cbb3794 Merge branch 'fork/xueyitt/feat/feat3' 2026-06-16 16:16:56 +08:00
金毛88
edd110ac4e Merge branch 'fork/xueyitt/feat/feat1' 2026-06-16 16:15:33 +08:00
xueyitt
7824219557 fix: 修正AppPreferences中defaultAvatar、dynamicTitle注释 (#8060) 2026-06-16 14:23:25 +08:00
雪忆天堂
dd4afec7ed feat: workbench公共组件增加支持slot方式进行自定义 2026-06-16 10:01:24 +08:00
雪忆天堂
ebebb42625 feat: 1、FieldMappingTime拆解独立FieldMappingTimeItem+集合形式,方便单独对象定义;
2、表单submitOnChange增加changeDebouncedTime防抖处理,允许自定义防抖周期;
3、handleValuesChange事件set增加cloneDeep,防止对象值污染;
2026-06-16 09:48:27 +08:00
雪忆天堂
d1e6d4a3da Merge remote-tracking branch 'origin/main' 2026-06-16 09:10:50 +08:00
Jefsky Wong
ad3f996bdb fix(@vben/common-ui): prevent footer slot from overlapping content when Page contains Grid (#8056)
The Page component's outer container used min-h-full, which doesn't
provide an explicit height for flex children. Combined with h-full on
the content div, this caused the footer slot to overlap table content
(Grid/vxe-table) because the content area didn't properly account for
footer space in the flex column layout.

Fix:
1. Change outer container from min-h-full to h-full — gives the flex
   container an explicit height so percentage heights resolve correctly.
2. Change content area from static h-full to flex-1 when autoContentHeight
   is false — lets the flex layout naturally distribute remaining space
   between content and footer.

Closes #5494

Co-authored-by: jefsky <jefsky@users.noreply.github.com>
2026-06-16 08:36:39 +08:00
HaroldZhangCode91
68877a7e97 Merge branch 'main' into feature/fix_confirm_regression 2026-06-15 17:46:19 +08:00
雪忆天堂
c5a839f652 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	packages/effects/plugins/src/vxe-table/use-vxe-grid.vue
2026-06-15 17:41:12 +08:00
HaroldZhangCode91
bf8c3d6411 feat: aligns ESLint with oxfmt's behavior (#8054) 2026-06-15 17:25:04 +08:00
HaroldZhangCode91
f753a3b75f Merge branch 'main' into feature/fix_confirm_regression 2026-06-15 16:45:08 +08:00
曾兴顺
fcf726f953 fix: 修复Tree组件不支持半选的问题(子节点全选时父节点选中图标为勾选状态,子节点部分选中时父节点图标为减号,也就是版勾选状态,子节点未被选中时,父节点不被选中) (#8050) 2026-06-15 16:38:21 +08:00
Harold Zhang
16ebc67796 feat: fixed useScrollLock() can not be unlock 2026-06-15 16:34:53 +08:00
Harold Zhang
6b109c9ae6 fix: fixed regression of confirm 2026-06-15 16:24:17 +08:00
xingyu
160114c5e0 fix: select and user-dropdown (#8042)
* fix: 偏好设置中下拉框无法选择的问题,原因: 同步 shadcn-vue 将 z-popup 同步为 shadcn 的 z-50

* fix: 鼠标hover到用户登录头像 下拉来回闪烁 隐藏 显示
2026-06-10 21:26:47 +08:00
金毛88
4b1fada0ab Merge branch 'fork/zhb410181/fix/style' 2026-06-09 11:22:58 +08:00
hiss
5c9daab2ff fix(style): 1.修复ToggleGroupItem边框样式问题 2.修复用户头像下拉框Badge背景颜色 2026-06-09 08:56:07 +08:00
Harold Zhang
c2a85f4ec2 feat: support unlocking scroll when modal dialog closes 2026-06-08 14:15:31 +08:00
abc_abc
e7f541f37e Merge branch 'main' into main 2026-06-08 10:31:39 +08:00
金毛88
f23c9f5e19 chore: update deps 2026-06-07 18:54:43 +08:00
ddfabc
4459389d4a feat: 将锁定屏幕和退出登录图标从用户下拉菜单移至头部栏
将锁定屏幕(LockKeyhole)和退出登录(LogOut)图标按钮从 UserDropdown 下拉菜单
移至 LayoutHeader 头部栏,位于通知图标的右侧。

变更内容:
- header.vue: 新增 lock-screen-btn 和 logout-btn 插槽,位于 notification 之后;
  添加 LockScreenModal/LogoutModal 及快捷键(Alt+L/Alt+Q)支持;
  新增 avatar/text props 用于锁屏弹窗显示
- layout.vue: 透传 avatar/text props 和 logout 事件
- user-dropdown.vue: 移除锁定屏幕和退出登录的菜单项、弹窗及快捷键逻辑
- 所有 5 个应用 basic.vue: 向 BasicLayout 传递 avatar/text,绑定 @logout 事件

头部右侧图标顺序: ... → 全屏 → 通知🔔 → 锁定🔒 → 退出🚪 → 用户头像
2026-06-06 23:24:54 +08:00
xingyu4j
8e0564cc42 chore: node v24 2026-06-06 21:07:55 +08:00
xingyu4j
017b3c3fce ci: bump actions/stale from 9 to 10 2026-06-06 20:49:34 +08:00
xingyu4j
126275b417 ci: bump dessant/lock-threads from 5 to 6 2026-06-06 20:48:51 +08:00
xingyu4j
bc908e29eb ci: bump amannn/action-semantic-pull-request from 5 to 6 2026-06-06 20:48:19 +08:00
xingyu4j
efe3c25310 chore: update deps 2026-06-06 19:36:39 +08:00
xingyu4j
d85ac2c976 feat: form 表单赋值 2026-06-06 19:33:31 +08:00
xingyu4j
c816591b69 fix: modal 下拉等不能选中 2026-06-06 19:32:31 +08:00
xingyu4j
564b349700 fix: vue/custom-event-name-casing 2026-06-06 16:21:25 +08:00
xingyu4j
ce495d67a0 feat: 同步 antdv-next 的组件 2026-06-06 16:20:36 +08:00
xingyu4j
8094d1ffb9 chore: update deps 2026-06-06 16:19:32 +08:00
afe1
748b182e44 fix: workflow (#8013)
* fix: catelog

* fix: system

* chore: sync upstream changes

* feat:  component and workflow error
2026-06-05 05:13:08 +08:00
金毛88
6544340d80 Merge branch 'fork/HaroldZhangCode91/feature/fix_freeze_scrollbar_of_modal' 2026-06-04 13:54:21 +08:00
Harold Zhang
6b7cb7b1fc feat: fixed the regression of changing Menu to MenuUI 2026-06-04 11:46:53 +08:00
Harold Zhang
d90d45a128 fix: fixed modal freeze issue 2026-06-04 11:19:38 +08:00
Harold Zhang
66077b3bcf Merge branch 'main' into feature/fix_freeze_scrollbar_of_modal 2026-06-03 18:07:37 +08:00
Harold Zhang
0328594747 feat: fixed the overlay layer can not work with reka-ui 2026-06-03 17:52:41 +08:00
金毛88
790e114d41 chore: 固定vite 8.0.10,避免编译后异常 2026-06-03 17:32:13 +08:00
Harold Zhang
cc60ca9592 feat: fixed the defects the scrollbar disapear when modal close 2026-06-03 16:10:17 +08:00
HaroldZhangCode91
79707a2ebd feat: fixed regression of modal for element plus (#7999) 2026-06-03 13:27:12 +08:00
金毛88
0eb72ca4fd feat: add useTDesignDesignTokens 2026-06-03 13:25:23 +08:00
金毛88
7fd4b1de04 Merge branch 'fork/SaleriHQ/feat/form-field-array' 2026-06-03 13:22:21 +08:00
Saleri
9ffd42f013 chore: add changeset for form field array 2026-05-31 23:06:00 +08:00
Saleri
40101911f0 style: format naive styles 2026-05-31 16:21:13 +08:00
xingyu
04fbb7a556 chore: 升级 shadcn-vue 组件到v4最新版 (#7972)
* fix: useStore is deprecated

* chore: update deps

* feat: 升级shadcn-ui v4

* fix: workbench style

* feat: 升级shadcn-ui v4 step2

* feat: 升级shadcn-ui v4 step3

* chore: 升级shadcn v4

* fix: pagination

* fix: dark style

* fix: doc import

* feat: 增加详情组件,参考 antdv-next

* docs: descriptions docs

* docs: Browser Support

* feat: add table action

* feat: icon use vbenIcon

* fix: type error

* fix: dropdown popConfirm

* feat: 使用默认的文字交互

* feat: 优化渲染性能
2026-05-31 15:18:46 +08:00
Saleri
e5f9106caa feat(@core/form-ui): 新增 useVbenForm 数组编辑器 VbenFormFieldArray 2026-05-31 15:03:55 +08:00
afe1
108d7ff335 chore: add commitlint config declaration (#7968)
* fix: catelog

* fix: system

* chore: sync upstream changes

* types: add commitlint config declaration
2026-05-28 15:50:47 +08:00
leo
1d6842fa69 build: change runtime config asset naming strategy for PWA compatibility (#7963)
replace query-based config url (_app.config.js?v=...)
with deterministic hashed filename (_app-config-v{version}-{hash}.js)
ensure service worker precache matches runtime injected asset
2026-05-28 12:53:51 +08:00
Saleri
d6a9eaf9e9 fix: 修复 web-naive 表单页 Input 输入 _ 不显示的问题 (#7962) (#7965)
* fix(@vben/web-naive): 修复 naive input 输入 _ 不显示的问题 (#7962)

* fix(@vben/web-naive): 限制 input 字体修复作用域,避免全局影响
2026-05-28 12:49:48 +08:00
boisduval
f7540c119b fix: 修复 useVbenModal useVbenDrawer 传入参数失效的问题 (#7964)
- 把provide的key值修改为与inject一致的options
2026-05-28 12:49:23 +08:00
过冬
acf289381e fix(@vben-core/popup-ui): modal 响应式适配,支持视口自适应 (#7951) 2026-05-25 13:27:17 +08:00
PanFu
f813245827 feat: 偏好设置的快捷键列表追加ESC快捷键的控制(关闭当前窗口) (#7947)
* feat: 快捷键追加ESC控制,关闭当前窗口

* feat: 偏好设置中,页面切换动画的颜色看不清的问题(使用当前主题色)

* feat: 三种弹出框支持快捷键ESC动作

* feat: 代码自动格式化(3个框架改动)

* feat: 代码自动格式化(3个框架改动)

* fix: 修正locale数据获取方式

* 单元测试问题修改

* 单元测试问题修改

* fix: 解决代码评论的问题

* fix: 解决代码评论的问题

* fix: 解决代码评论的问题

* fix: 解决代码评论的问题

* 单元测试问题修改

* fix: 解决评论问题

* fix: 解决代码格式导致pnpm run lint报错的问题

---------

Co-authored-by: PanFu <panfu@zhihuaai.com>
2026-05-23 09:50:35 +08:00
过冬
e98f0b7558 fix: 移动端禁用混合布局菜单拆分 (#7949) 2026-05-23 04:21:19 +08:00
Reese Wellin
cd86de54e1 fix(preferences): 修复主题等个性化信息持久化被初始化配置覆盖 (#7948)
调整 initPreferences 中 merge 顺序,使用户缓存优先于 initialPreferences。

Fixes #7943
2026-05-23 04:17:46 +08:00
Jin Mao
60eb1335f8 chore: vite 降级到8.0.10 2026-05-22 13:20:25 +08:00
xingyu
f2b3b12553 chore: pnpm v11 (#7942)
* chore: remove rolldown dep

* fix: issues-helper and maintain-one-comment are temporarily disabled due to security issues

* chore: update deps

* fix: change error type to TypeError for non-browser environment check in LocalStorageDriver

* chore: update pnpm v11
2026-05-22 12:02:14 +08:00
layhuts
c066889c37 Fix: 在isMobile=true时无法自定义Drawer的class问题 (#7941)
* fix: 在isMobile=true时无法自定义Drawer的class问题

* fix: 在ResizableHandle两边增加边距
2026-05-22 11:56:09 +08:00
928646789
6b81d1b0d5 fix: preferences-button click to show setting drawer (#7938) 2026-05-22 07:26:12 +08:00
afe1
126b33687a chore: vite config tsconfig include (#7936)
* fix: catelog

* fix: system

* fix(vite-config): include tsdown config in tsconfig
2026-05-22 07:25:50 +08:00
Jin Mao
5b67c2e740 chore: 更新pnpm-lock 2026-05-21 20:44:38 +08:00
Jin Mao
2d7c3c3072 chore: 更新pnpm-lock 2026-05-21 20:40:49 +08:00
Jin Mao
5cc68c9dd0 chore: 更新 vite 依赖版本
- 将 vite 版本从 ^8.0.13 降级到 ^8.0.10
- 保持其他依赖包版本不变
2026-05-21 20:22:28 +08:00
Jin Mao
63a38dce49 refactor(workflow): 优化发布工作流配置
- 简化触发条件,移除冗余的推送事件配置
- 更新标签创建输入参数描述,明确格式要求
- 移除 Husky 环境变量配置
- 重命名构建作业为发布作业,提高语义清晰度
- 移除 Node.js 版本矩阵策略配置
- 优化版本提取逻辑,支持工作流调度和推送事件
- 统一标签前缀处理,确保版本格式一致性
- 移除注释掉的冗余步骤配置
- 简化发布配置,移除不必要的发布操作注释块
2026-05-21 09:07:59 +08:00
Jin Mao
629f747795 feat(workflow): 添加手动触发release标签工作流
- 添加 workflow_dispatch 触发器支持手动运行
- 新增 tag 输入参数用于指定创建的标签
- 设置默认标签值为 staging
- 保留原有的 push tags 自动触发功能
2026-05-21 08:54:51 +08:00
Jin Mao
8585008f79 chore: release v5.7.0 2026-05-20 17:45:44 +08:00
xingyu
00990d9453 Merge branch 'main' into fix/lint 2026-05-20 17:38:19 +08:00
PanFu
2a84b590b5 feat: 偏好设置按钮,支持在右上角用户的下拉框中展示;偏好设置中支持设置时区(多一个入口); (#7931)
* feat: 偏好设置按钮支持显示在用户下拉窗中的特性

* feat: 时区设置功能支持在偏好设置列表进行配置

* feat: 偏好设置按钮支持显示在用户下拉窗中的特性 - 完善示例代码

* feat: 时区设置功能支持在偏好设置列表进行配置

* feat: 时区设置功能支持在偏好设置列表进行配置-单元测试报错问题

* feat: 时区设置功能支持在偏好设置列表进行配置-修改代码QC问题

---------

Co-authored-by: PanFu <panfu@zhihuaai.com>
2026-05-20 17:24:53 +08:00
PanFu
769c970e08 fix: 修复三个问题:偏好配置项修改后重启不会生效;锁屏弹出框的按钮文字错误;右上角偏好设置按钮排序问题优化; (#7930)
* fix: 修正偏好设置加载缓存的偏好设置并与初始配置合并的顺序

* fix: 修正锁屏弹出框的按钮文字

* fix: 偏好设置按钮排序优化(取第三个占位的数字,若是第三个占位不是数字,则自动分配排序索引)

* fix: 修正偏好设置加载缓存的偏好设置并与初始配置合并的顺序 - 代码QC问题修改

---------

Co-authored-by: PanFu <panfu@zhihuaai.com>
2026-05-20 17:24:18 +08:00
xingyu4j
4d3c481a93 fix: 当lint检查出问题后,不能在终端终止 2026-05-20 16:39:03 +08:00
xingyu4j
fda4b39c01 chore: update deps 2026-05-20 16:38:19 +08:00
xingyu4j
74d8942f39 chore: remove Unused deps 2026-05-20 16:24:59 +08:00
xingyu4j
9ec98f0846 refactor: replace depcheck with knip for dependency checking
Migrate vsh check-dep from depcheck to knip, reducing
315 transitive dependencies. Config is inlined in
DEFAULT_CONFIG, matching the check-circular pattern.
Also re-export CollapsibleParams from @vben/common-ui.
2026-05-20 16:14:21 +08:00
xingyu4j
f71094e878 refactor: migrate json-viewer from vue-json-viewer to vue-json-pretty
- Replace vue-json-viewer with vue-json-pretty (actively maintained, Vue 3 native)
- Map original props to vue-json-pretty API in bindProps for backward compatibility
- Implement copy functionality via renderNodeActions slot with i18n support
- Update style.scss from .jv-* to .vjs-* class names
2026-05-20 14:39:17 +08:00
xingyu4j
9badda3d11 chore: update deps 2026-05-20 11:30:03 +08:00
xingyu4j
03fcecadcc fix: lefthook config 2026-05-19 16:13:00 +08:00
xingyu4j
3a88adb8a6 feat: test 2026-05-19 16:10:18 +08:00
xingyu4j
c759cb2593 fix: lint config 2026-05-19 16:08:10 +08:00
xingyu4j
f77166b3a2 chore: update deps 2026-05-19 15:59:43 +08:00
xingyu4j
f7928b34b2 fix: lint 2026-05-19 15:58:34 +08:00
xingyu4j
454a5b54bd chore: lefthook config 2026-05-19 15:54:03 +08:00
Jin Mao
a4dd9d30ce chore: release 5.7.0 2026-05-19 14:39:46 +08:00
Jin Mao
76cfcda2e9 Merge branch 'fork/xingyu4j/antdv-next' 2026-05-19 14:14:28 +08:00
橙子
7ec4df4995 fix: search-panel when ArrowUp and ArrowDown (#7922) 2026-05-19 13:40:50 +08:00
leo
d71c81e8ff style: apply vsh lint formatting (#7923) 2026-05-19 13:40:13 +08:00
xingyu4j
aac626da32 feat: add system user view 2026-05-18 21:45:17 +08:00
xingyu4j
5db93a345a fix: doc build error 2026-05-18 20:17:35 +08:00
xingyu4j
7c943cc06b chore: disable oxc typeAware and add --threads option for oxlint
Type-aware linting was consuming excessive memory with nearly all
type-aware rules turned off. Add --threads CLI option to control
oxlint parallelism.
2026-05-18 18:46:13 +08:00
xingyu4j
5c8dd1a6da chore: docs config 2026-05-18 18:35:34 +08:00
xingyu4j
6592135cc5 chore: update vitepress v2 2026-05-18 18:23:10 +08:00
xingyu4j
2f16ee7cf5 docs: use antdv-next 2026-05-18 17:30:59 +08:00
xingyu4j
0c1b737325 fix: fix lint && typecheck 2026-05-18 16:50:14 +08:00
xingyu4j
5bbdcffb97 Merge branch 'main' into antdv-next 2026-05-18 16:38:56 +08:00
xingyu4j
1867015e97 Merge branch 'antdv-next' of https://github.com/xingyu4j/vue-vben-admin into antdv-next 2026-05-18 16:35:28 +08:00
xingyu
b6aeadd9a2 Merge branch 'main' into antdv-next 2026-05-18 16:35:18 +08:00
xingyu4j
1e44b87359 refactor: migrate playground deprecated antdv-next APIs
- Modal: destroyOnClose → destroyOnHidden
- Card: body-style → styles.body
- Alert: message prop/slot → title
- Spin: tip → description, wrapper-class-name → classes.root
2026-05-18 16:35:06 +08:00
xingyu4j
a1081bf7a6 fix: 修复 InputNumber 组件宽度在表单中不占满的问题 2026-05-18 16:28:19 +08:00
xingyu4j
9bb2026b4d fix: 修复 InputNumber 组件宽度在表单中不占满的问题 2026-05-18 16:25:49 +08:00
xingyu4j
4554cd016a fix: lint 2026-05-18 16:19:53 +08:00
xingyu4j
350d5ee60e refactor: playground use antdv-next 2026-05-18 16:18:46 +08:00
xingyu4j
1ec058cbe3 chore: update deps 2026-05-18 15:06:59 +08:00
xingyu4j
eb9cdbab9b fix: lint 2026-05-16 12:55:19 +08:00
xingyu4j
4907f281af chore: 更新 pnpm-workspace.yaml 配置,添加 publicHoistPattern 和 allowBuilds 设置 2026-05-16 11:56:39 +08:00
xingyu4j
aadf9b6e39 chore: update deps 2026-05-16 11:52:20 +08:00
Jin Mao
84e77f64ea Merge remote-tracking branch 'origin/main' 2026-05-16 11:18:52 +08:00
guoqiangui
3e89077d46 fix(deploy): use IMAGE_NAME variable in remove_image instead of hardcoded name (#7907)
The `remove_image` function was using a hardcoded image name `vben-admin-pro`
instead of the `$IMAGE_NAME` variable (`vben-admin-local`), so the old local
image was never actually cleaned up before each build.

Co-authored-by: guoqiangui <guoqiangui@zhongshitech.cn>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 11:18:09 +08:00
Jin Mao
c8c425538f Merge branch 'fork/xueyitt/main' 2026-05-16 10:49:33 +08:00
Jin Mao
b04c10aab6 Merge branch 'fork/LayHuts/feature/vxe-table-viewed' 2026-05-16 10:48:00 +08:00
JyQAQ
b5f79db321 fix(@vben/plugins): 修复 tiptap 重复注册扩展警告 (#7917)
StarterKit v3.22.0 已默认包含 Document、Link、Underline 扩展,
与单独导入产生重复注册,导致控制台警告:
[tiptap warn]: Duplicate extension names found: ['link', 'doc', 'underline']

- 移除 Document 单独导入和使用,StarterKit 已内置
- 移除 Underline 单独导入和使用,StarterKit 已内置
- StarterKit 配置中添加 link: false,禁用内置 Link,
  保留自定义配置的 Link.configure({...})
2026-05-16 10:45:30 +08:00
PanFu
42d82875ce feat: 1、完善tree组件的全选状态不正确、全选没有label、item内容超长导致复选框对齐错乱、item内容超长没有tips无法看到完整内容的问题 (#7915)
Co-authored-by: PanFu <panfu@zhihuaai.com>
2026-05-16 10:44:55 +08:00
Akuria
4d8d2de6ad fix: guard svg icon loading during docs SSR (#7912) 2026-05-16 10:43:47 +08:00
Akuria
294700a247 fix: skip fixed footer height in auto-content-height calculation (#7910)
* fix: skip fixed footer height in auto-content-height calculation

When the Page component's footer has position: fixed, it is removed
from the normal document flow and should not be subtracted from the
available content height. Previously, the footer's offsetHeight was
always subtracted, causing incorrect height calculation for fixed
footers.

Also reset shouldAutoHeight before recalculating to prevent stale
state on hot reload.

Fixes #4576

* fix: replace getComputedStyle footer height check with footerFixed prop

Use an explicit `footerFixed` boolean prop instead of runtime
getComputedStyle detection to determine whether the footer height
should be excluded from content height calculation. This avoids
unreliable style queries and makes the behavior deterministic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 10:43:10 +08:00
Akuria
f55b18ffd7 fix: update primary color when toggling dark/light mode with custom theme (#7909)
When a custom theme is selected and the user toggles between dark and
light mode, the primary color was not being recalculated. This was caused
by a guard condition in the builtin theme watcher that skipped updating
themeColorPrimary for custom themes during mode changes.

Remove the guard so that the primary color is always recalculated from
the theme preset when the mode changes, ensuring Element Plus CSS
variables stay in sync.

Fixes #6615
2026-05-16 10:42:35 +08:00
Akuria
ca5931e8c4 fix: preserve tree default value when treeData starts empty (#7908)
When treeData is initially an empty array (e.g. before async data
arrives), updateTreeValue() would clear the modelValue because no
matching items could be found in the empty flattened data. This caused
default values to be lost.

Only call updateTreeValue() when flattenData has items, so that
modelValue is preserved until the actual tree data arrives.

Fixes #6522
2026-05-16 10:41:42 +08:00
JyQAQ
aac4e88353 docs(@vben/docs): 添加 VCropper 图片裁剪组件文档 (#7904)
* docs(@vben/docs): 添加 VCropper 图片裁剪组件文档

- 新增中文文档 docs/src/components/common-ui/vben-cropper.md
- 新增英文文档 docs/src/en/components/common-ui/vben-cropper.md
- 新增基础用法示例 demos/vben-cropper/basic
- 新增固定比例裁剪示例 demos/vben-cropper/aspect-ratio
- 更新侧边栏配置添加 Cropper 入口

* fix: 更正跨域图片描述并修复 demo 内存泄漏

- 文档更正:网络图片导出裁剪结果需服务端 CORS 支持
- 修复 URL.createObjectURL 内存泄漏:添加 revokeObjectURL 释放
2026-05-11 12:50:44 +08:00
雪忆天堂
9b54e50510 fix: 修正vxtable不存在formConfig时,直接变更data失效问题 2026-05-11 10:10:34 +08:00
xueyitt
30356a24e6 fix: 修正vxtable不存在formConfig时,直接变更data失效问题
修正vxtable不存在formConfig时,直接变更data失效问题
2026-05-11 10:09:47 +08:00
MistyMoon
ba60bc3c14 fix(@vben/layouts): correct logo theme in semi-dark sidebar (#7785) (#7902) 2026-05-10 10:41:43 +08:00
JyQAQ
f5feddc6c7 feat(@vben/plugins): tiptap 组件新增 maxHeight 属性支持及文档 (#7897)
* feat(@vben/plugins): tiptap 组件新增 maxHeight 属性支持

- 新增 maxHeight prop 支持限制编辑器最大高度
- 编辑器内容区超出最大高度时自动滚动
- 移除 style.css 中未使用的 CSS 规则

* docs(@vben/plugins): 添加 tiptap 富文本编辑器组件文档

- 新增中文文档 docs/src/components/common-ui/vben-tiptap.md
- 新增英文文档 docs/src/en/components/common-ui/vben-tiptap.md
- 新增基础用法示例 demos/vben-tiptap/basic
- 新增图片上传示例 demos/vben-tiptap/image-upload
- 更新文档侧边栏配置

* fix(@vben/plugins): extract URL from response in image upload callback

The upload callback was incorrectly passing the AxiosResponse object
to resolve() instead of extracting the actual image URL string.
This caused the editor to insert [object Object] as image src,
resulting in broken images.

* chore: add changeset for tiptap maxHeight feature

* Revert "chore: add changeset for tiptap maxHeight feature"

This reverts commit a28fc4441f14641f6af6c1a143aa6959591315b2.
2026-05-10 10:38:21 +08:00
Yanghai.Lin
0868deb82b fix: 修复 Input 组件 focus 边框被裁剪问题 (#7894)
* fix(other): 修复 oxlint ignorePatterns 导致 pre-commit hook 失败

* fix(@vben-core/shadcn-ui): 修复 Input 组件 focus 时边框被父容器 overflow hidden 裁剪

* fix(@vben-core/shadcn-ui): 修复 SelectTrigger 组件 focus 时边框被父容器 overflow hidden 裁剪
2026-05-10 10:37:39 +08:00
layhuts
1299acd8f9 fix: 获取已存在的 key,避免重复写入刷新过期时间 2026-05-09 23:27:25 +08:00
layhuts
43717807a4 style: reformat code 2026-05-09 23:18:44 +08:00
layhuts
1b4e126128 fix: 处理localStorageDriver在某些受限浏览器环境下报错导致无法使用 2026-05-09 23:10:05 +08:00
layhuts
d23b246aee fix: 处理localStorage prefix === ''时提醒用户可能会全部删除数据 2026-05-09 23:04:38 +08:00
layhuts
71f2e5f504 fix: 去除onConfirm中的setTimeout 2026-05-09 22:51:39 +08:00
layhuts
4bbd34fab9 fix: 修复 labelField 和 nameField 2026-05-09 22:28:03 +08:00
layhuts
08e4bb40b4 style: reformat code 2026-05-09 18:28:23 +08:00
layhuts
9c49f4bb1e refactor: 优化viewed实例初始化,rowStyle rowClassName 从最新的配置中读取 2026-05-09 18:27:09 +08:00
layhuts
28905b0bec style: reformat code 2026-05-09 14:08:19 +08:00
layhuts
bbcad709ca style: 修改注释 2026-05-09 14:07:30 +08:00
layhuts
a5f0537cb0 fix: 处理viewedKeys由于 FIFO 顺序,显式提供的值可能会被异步存储恢复静默地移除。 2026-05-09 13:38:50 +08:00
layhuts
c78d89f549 fix: 处理非原子性的先清除后写入操作会setKeys带来永久性数据丢失的风险 2026-05-09 13:16:50 +08:00
layhuts
f2a17cbe78 fix: 处理getViewedKeys()返回对内部可变对象的直接引用问题 2026-05-09 13:10:41 +08:00
layhuts
9667232684 fix: 加上 - 分隔符来避免跨前缀误匹配 2026-05-09 12:56:50 +08:00
layhuts
1f584ff0c9 fix: 处理window不可用时降级使用Memory 2026-05-09 12:49:21 +08:00
layhuts
75ed17a1f9 docs: 更正saveToCache所属组件 2026-05-09 12:41:10 +08:00
layhuts
cc6ccaab38 docs: 为符合 Markdown lint 规范,指定代码块语言。 2026-05-09 12:38:13 +08:00
layhuts
0be4b51eaa fix: 解决window在构造函数中进行访问破坏SSR/Node环境。 2026-05-09 12:33:15 +08:00
layhuts
b40822e3ed fix: 解决indexedDB的getDB在失败重试时永远返回错误Promise问题 2026-05-09 12:02:41 +08:00
layhuts
df5cb426d1 fix: 解决indexedDB的setItem、,removeItem以及clear在请求成功时而不是事务完成时触发resolve问题 2026-05-09 11:54:11 +08:00
layhuts
2d36d6b510 style: reformat code 2026-05-09 11:03:47 +08:00
layhuts
88d5661e0c refactor: 重构ViewedRowPersistOptions处理扁平化问题
改成按 type 字段区分的联合类型
2026-05-09 11:02:16 +08:00
layhuts
8ce773f264 feat: 在storage-manager添加keys方法 2026-05-09 10:58:41 +08:00
layhuts
329fa68207 fix: 手动操作行标记示例时动态获取列表前两行 2026-05-09 09:23:10 +08:00
layhuts
e1f6449073 feat: 表格已读行操作标记 2026-05-08 20:03:05 +08:00
layhuts
51e8b27d4c style(@vben-core/shared): formatting 2026-05-08 17:36:47 +08:00
layhuts
e555ee065e feat(@vben-core/shared): 新增indexedDB
在cache下新增indexedDB缓存
2026-05-08 17:34:54 +08:00
Lin
b5dacd992f feat: add time zone option to preference settings (#7871) 2026-05-03 12:16:58 +08:00
Jin Mao
d55f17670a chore: 更新依赖包版本
- 更新 pkg-types 从 2.3.0 到 2.3.1
- 更新 rolldown 从 1.0.0-rc.15 到 1.0.0-rc.17
- 更新 typescript 从 6.0.2 到 6.0.3
- 更新 vite 从 8.0.8 到 8.0.10
2026-05-01 06:55:42 +08:00
Jin Mao
9f20d52b4e chore: 更新 FTP 部署操作版本
- 将 SamKirkland/FTP-Deploy-Action 从 v4.3.6 升级到 v4.4.0
- 所有部署任务中的 FTP 操作均已更新到新版本
- 保持了所有现有配置和凭据不变
2026-05-01 06:53:06 +08:00
Jin Mao
86445a38e4 Merge branch 'fork/jyqwq/feature/富文本支持图片上传' 2026-05-01 06:49:48 +08:00
leo
9a73e961fc fix(@vben/stores): respect base URL when opening route in new window (#7837)
* fix(@vben/stores): respect base URL when opening route in new window

* fix(@vben/stores): respect base URL when opening route in new window
2026-05-01 06:49:05 +08:00
boisduval
c0b2ef980e fix: 修复 IconPicker 在手动输入时表单值不更新的问题 (#7869)
- 修复 IconPicker.vue 在 updateCurrentSelect 时未同步更新 modelValue 的 Bug
- 优化 IconPicker 适配器配置,使其兼容 Element Plus 的 ElInput 组件
2026-04-30 15:46:07 +08:00
mew
e8dc464e79 fix: issue in tab bar chrome height is not full due to wrapper element div (#7867)
Caused by PR #7858
2026-04-30 15:45:44 +08:00
mew
99c38c93c8 feat: refactor context menu to capture native events (#7858)
* feat: refactor context menu to capture native events

prevent context-menu to show in html input fields

* fix: refactor context-menu.vue for improved structure

* chore: fix format

* chore: remove dead code

* chore: fix lint

* fix: update contenteditable selector in context menu

proposed fixed by coderabitai
2026-04-28 13:36:13 +08:00
yuan.ji
244c0a5884 fix(@vben/plugins): 根据代码审查意见修复 tiptap 图片上传
- 提取 findPlaceholderPos 辅助函数,消除重复的 descendants 查找
- 添加 editor.isDestroyed 守卫,防止操作已销毁编辑器
- renderHTML 不输出上传状态属性,防止 blob URL 泄露到序列化 HTML
- uploadImage 命令返回 boolean,添加 Commands 类型增强,移除 as any
- 拖拽/粘贴多图时仅处理第一张并提示仅支持单图上传
- 自定义 extensions 时不传 imageUpload 给工具栏,toolbar action 加运行时守卫
2026-04-27 14:33:30 +08:00
yuan.ji
c6fd599784 feat(@vben/plugins): 补充 tiptap 图片上传类型、工具栏和示例
- 新增 ImageUploadOptions 类型定义和 imageUpload 属性
- 工具栏图片按钮支持上传/URL 双模式
- playground 添加图片上传 mock 示例
2026-04-27 13:42:56 +08:00
yuan.ji
4ca2f1c6e8 feat(@vben/plugins): tiptap 支持图片上传功能
- 新增 imageUpload 配置项,支持自定义上传接口
- 支持文件选择、拖拽、粘贴三种上传方式
- 上传中显示 blob 预览图 + loading spinner / 进度条
- 支持 accept 和 maxSize 文件校验
- 支持 onUploadError 自定义错误处理
- 未配置 imageUpload 时保持原有 URL 插入行为不变
- 使用 NodeView 实现实时 DOM 控制的进度展示
2026-04-27 13:42:36 +08:00
Jin Mao
36d7dc23fa Merge branch 'fork/zilvya/ta1' 2026-04-26 16:26:30 +08:00
Lgf
42317ddf41 feat(watermark): 添加暗黑模式水印颜色适配
为水印功能添加暗黑模式适配,根据当前主题自动切换水印颜色。在暗黑模式下使用浅色水印,在亮色模式下使用深色水印,提升视觉体验。
2026-04-24 15:42:07 +08:00
boisduval
c7fd6ffb0e feat: 添加日期格式化函数的空值处理
- 当传入的时间参数为 undefined、null 或空字符串时,直接返回空字符串而不是继续执行格式化逻辑,避免无效的时间值导致程序错误。
2026-04-23 17:25:10 +08:00
AxiosLeo
3a83fb0c3e fix: ensure trigger function is awaited in useDependencies (#7830) 2026-04-22 07:09:09 +08:00
AxiosLeo
5907c04e00 fix: update selector for active menu item in useMenuScroll hook (#7829) 2026-04-22 07:08:40 +08:00
Jin Mao
6885927441 chore: fix actions error 2026-04-15 18:49:07 +08:00
2ylllll
c8c589ae7e fix: type check (#7818) 2026-04-15 18:11:06 +08:00
Jin Mao
d0889b5cc4 chore: 更新依赖包版本
- 更新 @tsdown/css 从 0.21.7 到 0.21.8
- 更新 @vitejs/plugin-vue 从 6.0.5 到 6.0.6
- 更新 dotenv 从 17.4.1 到 17.4.2
- 更新 globals 从 17.4.0 到 17.5.0
- 更新 happy-dom 从 20.8.9 到 20.9.0
- 更新 oxlint 从 1.59.0 到 1.60.0
- 更新 tsdown 从 0.21.7 到 0.21.8
2026-04-15 17:28:17 +08:00
Jin Mao
2f1a866cb4 chore: 更新 pnpm action 版本
- 将 .github/actions/setup-node/action.yml 中的 pnpm/action-setup 从 v4 升级到 v6
- 将 .github/workflows/ci.yml 中的 pnpm/action-setup 从 v5 升级到 v6
- 移除重复的 pnpm 安装步骤配置
- 统一使用最新的 pnpm action 版本以获得更好的兼容性
- 保持 run_install 配置为 false 以跳过自动安装依赖
2026-04-15 17:27:57 +08:00
Jin Mao
fee32c1d12 chore: 优化通知组件逻辑
- 移除冗余的空值检查,简化数组长度判断条件
- 统一导入语句的引号格式为双引号
- 优化 VbenScrollbar 组件的显示条件逻辑
- 更新清除按钮的禁用状态判断逻辑
2026-04-15 17:22:39 +08:00
Jin Mao
f2652833a1 Merge branch 'fork/xueyitt/main' 2026-04-15 17:20:10 +08:00
allen
c3aa63982f fix: devtools warning 2026-04-15 16:44:13 +08:00
allen
4a968d9379 fix: devtools warning 2026-04-15 16:39:56 +08:00
allen
ec9b323195 docs: demo注释修改 2026-04-15 14:54:40 +08:00
allen
d69455e8ef fix: dependencies访问extendApi 2026-04-15 14:42:21 +08:00
allen
33e2582f60 fix: fix lint and add new form-ui features
feat(form-ui): 在 dependencies 里提供访问extendApi的能力
2026-04-15 14:21:39 +08:00
allen
991408b451 fix: default precision error 2026-04-13 21:08:03 +08:00
allen
a096073a8e fix: lint 2026-04-13 20:43:29 +08:00
allen
f30157fa59 fix: class 2026-04-13 20:41:43 +08:00
allen
12a81a7a7d fix: demo validator usage & types import 2026-04-13 20:15:47 +08:00
allen
e808fe74c1 Merge branch 'feature-collapsible-component' of https://github.com/2yllll/vue-vben-admin into feature-collapsible-component 2026-04-13 19:44:45 +08:00
allen
4665a787a0 fix: collapsible component css fix 2026-04-13 19:44:21 +08:00
2ylllll
b7774fc9d9 Merge branch 'main' into feature-collapsible-component 2026-04-13 19:26:23 +08:00
allen
6f18718c87 feat: add collapsible 组件,form表单增加单项可折叠,支持schema配置默认关闭/开启
feat: add collapsible 组件,form表单增加单项可折叠,支持schema配置默认关闭/开启
- shadcn-ui 增加 collapsible组件,collapsible-params组件
- form新增支持单项折叠
- collapsible-params组件在Form表单应用
2026-04-13 19:20:01 +08:00
Caisin
2a32715c99 feat: enable project-scoped preferences extension tabs (#7803)
* feat: enable project-scoped preferences extension tabs

Add a typed extension schema so subprojects can define extra settings,
render them in the shared preferences drawer only when configured, and
consume them in playground as a real feature demo. Extension labels now
follow locale keys instead of hardcoded app-specific strings.

Constraint: Reuse the shared preferences drawer and field blocks
Rejected: Add app-specific fields to core preferences | too tightly coupled
Rejected: Inline localized label objects | breaks existing locale-key flow
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep extension labels as locale keys rendered via $t in UI
Tested: Vitest preferences tests
Tested: Turbo typecheck for preferences, layouts, web-antd, and playground
Tested: ESLint for touched preferences and playground files
Not-tested: Manual browser interaction in playground preferences drawer

* fix: satisfy lint formatting for preferences extension demo

Adjust the playground preferences extension demo template so formatter and
Vue template lint rules agree on the rendered markup. This keeps CI green
without changing runtime behavior.

Constraint: Must preserve the existing demo behavior while fixing CI only
Rejected: Disable the Vue newline rule | would weaken shared lint guarantees
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer computed/template structures that avoid formatter-vs-lint conflicts
Tested: pnpm run lint
Not-tested: Manual browser interaction in playground preferences extension demo

* fix: harden custom preferences validation and i18n labels

Tighten custom preferences handling so numeric extension fields respect
min, max, and step constraints. Number inputs now ignore NaN values,
and web-antd extension metadata uses locale keys instead of raw strings.
Also align tip-based hover guards in shared preference inputs/selects.

Constraint: Keep fixes scoped to verified findings only
Rejected: Broader refactor of preferences field components | not needed for these fixes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Reuse the same validation path for updates and cache hydration
Tested: Vitest preferences tests
Tested: ESLint for touched preferences and widget files
Tested: Typecheck for web-antd, layouts, and core preferences
Not-tested: Manual browser interaction for all preference field variants

* fix: remove localized default from playground extension config

Drop the hardcoded Chinese default value from the playground extension
report title field and fall back to an empty string instead. This keeps
extension config locale-neutral while preserving localized labels and
placeholders through translation keys.

Constraint: Keep the fix limited to the verified localized default issue
Rejected: Compute the default from runtime locale in config | unnecessary for this finding
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Avoid embedding localized literals in extension default values
Tested: ESLint for playground/src/preferences.ts
Tested: Oxfmt check for playground/src/preferences.ts
Not-tested: Manual playground preferences interaction

* docs: document project-scoped preferences extension workflow

Add Chinese and English guide sections explaining how to define,
initialize, read, and update project-scoped preferences extensions.
Also document numeric field validation and point readers to the
playground demo for a complete example.

Constraint: Keep this docs-only and aligned with the shipped API
Rejected: Update only Chinese docs | would leave English docs inconsistent
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep zh/en examples and playground demo paths synchronized
Tested: git diff --check; pnpm build:docs
Not-tested: Manual browser review of the rendered docs site

* fix: harden custom preferences defaults and baselines

Use a locale-neutral default for the web-antd report title.
Also stop preference getters from exposing mutable baseline
or extension schema objects, and add a regression test for
external mutation attempts.

Constraint: Keep behavior compatible with the shipped preferences API
Rejected: Return raw refs with readonly typing only | callers could still mutate internals
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep defensive copies for baseline and schema getters unless storage semantics change
Tested: eslint, oxlint, targeted vitest, filtered typecheck, git diff --check
Not-tested: Full monorepo typecheck and test suite

* test: relax custom preference cache key matching

Avoid coupling the custom-number cache test to one exact
localStorage key string. Match the intended cache lookup
more loosely so the test still verifies filtering behavior
without depending on the full namespaced cache key.

Constraint: Focus the test on cache filtering behavior
Rejected: Assert one exact key | brittle with namespace changes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer behavior tests over literal storage keys
Tested: targeted vitest, eslint, git diff --check
Not-tested: Full monorepo test suite

---------

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-04-13 17:52:17 +08:00
Caisin
46f323431c feat(form-ui): support schema valueFormat for getValues payload shaping (#7804)
* feat(@vben-core/form-ui): support schema valueFormat on getValues

Some form fields emit UI-friendly structures such as time-range arrays,
while consumers and backend APIs often need a different payload shape.
This adds schema-level `valueFormat` hooks so `getValues()` can
normalize field output at read time without forcing callers to
post-process every submission path.

Constraint: Must preserve existing range-time mapping and nested field behavior
Constraint: Must not mutate live vee-validate form state while formatting output
Rejected: Global formatter config | too coarse for per-field payload shaping
Rejected: Post-submit-only transform | misses reset/query/change handlers
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep `getValues()` output derivation side-effect free
Directive: Clone raw form values before formatting derived payloads
Tested: vitest form-api test for valueFormat and existing getValues paths
Tested: oxlint on changed form-ui source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* fix(@vben-core/form-ui): restore mount compatibility and share field path parsing

Follow-up review found two real regressions and one missing assertion in the
new value formatting flow. `FormApi.mount()` had become breaking by requiring
`componentRefMap`, and delete path resolution duplicated field-name parsing
instead of sharing the reader grammar. This patch restores backward
compatibility, centralizes field-name path parsing, and extends the test to
prove formatting does not mutate live form values.

Constraint: Must preserve current valueFormat behavior and nested field support
Constraint: Must not reintroduce mutation of live vee-validate values
Rejected: Keep duplicated delete parsing | risks grammar drift from read path
Rejected: Only loosen mount tests | would leave consumer-facing API breakage
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Reuse shared field-name parsing for read/delete semantics in form-ui
Tested: vitest form-api test suite
Tested: oxlint on changed form-ui files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors
EOF && git push hekx feature-form-value-format

* fix(@vben-core/form-ui): clear stale component refs on unmount

A follow-up review found that `unmount()` left the private component ref map
populated. Because `mount()` now accepts an optional `componentRefMap`, a later
mount without a new map could silently reuse stale refs from a prior form
instance. This change clears the ref map on unmount and adds a regression test
covering remount behavior without a new ref map.

Constraint: Must preserve backward-compatible optional `mount()` ref map behavior
Constraint: Focus and field-ref lookups must not observe stale refs after unmount
Rejected: Clear refs only during next mount | stale state would still leak between lifecycle calls
Rejected: Remove mount fallback entirely | would undo the compatibility fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When mount falls back to internal refs, unmount must always reset that cache
Tested: vitest form-api test suite
Tested: oxlint on changed form-api source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* refactor(@vben-core/form-ui): trim redundant valueFormat plumbing

Review feedback identified a few small cleanups in the value formatting path.
This removes an unnecessary shallow clone in `getValues()`, reuses the
already-parsed `rawKey` from `resolveFieldNamePath()` instead of re-resolving
it in multiple helpers, and clarifies the `FormValueFormat` contract for
undefined-as-delete decomposition behavior.

Constraint: Must not change runtime valueFormat behavior or payload shape
Constraint: Documentation and helper cleanup should stay behavior-preserving
Rejected: Leave duplicate raw-key resolution in place | adds needless parsing churn
Rejected: Expand the formatter API further | outside the scope of this cleanup
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep read/format helper plumbing lean and avoid duplicate field-name parsing
Tested: vitest form-api test suite
Tested: oxlint on changed form-ui source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* feat(@vben-core/form-ui): document valueFormat with live examples

The new `valueFormat` feature needed a concrete usage path in both the
playground and the docs so users can understand how raw component values differ
from the final payload returned by `getValues()`. This adds a dedicated form
example, wires it into the playground menu, and documents the API with an
interactive docs demo. The preview panels now stay in sync when values are set,
reset, or submitted.

Constraint: Must demonstrate both return-value and setValue decomposition flows
Constraint: Example previews must react to setValues, reset, and manual edits
Rejected: Only document via markdown snippet | insufficient for verifying live payload behavior
Rejected: Reuse an existing basic form page | would bury feature-specific behavior
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep playground and docs demos behaviorally aligned when extending valueFormat examples
Tested: eslint on playground/docs valueFormat demo files and route module
Tested: oxlint on playground route module
Not-tested: Full docs/playground app runtime was not launched in this session

* chore(@vben-core/form-ui): normalize valueFormat demo formatting

The previous feature/docs commit left a few formatter-only adjustments unstaged
after hooks rewrote line wrapping in the new demo and docs pages. This commit
captures those final non-behavioral formatting updates so the branch matches the
current working tree.

Constraint: Must not change runtime behavior or docs meaning
Rejected: Leave post-hook diffs unstaged | branch would not reflect local state
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: After hook-driven rewrites, verify the working tree is clean before final push
Tested: Git diff inspection of remaining changes
Not-tested: No additional runtime verification needed; formatting-only follow-up
EOF && git push hekx feature-form-value-format

* fix(@vben-core/form-ui): remove docs demo dayjs dependency

The docs valueFormat demo imported `dayjs` directly even though the docs
package does not declare it as a dependency. That caused `@vben/docs:build`
to fail in CI during VitePress bundling. This change removes the direct
import, keeps the preview formatter generic for day-like values, and drops
the docs-only preset button that required constructing dayjs instances.

Constraint: Docs build must succeed without adding new package dependencies
Constraint: Playground example should remain unchanged and fully interactive
Rejected: Add dayjs to docs dependencies | unnecessary for a small display demo
Rejected: Externalize dayjs in VitePress build | hides a package boundary issue
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Docs demos should avoid imports only available through transitive deps
Tested: pnpm exec eslint docs/src/demos/vben-form/value-format/index.vue
Tested: pnpm --dir docs run build
Not-tested: No browser-side manual verification of the docs demo in this session

---------

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-04-13 17:52:17 +08:00
Caisin
2b1fcb038b feat(common-ui): add labelFn support to ApiComponent (#7801)
* feat: allow api-component labels to be derived from option data

ApiComponent already normalizes option records into the label/value shape used by
consuming controls, but label text could only come from a single field. Add
labelFn so callers can build labels from the full option record while keeping
labelField as the fallback path.

This keeps the change inside the existing component instead of introducing a
wrapper, and it also normalizes direct options through the same transform path
as API-loaded options for consistent behavior.

Constraint: Must extend the existing ApiComponent API instead of adding a second
Constraint: wrapper component
Rejected: Add a separate ApiLabelComponent wrapper |
Rejected: extra surface area for one option-mapping concern
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep labelFn as a presentation transform and preserve labelField
Directive: fallback for existing callers
Tested: pnpm exec eslint api-component.vue index.ts types.ts
Tested: pnpm exec vue-tsc --noEmit -p packages/effects/common-ui/tsconfig.json
Not-tested: runtime integration in consuming select/tree-select components

* Update packages/effects/common-ui/src/components/api-component/api-component.vue

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-13 17:52:17 +08:00
过冬
d779a39862 fix: antdv-next message/notification 跟随暗色主题 (#7799) 2026-04-13 17:52:17 +08:00
Jin Mao
0c8db0f6be fix: 修复VITE_APP_TITLE变量替换语法
- 将index.html中的<%= VITE_APP_TITLE %>替换为%VITE_APP_TITLE%
- 更新web-antd、web-antdv-next、web-ele、web-naive、web-tdesign应用
- 修改文档中loading组件的VITE_APP_TITLE引用方式
- 修复vite-config插件中默认加载模板的变量语法
- 统一所有应用和模板中的环境变量引用格式
2026-04-13 17:52:17 +08:00
Jin Mao
37393e1820 chore: fix actions error 2026-04-13 17:52:16 +08:00
xingyu4j
93e23c6b05 chore: update deps 2026-04-13 17:52:16 +08:00
xingyu4j
e023a0852a fix: tailwindcss lint config 2026-04-13 17:52:16 +08:00
xingyu4j
306739cabb fix: lint 2026-04-13 17:52:16 +08:00
xingyu4j
093479bb33 chore: remove vite-plugin-html 2026-04-13 17:52:16 +08:00
xingyu4j
bd369df3bc fix: check deps 2026-04-13 17:52:16 +08:00
xingyu4j
4f7b396ebb chore: update deps 2026-04-13 17:52:16 +08:00
xingyu4j
d700b04841 fix: tailwindcss lint 2026-04-13 17:52:16 +08:00
xingyu4j
243456d928 fix: ts config 2026-04-13 17:52:16 +08:00
Jin Mao
7e8b9c2368 fix: 配置 TypeScript 构建根目录
- 添加 rootDir 编译选项指向 ./src 目录
- 保持现有编译配置不变
- 排除测试文件和 node_modules 目录
2026-04-13 17:52:15 +08:00
Jin Mao
92298bac2b chore: update deps 2026-04-13 17:52:15 +08:00
dullathanol
436a865bef chore: 修正注释 2026-04-13 17:52:15 +08:00
dullathanol
185011ee21 fix: tailwindcss config 2026-04-13 17:52:15 +08:00
过冬
feca01484b Merge branch 'vbenjs:main' into main 2026-04-13 17:52:15 +08:00
Jin Mao
35e1166b9f chore: fix lint 2026-04-13 17:52:15 +08:00
dullathanol
d0c17090ef fix: 修正 Modal/Drawer 中 loading 属性注释 2026-04-13 17:52:15 +08:00
dullathanol
cc32ebeb12 feat: 支持 overflow 配置以允许拖拽超出可视区 2026-04-13 17:52:15 +08:00
dullathanol
02372f12ba fix: 弹窗组件拖拽后全屏位置异常 2026-04-13 17:52:15 +08:00
Jin Mao
e9bdbb610a chore: fix lint
- 关闭 vitest/require-mock-type-parameters 规则
2026-04-13 17:52:15 +08:00
dullathanol
2013ba4de4 fix: 补全 ComponentPropsMap 与 Vxe 表格表单链路的类型 2026-04-13 17:52:15 +08:00
dullathanol
e417a2c209 fix: 修复 FormField 在 SFC 中的运行时异常 2026-04-13 17:52:14 +08:00
dullathanol
f1273571c7 fix: 修复部分情况 component 类型丢失问题 2026-04-13 17:52:14 +08:00
dullathanol
064a6a20f0 feat: 表单 Schema 支持组件 Props 映射泛型,同步适配VxeGrid 2026-04-13 17:52:14 +08:00
dullathanol
cb5e7e00f1 refactor: 简化 componentProps 回调的类型写法 2026-04-13 17:52:14 +08:00
dullathanol
5ed39c03a4 fix: 函数式 componentProps 按已注册 component 的 Props 校验返回值 2026-04-13 17:52:14 +08:00
dullathanol
794b103aa9 feat: Schema 中 componentProps 随注册组件联动类型提示 2026-04-13 17:52:14 +08:00
墨苒孤
c7b1bb3492 fix(form): 修复表单示例中 switch 组件无法切换的问题 (#7636) (#7763) 2026-04-13 17:52:14 +08:00
橙子
89349f8d91 fix: interface DropdownMenuProps don‘t have key prop (#7757) 2026-04-13 17:52:14 +08:00
HaroldZhangCode91
8e0b65a0e1 feat: fix oxlint error for oxlint upgrade (#7756)
1. remove unknown rule out of oxlint
2. add the corresponding back to eslint-config
3. fixed the eslint error for package.json
2026-04-13 17:52:13 +08:00
墨苒孤
b096e83f93 fix: make search case-insensitive (#7689) (#7755) 2026-04-13 17:52:13 +08:00
橙子
4a69c9e665 perf: replace onUnMounted to tryOnScopeDispose (#7747)
* perf: replace `onUnMounted` to `tryOnScopeDispose`

* perf: replace `onUnMounted` to `tryOnScopeDispose`
2026-04-13 17:52:13 +08:00
Jin Mao
7a60a081a2 chore: update deps 2026-04-13 17:52:13 +08:00
xingyu4j
c693c854a7 fix: extension-document 2026-04-13 17:52:13 +08:00
xingyu4j
5eca357a5c feat(@vben/plugins): add tiptap rich text editor 2026-04-13 17:52:13 +08:00
xingyu4j
2930dcd78e chore: typescript config is expired‌ 2026-04-13 17:52:13 +08:00
xingyu4j
e421d9d99b chore: update deps 2026-04-13 17:52:12 +08:00
xueyitt
6c029bfa32 Merge branch 'main' into main 2026-04-13 16:10:29 +08:00
雪忆天堂
fe77bc8bc9 feat: 通知模块自定义加强 2026-04-13 16:05:42 +08:00
Caisin
ccabbf0e97 feat: enable project-scoped preferences extension tabs (#7803)
* feat: enable project-scoped preferences extension tabs

Add a typed extension schema so subprojects can define extra settings,
render them in the shared preferences drawer only when configured, and
consume them in playground as a real feature demo. Extension labels now
follow locale keys instead of hardcoded app-specific strings.

Constraint: Reuse the shared preferences drawer and field blocks
Rejected: Add app-specific fields to core preferences | too tightly coupled
Rejected: Inline localized label objects | breaks existing locale-key flow
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep extension labels as locale keys rendered via $t in UI
Tested: Vitest preferences tests
Tested: Turbo typecheck for preferences, layouts, web-antd, and playground
Tested: ESLint for touched preferences and playground files
Not-tested: Manual browser interaction in playground preferences drawer

* fix: satisfy lint formatting for preferences extension demo

Adjust the playground preferences extension demo template so formatter and
Vue template lint rules agree on the rendered markup. This keeps CI green
without changing runtime behavior.

Constraint: Must preserve the existing demo behavior while fixing CI only
Rejected: Disable the Vue newline rule | would weaken shared lint guarantees
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer computed/template structures that avoid formatter-vs-lint conflicts
Tested: pnpm run lint
Not-tested: Manual browser interaction in playground preferences extension demo

* fix: harden custom preferences validation and i18n labels

Tighten custom preferences handling so numeric extension fields respect
min, max, and step constraints. Number inputs now ignore NaN values,
and web-antd extension metadata uses locale keys instead of raw strings.
Also align tip-based hover guards in shared preference inputs/selects.

Constraint: Keep fixes scoped to verified findings only
Rejected: Broader refactor of preferences field components | not needed for these fixes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Reuse the same validation path for updates and cache hydration
Tested: Vitest preferences tests
Tested: ESLint for touched preferences and widget files
Tested: Typecheck for web-antd, layouts, and core preferences
Not-tested: Manual browser interaction for all preference field variants

* fix: remove localized default from playground extension config

Drop the hardcoded Chinese default value from the playground extension
report title field and fall back to an empty string instead. This keeps
extension config locale-neutral while preserving localized labels and
placeholders through translation keys.

Constraint: Keep the fix limited to the verified localized default issue
Rejected: Compute the default from runtime locale in config | unnecessary for this finding
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Avoid embedding localized literals in extension default values
Tested: ESLint for playground/src/preferences.ts
Tested: Oxfmt check for playground/src/preferences.ts
Not-tested: Manual playground preferences interaction

* docs: document project-scoped preferences extension workflow

Add Chinese and English guide sections explaining how to define,
initialize, read, and update project-scoped preferences extensions.
Also document numeric field validation and point readers to the
playground demo for a complete example.

Constraint: Keep this docs-only and aligned with the shipped API
Rejected: Update only Chinese docs | would leave English docs inconsistent
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep zh/en examples and playground demo paths synchronized
Tested: git diff --check; pnpm build:docs
Not-tested: Manual browser review of the rendered docs site

* fix: harden custom preferences defaults and baselines

Use a locale-neutral default for the web-antd report title.
Also stop preference getters from exposing mutable baseline
or extension schema objects, and add a regression test for
external mutation attempts.

Constraint: Keep behavior compatible with the shipped preferences API
Rejected: Return raw refs with readonly typing only | callers could still mutate internals
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep defensive copies for baseline and schema getters unless storage semantics change
Tested: eslint, oxlint, targeted vitest, filtered typecheck, git diff --check
Not-tested: Full monorepo typecheck and test suite

* test: relax custom preference cache key matching

Avoid coupling the custom-number cache test to one exact
localStorage key string. Match the intended cache lookup
more loosely so the test still verifies filtering behavior
without depending on the full namespaced cache key.

Constraint: Focus the test on cache filtering behavior
Rejected: Assert one exact key | brittle with namespace changes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Prefer behavior tests over literal storage keys
Tested: targeted vitest, eslint, git diff --check
Not-tested: Full monorepo test suite

---------

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-04-13 15:11:57 +08:00
Caisin
5b84ac5b13 feat(form-ui): support schema valueFormat for getValues payload shaping (#7804)
* feat(@vben-core/form-ui): support schema valueFormat on getValues

Some form fields emit UI-friendly structures such as time-range arrays,
while consumers and backend APIs often need a different payload shape.
This adds schema-level `valueFormat` hooks so `getValues()` can
normalize field output at read time without forcing callers to
post-process every submission path.

Constraint: Must preserve existing range-time mapping and nested field behavior
Constraint: Must not mutate live vee-validate form state while formatting output
Rejected: Global formatter config | too coarse for per-field payload shaping
Rejected: Post-submit-only transform | misses reset/query/change handlers
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep `getValues()` output derivation side-effect free
Directive: Clone raw form values before formatting derived payloads
Tested: vitest form-api test for valueFormat and existing getValues paths
Tested: oxlint on changed form-ui source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* fix(@vben-core/form-ui): restore mount compatibility and share field path parsing

Follow-up review found two real regressions and one missing assertion in the
new value formatting flow. `FormApi.mount()` had become breaking by requiring
`componentRefMap`, and delete path resolution duplicated field-name parsing
instead of sharing the reader grammar. This patch restores backward
compatibility, centralizes field-name path parsing, and extends the test to
prove formatting does not mutate live form values.

Constraint: Must preserve current valueFormat behavior and nested field support
Constraint: Must not reintroduce mutation of live vee-validate values
Rejected: Keep duplicated delete parsing | risks grammar drift from read path
Rejected: Only loosen mount tests | would leave consumer-facing API breakage
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Reuse shared field-name parsing for read/delete semantics in form-ui
Tested: vitest form-api test suite
Tested: oxlint on changed form-ui files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors
EOF && git push hekx feature-form-value-format

* fix(@vben-core/form-ui): clear stale component refs on unmount

A follow-up review found that `unmount()` left the private component ref map
populated. Because `mount()` now accepts an optional `componentRefMap`, a later
mount without a new map could silently reuse stale refs from a prior form
instance. This change clears the ref map on unmount and adds a regression test
covering remount behavior without a new ref map.

Constraint: Must preserve backward-compatible optional `mount()` ref map behavior
Constraint: Focus and field-ref lookups must not observe stale refs after unmount
Rejected: Clear refs only during next mount | stale state would still leak between lifecycle calls
Rejected: Remove mount fallback entirely | would undo the compatibility fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When mount falls back to internal refs, unmount must always reset that cache
Tested: vitest form-api test suite
Tested: oxlint on changed form-api source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* refactor(@vben-core/form-ui): trim redundant valueFormat plumbing

Review feedback identified a few small cleanups in the value formatting path.
This removes an unnecessary shallow clone in `getValues()`, reuses the
already-parsed `rawKey` from `resolveFieldNamePath()` instead of re-resolving
it in multiple helpers, and clarifies the `FormValueFormat` contract for
undefined-as-delete decomposition behavior.

Constraint: Must not change runtime valueFormat behavior or payload shape
Constraint: Documentation and helper cleanup should stay behavior-preserving
Rejected: Leave duplicate raw-key resolution in place | adds needless parsing churn
Rejected: Expand the formatter API further | outside the scope of this cleanup
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep read/format helper plumbing lean and avoid duplicate field-name parsing
Tested: vitest form-api test suite
Tested: oxlint on changed form-ui source and test files
Not-tested: Full repo typecheck baseline has unrelated .vue module resolution errors

* feat(@vben-core/form-ui): document valueFormat with live examples

The new `valueFormat` feature needed a concrete usage path in both the
playground and the docs so users can understand how raw component values differ
from the final payload returned by `getValues()`. This adds a dedicated form
example, wires it into the playground menu, and documents the API with an
interactive docs demo. The preview panels now stay in sync when values are set,
reset, or submitted.

Constraint: Must demonstrate both return-value and setValue decomposition flows
Constraint: Example previews must react to setValues, reset, and manual edits
Rejected: Only document via markdown snippet | insufficient for verifying live payload behavior
Rejected: Reuse an existing basic form page | would bury feature-specific behavior
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep playground and docs demos behaviorally aligned when extending valueFormat examples
Tested: eslint on playground/docs valueFormat demo files and route module
Tested: oxlint on playground route module
Not-tested: Full docs/playground app runtime was not launched in this session

* chore(@vben-core/form-ui): normalize valueFormat demo formatting

The previous feature/docs commit left a few formatter-only adjustments unstaged
after hooks rewrote line wrapping in the new demo and docs pages. This commit
captures those final non-behavioral formatting updates so the branch matches the
current working tree.

Constraint: Must not change runtime behavior or docs meaning
Rejected: Leave post-hook diffs unstaged | branch would not reflect local state
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: After hook-driven rewrites, verify the working tree is clean before final push
Tested: Git diff inspection of remaining changes
Not-tested: No additional runtime verification needed; formatting-only follow-up
EOF && git push hekx feature-form-value-format

* fix(@vben-core/form-ui): remove docs demo dayjs dependency

The docs valueFormat demo imported `dayjs` directly even though the docs
package does not declare it as a dependency. That caused `@vben/docs:build`
to fail in CI during VitePress bundling. This change removes the direct
import, keeps the preview formatter generic for day-like values, and drops
the docs-only preset button that required constructing dayjs instances.

Constraint: Docs build must succeed without adding new package dependencies
Constraint: Playground example should remain unchanged and fully interactive
Rejected: Add dayjs to docs dependencies | unnecessary for a small display demo
Rejected: Externalize dayjs in VitePress build | hides a package boundary issue
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Docs demos should avoid imports only available through transitive deps
Tested: pnpm exec eslint docs/src/demos/vben-form/value-format/index.vue
Tested: pnpm --dir docs run build
Not-tested: No browser-side manual verification of the docs demo in this session

---------

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-04-13 11:22:04 +08:00
Caisin
6be3a0e204 feat(common-ui): add labelFn support to ApiComponent (#7801)
* feat: allow api-component labels to be derived from option data

ApiComponent already normalizes option records into the label/value shape used by
consuming controls, but label text could only come from a single field. Add
labelFn so callers can build labels from the full option record while keeping
labelField as the fallback path.

This keeps the change inside the existing component instead of introducing a
wrapper, and it also normalizes direct options through the same transform path
as API-loaded options for consistent behavior.

Constraint: Must extend the existing ApiComponent API instead of adding a second
Constraint: wrapper component
Rejected: Add a separate ApiLabelComponent wrapper |
Rejected: extra surface area for one option-mapping concern
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep labelFn as a presentation transform and preserve labelField
Directive: fallback for existing callers
Tested: pnpm exec eslint api-component.vue index.ts types.ts
Tested: pnpm exec vue-tsc --noEmit -p packages/effects/common-ui/tsconfig.json
Not-tested: runtime integration in consuming select/tree-select components

* Update packages/effects/common-ui/src/components/api-component/api-component.vue

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-12 14:29:18 +08:00
过冬
a9b76ba2ed fix: antdv-next message/notification 跟随暗色主题 (#7799) 2026-04-12 11:51:23 +08:00
Jin Mao
53ccec1d80 fix: 修复VITE_APP_TITLE变量替换语法
- 将index.html中的<%= VITE_APP_TITLE %>替换为%VITE_APP_TITLE%
- 更新web-antd、web-antdv-next、web-ele、web-naive、web-tdesign应用
- 修改文档中loading组件的VITE_APP_TITLE引用方式
- 修复vite-config插件中默认加载模板的变量语法
- 统一所有应用和模板中的环境变量引用格式
2026-04-11 14:29:18 +08:00
Jin Mao
4af5d6152b chore: fix actions error 2026-04-11 14:13:13 +08:00
xingyu4j
307781f437 chore: update deps 2026-04-10 22:16:33 +08:00
xingyu4j
1326994d8e fix: tailwindcss lint config 2026-04-10 22:14:09 +08:00
xingyu4j
fd70a3f3e0 fix: lint 2026-04-10 22:01:01 +08:00
xingyu4j
298930b0d7 chore: remove vite-plugin-html 2026-04-10 22:00:33 +08:00
xingyu4j
54d95b8761 fix: check deps 2026-04-10 21:23:24 +08:00
xingyu4j
4a16040d3e chore: update deps 2026-04-10 21:18:26 +08:00
xingyu4j
ee95548340 fix: tailwindcss lint 2026-04-10 21:13:04 +08:00
xingyu4j
320e687bad fix: ts config 2026-04-10 21:08:54 +08:00
Jin Mao
ad43c6817e fix: 配置 TypeScript 构建根目录
- 添加 rootDir 编译选项指向 ./src 目录
- 保持现有编译配置不变
- 排除测试文件和 node_modules 目录
2026-04-09 14:48:26 +08:00
Jin Mao
c8747c079d chore: update deps 2026-04-08 18:25:39 +08:00
dullathanol
224bfe7fcb chore: 修正注释 2026-04-08 10:19:53 +08:00
dullathanol
f443bfbc7b fix: tailwindcss config 2026-04-08 10:11:05 +08:00
过冬
195b2ea0d2 Merge branch 'vbenjs:main' into main 2026-04-08 09:34:24 +08:00
Jin Mao
4150479549 chore: fix lint 2026-04-08 07:20:52 +08:00
dullathanol
5ebf513498 fix: 修正 Modal/Drawer 中 loading 属性注释 2026-04-07 12:28:57 +08:00
dullathanol
4e4ffc439c feat: 支持 overflow 配置以允许拖拽超出可视区 2026-04-07 11:41:39 +08:00
dullathanol
ad7ed50b52 fix: 弹窗组件拖拽后全屏位置异常 2026-04-06 22:26:27 +08:00
Jin Mao
92f8916225 chore: fix lint
- 关闭 vitest/require-mock-type-parameters 规则
2026-04-06 21:20:53 +08:00
dullathanol
7e4edd270d fix: 补全 ComponentPropsMap 与 Vxe 表格表单链路的类型 2026-04-05 19:03:03 +08:00
dullathanol
332ff44219 fix: 修复 FormField 在 SFC 中的运行时异常 2026-04-05 03:05:01 +08:00
dullathanol
834ce3efc0 fix: 修复部分情况 component 类型丢失问题 2026-04-05 01:59:17 +08:00
dullathanol
5211f5065d feat: 表单 Schema 支持组件 Props 映射泛型,同步适配VxeGrid 2026-04-04 23:40:27 +08:00
dullathanol
96d6f89732 refactor: 简化 componentProps 回调的类型写法 2026-04-03 15:02:32 +08:00
dullathanol
6ab06584eb fix: 函数式 componentProps 按已注册 component 的 Props 校验返回值 2026-04-03 13:36:03 +08:00
dullathanol
a6433c2b50 feat: Schema 中 componentProps 随注册组件联动类型提示 2026-04-03 01:39:49 +08:00
墨苒孤
128a131797 fix(form): 修复表单示例中 switch 组件无法切换的问题 (#7636) (#7763) 2026-04-02 18:18:56 +08:00
橙子
c775d7ed80 fix: interface DropdownMenuProps don‘t have key prop (#7757) 2026-04-02 08:33:26 +08:00
HaroldZhangCode91
b8b4308e1c feat: fix oxlint error for oxlint upgrade (#7756)
1. remove unknown rule out of oxlint
2. add the corresponding back to eslint-config
3. fixed the eslint error for package.json
2026-04-01 19:28:57 +08:00
墨苒孤
80d6e2255f fix: make search case-insensitive (#7689) (#7755) 2026-04-01 19:17:36 +08:00
橙子
4e0968d4b7 perf: replace onUnMounted to tryOnScopeDispose (#7747)
* perf: replace `onUnMounted` to `tryOnScopeDispose`

* perf: replace `onUnMounted` to `tryOnScopeDispose`
2026-04-01 10:30:54 +08:00
Jin Mao
44a5809a46 chore: update deps 2026-04-01 08:10:49 +08:00
xingyu4j
2428fb1407 fix: extension-document 2026-03-30 19:50:44 +08:00
xingyu4j
bb78882f72 feat(@vben/plugins): add tiptap rich text editor 2026-03-30 19:36:29 +08:00
xingyu4j
df88a23102 chore: typescript config is expired‌ 2026-03-30 18:26:07 +08:00
xingyu4j
ca5f360231 chore: update deps 2026-03-30 18:24:25 +08:00
Anonymouscen
147b50ec45 chore: 修复名称错误问题,帐户改为账户 (#7735) 2026-03-29 14:17:00 +08:00
橙子
34439dce4e fix: history search can not remove (#7732) 2026-03-29 14:16:32 +08:00
Jin Mao
9a22027b35 chore: 更新 GitHub Actions 依赖版本
- 将 pnpm/action-setup 从 v4 升级到 v5
- 将 release-drafter/release-drafter 从 v6 升级到 v7
- 更新所有工作流中的依赖版本以确保兼容性
2026-03-25 17:58:47 +08:00
Jin Mao
282a102826 chore: fix lint 2026-03-25 17:31:33 +08:00
Jin Mao
417e6c2ade chore: fix lint && typecheck 2026-03-25 16:33:41 +08:00
Jin Mao
9d69d7f46c Merge branch 'main' into chore/plugins 2026-03-25 15:19:21 +08:00
Jin Mao
87d1593a1f refactor(effects): 扩展 echarts 类型定义并优化插件配置合并逻辑
- 添加 PieSeriesOption 和 RadarSeriesOption 到 echarts 类型定义
- 添加 LegendComponentOption 和 ToolboxComponentOption 组件选项
- 重构 providePluginsOptions 函数实现深合并逻辑
- 优化 vxe-table 初始化中的表单工厂优先级处理
- 调整 playground 中的 import 语句顺序和格式
2026-03-25 15:16:24 +08:00
过冬
7fbdf3d914 fix(@vben/common-ui): 修复 JsonViewer 在 Vite 下因 CJS 默认导出未解包导致的渲染失败 (#7728)
* fix: lint

* fix(@vben/common-ui): 修复 JsonViewer 在 Vite 下因 CJS 默认导出未解包导致的渲染失败
2026-03-25 14:54:14 +08:00
JyQAQ
65287cf4b7 feat: Dockerfile构建调整 (#7727)
Co-authored-by: 吉远 <jiyuan@txhmo.com>
2026-03-25 14:53:26 +08:00
Jin Mao
6da3017dcf feat: 插件新增依赖注入功能 2026-03-25 14:46:55 +08:00
Jin Mao
5c02057198 refactor(effects): 替换上下文创建逻辑为全局选项管理
- 移除 createContext 依赖并实现全局插件选项存储
- 添加 providePluginsOptions 函数用于提供插件配置
- 添加 injectPluginsOptions 函数用于注入插件配置
- 添加 resetPluginsOptions 函数用于重置插件配置
- 更新 package.json 导出配置添加主入口点定义
2026-03-25 14:42:40 +08:00
Jin Mao
a7ca7cdb9f refactor(vxe-table): 重构 useTableForm 函数实现并优化初始化逻辑
- 将 useTableForm 从箭头函数改为普通函数声明
- 简化表单工厂函数的获取逻辑,支持上下文注入
- 移除初始化时的重复上下文注入代码
- 改进错误提示信息的准确性
- 调整代码结构以提高可读性和维护性
- 将 SetupVxeTable 接口中的 useVbenForm 字段改为可选参数
2026-03-25 14:42:31 +08:00
Jin Mao
79408d406d feat: 添加插件模块导出
- 导出 types 模块
- 导出 plugins-context 模块
2026-03-25 13:33:12 +08:00
Jin Mao
e555f71bf8 feat(vxe-table): 集成表格插件并优化初始化配置
- 添加了完整的 vxe-table 插件功能实现
- 实现了插件上下文选项注入机制
- 重构了 useTableForm 工厂函数的初始化逻辑
- 支持通过参数或上下文注入 useVbenForm 函数
- 优化了组件导入和类型定义
- 添加了插件使用文档说明
- 移除了未使用的组件注释代码
- 统一了字符串引号格式为双引号
2026-03-25 13:32:21 +08:00
Jin Mao
4c320346c3 docs(motion): 添加 motion 插件文档
- 创建了 Motion 插件的 README.md 文件
- 添加了插件导出组件和类型的说明表格
- 提供了插件的基本使用示例代码
- 包含了 MotionOptions 和 MotionVariants 类型导入说明
2026-03-25 13:27:10 +08:00
Jin Mao
e5ec88169a refactor: 重构 ECharts 插件类型定义和导出结构
- 将 ECOption 类型定义移至独立的 types.ts 文件
- 修改 echarts.ts 文件导入 ECOption 类型而不是定义
- 更新 index.ts 添加 types 导出
- 移除 echarts.ts 中冗余的类型导入和定义
- 添加完整的 README.md 文档说明插件使用方法
- 优化代码组织结构提高可维护性
2026-03-25 13:27:02 +08:00
Jin Mao
914711ae04 feat: 添加插件上下文和类型定义
- 创建了插件选项的 createContext 功能
- 定义了 VbenPluginsOptions 接口结构
- 添加了表单、模态框、消息和组件的插件选项接口
- 提供了插件选项的注入和提供功能
2026-03-25 13:25:19 +08:00
Jin Mao
4c1e3b9548 Merge branch 'fork/Voidlurk/fix-default' 2026-03-24 10:36:40 +08:00
Jin Mao
9cd3987475 Merge branch 'main' into fix 2026-03-24 10:24:18 +08:00
xueyitt
47a853330d feat: ApiSelect增加shouldFetch控制,在api请求之前的判断是否允许请求的回调函数 (#7713) 2026-03-24 10:22:02 +08:00
xueyitt
2aced2f659 feat: 增加table 帮助信息help通过表单values动态展示内容 (#7712) 2026-03-24 10:20:43 +08:00
Jin Mao
cd955df02f chore: fix lint 2026-03-24 10:19:24 +08:00
Bk201
0a819df2bf fix bug
[Vue warn]: Invalid prop: custom validator check failed for prop "variant".
2026-03-24 03:01:00 +08:00
xingyu4j
67afcadcf0 fix: rollup -> rolldown 2026-03-23 17:51:46 +08:00
xingyu4j
1128ef5acd chore: update deps 2026-03-23 17:13:39 +08:00
雪忆天堂
6b3506f128 feat: table 类型VxeTableGridColumns替代VxeTableGridOptions['columns']魔法值写法 2026-03-23 10:06:35 +08:00
雪忆天堂
5613dcef99 feat: table允许通过props动态变化data数据 2026-03-23 10:05:32 +08:00
MistyMoon
3528517fe0 fix(project): fix sub sidebar theme in two-column menu (#7708)
- Reset light tokens for nested sub sidebars.
- Align the extra title logo theme with sidebarThemeSub.
2026-03-22 09:15:56 +08:00
Jin Mao
2a5b520ec9 chore: update deps 2026-03-22 09:15:27 +08:00
lmx
e2fb3602f1 fix: 修复菜单项外部链接跳转问题
- 引入 isHttpUrl 工具函数用于判断 URL 类型
- 添加 isHttp 计算属性检测父路径是否为 HTTP 链接
- 修改菜单项渲染逻辑,对外部链接直接使用原地址跳转
- 调整 HTML 结构,将链接属性移到正确位置
- 确保内部路由和外部链接都能正常工作
2026-03-19 23:56:13 +08:00
lmx
da3580cbd7 Merge remote-tracking branch 'origin/main' 2026-03-19 22:07:20 +08:00
xingyu
0c300d040c fix: tailwindcss config (#7693)
* chore: update deps

* fix: tailwindcss config

* fix: lint

* fix: lint

* chore: update deps
2026-03-19 15:51:09 +08:00
橙子
d43a3729c3 fix: playground(drawer) comment (#7695) 2026-03-19 09:03:40 +08:00
Jin Mao
bed97a84d8 revert: "fix: sass-embedded@1.98.0 在 macOS 13 会直接崩 (#7692)" 2026-03-19 09:02:28 +08:00
afe1
b908076846 fix: sass-embedded@1.98.0 在 macOS 13 会直接崩 (#7692)
* fix: catelog

* fix: system
2026-03-18 20:18:25 +08:00
Noah Lan
885a0a9a00 fix: build.mjs commands could not be executed correctly. (#7682)
* fix: Fix issue where commands could not be executed correctly when they contained spaces

* chore: oxfmt
2026-03-17 18:59:35 +08:00
Jin Mao
340baf4f0b chore: 处理合并的一些问题 2026-03-16 20:50:01 +08:00
Jin Mao
82cda0edaa Merge branch 'fork/xingyu4j/tsdown'
# Conflicts:
#	pnpm-lock.yaml
2026-03-16 20:36:27 +08:00
Jin Mao
9fe875355a fix: 修复构建脚本中的进程执行问题
- 移除平台特定的 pnpm 命令路径检测逻辑
- 统一使用 'pnpm' 命令执行
- 启用 shell 模式以正确处理命令执行
- 确保子进程继承正确的标准输入输出流
2026-03-16 20:30:27 +08:00
Jin Mao
5f21bd2036 Merge branch 'fork/jyqwq/feature/antd上传组件支持拖拽排序' 2026-03-16 19:54:08 +08:00
Sun
5b5ea6d2d8 chore: Configure the ESLint auto-repair feature (#7670) 2026-03-16 18:26:42 +08:00
JyQAQ
3dcfd23036 perf: 裁剪组件默认输出格式调整 (#7673)
Co-authored-by: 吉远 <jiyuan@txhmo.com>
2026-03-16 18:25:04 +08:00
xingyu
186914bcac fix: vxe i18n (#7675)
* chore: engines node

* chore: update deps

* fix: oxlint

* chore: fix lint issues

* chore: update deps

* fix: vxe i18n
2026-03-16 18:24:28 +08:00
吉远
4b3205fee8 feat: antd Upload 组件上传文件组支持拖拽排序 2026-03-16 15:01:43 +08:00
lmx
e4453841db fix: 修复在vue-router 的模式hash复制路径不对 2026-03-16 01:32:11 +08:00
xingyu4j
32db4cbd11 fix: build warn 2026-03-15 23:11:59 +08:00
xingyu4j
5558249cd3 chore: unbuild 2026-03-15 23:11:41 +08:00
xingyu4j
86b636ae54 fix(@vben/vite-config): externalize node utils dependency 2026-03-15 22:47:28 +08:00
xingyu4j
c9f7154524 chore(tsdown): remove unbuild leftovers 2026-03-15 22:04:48 +08:00
xingyu4j
d72f872369 refactor(tsdown): migrate styled ui-kit packages 2026-03-15 21:42:44 +08:00
xingyu4j
b300011d07 refactor(tsdown): migrate ui-kit vue packages 2026-03-15 21:30:13 +08:00
xingyu4j
3946253d6e chore(tsdown): align stub scripts and package exports 2026-03-15 21:17:41 +08:00
xingyu4j
11fc367845 chore: migrate vite build to tsdown 2026-03-15 21:04:12 +08:00
xingyu4j
bdc65cc250 chore: update deps 2026-03-15 21:03:41 +08:00
xingyu4j
70dad0f600 fix(node-utils): avoid find-up sync API in monorepo root lookup 2026-03-15 20:50:07 +08:00
xingyu4j
26e9aa244b fix(vite): adapt rolldown workspace resolution 2026-03-15 20:27:01 +08:00
xingyu4j
913f77fd2f chore(pnpm): sync lockfile for tsdown migration 2026-03-15 19:41:17 +08:00
xingyu4j
dba774e1c7 chore(vsh): migrate build to tsdown 2026-03-15 19:41:00 +08:00
xingyu4j
af09d652a3 chore(turbo-run): migrate build to tsdown 2026-03-15 19:40:54 +08:00
xingyu4j
0babdfbc44 chore(core-preferences): migrate build to tsdown 2026-03-15 19:40:48 +08:00
xingyu4j
f154d53be9 chore(core-composables): migrate build to tsdown 2026-03-15 19:40:42 +08:00
xingyu4j
ed3cd2fe3b chore(core-typings): migrate build to tsdown 2026-03-15 19:40:36 +08:00
xingyu4j
59912a00bc chore(core-shared): migrate build to tsdown 2026-03-15 19:40:29 +08:00
xingyu4j
675d8b0179 chore(core-icons): migrate build to tsdown 2026-03-15 19:40:17 +08:00
xingyu4j
a1ca296fc0 chore(node-utils): migrate build to tsdown 2026-03-15 19:40:09 +08:00
xingyu4j
c1b1fe90fd chore(oxlint-config): migrate build to tsdown 2026-03-15 19:39:59 +08:00
xingyu4j
30b5610a73 chore(oxfmt-config): migrate build to tsdown 2026-03-15 19:39:51 +08:00
xingyu4j
db9b9df8f7 chore(eslint-config): migrate build to tsdown 2026-03-15 19:39:43 +08:00
xingyu4j
ae6a75e913 build: migrate core ts packages to tsdown 2026-03-15 18:13:49 +08:00
xingyu
37d72c1628 fix: oxlint config (#7661)
* chore: engines node

* chore: update deps

* fix: oxlint

* chore: fix lint issues
2026-03-15 17:41:47 +08:00
xingyu4j
ab3e6bb37c chore: fix lint issues 2026-03-15 16:35:34 +08:00
xingyu4j
9ddb899a1a fix: oxlint 2026-03-15 16:23:18 +08:00
xingyu4j
1f0cda8aee chore: update deps 2026-03-15 12:35:42 +08:00
xingyu4j
90ae85317c chore: engines node 2026-03-15 12:33:23 +08:00
Jin Mao
a8ae891aff chore: update pnpm-lock 2026-03-15 03:57:55 +08:00
Jin Mao
1f2df3e944 Merge branch 'fork/Lmx1220/main'
# Conflicts:
#	pnpm-lock.yaml
2026-03-15 03:53:43 +08:00
Jin Mao
e39a432210 Merge branch 'fork/caodachen/fix_useEcharts' 2026-03-15 03:50:21 +08:00
xingyu4j
6b3bcee582 docs(@vben/docs): sync component docs with current APIs 2026-03-14 21:34:48 +08:00
xingyu4j
6c274b75b8 docs(@vben/docs): align guide docs with current tooling 2026-03-14 21:33:55 +08:00
xingyu4j
278032c94b docs: remove docs 2026-03-14 20:29:49 +08:00
xingyu4j
23a8982f5c chore: add prepare 2026-03-14 20:19:34 +08:00
xingyu4j
5df6c32d04 fix: lint 2026-03-14 20:14:35 +08:00
xingyu4j
7cae330c3c chore: deps 2026-03-14 19:48:49 +08:00
xingyu4j
100aaa4cee chore: vsh lint 2026-03-14 19:48:40 +08:00
xingyu4j
ead0b73e7b fix: lint 2026-03-14 19:47:02 +08:00
xingyu4j
2ace846e38 chore: recommend vscode yaml extension 2026-03-14 19:41:28 +08:00
xingyu4j
1d98393f0c chore: recommend vscode eslint extension 2026-03-14 19:39:37 +08:00
xingyu4j
c48ee2a364 revert: restore vscode extensions comments 2026-03-14 19:38:09 +08:00
xingyu4j
95d1e8432f fix: surface eslint diagnostics in vscode 2026-03-14 19:36:27 +08:00
xingyu4j
4d59ac78bd fix: lint 2026-03-14 19:34:22 +08:00
xingyu4j
f1143e134e fix: match root json files in oxfmt overrides 2026-03-14 19:33:55 +08:00
xingyu4j
e3e869faee fix: align oxfmt json commas with lint 2026-03-14 19:31:01 +08:00
xingyu4j
8350e72393 fix: align json formatter with lint rules 2026-03-14 19:28:25 +08:00
xingyu4j
15f74b9d97 refactor: drop unused turbo eslint shim 2026-03-14 19:20:39 +08:00
xingyu4j
55b54e24fe refactor: migrate command lint to oxlint 2026-03-14 19:13:50 +08:00
xingyu4j
46b4ce81e4 refactor: shrink eslint fallback layer 2026-03-14 19:10:22 +08:00
xingyu4j
7a723d03d0 fix: tailwindcss 2026-03-14 18:48:30 +08:00
xingyu4j
9d6fbfd0d6 refactor: replace simple px utility styles 2026-03-14 18:43:00 +08:00
xingyu4j
8fd6bf47b1 revert: restore px-based calc utilities 2026-03-14 18:36:31 +08:00
xingyu4j
f25f3a34d0 refactor: replace px calc spacing utilities 2026-03-14 18:31:35 +08:00
xingyu4j
2823848fae refactor: migrate spacing utilities to tailwind v4 syntax 2026-03-14 18:27:16 +08:00
xingyu4j
b9467b2bc3 chore: configure tailwind v4 dynamic spacing 2026-03-14 18:14:44 +08:00
xingyu4j
fa190e0975 chore: checkpoint tailwind spacing updates 2026-03-14 18:11:08 +08:00
xingyu4j
90dc8cf997 chore: update deps 2026-03-14 17:52:40 +08:00
Jin Mao
a6a6efdf59 chore: release 5.7.0
- 更新 backend-mock 包版本
- 更新 web-antd 包版本
- 更新 web-antdv-next 包版本
- 更新 web-ele 包版本
- 更新 web-naive 包版本
- 更新 web-tdesign 包版本
- 更新 docs 包版本
- 更新 commitlint-config 包版本
- 更新 eslint-config 包版本
- 更新 oxfmt-config 包版本
- 更新 oxlint-config 包版本
- 更新 stylelint-config 包版本
- 更新 node-utils 包版本
- 更新 tsconfig 包版本
- 更新 vite-config 包版本
- 更新 @core/base/design 包版本
- 更新 @core/base/icons 包版本
- 更新 @core/base/shared 包版本
- 更新 @core/base/typings 包版本
- 更新 @core/composables 包版本
- 更新 @core/preferences 包版本
- 更新 @core/ui-kit/form-ui 包版本
- 更新 @core/ui-kit/layout-ui 包版本
- 更新 @core/ui-kit/menu-ui 包版本
- 更新 @core/ui-kit/popup-ui 包版本
- 更新 @core/ui-kit/shadcn-ui 包版本
- 更新 @core/ui-kit/tabs-ui 包版本
- 更新 constants 包版本
- 更新 access 包版本
- 更新 common-ui 包版本
- 更新 hooks 包版本
- 更新 layouts 包版本
- 更新 plugins 包版本
- 更新 request 包版本
- 更新 icons 包版本
- 更新 locales 包版本
- 更新 preferences 包版本
- 更新 stores 包版本
- 更新 styles 包版本
- 更新 types 包版本
- 更新 utils 包版本
- 更新 playground 包版本
- 更新 turbo-run 包版本
- 更新 vsh 包版本
- 更新根目录包版本
2026-03-14 09:14:23 +08:00
xingyu4j
8043faf6c7 docs: remove doc 2026-03-14 00:18:54 +08:00
xingyu4j
ebed9e64ed fix: lint 2026-03-14 00:17:06 +08:00
xingyu4j
913636ae44 refactor: simplify oxc eslint compatibility 2026-03-14 00:16:27 +08:00
xingyu4j
7b064e9f33 chore: vsh lint 2026-03-13 23:41:17 +08:00
xingyu4j
16da0eaca3 fix: vsh lint 2026-03-13 23:31:19 +08:00
xingyu4j
6acfee2737 fix: vsh lint 2026-03-13 23:26:29 +08:00
xingyu4j
92abf7edaa chore: oxlint-tsgolint 2026-03-13 23:22:52 +08:00
xingyu4j
395babc1f5 feat: tsgolint 2026-03-13 23:13:10 +08:00
xingyu4j
68cde54bad feat: add tsgolint 2026-03-13 23:13:01 +08:00
xingyu4j
c7d7529c00 chore: ts 2026-03-13 23:07:04 +08:00
xingyu4j
748f60c7bb chore: lint config 2026-03-13 22:12:15 +08:00
xingyu4j
ffee62e940 chore(vscode): update workspace editor settings 2026-03-13 22:02:50 +08:00
xingyu4j
a0ea221131 style(common-ui): normalize generic formatting 2026-03-13 21:57:18 +08:00
xingyu4j
2846bcb84e fix(common-ui): guard resize drag start state 2026-03-13 21:56:53 +08:00
xingyu4j
542ed6c08f refactor: rename formatter utilities 2026-03-13 21:56:23 +08:00
xingyu4j
6dabb848a5 build: migrate formatting pipeline to oxfmt 2026-03-13 21:56:08 +08:00
xingyu4j
de0181e0d9 fix: lint 2026-03-13 20:58:07 +08:00
xingyu4j
a850d426ef chore: fix lint and typecheck issues 2026-03-13 20:57:52 +08:00
xingyu4j
771277d5d9 fix: align oxlint compat config typing 2026-03-13 20:28:56 +08:00
xingyu4j
20b4f5c99f chore: oxlint config 2026-03-13 20:26:10 +08:00
xingyu4j
e7fa87b301 chore: finalize oxlint migration config 2026-03-13 20:25:25 +08:00
xingyu4j
40c66958bc chore: remove un use deps 2026-03-13 15:59:04 +08:00
xingyu4j
600fc71aed fix: eslint 2026-03-13 15:58:53 +08:00
xingyu4j
443e4b04cd chore: update vite 8 2026-03-13 15:51:28 +08:00
Lmx1220
556a3c0fab Update pnpm-lock.yaml 2026-03-13 15:25:14 +08:00
Lmx1220
1eca52f962 Update pnpm-lock.yaml
更新到使用vue3版本
2026-03-13 15:20:58 +08:00
Lmx1220
e21adb395b Merge branch 'main' into main 2026-03-13 15:08:24 +08:00
xingyu4j
0e4bf80bf4 chore: update deps 2026-03-13 10:33:23 +08:00
cdc
107750971b fix: fix useEcharts 2026-03-10 21:48:33 +08:00
橙子
24e1be47ca fix: fix component type (#7601) 2026-03-10 05:11:06 +08:00
Mr. Xie
7e0978c764 fix: 修复验证码登录发送逻辑,未校验手机号或发送失败仍开始倒计时的问题 (#7616) 2026-03-10 05:10:34 +08:00
Leo
83a0c9662d fix: 修复路由重复 (#7590)
* fix: 修复路由重复

优化mixed模式路由合并逻辑。以backend 为基础,并从frontend补充

* fix: 修复名称冲突时子项合并顺序/覆盖(后端子项可能会丢失)。

* fix: 优化可访问性判断逻辑

* fix: error Forbidden non-null assertion

* refactor(access): 调整可访问性判断逻辑
2026-03-10 05:09:48 +08:00
xingyu
a4736a49f8 feat: migrate to Tailwind CSS v4 (#7614)
* chore: update deps

* feat: use jsonc/x language

* chore: update eslint 10.0

* fix: no-useless-assignment

* feat: add CLAUDE.md

* chore: ignore

* feat: claude

* fix: lint

* chore: suppot eslint v10

* fix: lint

* fix: lint

* fix: type check

* fix: unit test

* fix: Suggested fix

* fix: unit test

* chore: update stylelint v17

* chore: update all major deps

* fix:  echarts console warn

* chore: update vitest v4

* feat: add skills ignores

* chore: update deps

* chore: update deps

* fix: cspell

* chore: update deps

* chore: update tailwindcss v4

* chore: remove postcss config

* fix: no use catalog

* chore: tailwind v4 config

* fix: tailwindcss v4 sort

* feat: use eslint-plugin-better-tailwindcss

* fix: Interference between enforce-consistent-line-wrapping, jsx-curly-brace-presence and Prettier

* fix: Interference between enforce-consistent-line-wrapping, jsx-curly-brace-presence and Prettier

* fix(lint): resolve prettier and better-tailwindcss formatting conflicts

* fix(tailwind): update theme references and lint sources

* style(format): normalize apps docs and playground vue files

* style(format): normalize core ui-kit components

* style(format): normalize effects ui and layout components
2026-03-10 05:08:45 +08:00
zouawen
aa7d8630b5 fix: 侧边菜单栏拖拽优化 (#7606)
* fix: 拖拽使用遮罩层实现,使得拖拽到min或max临界值时cursor显示not-allowed,同时拖拽线条颜色变浅,类似于disabled,提升用户体验

* fix: 修复代码审查建议;修复lint和test报错

* fix: 修复遮罩层挡住hover:bg-primary视觉效果问题
2026-03-07 05:32:09 +08:00
lmx
36313f378e chore: update package.json and cspell.json 2026-03-04 19:17:33 +08:00
lmx
45054d3238 chore: update pnpm-lock.yaml 2026-03-04 19:03:41 +08:00
lmx
173e6b08c9 fix: 修复执行: check:cspell 命令路径参数传入没有转义导致检测路径失效。添加菜单右键功能。优化:多余监听 activePath 变化,自动滚动到激活项 watch 2026-03-04 18:25:15 +08:00
zouawen
2a86404ba5 fix: 修复混合双列布局侧边栏拖拽线条位置显示bug,同步修复普通布局和混合双列布局切换时width计算导致侧边栏宽度显示异常问题,新增普通布局和混合双列布局侧边栏菜单折叠状态同步 (#7596) 2026-03-02 15:31:29 +08:00
han
b8a0199cde feat(preferences): add toggle for copy preferences button (#7594)
Co-authored-by: hl <hl@nmcsoft.com>
2026-03-02 15:30:38 +08:00
Bryan Qiu
a46ed55a86 fix: bump version to 5.6.0 (#7592) 2026-03-02 04:22:21 +08:00
Jin Mao
1a9fbddef4 Merge branch 'main' into main 2026-02-28 12:04:48 +08:00
zouawen
1209aaafb4 fix: 修复lint报错 2026-02-28 11:25:08 +08:00
zouawen
8e71261d49 fix: 侧边栏菜单拖拽功能在设置内增加开关 2026-02-28 11:19:24 +08:00
dependabot[bot]
49e45eab54 chore(deps): bump vue-router from 4.6.4 to 5.0.3 (#7583)
Bumps [vue-router](https://github.com/vuejs/router) from 4.6.4 to 5.0.3.
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/compare/v4.6.4...v5.0.3)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-27 17:06:18 +08:00
Jin Mao
bd22793ceb feat: add the attribute routeCached to route to control cache the DOM corresponding to the route 2026-02-27 16:04:01 +08:00
zouawen
b2013436c5 fix: 优化最大值限制 2026-02-27 11:12:51 +08:00
zouawen
cc808cb8c5 fix: 优化最小值限制 2026-02-27 11:07:28 +08:00
zouawen
afffc4b3f0 fix: 优化侧边栏拖拽逻辑,支持展开和折叠 2026-02-27 10:54:15 +08:00
zouawen
99710ef9dc feat: 优化侧边栏拖拽逻辑 2026-02-26 18:11:53 +08:00
zouawen
3d4ae04d9b Merge branch 'main' into main 2026-02-26 10:20:32 +08:00
zouawen
707b391449 feat: 侧边栏宽度拖拽改为composable实现,同时修复tabbar.ts文件lint报错 2026-02-26 10:09:57 +08:00
ming4762
45b843f344 fix: fix bug where renderEcharts gets stuck in a dead loop (#7561)
* 触发条件:echart所在页面开启keepalive 在其他页面切换颜色模式
2026-02-26 06:21:08 +08:00
Wu Clan
191fd90f06 chore: 更新表单描述显示样式 (#6938) 2026-02-26 06:17:04 +08:00
moil-xm
05920cd66d feat(vite-config): vite export typing (#7569)
* feat(vite-config): vite export typing

* feat(vite-config): add type

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2026-02-26 06:14:12 +08:00
Jin Mao
01508d5e42 fix: fix lint 2026-02-26 05:45:36 +08:00
zouawen
57cf6cbc9e feature: 简易版菜单宽度拖拽功能 2026-02-25 17:50:22 +08:00
AxiosLeo
03ebbea46a fix(menu): update hover color variable to use the correct reference (#7544)
* fix(menu): update hover color variable to use the correct reference

Medium Severity

In the horizontal .is-light menu section, --menu-item-hover-color is set to hsl(var(--menu-item-color)), but --menu-item-color is already defined as hsl(var(--accent-foreground)). This results in hsl(hsl(...)) at computed-value time, which is invalid CSS. The non-horizontal .is-light block correctly uses var(--menu-item-color) without the extra hsl() wrapper.

* fix(menu): simplify hover styles by removing redundant nested hover rules

Low Severity

The SCSS &:not(.is-active):hover { &:hover { ... } } compiles to a :hover:hover pseudo-class chain, which is functionally identical to a single :hover. The inner &:hover nesting is redundant and adds unnecessary complexity compared to placing styles directly inside the &:not(.is-active):hover block.
2026-02-12 22:22:53 +08:00
zouawen
8e7a5d1ec3 fix: Fix layout change, ensure div[ref="asideRef"] is contained within <aside> (#7551) 2026-02-12 22:22:34 +08:00
AxiosLeo
aa74a2535b fix(tabbar): visitHistory field (#7543)
High Severity

The visitHistory field is a Stack<string> class instance persisted to sessionStorage via pinia-plugin-persistedstate. There's no custom serializer or hydration hook. When the page reloads, JSON.parse(JSON.stringify(stack)) produces a plain object {dedup, items, maxSize} that lacks all Stack methods (push, pop, remove, retain, etc.) and the size getter. Pinia's $patch replaces the Stack instance with this plain object, so subsequent calls like this.visitHistory.push(...) will throw a TypeError.
2026-02-11 16:09:37 +08:00
zouawen
32379ba4b7 fix: 双列菜单模式下新增深色侧边栏和深色侧边栏子栏 (#7542)
* fix: 双列菜单模式下新增深色侧边栏和深色侧边栏子栏

* fix: 修复报错 config.test.ts.snap

* fix: 修复lint报错

* fix: 修复侧边栏菜单文本内容溢出问题

* fix: 修复lint报错
2026-02-11 16:08:32 +08:00
moil-xm
7fe8d7b4be fix: ts 错误: 类型实例化过深,且可能无限 2026-02-10 16:13:36 +08:00
Bin
aace726a91 feat(playground): add antdv-next router link (#7532)
Co-authored-by: fuwb <fuwb@sunsharing.com.cn>
2026-02-10 13:09:34 +08:00
Jin Mao
e6f6e5464a Merge branch 'main' into main 2026-02-10 12:08:16 +08:00
Aliner
7d04b600fb fix: correct updateDate to updateData in the echarts hook (#7538)
* fix(@vben/plugins): Fixed the misspelling of the data update method name in the echarts hook

Correct updateDate to updateData, ensuring that the API method name is correct and consistent

* Revert "fix(@vben/plugins): Fixed the misspelling of the data update method name in the echarts hook"

This reverts commit 86d679cf25631bd1abd56d4f971e6db3a9b9d6d5.

* fix(@vben/plugins): fixed the misspelling of the data update method name in the echarts hook

Correct updateDate to updateData, ensuring that the API method name is correct and consistent
2026-02-10 11:19:45 +08:00
zouawen
463bfde2ac fix: config.test.ts.snap新增showRefresh参数 2026-02-10 08:50:06 +08:00
zouawen
893f74dc3e fix: 优化横向布局时菜单激活或聚焦时背景色,标签工具栏新增刷新按钮,其他样式优化 2026-02-09 16:32:02 +08:00
Jin Mao
8a215fbcc7 chore: release 5.6.0 2026-02-09 05:09:57 +08:00
Jin Mao
ac5e4c4722 chore: update deps 2026-02-09 04:52:06 +08:00
Jin Mao
04d01b0bab chore: fix lint 2026-02-09 04:49:06 +08:00
Jin Mao
cb1d7565a3 Merge branch 'fork/ffgenius/antd-vue-next' 2026-02-09 03:09:01 +08:00
Jin Mao
1d9b6407a4 chore: 更新开发环境端口号配置
- 将 VITE_PORT 从 5555 修改为 5999
- 保持其他环境变量配置不变
2026-02-09 03:04:42 +08:00
MistyMoon
22ed522711 feat: support menuVisibleWithForbidden in generate-routes-backend (#7526)
当后端菜单项 `meta.menuVisibleWithForbidden` 为 true 时,将其路由组件替换为 403 页,菜单仍展示该项,访问时展示 403,便于用户知悉功能并申请权限。
2026-02-09 02:44:29 +08:00
Jin Mao
a3598ef859 chore: fix lint 2026-02-09 02:42:50 +08:00
Jin Mao
6fe09ec2dd perf: optimize the closing jump logic of tabs 2026-02-09 02:36:38 +08:00
Jin Mao
57911d9e09 Merge branch 'tab-2026020401' of https://github.com/ming4762/smart-boot-ui-vben into ming4762-tab-2026020401 2026-02-09 02:36:04 +08:00
Bin
3aee283495 Revert "feat(web): cancel pnpm-lock.yaml submission"
This reverts commit 54b24c2677.
2026-02-08 23:14:31 +08:00
Bin
54b24c2677 feat(web): cancel pnpm-lock.yaml submission 2026-02-08 23:12:40 +08:00
Bin
8cadad0a1e feat(web): add antdv-next model 2026-02-08 23:00:19 +08:00
zhongming4762
633c5f3cda perf: optimize the closing jump logic of tabs
* 依据tab访问历史回退上一个tab,原逻辑是返回一下个 或 上一个
 * 支持在配置中开启或关闭
2026-02-08 20:50:54 +08:00
zhongming4762
a8431e2040 perf: optimize the closing jump logic of tabs
* 依据tab访问历史回退上一个tab,原逻辑是返回一下个 或 上一个
 * 支持在配置中开启或关闭
2026-02-08 20:36:32 +08:00
zhongming4762
7a2b916387 perf: optimize the closing jump logic of tabs
* 依据tab访问历史回退上一个tab,原逻辑是返回一下个 或 上一个
 * 支持在配置中开启或关闭
2026-02-08 20:36:16 +08:00
Jin Mao
f4dfb68b7b Merge branch 'MrLeo-main' 2026-02-06 15:41:55 +08:00
Jin Mao
8f4f27d860 Merge branch 'main' of https://github.com/MrLeo/vue-vben-admin into MrLeo-main 2026-02-06 15:39:48 +08:00
tikitoki
e9eab29953 fix:fix password input icon visual bug in certain browser (#7521)
Co-authored-by: nick8799981325 <zc1078134211@163.com>
2026-02-06 15:28:48 +08:00
Leo Caan (陈栋)
4f1eeb7da5 fix: 修复设置default-expanded-level后无法check更低层级节点 logic and tree value updates (#7155)
假设缺省展开2级,当check 3级节点时,会触发effectWatch重新收缩到2级,并丢失check操作check操作andling.
2026-02-06 12:55:14 +08:00
Leo
6fd426d719 fix: 当 showToolbar 为 false 时禁用工具栏(vxe-table),减少无 Toolbar 的 Gird 留白 2026-02-04 22:20:17 +08:00
zhongming4762
331da3c8c7 perf: optimize the closing jump logic of tabs
* 依据tab访问历史回退上一个tab,原逻辑是返回一下个 或 上一个
2026-02-04 19:29:33 +08:00
ming4762
c48943bc67 fix: fix Nested Objects dependencies not effective (#7345) 2026-01-31 16:44:20 +08:00
xingyu
7680b33b99 fix: #7140 (#7153)
* chore: add yaml eslint validate

* chore: update deps

* fix: unused ts lint

* fix: 弹窗只能点击一次 #7140

* chore: update actions/checkout v6

* chore: update node version v22.22.0
2026-01-28 18:05:20 +08:00
Jin Mao
bb5d75bc7e fix: 修复表单展开无效 (#7148)
- 修正模板中 ref 属性的引用名称
2026-01-27 11:35:50 +08:00
ming4762
528395e2c3 perf: optimizing hidden fields cannot trigger dependencies (#7142) 2026-01-26 16:12:26 +08:00
programmer
6a9012e5e4 chore: 给个人中心的2个按钮加上 i18n (#7138)
* fix: 个人中心按钮i18n

* fix: eslint format

* fix: 调整label宽度让英文显示在一行

* chore: 调整label小点

* fix: import

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2026-01-26 16:12:09 +08:00
橙子
6e8315ab40 fix: arguments order update (#7132)
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2026-01-26 16:11:37 +08:00
Jin Mao
7cb2699f19 chore: 更新pnpm工作区配置
- 移除 neverBuiltDependencies 配置
- 移除 peerDependencyRules.allowedVersions 配置
- 重新整理 overrides 和 catalog 部分
- 保持 @ast-grep/napi 等依赖的目录引用配置
- 维持 eslint 版本约束在目录顶层配置中
2026-01-25 19:55:53 +08:00
Jin Mao
4b5da81ba6 chore(deps): 更新项目依赖包版本
- 更新 @playwright/test 从 1.57.0 到 1.58.0
- 更新 @tanstack/vue-query 从 5.92.8 到 5.92.9
- 更新 cheerio 从 1.1.2 到 1.2.0
- 更新 eslint-config-turbo 从 2.7.5 到 2.7.6
- 更新 playwright 从 1.57.0 到 1.58.0
- 更新 turbo 从 2.7.5 到 2.7.6
- 更新 vxe-pc-ui 从 4.12.10 到 4.12.12
- 更新 @babel/helper-define-polyfill-provider 从 0.6.5 到 0.6.6
- 更新 @cspell/dict-fullstack 从 3.2.7 到 3.2.8
- 更新 @cspell/dict-git 从 3.0.7 到 3.1.0
- 更新 @cspell/dict-node 从 5.0.8 到 5.0.9
- 更新 @cspell/dict-npm 从 5.2.29 到 5.2.30
- 更新 @parcel/watcher 相关包从 2.5.4 到 2.5.6
- 更新 @tanstack/query-core 从 5.90.19 到 5.90.20
- 更新 babel-plugin-polyfill 相关包到最新版本
- 更新 baseline-browser-mapping 从 2.9.17 到 2.9.18
- 更新 caniuse-lite 从 1.0.30001765 到 1.0.30001766
- 更新 electron-to-chromium 从 1.5.277 到 1.5.278
- 更新 eslint-plugin-turbo 从 2.7.5 到 2.7.6
- 更新 playwright-core 从 1.57.0 到 1.58.0
- 更新 turbo 平台特定版本到 2.7.6
- 更新 undici 从 7.19.0 到 7.19.1
2026-01-25 15:05:14 +08:00
Jin Mao
6aca9a9c99 test(dom): 更新元素可见区域计算的测试用例
- 修正了getElementVisibleRect函数的期望值断言
- 将bottom值从800更正为0以匹配实际计算结果
- 将left值从1100更正为0以匹配实际计算结果
- 将right值从1000更正为0以匹配实际计算结果
- 将top值从900更正为0以匹配实际计算结果
2026-01-25 14:22:22 +08:00
xingyu4j
fa195fde8e fix: lint 2026-01-23 14:48:21 +08:00
xingyu4j
1057f2932b chore: update deps 2026-01-23 14:48:06 +08:00
Jin Mao
b9224fc379 Merge branch 'main' into fix 2026-01-23 13:48:54 +08:00
Jin Mao
57dd818170 Merge branch 'fork/kuchaguangjie/fix' 2026-01-23 13:47:54 +08:00
Jin Mao
49256ec1b7 Merge branch 'main' into fix 2026-01-23 13:46:59 +08:00
Jin Mao
f6f92e5403 Merge branch 'fork/kuchaguangjie/fix' 2026-01-23 13:45:38 +08:00
Jin Mao
613c311076 Merge branch 'fork/abcd0f/dev/sun-local' 2026-01-23 13:25:03 +08:00
Jin Mao
9ee7a7d9ff Merge branch 'fork/Child-qjj/patch-1' 2026-01-23 13:21:49 +08:00
橙子
44f8aed06d fix: timer not need reactivity (#7128) 2026-01-23 13:16:09 +08:00
Sun
d5d4a5c591 feat(effects-plugins): 添加 echarts 图表更新功能
新增 updateDate 方法用于更新 echarts 图表选项,支持合并配置、
完全替换和延迟更新等模式。该方法会在组件未初始化时自动执
行首次渲染,并能够合并全局配置如 backgroundColor 等选项。
2026-01-23 11:06:45 +08:00
yuhengshen
74381aa8c1 fix: 嵌套弹窗,错误 merge options (#7126) 2026-01-22 20:07:13 +08:00
橙子
203ee9b623 fix(@vben-core/shared): element outside viewport, the element visible rect each prop expect 0 (#7120)
* fix(@vben-core/shared): element outside viewport

* fix(@vben-core/shared): element outside viewport
2026-01-22 11:37:01 +08:00
JyQAQ
6c8c49966a Perf: 优化antd upload组件参数获取 (#7114)
* perf(antd upload params): 优化组件参数取值 确保不同调用场景配置参数可用

* perf(antd upload params): 优化组件参数取值 确保不同调用场景配置参数可用

* perf(antd upload params): 优化组件参数取值 确保不同调用场景配置参数可用

* perf(antd upload params): 优化组件参数取值 确保不同调用场景配置参数可用
2026-01-21 17:20:53 +08:00
Qiu
3862942e9f fix: chart instance disposal condition
dom has been disposed in vue3 v-if,but chartInstance exist
2026-01-21 11:47:01 +08:00
xingyu
8571fc43b0 Merge branch 'main' into fix 2026-01-19 15:28:12 +08:00
JyQAQ
59aabd956d Perf: Optimization of cropping component result acquisition & optimization of cropping frame prompts (#7111)
* perf(cropper): enhance image cropping functionality and add output type support

* perf(cropper): enhance image cropping functionality and add output type support
2026-01-19 14:18:36 +08:00
xingyu
9b09ba4483 Merge branch 'main' into fix 2026-01-19 10:54:43 +08:00
橙子
686c3f9208 docs(@vben-core/preferences): update comments (#7107) 2026-01-14 19:36:45 +08:00
MRSWC
8a7e2bd8e4 fix:修复默认默认首页如果携带参数时刷新页面参数丢失问题 (#7102)
Co-authored-by: chenwei <chenw@jiuzhekan.com>
2026-01-14 15:38:55 +08:00
JyQAQ
174c4ae749 fix(antd Upload onChange Event): rewrite onChange event to handle upl… (#7098)
* fix(antd Upload onChange Event): rewrite onChange event to handle upload success or error messages

* fix(antd Upload onChange Event): rewrite onChange event to handle upload success or error messages

* fix(antd Upload onChange Event): rewrite onChange event to handle upload success or error messages
2026-01-14 15:38:21 +08:00
JyQAQ
67da9417a8 feat(upload prop:crop,aspectRatio): from Upload component accept prop… (#7095)
* feat(upload prop:crop,aspectRatio): from Upload component accept prop crop,aspectRatio

* feat(upload prop:crop,aspectRatio): from Upload component accept prop crop,aspectRatio

* feat(upload prop:crop,aspectRatio): from Upload component accept prop crop,aspectRatio

* feat(upload prop:crop,aspectRatio): from Upload component accept prop crop,aspectRatio
2026-01-14 15:38:05 +08:00
ppxb
f4a4ced88d fix: header auto mode issue (#7096) 2026-01-12 21:40:26 +08:00
ppxb
19b2d7af41 fix: tdesign theme toggle and demos (#7087) 2026-01-10 14:11:08 +08:00
yuhengshen
343d8a1c1e fix: 切换时区后,页面不刷新 (#7085)
* fix: 切换时区后,页面不刷新

* fix: keep-alive 的页面,i18n 和 timezone 不更新
2026-01-10 14:10:27 +08:00
JyQAQ
9480f8272a feat(common-ui cropper): Implement the image cropping component VCropper (#7082)
* feat(common-ui cropper): Implement the image cropping component VCropper

* feat(common-ui cropper): Implement the image cropping component VCropper

* feat(common-ui cropper): Implement the image cropping component VCropper

* feat(common-ui cropper): Implement the image cropping component VCropper

* feat(common-ui cropper): Implement the image cropping component VCropper
2026-01-10 14:08:15 +08:00
ppxb
0d9e260a6a fix: vite.config.mts type error (#7081) 2026-01-10 14:07:28 +08:00
ppxb
51bca25345 fix(lint): pnpm format lint warning (#7080) 2026-01-10 14:06:03 +08:00
eric
694396dcfb refactor: move cleanup to finally block 2026-01-09 23:22:49 +08:00
eric
1cb53e943e refactor: 将跳转放到最后 2026-01-09 23:13:06 +08:00
eric
13c8318adc refactor: 1. 用 ref 包装 flag; 2. 在最后 清理 flag; 2026-01-09 23:05:05 +08:00
eric
48ed797055 fix: 防止 /logout 死循环 2026-01-09 22:38:11 +08:00
xingyu4j
3c2285141c chore: update deps 2026-01-06 13:58:42 +08:00
xingyu
49b884c0b1 Merge branch 'main' into fix 2026-01-06 13:50:26 +08:00
ppxb
24d20ca9ee refactor: preference manager and export (#7068)
* fix: preferences drawer outline z-index

* refactor: preferencesManager and exports
2026-01-06 12:42:32 +08:00
wyc001122
6f02181024 fix(layout): 修复双列模式下重复显示logo的问题(#7071) (#7072) 2026-01-05 21:13:06 +08:00
ppxb
ed3353a271 fix: preferences drawer outline z-index (#7067) 2026-01-04 14:44:33 +08:00
xingyu4j
965f5f96b7 chore: update deps 2026-01-04 11:03:19 +08:00
xingyu4j
61d9df7f58 feat: add cascader cspell:words 2026-01-04 11:00:07 +08:00
xingyu4j
231a5169ec fix: lint 2026-01-04 10:56:55 +08:00
xingyu4j
ce7b7b910a Merge branch 'main' of https://github.com/xingyu4j/vue-vben-admin into fix 2026-01-04 10:56:14 +08:00
JyQAQ
81a61558cb feat(upload prop:maxSize): from Upload component accept prop maxSize (AI prompt fixed) (#7059)
* feat(upload prop:maxSize): from component accept prop maxSize

* feat(upload prop:maxSize): from component accept prop maxSize

* feat(upload prop:maxSize): from component accept prop maxSize

* feat(upload prop:maxSize): from component accept prop maxSize
2026-01-03 13:19:40 +08:00
ppxb
7d2bc2e885 fix: dropdown raido menu type error (#7062)
* fix: dropdown raido menu type

* chore: format code
2026-01-02 14:25:19 +08:00
luoqiz
89b237f6b4 feat: 添加上下文菜单演示,添加菜单项隐藏性 (#7057)
Co-authored-by: luoqiz <851092732@qq.com>
2026-01-02 14:22:19 +08:00
JyQAQ
a1bb132233 feat(api-cascader): 添加联级组件ApiCascader (#7031) 2025-12-22 20:00:31 +08:00
zhenghaoyang24
022d538940 Fix formatting in thin.md for clarity (#7008)
修改一些语句错误
2025-12-22 19:58:05 +08:00
xueyitt
ccf70a1b76 feat: 修正菜单排序在二级菜单不生效问题 (#7007)
* treeUtil增加对树形结构数据进行递归排序

* 菜单sort排序各级菜单均生效
2025-12-22 19:57:21 +08:00
xingyu4j
af3fe53ec8 fix: type error 2025-12-22 17:50:06 +08:00
xingyu4j
e981fb159f chore: update deps 2025-12-22 17:49:51 +08:00
xingyu
79b9d55854 Merge branch 'main' into fix 2025-12-22 16:42:15 +08:00
xingyu4j
b2055a4457 chore: update deps 2025-12-17 13:47:37 +08:00
JyQAQ
1479f159aa feat(CellImage): CellImage组件支持图片属性写入 (#6992) 2025-12-06 10:12:58 +08:00
xingyu4j
7bf7e09002 fix: lint 2025-12-05 15:09:43 +08:00
xingyu4j
de8d39ffed chore: workspace file is deprecated 2025-12-05 15:07:39 +08:00
xingyu4j
543a7e3962 chore: update deps 2025-12-05 14:55:44 +08:00
xingyu4j
9dfe3f5af8 fix: type not find 2025-12-04 18:03:55 +08:00
xingyu4j
f11b08d8cb chore: update deps 2025-12-04 17:59:12 +08:00
xingyu4j
45b6f08984 chore: neverBuiltDependencies 2025-12-03 16:34:14 +08:00
xingyu4j
92a4676f8d chore: update version 2025-12-03 16:27:14 +08:00
xingyu4j
7bf7c0bb06 chore: remove unused deps 2025-12-03 16:26:58 +08:00
xingyu4j
8f8cf5b704 chore: update deps 2025-12-03 16:22:14 +08:00
xingyu4j
6be238430d chore: add cspell 2025-12-03 16:12:08 +08:00
xingyu4j
f77216d8f4 feat: lint add pnpm config 2025-12-03 16:11:51 +08:00
xingyu4j
d42a9b2409 feat: lint add yaml config 2025-12-03 16:01:27 +08:00
xingyu4j
6753834054 fix: lint 2025-12-03 15:37:33 +08:00
xingyu4j
77a4a64eb4 fix: stylelint 2025-12-03 15:37:20 +08:00
xingyu4j
49db40d557 feat: cspell sort 2025-12-03 15:37:04 +08:00
xingyu4j
0032c608f1 chore: update deps 2025-12-03 15:36:43 +08:00
xingyu4j
fa603b32b1 fix: locales 2025-12-03 13:51:30 +08:00
JyQAQ
9105d4d14a feat(api-component): api-component组件的options支持指定disabled值 (#6991) 2025-12-03 10:03:23 +08:00
luoqiz
c76db7d8d1 fix: 修复icon丢失根属性导致的样式错误 (#6986) 2025-12-01 09:51:27 +08:00
Jin Mao
6f39e9136e Merge branch 'main' into feature/antd上传组件支持调用Image组件查看图片 2025-11-24 21:59:34 +08:00
milletpeak
1f1ba16ead Merge branch 'main' into milletpeak-fontsize 2025-11-24 08:55:54 +08:00
panda7
b6edc5f574 fix: centered 为 true 时设置 draggable 无法拖拽 (#6948)
Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-11-24 08:38:10 +08:00
Jin Mao
8b0f138100 Merge branch 'main' into deps 2025-11-24 08:23:02 +08:00
ming4762
a810cd0b48 fix: fix IconPicker reporting an error when using search if no icon is found (#6944)
* 修复未搜索图标时分页报错的问题
 * 优化`IconPicker` 的分页逻辑,由total触发跳转到第一页,而不是用户控制
2025-11-24 07:56:55 +08:00
aonoa
b17fec41b0 fix: tree component cannot set a value (#6941)
Signed-off-by: aonoa <1991849113@qq.com>
2025-11-24 07:56:16 +08:00
Rex
5fcfabf1d4 fix: 修复菜单管理中标题栏样式异常问题 (#6934) 2025-11-24 07:00:08 +08:00
yuan.ji
1d77b018bb feat(function): add antd上传组件支持调用Image组件查看图片 2025-11-21 17:33:59 +08:00
米山
f7d9d1b1af chore: update package.json and app.vue imports, and ensure global styles are included 2025-11-19 11:13:06 +08:00
米山
aaf0274fe9 feat: add menu font size variable and update related components
- Introduced a new CSS variable `--menu-font-size` calculated from the base font size.
- Updated `PreferenceManager` to trigger CSS variable updates when `fontSize` is modified.
- Adjusted `updateCSSVariables` to set the new `--menu-font-size` based on the theme's font size.
- Ensured that the menu components utilize the updated font size with `!important` to maintain styling consistency.
2025-11-19 10:51:10 +08:00
米山
c142af482b fix: update snapshot for defaultPreferences immutability test to reflect fontSize change
- Adjusted the snapshot to ensure consistency with the updated defaultPreferences configuration, specifically retaining the fontSize property.
2025-11-19 10:19:16 +08:00
米山
cd7c11c7d0 fix: run 'pnpm format' update various components and improve layout structure
- Updated demo-preview and preview-group components for better error handling and layout.
- Enhanced drawer and modal components for improved auto-height functionality.
- Refactored layout components including header, footer, sidebar, and tabbar for better responsiveness and usability.
- Adjusted tooltip and help tooltip components for better user guidance.
- Fixed issues in various UI components to ensure consistent styling and functionality across the application.
2025-11-19 10:14:04 +08:00
milletpeak
fb8f36eeec Merge branch 'main' into milletpeak-fontsize 2025-11-19 09:41:55 +08:00
xingyu4j
9a4f0f6ab1 feat: Consider multi-line formatting for readability 2025-11-17 14:24:43 +08:00
xingyu4j
bed52983a0 fix: lint 2025-11-17 12:15:14 +08:00
xingyu4j
655ce2c2e8 chore: update node version >=20.12.0 2025-11-17 12:11:43 +08:00
xingyu4j
f841568e5a chore: update vue-tsc 2025-11-17 12:04:30 +08:00
xingyu4j
469697845c fix: sort 2025-11-17 11:21:49 +08:00
xingyu4j
273f3cbaf8 Merge branch 'main' of https://github.com/xingyu4j/vue-vben-admin into deps 2025-11-17 11:21:16 +08:00
xingyu4j
96f671908e chore: update deps 2025-11-17 11:17:47 +08:00
Jin Mao
f09aace765 fix: 更新依赖后的表格显示问题 2025-11-14 21:44:32 +08:00
Copilot
772529e2fb fix: rollback zod-defaults version to 0.1.3 (#6925)
* Initial plan

* fix: downgrade zod-defaults from 0.2.3 to 0.1.3 for Zod v3 compatibility

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
2025-11-14 16:16:45 +08:00
xingyu4j
eeff017b9f chore: add tdesign cspell 2025-11-14 10:22:18 +08:00
xingyu4j
22394ebdeb chore: move tdesign-vue-next to workspace 2025-11-14 10:21:48 +08:00
dependabot[bot]
ffbc9b22a7 chore(deps): bump the non-breaking-changes group across 1 directory with 26 updates (#6914)
Bumps the non-breaking-changes group with 20 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [vue](https://github.com/vuejs/core) | `3.5.23` | `3.5.24` |
| [@clack/prompts](https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts) | `0.10.1` | `0.11.0` |
| [@iconify/json](https://github.com/iconify/icon-sets) | `2.2.404` | `2.2.406` |
| [@pnpm/workspace.read-manifest](https://github.com/pnpm/pnpm) | `1000.2.5` | `1000.2.6` |
| [@tanstack/vue-query](https://github.com/TanStack/query/tree/HEAD/packages/vue-query) | `5.90.7` | `5.91.0` |
| [@tanstack/vue-store](https://github.com/TanStack/store/tree/HEAD/packages/vue-store) | `0.7.7` | `0.8.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.46.3` | `8.46.4` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.46.3` | `8.46.4` |
| [@vue/shared](https://github.com/vuejs/core/tree/HEAD/packages/shared) | `3.5.23` | `3.5.24` |
| [commitlint-plugin-function-rules](https://github.com/vidavidorra/commitlint-plugin-function-rules) | `4.1.0` | `4.1.1` |
| [eslint-config-turbo](https://github.com/vercel/turborepo/tree/HEAD/packages/eslint-config-turbo) | `2.6.0` | `2.6.1` |
| [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next) | `0.507.0` | `0.553.0` |
| [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) | `0.6.14` | `0.7.1` |
| [sass](https://github.com/sass/dart-sass) | `1.93.3` | `1.94.0` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.8.2` | `5.9.3` |
| [unplugin-element-plus](https://github.com/element-plus/unplugin-element-plus) | `0.10.0` | `0.11.1` |
| [vxe-pc-ui](https://github.com/x-extends/vxe-pc-ui) | `4.10.16` | `4.10.22` |
| [vxe-table](https://github.com/x-extends/vxe-table) | `4.17.10` | `4.17.14` |
| [zod-defaults](https://github.com/Ced-Sharp/zod-defaults) | `0.1.3` | `0.2.3` |
| [@ast-grep/napi](https://github.com/ast-grep/ast-grep) | `0.37.0` | `0.39.9` |



Updates `vue` from 3.5.23 to 3.5.24
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.5.23...v3.5.24)

Updates `@clack/prompts` from 0.10.1 to 0.11.0
- [Release notes](https://github.com/bombshell-dev/clack/releases)
- [Changelog](https://github.com/bombshell-dev/clack/blob/@clack/prompts@0.11.0/packages/prompts/CHANGELOG.md)
- [Commits](https://github.com/bombshell-dev/clack/commits/@clack/prompts@0.11.0/packages/prompts)

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

Updates `@pnpm/workspace.read-manifest` from 1000.2.5 to 1000.2.6
- [Release notes](https://github.com/pnpm/pnpm/releases)
- [Commits](https://github.com/pnpm/pnpm/commits)

Updates `@tanstack/vue-query` from 5.90.7 to 5.91.0
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/vue-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/vue-query@5.91.0/packages/vue-query)

Updates `@tanstack/vue-store` from 0.7.7 to 0.8.0
- [Release notes](https://github.com/TanStack/store/releases)
- [Commits](https://github.com/TanStack/store/commits/v0.8.0/packages/vue-store)

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

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

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

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

Updates `commitlint-plugin-function-rules` from 4.1.0 to 4.1.1
- [Release notes](https://github.com/vidavidorra/commitlint-plugin-function-rules/releases)
- [Changelog](https://github.com/vidavidorra/commitlint-plugin-function-rules/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vidavidorra/commitlint-plugin-function-rules/compare/v4.1.0...v4.1.1)

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

Updates `lodash.clonedeep` from 4.5.0 to 
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Updates `lodash.get` from 4.4.2 to 
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Updates `lodash.isequal` from 4.5.0 to 
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Updates `lodash.set` from 4.3.2 to 
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

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

Updates `prettier-plugin-tailwindcss` from 0.6.14 to 0.7.1
- [Release notes](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/compare/v0.6.14...v0.7.1)

Updates `sass` from 1.93.3 to 1.94.0
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.93.3...1.94.0)

Updates `typescript` from 5.8.2 to 5.9.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.2...v5.9.3)

Updates `unplugin-element-plus` from 0.10.0 to 0.11.1
- [Release notes](https://github.com/element-plus/unplugin-element-plus/releases)
- [Commits](https://github.com/element-plus/unplugin-element-plus/compare/v0.10.0...v0.11.1)

Updates `vxe-pc-ui` from 4.10.16 to 4.10.22
- [Release notes](https://github.com/x-extends/vxe-pc-ui/releases)
- [Commits](https://github.com/x-extends/vxe-pc-ui/commits)

Updates `vxe-table` from 4.17.10 to 4.17.14
- [Release notes](https://github.com/x-extends/vxe-table/releases)
- [Commits](https://github.com/x-extends/vxe-table/compare/4.17.10...4.17.14)

Updates `zod-defaults` from 0.1.3 to 0.2.3
- [Commits](https://github.com/Ced-Sharp/zod-defaults/commits)

Updates `@ast-grep/napi` from 0.37.0 to 0.39.9
- [Release notes](https://github.com/ast-grep/ast-grep/releases)
- [Changelog](https://github.com/ast-grep/ast-grep/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ast-grep/ast-grep/compare/0.37.0...0.39.9)

Updates `@vue/reactivity` from 3.5.23 to 3.5.24
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/commits/v3.5.24/packages/reactivity)

---
updated-dependencies:
- dependency-name: vue
  dependency-version: 3.5.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@clack/prompts"
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@iconify/json"
  dependency-version: 2.2.406
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@pnpm/workspace.read-manifest"
  dependency-version: 1000.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@tanstack/vue-query"
  dependency-version: 5.91.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@tanstack/vue-store"
  dependency-version: 0.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: "@vue/shared"
  dependency-version: 3.5.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: autoprefixer
  dependency-version: 10.4.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: commitlint-plugin-function-rules
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: eslint-config-turbo
  dependency-version: 2.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: lodash.clonedeep
  dependency-version: 
  dependency-type: direct:production
  dependency-group: non-breaking-changes
- dependency-name: lodash.get
  dependency-version: 
  dependency-type: direct:production
  dependency-group: non-breaking-changes
- dependency-name: lodash.isequal
  dependency-version: 
  dependency-type: direct:production
  dependency-group: non-breaking-changes
- dependency-name: lodash.set
  dependency-version: 
  dependency-type: direct:production
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-version: 0.553.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: prettier-plugin-tailwindcss
  dependency-version: 0.7.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: sass
  dependency-version: 1.94.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: typescript
  dependency-version: 5.9.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: unplugin-element-plus
  dependency-version: 0.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: vxe-pc-ui
  dependency-version: 4.10.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: vxe-table
  dependency-version: 4.17.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
- dependency-name: zod-defaults
  dependency-version: 0.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@ast-grep/napi"
  dependency-version: 0.39.9
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: "@vue/reactivity"
  dependency-version: 3.5.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-14 08:05:04 +08:00
Jin Mao
c3a7562e2c Merge branch 'main' into milletpeak-fontsize 2025-11-13 17:01:42 +08:00
Jin Mao
605e0ea128 chore: 更新依赖 2025-11-13 09:23:12 +08:00
dependabot[bot]
c89a83f980 chore(deps): bump stylelint-config-recommended from 14.0.1 to 17.0.0 (#6901)
Bumps [stylelint-config-recommended](https://github.com/stylelint/stylelint-config-recommended) from 14.0.1 to 17.0.0.
- [Release notes](https://github.com/stylelint/stylelint-config-recommended/releases)
- [Changelog](https://github.com/stylelint/stylelint-config-recommended/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint-config-recommended/compare/14.0.1...17.0.0)

---
updated-dependencies:
- dependency-name: stylelint-config-recommended
  dependency-version: 17.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-13 09:17:44 +08:00
Jin Mao
cfad88666b chore: 替换 lodash-es为 es-toolkit 并调整样式引入方式 (#6912) 2025-11-13 08:20:30 +08:00
Jin Mao
f918dc24c6 chore(@vben/utils): 移除冗余的 lodash 依赖 2025-11-13 07:47:48 +08:00
Jin Mao
e898993fe8 chore(@vben/utils): 替换 lodash 工具函数为 es-toolkit 实现 2025-11-13 07:45:10 +08:00
Jin Mao
5cafcb4a01 refactor(shared): 替换 lodash 工具函数为 es-toolkit 兼容版本
- 将 get 和 isEqual 方法从 lodash 替换为 es-toolkit/compat 导出
- 更新 package.json 添加 es-toolkit 依赖
- 注释掉原有的 lodash.get 和 lodash.isequal 导出语句- 锁定 es-toolkit 版本至1.41.0 并更新相关依赖配置
2025-11-13 07:28:52 +08:00
Jin Mao
03154cde88 chore: update depends 2025-11-13 07:16:28 +08:00
dependabot[bot]
a74bf7b63f chore(deps): bump echarts from 5.6.0 to 6.0.0 (#6859)
Bumps [echarts](https://github.com/apache/echarts) from 5.6.0 to 6.0.0.
- [Release notes](https://github.com/apache/echarts/releases)
- [Commits](https://github.com/apache/echarts/compare/5.6.0...6.0.0)

---
updated-dependencies:
- dependency-name: echarts
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-11-13 07:10:59 +08:00
米山
0bc7169698 feat: add global font size adjustment 2025-11-12 17:39:07 +08:00
米山
24b6e7a835 feat: add global font size adjustment 2025-11-12 17:38:41 +08:00
Jin Mao
f59e33682c Merge branch 'main' into main 2025-11-12 04:27:57 +08:00
Jin Mao
d811af37dd Merge branch 'main' into profile 2025-11-12 04:03:27 +08:00
Jin Mao
0e1a7d61f3 Merge branch 'main' into fix-downloader 2025-11-12 02:05:03 +08:00
panda7
573637222d feat: add form handleCollapsedChange event (#6893)
* feat: add form handleCollapsedChange event

* fix: ts lint

* fix: ts error

---------

Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-11-12 02:03:12 +08:00
shixi
05e9d65251 fix: for tdesign 2025-11-12 01:14:28 +08:00
shixi
0bbb20fee0 feat: sport notification link 2025-11-12 00:55:24 +08:00
shixi
dbc5ea32ae feat: add read and delete for each notification 2025-11-12 00:02:13 +08:00
xingyu4j
0319604863 feat: playground add profile 2025-11-10 18:00:50 +08:00
xingyu4j
acf99f2441 feat: tdesign add profile 2025-11-10 18:00:25 +08:00
xingyu4j
cbf2a02877 feat: naive add profile 2025-11-10 17:59:58 +08:00
xingyu4j
226d9bd1ad feat: ele add profile 2025-11-10 17:59:33 +08:00
xingyu4j
48b3d30088 fix: types 2025-11-10 17:54:01 +08:00
xingyu4j
e311cfb8da feat: route add profile 2025-11-10 17:51:10 +08:00
xingyu4j
4347fba80a feat: antdv add profile 2025-11-10 17:50:47 +08:00
xingyu4j
7dc68ed368 feat: add profile comps 2025-11-10 17:49:58 +08:00
Jin Mao
a4aa133db5 Merge branch 'main' into tdesign 2025-11-09 12:04:30 +08:00
Utopia
6bbe523f6f chore: 增强 util-formatDate ts 类型提示 (#6886)
* feat: 为 auth layout 添加 slot: logo, 提升组件的灵活性和可复用性

* feat: 增强 util-formatDate ts 类型提示
2025-11-09 12:00:49 +08:00
Copilot
fef1e35c54 fix: prevent JSONBigInt parsing error on non-string data (#6891)
* Initial plan

* Fix json-bigint serialization error when data is not a string

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
2025-11-09 11:49:38 +08:00
xingyu
20410aeb03 fix: updating Tailwind CSS variables from --radix-* to --reka-* (#6890)
* fix: radix => reka

* chore: add reka cspell

* fix: Composition url
2025-11-09 11:49:01 +08:00
Li Kui
83ea27af3e fix: fix lint 2025-11-06 23:16:23 +08:00
Li Kui
b7bfd69788 fix: fix lint 2025-11-06 23:10:03 +08:00
Li Kui
99d663a6f2 fix: fix typecheck 2025-11-06 23:02:24 +08:00
Li Kui
1af11240a6 chore: add tdesign logo 2025-11-06 22:37:55 +08:00
Li Kui
3e8e8690e3 chore: Merge branch 'main' into tdesign 2025-11-06 17:49:51 +08:00
Li Kui
be843300be chore: update demo routes 2025-11-06 17:44:34 +08:00
Li Kui
dc77721c11 chore: demo i18n 2025-11-06 16:42:25 +08:00
Li Kui
a38d081f17 chore: enable VITE_NITRO_MOCK 2025-11-06 16:37:15 +08:00
Copilot
1e09fa4642 feat: migrate from Radix Vue to Reka UI (#6870)
* Initial plan

* Update dependencies and imports from radix-vue to reka-ui

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

* Fix type errors after reka-ui migration

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

* Run formatter to fix code style

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
2025-11-06 16:22:24 +08:00
Li Kui
bd8ff73f9e fix: fix build error 2025-11-06 15:26:24 +08:00
Li Kui
57620dc2ea chore: apply coderabbitai suggestions 2025-11-06 15:11:28 +08:00
Li Kui
b472fbb72f Merge branch 'main' into tdesign 2025-11-06 14:36:27 +08:00
Copilot
04321b16c1 fix: replace ant-design-vue with tdesign components in web-tdesign app (#6880)
* Initial plan

* fix: replace ant-design-vue with tdesign components

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

* fix: remove trailing comma in package.json

Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
2025-11-06 14:35:50 +08:00
Olexandr88
7268824612 Update README.md (#6828)
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-11-04 04:34:55 +08:00
dependabot[bot]
23c41a8059 chore(deps): bump @types/node from 12.20.55 to 24.9.2 (#6860)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 12.20.55 to 24.9.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.9.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-04 04:16:59 +08:00
dependabot[bot]
fdc78faa13 chore(deps): bump @vueuse/integrations from 12.8.2 to 14.0.0 (#6861)
Bumps [@vueuse/integrations](https://github.com/vueuse/vueuse/tree/HEAD/packages/integrations) from 12.8.2 to 14.0.0.
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v14.0.0/packages/integrations)

---
updated-dependencies:
- dependency-name: "@vueuse/integrations"
  dependency-version: 14.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-04 04:16:37 +08:00
dependabot[bot]
c8af580866 chore(deps): bump SamKirkland/FTP-Deploy-Action (#6873)
Bumps the non-breaking-changes group with 1 update: [SamKirkland/FTP-Deploy-Action](https://github.com/samkirkland/ftp-deploy-action).


Updates `SamKirkland/FTP-Deploy-Action` from 4.3.5 to 4.3.6
- [Release notes](https://github.com/samkirkland/ftp-deploy-action/releases)
- [Commits](https://github.com/samkirkland/ftp-deploy-action/compare/v4.3.5...v4.3.6)

---
updated-dependencies:
- dependency-name: SamKirkland/FTP-Deploy-Action
  dependency-version: 4.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-04 04:14:47 +08:00
Jin Mao
348c97710f Revert "refactor(jwt): 更新 JWT 工具函数实现方式 (#6869)"
This reverts commit a854760d26.
2025-11-03 19:34:45 +08:00
zengmingyong
a854760d26 refactor(jwt): 更新 JWT 工具函数实现方式 (#6869)
refactor(jwt): 更新 JWT 工具函数实现方式

- 将默认导入 jsonwebtoken 改为解构导入 sign 和 verify 方法
2025-11-03 13:08:06 +08:00
Copilot
c7c39047de feat: add theme-aware logo support via optional sourceDark configuration (#6866)
* Initial plan

* Initial exploration and setup

Co-authored-by: aonoa <32682251+aonoa@users.noreply.github.com>

* Add support for separate light and dark theme logos

Co-authored-by: aonoa <32682251+aonoa@users.noreply.github.com>

* Update documentation with dark theme logo configuration

Co-authored-by: aonoa <32682251+aonoa@users.noreply.github.com>

* feat: Add theme-aware logo support for authentication/login page

Co-authored-by: aonoa <32682251+aonoa@users.noreply.github.com>

* revert: .npmrc

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

---------

Signed-off-by: aonoa <1991849113@qq.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aonoa <32682251+aonoa@users.noreply.github.com>
Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
Co-authored-by: aonoa <1991849113@qq.com>
2025-11-03 13:07:36 +08:00
Jin Mao
f8a7a0a9a2 chore: lint 2025-10-31 09:11:40 +08:00
Jin Mao
2cb3dcf499 Merge branch 'fork/ming4762/timezone-fix-20251030'
# Conflicts:
#	packages/stores/src/modules/timezone.ts
2025-10-31 09:08:08 +08:00
Jin Mao
b36d32b66d chore(timezone): 添加 $reset 方法并初始化时区存储
- 在时区存储中添加 `$reset` 方法
-修复导入语句引号为双引号
- 优化时区初始化错误处理逻辑- 导出 `$reset` 方法以便外部调用- 确保时区设置与默认选项同步
- 提升代码一致性和可维护性
2025-10-30 23:27:53 +08:00
zhongming4762
639ea96bb9 fix: resolve the issue of logout failure caused by the timezone store 2025-10-30 17:12:45 +08:00
zhongming4762
565be77e96 fix: resolve the issue of logout failure caused by the timezone store 2025-10-30 17:01:49 +08:00
Jin Mao
ac6de0324c Merge branch 'fork/ming4762/timezone-20251020' 2025-10-30 00:42:05 +08:00
zhongming4762
f46ae023ba feat: increase support for multiple time zones
* 优化实现方法
2025-10-29 20:14:48 +08:00
zhongming4762
212144feca feat: increase support for multiple time zones
* 优化实现方法
2025-10-29 20:10:25 +08:00
zhongming4762
3eed51fd3e feat: increase support for multiple time zones
* 优化实现方法
2025-10-29 20:03:21 +08:00
zhongming4762
4d713db546 feat: increase support for multiple time zones
* 优化实现方法
2025-10-29 19:47:10 +08:00
Jin Mao
0cd9f4615c Merge branch 'main' into fix-downloader 2025-10-26 15:28:34 +08:00
Jin Mao
cfbce0d737 chore: fix lint 2025-10-26 15:27:28 +08:00
Jin Mao
1d9cd88dd7 Merge branch 'main' into fix-downloader 2025-10-26 15:16:32 +08:00
Jin Mao
0e62862119 chore: fix lint 2025-10-26 15:01:58 +08:00
Jin Mao
6b6cdef42d chore: 一些调整 2025-10-26 15:00:47 +08:00
Jin Mao
33b7a605c0 chore: 一些调整和兼容性更新 2025-10-26 14:23:37 +08:00
zhongming4762
e01803ce9d feat: increase support for multiple time zones 2025-10-22 20:39:00 +08:00
zhongming4762
e3e5755903 feat: increase support for multiple time zones 2025-10-22 20:29:53 +08:00
zhongming4762
61ce53b686 feat: increase support for multiple time zones 2025-10-22 20:23:55 +08:00
zhongming4762
b029f77b6a feat: increase support for multiple time zones 2025-10-22 20:18:25 +08:00
zhongming4762
0a8339a405 feat: increase support for multiple time zones 2025-10-22 19:52:01 +08:00
Jin Mao
2264eaae18 feat: 新增集成tdesign组件的apps 2025-10-21 10:47:39 +08:00
zoumingjun
38f91da5af fix: 优化双列布局组件点击展开左侧按钮位置不居中问题 2025-10-18 21:22:58 +08:00
zoumingjun
8edea3aee5 fix: 调整zh-CN/system.json中<"title": "系统管理">配置位置,保持与en-US/system.json中位置一致 2025-10-18 21:20:54 +08:00
zoumingjun
08b6e7713e fix: 修复对话框modal组件方法名错误 2025-10-18 21:13:34 +08:00
zoumingjun
6a89814b83 chore: 优化侧边栏展开折叠图标 2025-10-18 20:59:14 +08:00
zoumingjun
52d3aa9315 fix: 优化Checkbox组件hover样式,Input组件placeholder样式,TabsList组件圆角样式 2025-10-18 20:58:48 +08:00
zoumingjun
4e264c503a fix: 锁屏和解锁密码输入框自动聚焦 2025-10-18 20:55:53 +08:00
zoumingjun
32051e9ca0 fix: 优化左侧和右侧认证面板动画效果 2025-10-18 20:52:27 +08:00
zoumingjun
2b0079580b fix: 修复mock-data.ts父id错误 2025-10-18 16:32:23 +08:00
lidongcheng88
03ce030e7c fix: 混合双列 onMounted 关闭二级侧边栏 (#6807)
Co-authored-by: ldc <lidchen@tencent.com>
2025-10-14 06:56:00 +08:00
zouawen
59097e2466 chore: 新增是否开启首选项导航栏(外观、布局、快捷键、通用)吸顶效果,调整部分样式 (#6804) 2025-10-14 06:55:11 +08:00
zouawen
2ce161e585 feat: 1、新增水印文案自定义功能;2、input-item输入框组件新增清除功能(可用于快捷清除水印文案);3、偏好设置、主题切换、语言选择、是否全屏按钮新增动画效果 (#6800)
* feature: 新增水印文案自定义功能;

* chore: 偏好设置、主题切换、语言选择、是否全屏按钮新增动画效果
2025-10-07 06:15:41 +08:00
zouawen
33306a5aff chore: 更换其他登录方式图标为彩色图标,新增其他登录方式tooltip文字提示 (#6799) 2025-10-06 06:56:54 +08:00
lw567
6e03de5011 fix: watermark create error #6788 (#6789)
Co-authored-by: liwei567 <liwei567@example.com>
2025-09-30 19:53:09 +08:00
HaHa
713281a8ba fix(theme-button): fix flicker during theme switch (#6782) 2025-09-30 05:10:51 +08:00
shierd
42e3de9e2c fix: 修复设置表单值时合并子对象的错误 (#6780)
Co-authored-by: shier <shier@shierd.com>
2025-09-30 05:10:39 +08:00
vent
1e029dbc9a fix: 修复部分场景 echarts 在使用 v-show 时获取不到 width 的问题 (#6776) 2025-09-30 05:09:33 +08:00
Cup_Of_Bread
81bb7456f8 fix: 修复注解错误 (#6763) 2025-09-23 23:49:25 +08:00
pangyajun123
26f8d2aa30 perf: 表单需要通过权限控制是否需要展示,dependencies.if 这种方式需要别triggerFields触发字段,不能满足要求 (#6756) 2025-09-23 23:48:27 +08:00
boisduval
a8b848d367 fix: 解决搜索表单中arrayToStringFields属性无法在搜索时生效的问题 (#6591)
- 合并handleArrayToStringFields与handleStringToArrayFields为handleMultiFields
- 在handleMultiFields判断arrayToString或stringToArray
- 删除两个方法在其他地方的引用 统一为在handleRangeTimeValue内调用handleMultiFields实现数据转换

Co-authored-by: 宛晴 <wanqing@mengtaigroup.com>
2025-09-23 23:45:26 +08:00
ming4762
482ce981ce chore: update deps vxe, vxe-table: 4.14.4 -> 4.16.11 vxe-pc-ui: 4.7.… (#6752)
* chore: update deps vxe, vxe-table: 4.14.4 -> 4.16.11  vxe-pc-ui: 4.7.12 -> 4.9.29

* fix: resolve the ESLint warning generated by #6317
2025-09-17 17:42:39 +08:00
Jin Mao
97ad93ab1f Merge branch 'zouawen-main' 2025-09-17 17:41:05 +08:00
Jin Mao
319b7fcdaa Merge branch 'main' of https://github.com/zouawen/vue-vben-admin into zouawen-main 2025-09-17 17:37:43 +08:00
Jin Mao
4de8220ce6 feat(common-ui): 添加 Tree 组件
- 在 common-ui 包中新增 Tree 组件
- 实现了基本的树形结构展示功能
- 集成了 VbenTree 组件和自定义样式- 添加了空数据时的占位展示
2025-09-17 17:28:39 +08:00
Jin Mao
9114692f95 Merge branch 'main' into main 2025-09-15 08:08:31 +08:00
Jin Mao
0f7731b611 Merge branch 'ming4762-stream-2025091101' 2025-09-15 08:03:52 +08:00
Jin Mao
8040bc1a22 Merge branch 'stream-2025091101' of https://github.com/ming4762/smart-boot-ui-vben into ming4762-stream-2025091101 2025-09-15 08:02:30 +08:00
oc
11d273cbb6 feat(authentication): 二维码登录和验证码登录组件增加返回按钮显隐配置 (#6713)
- 在 CodeLogin 和 QrcodeLogin 组件中添加 showBack 属性
- 根据 showBack 属性决定是否显示返回按钮
- 默认值为 true,即默认显示返回按钮
2025-09-15 07:43:18 +08:00
zouawen
a4b8f8f795 fix: 节点选中时过滤父节点禁用状态 2025-09-12 17:31:42 +08:00
zouawen
dfa2ac3435 fix: 全选时过滤disabled的节点 2025-09-11 18:16:10 +08:00
zouawen
39820c783c fix:
1、VbenTree新增是否全选、展开折叠功能;
2、解决当点击子节点label文字区域,而非checkbox时,关联父组件不能选中问题;
3、优化子节点选中时关联父节点选中功能:删除VbenTree中processParentSelection方法,改为在onSelect中实现,原因:processParentSelection在每次模型值更新时都会被调用,且计算复杂度为O(n^2),onSelect只在交互时触发,复杂度为O(n);
4、新增中间层tree组件,处理无数据时显示场景(显示图标Inbox和国际化comom.noData文本);
5、为防止父组件传值子组件boolean类型默认false问题,新增treePropsDefaults方法,为TreeProps赋默认值,Tree组件和VbenTree组件统一使用;
6、优化VbenTree组件整体样式(优化padding、margin、gap值,优化type为button时outline左右空白区域不对称问题),优化内部header、footer插槽样式。
2025-09-11 16:41:42 +08:00
zhongming4762
66822a5f95 feat: add SSE support to request-client 2025-09-11 11:22:47 +08:00
zhongming4762
eb4f1f8164 feat: add SSE support to request-client 2025-09-11 10:50:19 +08:00
谦元吉
6a85b3ab84 fix(@vben/common-ui): resolve #6698 (#6700)
* fix(@vben/common-ui): resolve #6698

* fix(@vben/common-ui): resolve #6698

* fix(@vben/common-ui): resolve conversation

* fix(@vben/common-ui): resolve #6698
2025-09-02 17:02:11 +08:00
谦元吉
c57592f3a6 fix(@vben-core/shadcn-ui): 修复VbenPinInput组件在点击获取验证码和回车同时进行时会重复触发计时器的问题 (#6705) 2025-09-02 16:56:46 +08:00
Ken Hai
b0d7b177be fix: 角色管理,授权的树形组件,取消勾选叶子节点,父级节点状态错误 (#6680)
Co-authored-by: haiyinlong <haiyinlong@uhigame.com>
2025-08-25 21:32:01 +08:00
LinaBell
566d3bdf7c fix: appendToMain warning (#6684) 2025-08-25 21:25:29 +08:00
螃蟹
adbf793e79 fix(@vben/web-ele): the main color tone for switching between dark and light themes has been reset (#6678) 2025-08-25 11:03:54 +08:00
LinaBell
cf6c4c9aae fix: cannot read properties of null (reading 'nextSibling') (#6667) 2025-08-21 22:26:10 +08:00
Ken Hai
ffaf85c8f3 fix: 修复角色修改时VbenTree组件没有回显选中 (#6662)
* fix: 修复角色修改时VbenTree组件没有回显选中

* chore: use nextTick

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: merge

* chore: 更新

---------

Co-authored-by: haiyinlong <haiyinlong@uhigame.com>
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-21 15:30:58 +08:00
panda7
2cc78f925f fix: the bug in the lock method of the vbenModal component (#6648) 2025-08-21 15:17:55 +08:00
ming4762
93f0eea4e7 fix: fix the issue of excessive line spacing in vbenForm (#6653)
* gap-2和 pb-4/2 重叠导致间距过宽,gap-x只保留列间距
2025-08-21 12:41:04 +08:00
lighua
fddfc6d494 fix: 增加对不支持的 HTTP 方法的错误处理 2025-08-21 11:13:02 +08:00
谦元吉
58e3941810 chore(docs): update the component import of the form adapter description in the document (#6656) 2025-08-19 16:48:10 +08:00
Svend
3ad433a50b fix: 修复在 hash 路由模式下无法在新窗口打开路由的问题 (#6652)
此问题是由于 PR #6583 中新增的 `resolveHref` 函数导致的。其在 hash 路由模式下,得到的 URL 会包含 #/ 前缀。在经过 openRouteInNewWindow 的逻辑后就会出现两次 /# 前缀
2025-08-19 16:47:45 +08:00
ming4762
8ac2db5b7c fix: fix the issue of VbenForm compact reactive failure (#6654) 2025-08-19 16:46:14 +08:00
Elm1992
a441dcebae fix: meta.link invalid issue 2025-08-19 16:40:16 +08:00
Vben
ff4704d5ea chore: Upgrade vite to version 7.x (#6645) 2025-08-16 22:50:31 +08:00
菠萝吹雪
6ddfbd84b0 chore: modify the contributor showcase in the README (#6636) 2025-08-16 22:47:08 +08:00
ming4762
1e6417f95b feat: vBenForm add layout: inline (#6644) 2025-08-16 22:41:08 +08:00
vben
e147a9d2fd chore: release 5.5.9 2025-08-16 22:16:02 +08:00
谦元吉
4efebb8c0b fix:update (#6635) 2025-08-14 22:01:12 +08:00
gxc685
9ce0df88ae fix: 修复mock里面eventHandler重复导致无法启动 (#6631) 2025-08-14 22:00:54 +08:00
谦元吉
3cf0c0eb04 fix(@vben/backend-mock): go back to the last modification (#6634)
* fix(@vben/backend-mock): the version went back to the last submission, and the latest submission was completely useless.

* fix: resolve conflicts
2025-08-14 12:06:41 +08:00
谦元吉
ab7e363279 fix(@vben/backend-mock): fix all ts type errors in this module (#6613)
* fix(@vben/backend-mock): 修复所有 ts 类型报错

* fix(@vben/backend-mock): 修复该模块所有 ts 类型报错

* fix(@vben/backend-mock): 解决 coderabbitai

* fix(@vben/backend-mock): 解决 coderabbitai

* fix(@vben/backend-mock): 解决 coderabbitai
2025-08-12 17:23:39 +08:00
lighua
df655015b1 fix: 优化文件下载器方法 2025-08-08 15:31:31 +08:00
xueyang
9fc594434f perf: 优化useVbenForm样式 (#6611)
* perf(style): 优化useVbenForm垂直布局 actions 样式

* perf(style): 优化useVbenForm actions 布局样式

- 操作按钮组显示位置
```
actionPosition?: 'center' | 'left' | 'right';
```
- 操作按钮组的样式
```
actionType?: 'block' | 'inline'
inline: 行类显示,block: 新一行单独显示
```

* perf: 优化useVbenForm actions 布局样式

删除 actionType
增加 actionLayout
- actionLayout?: 'inline' | 'newLine' | 'rowEnd';
- newLine: 在新行显示。rowEnd: 在行内显示,靠右对齐(默认)。inline: 使用grid默认样式
- 删除无用代码 queryFormStyle

* perf: 优化useVbenForm使用案例

* perf: 优化form组件样式

去掉padding,改为gap

* docs: update vben-form.md

* fix: 修复FormMessage位置

* perf: Avoid direct mutation of props object.

-  props.actionLayout = props.actionLayout || 'rowEnd';
-  props.actionPosition = props.actionPosition || 'right';
+  const actionLayout = props.actionLayout || 'rowEnd';
+  const actionPosition = props.actionPosition || 'right';

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: 修复 wrapperClass 权重

* fix: 全局搜索结果不匹配 #6603

* fix: 避免FormMessage溢出

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-07 23:48:34 +08:00
leo
b93e22c45a fix(@vben/layouts): respect base URL when opening route in new window (#6583)
Previously, the generated URL for opening routes in a new window did not include the router base,
which led to incorrect paths when the app was deployed under a subdirectory (e.g., /admin/).
This change ensures that the resolved path includes the configured base by using
router.resolve(path).href.
2025-07-29 13:46:05 +08:00
Jin Mao
193f5b6512 Merge branch 'main' into 2025072604 2025-07-28 15:53:04 +08:00
Jin Mao
cb3f96683f fix: 修复双列布局模式下,路由为hideInMenu时,空白右列 2025-07-28 15:50:21 +08:00
zhongming4762
06ffdf164a feat: add dingding login 2025-07-25 22:02:55 +08:00
ming4762
5b75e5e917 perf: perf the control logic of VbenModal full screen and header (#6566)
* resolve the issue of header=false and full screen button display but not operable
2025-07-25 21:45:45 +08:00
aonoa
fad0b49841 fix: adding roles does not automatically refresh (#6548)
* fix: adding roles does not automatically refresh

* style: fix code style err
2025-07-25 21:35:57 +08:00
Jin Mao
260e45cd7b Merge branch 'main' into feat/add-vben-modal-animation 2025-07-25 21:33:11 +08:00
vben
1575619d53 chore: release v5.5.8 2025-07-19 22:19:50 +08:00
Jin Mao
d5a36a167d fix: fix vxeTable commit proxy (#6536)
* fix: 修正use-vxe-grid中的代理配置提交类型

* chore: change config
2025-07-19 16:07:15 +08:00
panda7
fc9ea347ca Merge branch 'main' into feat/add-vben-modal-animation 2025-07-18 00:38:54 +08:00
 panda7
1a9b0509d5 feat: add animation effects to VbenModal component 2025-07-18 00:15:40 +08:00
panda7
07b64ad384 feat: add function support for formItemClass prop (#6511)
* feat: add function support for formItemClass prop

* feat: add try-catch to formItemClass function

* fix: formItemClass function ts error

---------

Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-07-17 09:37:39 +08:00
Jin Mao
1bc5d2986b chore: update-vxe-table (#6516)
* chore: update vxe-pc-ui,vxe-table

* fix(ui): 修复代理配置初始化方法名错误

* fix(ui): 修改远程表格刷新配置

* chroe: update vxeTable

更新到最新
2025-07-16 19:15:39 +08:00
HamWong
bb36cca315 fix: 锁定屏幕页面样式自适应 (#6480) 2025-07-15 09:08:08 +08:00
Jin Mao
b8bf482c6a Merge branch 'main' into form 2025-07-07 09:16:54 +08:00
Jin Mao
3b673ca915 Merge branch 'main' into feature/scroll_to_the_error_field 2025-07-07 08:21:50 +08:00
Jin Mao
bbf0287511 chore: fix lint warning (#6487) 2025-07-07 08:21:25 +08:00
panda7
d4786f3f75 Merge branch 'main' into feature/scroll_to_the_error_field 2025-07-06 21:19:52 +08:00
xue-jn
b333fd676d docs: update vben-drawer.md (#6478)
* docs: update vben-drawer.md

* docs: update vben-drawer.md

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-07-06 20:26:06 +08:00
sqchen
f1051c8773 feat: add scrollToFirstError to the form component 2025-07-05 00:50:53 +08:00
sqchen
243f3a201d feat: add scrollToFirstError to the form component 2025-07-05 00:19:12 +08:00
陈蔚然
2f7de243f6 Merge branch 'vbenjs:main' into slider-translate-captcha 2025-07-04 10:28:40 +08:00
chenweiran
1aafb43103 feat: 增加基于图片拼图切片平移的验证码 2025-07-04 10:26:02 +08:00
chenweiran
8ccd01ade5 feat: 增加基于图片拼图切片平移的验证码 2025-07-04 10:23:47 +08:00
Netfan
e6bfbce6cb revert: page height fixed,revert #6422 2025-07-03 22:29:48 +08:00
someone-cool
1f63aed64c fix(@vben/common-ui): add page footer's height to calc contentstyle (#6422) 2025-07-03 18:36:42 +08:00
xue-jn
253b0da7d2 fix: 接口返回子节点为空数组时,还会显示折叠箭头 (#6463) 2025-07-03 18:35:03 +08:00
RanMaoting
33a4d524db feat(@vben/plugins): 新增VxeGrid组件插槽类型定义 (#6452)
* feat(@vben/plugins): 新增VxeGrid组件插槽类型定义

Closes: #6451

* fix(@vben/plugins): 优化vxe-table组件的插槽类型定义

修复Omit导致的类型丢失
2025-07-03 18:34:37 +08:00
chenweiran
bbd8a53d9d feat: 增加基于图片拼图切片平移的验证码 2025-07-03 18:20:20 +08:00
chenweiran
8554924cb9 feat: 增加基于图片拼图切片平移的验证码 2025-07-03 17:43:19 +08:00
RanMaoting
fee811d950 fix: 优化组件方法透传并新增表单弹窗示例 (#6443) 2025-07-02 19:58:48 +08:00
Netfan
78076e70b4 chore: update deps 2025-07-02 16:55:55 +08:00
chewenye
b78bc65ce7 feat: 组件json-viewer支持bigint数据显示 cwy (#6377)
Co-authored-by: 车文烨 <chewy@china-lehua.com>
2025-06-29 04:32:30 +08:00
Utopia
b1fb623113 feat: 为 auth layout 添加 slot: logo, 提升组件的灵活性和可复用性 (#6442) 2025-06-27 19:23:24 +08:00
Stephen Chang
de14908fd3 fix(icon-picker): 解决icon-picker组件切换分页后,关键词检索失效问题 (#6437)
当icon-picker组件切换分页后,在输入关键词检索,但是分页没有重置,导致检索结果异常
2025-06-27 19:21:23 +08:00
Li Kui
5c3972196a fix: Add $t import to login expired modal (#6429)
closes #6230
2025-06-27 19:20:25 +08:00
CG.gatspy
3230781538 feat: [vben-tree]增加数据disabled (#6343)
* feat: [vben-tree]增加数据disabled

* Update packages/@core/ui-kit/shadcn-ui/src/ui/tree/tree.vue

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-27 19:09:30 +08:00
broBinChen
e7fd0e3b6a feat(hooks): useHoverToggle的入参refElement支持传入响应式数组 (#6333)
* feat(hooks): useHoverToggle的入参refElement支持传入响应式数组

* feat(hooks): 1、增加 useHoverToggle 中 refElement 参数关于传入响应式数组的注释说明。 2、修改 watch 监听深度,仅需浅层监听 refs 变化。 3、使用 effectScope 管理 useElementHover 实例,避免 refs 变化时事件监听器累积导致的内存泄漏问题

* feat(hooks): 在useHoverToggle中增强 updateHovers  的边界处理,优化watch方案,只监听元素数量变化而不是整个数组变化,避免过度依赖收集

---------

Co-authored-by: xiaobin <xiaobin_chen@fzzixun.com>
2025-06-27 19:08:41 +08:00
yuhengshen
2f7d1f009d fix: 全屏状态下弹窗圆角优化 (#6413) 2025-06-24 23:41:54 +08:00
yuhengshen
946f91f387 feat: optimize modal dragging range(#6414)
* 当弹窗指定了容器时,拖拽将被限制在容器范围内
2025-06-24 17:05:59 +08:00
lghuahua
986eacae9a fix: improve request logic in api-component
* 修复某些情况下updateParam设置的参数可能不会提交给api的问题
* 修复在上一个请求尚未完成前如果params发生了变更,将不会再触发新的api请求
---------

Co-authored-by: Netfan <netfan@foxmail.com>
2025-06-20 08:42:45 +08:00
Netfan
97b8e28a2b docs: fix delete request usage (#6389) 2025-06-17 08:52:59 +08:00
Netfan
c0962fec18 fix: auto close popup on deactivated (#6368)
* 修复挂载到内容区域的弹窗和抽屉被意外关闭的问题
2025-06-11 12:20:52 +08:00
XiaoHetitu
8ba7bdf2bd fix(button): 为按钮添加type属性防止表单提交意外触发表单验证机制 (#6340)
在按钮组件中,按钮元素缺少type="button"属性可能导致在表单中意外提交。添加此属性以确保按钮行为符合预期。

Co-authored-by: yuanwj <ywj6792341@qq.com>
2025-06-08 17:56:24 +08:00
zyy
b015fbc9fc fix: [adapter] 表格配置类型报错 (#6327)
配置toolbarConfig中的search时会有类型报错
2025-06-08 17:53:55 +08:00
broBinChen
b69320c070 feat(hooks): support separate enter/leave delays in useHoverToggle (#6325)
Co-authored-by: xiaobin <xiaobin_chen@fzzixun.com>
2025-06-08 17:53:29 +08:00
zhang
dcccc213ce fix: requestClient.upload会将vbenform中value为undefined的值转为字符串undefined’提… (#6300)
* fix: requestClient.upload会将vbenform中value为undefined的值转为字符串undefined’提交给后台保存

* fix: requestClient.upload会将vbenform中value为undefined的值转为字符串'undefined’提交给后台保存
2025-06-08 17:51:16 +08:00
ali-pay
c0e601c020 fix: menu type is not 'button' (#6277)
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-06-08 17:50:44 +08:00
RanMaoting
017ed1a9e1 types: 为useVbenVxeGrid添加泛型声明,使grid实例上能正确获取到行数据的类型 (#5653)
Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
2025-06-08 17:43:02 +08:00
vben
b9aef618fe chore: release 5.5.7 2025-06-04 05:33:06 +08:00
Netfan
4102cc2211 feat: improve vbenCheckButtonGroup (#6329)
* 按钮组支持单选清除和多选限制最大选项数

* 按钮组支持icon插槽来定制图标
2025-06-03 23:11:56 +08:00
chewenye
ea776aa710 types: 扩展user-dropdown组件的menus类型,支持iconify (#6283)
Co-authored-by: 车文烨 <chewy@china-lehua.com>
2025-06-03 06:07:06 +08:00
huanghezhen
feb96dc8ea fix: resolve onClosed method failure in connectedComponent of useVbenModal (#6309) 2025-06-02 08:16:48 +08:00
wyc001122
470fd43b49 fix: 修复使用useVbenVxeGrid配置hasEmptyText、hasEmptyRender不生效的问题 (#6310) 2025-06-02 08:16:26 +08:00
zhang
76d106e474 fix: When defaultHomePage is inconsistent with user.homePath, the pa… (#6299)
* fix:  When defaultHomePage is inconsistent with user.homePath, the page refresh route jump will be abnormal

* fix:  When defaultHomePage is inconsistent with user.homePath, the page refresh route jump will be abnormal
2025-06-02 08:07:06 +08:00
wyc001122
78c3c9da6f docs(settings): 完善'生产环境动态配置'步骤 (#6297) 2025-06-02 08:05:23 +08:00
Netfan
081d08a7f8 fix: alert width fixed in small screen (#6312) 2025-05-30 19:54:26 +08:00
Netfan
96a10ca83f style: fix lint error (#6298) 2025-05-28 19:23:21 +08:00
wyc001122
f31360ba4e feat: support for hybrid permission access control mode (#6294)
* feat: 添加混合权限访问控制模式

* feat: 文档补充
2025-05-28 17:01:58 +08:00
wyc001122
4eb16d6d3a fix: fix table-title slot not work (#6295) 2025-05-28 17:01:11 +08:00
liqiang0330
53304514b6 fix: Update index.ts (#6268)
* Update index.ts

VxeGridPropTypes.原文件缺少这个,现在补全!

* Update index.ts

增加空格!
2025-05-26 13:29:27 +08:00
Netfan
6fbf1387f5 fix: reset slider-captcha after login failed (#6275) 2025-05-25 16:04:56 +08:00
Netfan
e5c937396d fix: json-bigint parse used in vxeTable (#6271)
* 修复vxeTable不能加载json-bigint解析的数据的问题
2025-05-24 13:01:58 +08:00
littlesparklet
af186f878d fix: repair the unexpected form default value (#5567)
* fix: Fix inconsistent spacing around search form (issue #5429)

* fix: repair the unexpected default value in validated form.(issue #5451)

* Update packages/@core/ui-kit/form-ui/src/use-form-context.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-05-23 16:05:11 +08:00
wyc001122
97894a940e feat: optimize logo display (#6267)
* feat(VbenAvatar): add fit property to VbenAvatar component

* feat(VbenLogo): add fit property to VbenLogo component

* feat(VbenLogo): add logo fit preference configuration

- Add preferences.logo.fit setting for logo display control
- Include corresponding documentation for the new preference

* feat(preferences): add default value for logo.fit preference

- Set default configuration for logo fit behavior
- Ensures consistent logo display across applications

* test(preferences): update configuration snapshots

---------

Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-23 15:24:01 +08:00
yingzi2019
48d70182b4 feat: improve check updates (#6257)
Co-authored-by: monkey <maotao@tutamail.com>
2025-05-23 15:23:06 +08:00
Netfan
a1091bad46 feat: enhances compatibility with APIs returning large numeric values (#6250) 2025-05-23 15:22:18 +08:00
zhang
9f9be21e2a fix: component Input is not registered when initialize page (#6246)
* fix: Component Input is not registered when initialize page

* fix: Component Input is not registered when initialize page
2025-05-23 15:21:09 +08:00
panda7
a2bdcd6e49 feat: ellipsis text automatically displays tooltip based on ellipsis (#6244)
* feat: ellipsis text automatically displays tooltip based on ellipsis

* feat: ellipsis text automatically displays tooltip based on ellipsis

---------

Co-authored-by: sqchen <9110848@qq.com>
Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-05-23 15:20:38 +08:00
ali-pay
11b2b5bcc2 fix: 修复菜单管理中按钮类型值错误的问题 (#6255) 2025-05-22 09:09:31 +08:00
LinaBell
ebef2c91e2 fix: tab cannot be displayed correctly after browser refresh (#6256) 2025-05-22 09:04:40 +08:00
Netfan
0c3edb10b0 fix: getFieldComponentRef will return actual ref within AsyncComponentWrapper (#6252)
修复异步加载组件时,表单的getFieldComponentRef方法没能获取到正确的组件实例
2025-05-21 14:48:51 +08:00
zwtvip
f7bae8ac0f chore: export framework components for use in independent pages 2025-05-21 00:37:26 +08:00
wyc001122
8ac97688da fix(preferences): 更新内容内边距默认值 (#6233)
Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-20 09:50:23 +08:00
李轻舟
2efacb3e5b docs: Update build.md (#6228) 2025-05-19 16:30:39 +08:00
wyc001122
dae46abb71 feat: additional-settings (#6225)
* feat(preferences): 补充VbenAdminLayout传入属性(来自偏好设置)

* docs(@vben/docs):update settings doc

---------

Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-19 16:29:15 +08:00
wyc001122
5ee2a74e2d fix(use-design-tokens): 完善element-plus暗色主题颜色 (#6224)
Co-authored-by: wyc001122 <wangyongchao@testor.com.cn>
2025-05-19 16:27:34 +08:00
afe1
d0b8349a2d perf: stub unbuild params (#6210) 2025-05-18 10:35:20 +08:00
wyc001122
34c4ecb047 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-18 10:34:41 +08:00
ming4762
3d9dba965f 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-18 10:33:02 +08:00
wyc001122
024c01d350 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-16 14:13:43 +08:00
afe1
2adb8acd80 fix: css style (#6176) 2025-05-16 09:40:40 +08:00
panda7
a23bc4cb5c fix: the mobile terminal can wrap lines and expand slot attributes (#6165)
Co-authored-by: sqchen <chenshiqi@sshlx.com>
2025-05-16 09:40:05 +08:00
XiaoHetitu
cf17a45d8d 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-16 09:37:50 +08:00
chewenye
b46ebe756e types: 导出authentication组件的type,自定义toolbarList时类型使用ToolbarType (#6158)
Co-authored-by: 车文烨 <chewy@china-lehua.com>
2025-05-16 09:36:49 +08:00
Netfan
e89cf400c0 fix: refresh command of tabbar issue, fixed: #6162 (#6169) 2025-05-12 23:34:08 +08:00
anyup
9e67929ee7 feat: support to refresh the tab page by route name (#6153)
Co-authored-by: anyup <anyupxing@163.com>
2025-05-10 22:33:31 +08:00
1603 changed files with 116123 additions and 16207 deletions

View File

@@ -0,0 +1,3 @@
{
"singleQuote": true
}

View File

@@ -0,0 +1,7 @@
---
'@vben/styles': patch
'@vben-core/form-ui': patch
'@vben/web-naive': patch
---
feat(@core/form-ui): 新增 useVbenForm 数组编辑器 VbenFormFieldArray

View File

@@ -1,8 +1,16 @@
---
description: nl-admin 管理后台(Vben Admin v5 + Vue 3 + TS + Ant Design Vue)代码规范
description: nl-admin 管理后台(Vben Admin 5.7 + Vue 3.5 + TS + Ant Design Vue 4)代码规范
alwaysApply: true
---
# 技术栈基线(升级后必守)
- **Vben Admin 5.7.0**(monorepo 根 `package.json` / `@vben/web-antd` 版本)
- **Vue 3.5** + **TypeScript** + **Ant Design Vue 4.x**;业务只改 `apps/web-antd`
- **Tailwind CSS v4**(CSS-first,主题在 `@vben/tailwind-config`);不要再引入 `tailwind.config.*` / PostCSS Tailwind 插件那套 v3 写法
- 格式化 / Lint 以仓库现有工具链为准:`oxfmt` + `oxlint`(配合 eslint / stylelint),**不要**再单独引入 Prettier 作为主格式化器
- 组件细则见同目录 `Vben-Components.mdc`(与 https://doc.vben.pro/components/ 对齐)
# 基础规范(所有项目通用)
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
@@ -133,7 +141,9 @@ alwaysApply: true
- 表格空态、分割线、次要文案:用 `--muted` / `--muted-foreground` / `--border`
- 改完后切换暗色主题肉眼过一遍,不要只测亮色
## Vben 组件使用规范
## Vben 组件使用规范(5.7 基线)
> 完整 API / 踩坑见 `Vben-Components.mdc`。下列为业务页强制约定;`lock` / `unlock` / Promise 版 `onBeforeClose` 在 5.7 已是默认能力,**不要再写「需 >5.5.x」这类过时版本门槛**。
### VbenModal(来自 @vben/common-ui)
@@ -141,18 +151,18 @@ alwaysApply: true
- 抽离弹窗内容到子组件时,外层用 `connectedComponent` 参数连接,内外组件共享 `modalApi`
- 底部按钮扩展 slot 优先级:`prepend-footer`(取消按钮左侧)> `center-footer`(取消/确定之间)> `append-footer`(确定右侧)
- **严禁覆盖 `#footer` slot**,会丢失默认的取消/确定按钮和 loading 行为
- 表单提交 loading 走 `modalApi.setState({ confirmLoading: true })`,禁止自己写 button loading
- 提交防抖/防重复用 `modalApi.lock()` / `unlock()`(>5.5.3),禁止手动 disabled
- 提交防抖/防重复优先 `modalApi.lock()` / `unlock()`(锁定时确认按钮 loading,并禁止关闭);也可用 `setState({ confirmLoading: true })`,禁止自己写 button loading / disabled
- 拖拽开 `draggable: true`,需要拖出可视区时同时开 `overflow: true`
- 数据回填走 `modalApi.setData()` + `onOpenChange(isOpen) { const data = modalApi.getData() }`
- `animationType: 'slide' | 'scale'`(默认 slide);挂内容区时开 `appendToMain`,且 Page 必须 `auto-content-height`
### VbenDrawer(来自 @vben/common-ui)
- 创建抽屉必须用 `useVbenDrawer`,禁止直接用 antd `Drawer`
- 底部按钮扩展 slot 与 Modal 一致:`prepend-footer` / `center-footer` / `append-footer`
- **同样严禁覆盖 `#footer` slot**
- 关闭前校验用 `onBeforeClose`(>5.5.2 支持 Promise),禁止自己拦截
- 提交防抖/防重复用 `drawerApi.lock()` / `unlock()`(>5.5.3)
- 关闭前校验用 `onBeforeClose`(支持 Promise / 返回 `false`),禁止自己拦截
- 提交防抖/防重复用 `drawerApi.lock()` / `unlock()`
### VbenVxeTable(来自 #/adapter/vxe-table)
@@ -175,5 +185,10 @@ alwaysApply: true
- 校验用 `formApi.validate().then(e => { if (e.valid) {...} })` 或 `formApi.validateAndSubmitForm()`
- 必填规则用字符串 `'required'` / `'selectRequired'`,规则在 `#/adapter/form.ts` 的 `defineRules` 注册
- schema 中字段名(`fieldName`)必须与后端字段 snake_case 对齐,禁止前端 camelCase
- 密码/敏感字段用 `VbenInputPassword` 组件,禁止用 `VbenInput` 配 `type="password"`
- 业务表单密码字段用适配器组件名 `InputPassword`;禁止 `Input` + `type="password"`(框架自带页可用 `VbenInputPassword`)
- 单选/多选选项来自接口时,必须在弹窗/页面 `onMounted` 或 `onOpenChange` 里拉取后通过 `updateSchema` 注入,禁止写死常量
## 代码生成与 uniapp
- PC「代码生成」下载的 zip **同时包含** `view/`(本仓库 my-gen)与 `uniapp/`(移动端 `pages-sub/my-gen`)
- PC 侧只维护 Vben 模板与粘贴路径;uniapp 的 **C 端 UI / 三端兼容** 以 uniapp 与后端代码生成规则为准,禁止要求移动端照搬本仓库表格形态

View File

@@ -1,13 +1,14 @@
---
description: nl-admin-view Vben 官方组件用法规范(Page/Form/Modal/Drawer/VxeTable 等)
description: nl-admin-view Vben 5.7 官方组件用法规范(Page/Form/Modal/Drawer/VxeTable 等)
globs: apps/web-antd/**/*.{vue,ts}
alwaysApply: false
---
# Vben 组件规则(对齐官方文档 + 本仓库约定)
# Vben 组件规则(对齐 5.7.0 官方文档 + 本仓库约定)
文档来源:https://doc.vben.pro/components/
业务页统一在 `apps/web-antd`;表单/表格必须走本仓库适配器,不要直接依赖底层实现细节。
当前版本:**Vben Admin 5.7.0**。文档来源:https://doc.vben.pro/components/
业务页统一在 `apps/web-antd`;表单/表格必须走本仓库适配器,不要直接依赖底层实现细节。
`lock` / `unlock`、Promise 版 `onBeforeClose`、`animationType`、`center-footer` 等在 5.7 已是基线能力,规则里不再标注「>5.5.x」版本门槛。
## 选型速查
@@ -53,13 +54,14 @@ const [Modal, modalApi] = useVbenModal({
- 复杂弹窗用 `connectedComponent`;内外共享 `modalApi`
- **严禁覆盖 `#footer`**(会丢掉默认取消/确定与 loading)
- 扩展底部只用:`prepend-footer` / `center-footer` / `append-footer`
- 提交防重复:`modalApi.lock()` / `unlock()`(或 `setState({ confirmLoading: true })`)
- 提交防重复:优先 `modalApi.lock()` / `unlock()`(`unlock` = `lock(false)`;锁定时确认按钮 loading、禁关弹窗);或 `setState({ confirmLoading: true })`
- 回填:`modalApi.setData(data).open()`;内部 `onOpenChange` 里 `modalApi.getData()`
- 参数优先级:`slot` > `props` > `state`;`connectedComponent` 时同名事件**以内侧为准**(`onOpenChange` 内外都会触发)
- 默认属性可在 `apps/web-antd/src/bootstrap.ts` 的 `setDefaultModalProps` 统一改
- 动画:`animationType: 'slide' | 'scale'`(默认 slide)
- `destroyOnClose`:关闭后销毁内部 Modal 及子组件(配合 `connectedComponent` 时同样生效)
常用 API:`open` / `close` / `setState` / `setData` / `getData` / `lock` / `unlock`
常用 API:`open` / `close` / `setState` / `setData` / `getData` / `lock` / `unlock` / `useStore`
---
@@ -68,7 +70,7 @@ const [Modal, modalApi] = useVbenModal({
- API 形态与 Modal 基本一致:`connectedComponent`、`setData/getData`、`lock/unlock`、footer 三插槽
- **同样严禁覆盖 `#footer`**
- `placement`: `left | right | top | bottom`(默认 `right`)
- 关闭前校验用 `onBeforeClose`(支持 Promise);需要重置内部状态可开 `destroyOnClose`
- 关闭前校验用 `onBeforeClose`(支持 Promise / 返回 `false`);需要重置内部状态可开 `destroyOnClose`
- 挂内容区同样要配合 Page 的 `auto-content-height`
- 默认属性:`setDefaultDrawerProps`
@@ -224,8 +226,10 @@ const blob = await cropperRef.value?.getCropImage('image/jpeg', 0.9, 'blob');
## 与本仓库踩坑清单(必守)
1. Form 无 `setComponentProps` / 无 `resetFields`
2. Modal/Drawer 禁止覆盖 `#footer`;提交用 `lock/unlock`
2. Modal/Drawer 禁止覆盖 `#footer`;提交用 `lock/unlock`(5.7 基线,无需再判断版本)
3. 表格返回必须是 `{ items, total }`;刷新分清 `query` vs `reload`
4. 字段名 `fieldName` 用后端 snake_case(如 `created_at`、`nick_name`)
5. 状态枚举与后端一致:**0 正常 / 1 禁用**
6. 暗色主题:业务样式用 CSS 变量,禁止写死亮色色值(见 `Code-Standards.mdc`)
7. Tailwind 已是 v4:业务样式优先主题 CSS 变量 / 现有 utility;不要新建 v3 的 `tailwind.config.*`
8. 业务 CRUD 只改 `apps/web-antd`;不要往 `web-ele` / `web-naive` / `web-antdv-next` 等演示端塞业务代码

16
.gitattributes vendored
View File

@@ -4,8 +4,18 @@
* text=auto eol=lf
# Declare files that will always have CRLF line endings on checkout.
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
*.cmd text eol=crlf
*.[cC][mM][dD] text eol=crlf
*.bat text eol=crlf
*.[bB][aA][tT] text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary
*.ico binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.webp binary
*.svg binary
*.woff binary
*.woff2 binary

View File

@@ -6,10 +6,10 @@ runs:
using: 'composite'
steps:
- name: Install pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@v6
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: .node-version
cache: 'pnpm'

3
.github/config.yml vendored
View File

@@ -21,12 +21,10 @@ newPRWelcomeComment: |
firstPRMergeComment: >
Thanks for your contribution! 🎉🎉🎉
# Comment to be posted to on first time issues
newIssueWelcomeComment: >
Thanks for opening your first issue! Be sure to follow the issue template and provide every bit of information to help the developers!
# *OPTIONAL* default titles to check against for lack of descriptiveness
# MUST BE ALL LOWERCASE
requestInfoDefaultTitles:
@@ -36,4 +34,3 @@ requestInfoDefaultTitles:
# *Required* Comment to reply with
requestInfoReplyComment: >
Thanks for filing this issue/PR! It would be much appreciated if you could provide us with more information so we can effectively analyze the situation in context.

View File

@@ -19,11 +19,9 @@ Project maintainers have the right and responsibility to remove, edit, or reject
- Checkout a topic branch from the relevant branch, e.g. main, and merge back against that branch.
- If adding a new feature:
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
- If fixing bug:
- Provide a detailed description of the bug in the PR. Live demo preferred.
- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.

View File

@@ -30,7 +30,7 @@ jobs:
- windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0

View File

@@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0

View File

@@ -28,12 +28,12 @@ jobs:
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@v6
with:
run_install: false
@@ -67,7 +67,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -90,7 +90,7 @@ jobs:
- windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0

View File

@@ -57,11 +57,11 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -89,6 +89,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: '/language:${{matrix.language}}'

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -30,7 +30,7 @@ jobs:
run: pnpm build:play
- name: Sync Playground files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
@@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -54,7 +54,7 @@ jobs:
run: pnpm build:docs
- name: Sync Docs files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
@@ -67,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -85,7 +85,7 @@ jobs:
run: pnpm run build:antd
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
@@ -98,7 +98,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -116,7 +116,7 @@ jobs:
run: pnpm run build:ele
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
@@ -129,7 +129,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -147,7 +147,7 @@ jobs:
run: pnpm run build:naive
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}

View File

@@ -20,6 +20,6 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v6
- uses: release-drafter/release-drafter@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -19,7 +19,7 @@ jobs:
steps:
# 关闭未活动的 Issues
- name: Close Inactive Issues
uses: actions/stale@v9
uses: actions/stale@v11
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: needs-reproduction # Label that flags an issue as stale.

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- name: remove enhancement pending
if: github.event.label.name == 'enhancement'
uses: actions-cool/issues-helper@v3
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
with:
actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}
@@ -27,7 +27,7 @@ jobs:
- name: remove bug pending
if: github.event.label.name == 'bug'
uses: actions-cool/issues-helper@v3
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
with:
actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}
@@ -36,7 +36,7 @@ jobs:
- name: needs reproduction
if: github.event.label.name == 'needs reproduction'
uses: actions-cool/issues-helper@v3
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
with:
actions: 'create-comment, remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -14,7 +14,7 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
- uses: dessant/lock-threads@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: '14'

View File

@@ -3,78 +3,48 @@ name: Create Release Tag
on:
push:
tags:
- 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10
env:
HUSKY: '0'
- 'v*.*.*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to create (e.g. v1.2.3)'
required: true
type: string
permissions:
pull-requests: write
contents: write
jobs:
build:
release:
name: Create Release
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20]
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
fetch-depth: 0
# - name: Checkout code
# uses: actions/checkout@v4
# with:
# fetch-depth: 0
# - name: Install pnpm
# uses: pnpm/action-setup@v4
# - name: Use Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v4
# with:
# node-version: ${{ matrix.node-version }}
# cache: "pnpm"
# - name: Install dependencies
# run: pnpm install --frozen-lockfile
# - name: Test and Build
# run: |
# pnpm run test
# pnpm run build
- name: version
- name: Extract version
id: version
run: |
tag=${GITHUB_REF/refs\/tags\//}
version=${tag#v}
major=${version%%.*}
echo "tag=${tag}" >> $GITHUB_OUTPUT
echo "version=${version}" >> $GITHUB_OUTPUT
echo "major=${major}" >> $GITHUB_OUTPUT
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
raw_tag="${{ inputs.tag }}"
else
raw_tag="${GITHUB_REF_NAME}"
fi
# Normalize: ensure v prefix
tag="${raw_tag}"
[[ "${tag:0:1}" != "v" ]] && tag="v${tag}"
version="${tag#v}"
major="${version%%.*}"
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "major=${major}" >> "${GITHUB_OUTPUT}"
- uses: release-drafter/release-drafter@v6
- uses: release-drafter/release-drafter@v7
with:
version: ${{ steps.version.outputs.version }}
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# - name: force update major tag
# run: |
# git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f
# git push origin refs/tags/v${{ steps.version.outputs.major }} -f
# - name: Create Release for Tag
# id: release_tag
# uses: ncipollo/release-action@v1
# with:
# token: ${{ secrets.GITHUB_TOKEN }}
# generateReleaseNotes: "true"
# body: |
# > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details.

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5
uses: amannn/action-semantic-pull-request@v6
with:
wip: true
subjectPattern: ^(?![A-Z]).+$

View File

@@ -9,7 +9,7 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
- uses: actions/stale@v11
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'

20
.gitignore vendored
View File

@@ -5,6 +5,11 @@ dist-ssr
dist.zip
dist.tar
dist.war
# 双品牌构建产物:build:brm / build:wl
dist-brm
dist-wl
dist-brm.zip
dist-wl.zip
.nitro
.output
*-dist.zip
@@ -22,7 +27,8 @@ yarn.lock
package-lock.json
.VSCodeCounter
**/backend-mock/data
.omx
.pnpm-store
# local env files
.env.local
.env.*.local
@@ -49,3 +55,15 @@ vite.config.ts.*
*.sln
*.sw?
.history
.cursor
# AI
.agent
.agents
.claude
.codex
skills-lock.json
.atomcode
datalog
.playwright-mcp
/apps/desktop/release/win-unpacked/

View File

@@ -1 +1 @@
22.1.0
24.16.0

20
.npmrc
View File

@@ -1,13 +1,7 @@
registry = "https://registry.npmmirror.com"
public-hoist-pattern[]=lefthook
public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier
public-hoist-pattern[]=prettier-plugin-tailwindcss
public-hoist-pattern[]=stylelint
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=@commitlint/*
public-hoist-pattern[]=czg
strict-peer-dependencies=false
auto-install-peers=true
dedupe-peer-dependents=true
registry=https://registry.npmmirror.com
# electron 二进制与 electron-builder 打包工具链走国内镜像(不配国内基本装不动)
# 注意:新版 @electron/get 只认环境变量,若 pnpm install 后 electron 二进制缺失,
# 手动补装:PowerShell 里 $env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
# 然后在 apps/desktop 下执行 node ./node_modules/electron/install.js
electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

View File

@@ -1,18 +0,0 @@
dist
dev-dist
.local
.output.js
node_modules
.nvmrc
coverage
CODEOWNERS
.nitro
.output
**/*.svg
**/*.sh
public
.npmrc
*-lock.yaml

View File

@@ -1 +0,0 @@
export { default } from '@vben/prettier-config';

View File

@@ -2,3 +2,7 @@ dist
public
__tests__
coverage
.codex
.claude
.agent
.agents

View File

@@ -2,14 +2,18 @@
"recommendations": [
// Vue 3 的语言支持
"Vue.volar",
// 将 ESLint JavaScript 集成到 VS Code 中。
// 将 eslint 集成到 VS Code 中。
"dbaeumer.vscode-eslint",
// 将 oxlint 集成到 VS Code 中。
"oxc.oxc-vscode",
// Visual Studio Code 的官方 Stylelint 扩展
"stylelint.vscode-stylelint",
// 使用 Prettier 的代码格式化程序
"esbenp.prettier-vscode",
// 使用 oxfmt 的代码格式化程序
"oxc.oxc-vscode",
// 支持 dotenv 文件语法
"mikestead.dotenv",
// YAML 语言支持,供 ESLint 校验 pnpm-workspace.yaml 等文件
"redhat.vscode-yaml",
// 源代码的拼写检查器
"streetsidesoftware.code-spell-checker",
// Tailwind CSS 的官方 VS Code 插件

70
.vscode/settings.json vendored
View File

@@ -1,5 +1,6 @@
{
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/theme.css",
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
// workbench
"workbench.list.smoothScrolling": true,
"workbench.startupEditor": "newUntitledFile",
@@ -31,39 +32,51 @@
"editor.autoClosingOvertype": "always",
"editor.autoClosingQuotes": "beforeWhitespace",
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
"editor.quickSuggestions": {
"strings": "on"
},
// lint && format
"oxc.enable": true,
"oxc.typeAware": true,
"oxc.configPath": "oxlint.config.ts",
"oxc.fmt.configPath": "oxfmt.config.ts",
"eslint.useFlatConfig": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.oxc": "explicit",
"source.fixAll.stylelint": "explicit",
"source.organizeImports": "never"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.defaultFormatter": "oxc.oxc-vscode",
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
// extensions
"extensions.ignoreRecommendations": true,
@@ -79,6 +92,7 @@
"files.insertFinalNewline": true,
"files.simpleDialog.enable": true,
"files.associations": {
"*.css": "tailwindcss",
"*.ejs": "html",
"*.art": "html",
"**/tsconfig.json": "jsonc",
@@ -118,7 +132,7 @@
// search
"search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false,
// 在使用搜索功能时,将这些文件夹/文件排除在外
// 使用搜索功能时,将这些文件和文件夹排除在外
"search.exclude": {
"**/node_modules": true,
"**/*.log": true,
@@ -158,7 +172,7 @@
"emmet.triggerExpansionOnTab": false,
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
"errorLens.excludeBySource": ["cSpell", "Grammarly"],
"stylelint.enable": true,
"stylelint.packageManager": "pnpm",
@@ -166,9 +180,10 @@
"stylelint.customSyntax": "postcss-html",
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
"typescript.inlayHints.enumMemberValues.enabled": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.preferences.includePackageJsonAutoImports": "on",
"js/ts.tsdk.path": "node_modules/typescript/lib",
"js/ts.inlayHints.enumMemberValues.enabled": true,
"js/ts.preferences.preferTypeOnlyAutoImports": true,
"js/ts.preferences.includePackageJsonAutoImports": "on",
"eslint.validate": [
"javascript",
@@ -180,7 +195,8 @@
"markdown",
"json",
"jsonc",
"json5"
"json5",
"yaml"
],
"tailwindCSS.experimental.classRegex": [
@@ -194,7 +210,7 @@
"yaml": false
},
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
"cssVariables.lookupFiles": ["packages/@core/base/design/src/**/*.css"],
"i18n-ally.localesPaths": [
"packages/locales/src/langs",
@@ -219,23 +235,9 @@
"*.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,lefthook.yml",
"tailwind.config.mjs": "postcss.*"
"oxlint.config.ts": ".eslintignore,.stylelintignore,.commitlintrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml,oxfmt.config.*,eslint.config.*"
},
"commentTranslate.hover.enabled": false,
"commentTranslate.multiLineMerge": true,
"vue.server.hybridMode": true,
"typescript.tsdk": "node_modules/typescript/lib",
"oxc.enable": false,
"cSpell.words": [
"archiver",
"axios",
"dotenv",
"isequal",
"jspm",
"napi",
"nolebase",
"rollup",
"vitest"
]
"vue.server.hybridMode": true
}

View File

@@ -114,7 +114,7 @@ pnpm build
## ブラウザサポート
ローカル開発には `Chrome 80+` ブラウザを推奨します
Tailwind CSS v4.0 is designed for Safari 16.4+, Chrome 111+, and Firefox 128+
モダンブラウザをサポートし、IEはサポートしません
@@ -140,8 +140,12 @@ pnpm build
## 貢献者
<a href="https://openomy.app/github/vbenjs/vue-vben-admin" target="_blank" style="display: block; width: 100%;" align="center">
<img src="https://openomy.app/svg?repo=vbenjs/vue-vben-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
</a>
<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://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
</a>
## Discord

View File

@@ -1 +1,67 @@
# 奶酪云后台管理脚手架
# lgp-admin-plus
LGP 管理后台前端(Vben Admin 5.7 / `apps/web-antd`)。
两个家具品牌共用一套代码,靠构建模式区分。
| 品牌 | 命令后缀 | AppID | 产出目录 |
|---|---|---|---|
| 佛山铂尔曼 | `brm` | `wx679d36842570cea7` | `apps/web-antd/dist-brm` |
| 维伦家具 | `wl` | `wx57b54060a579c31a` | `apps/web-antd/dist-wl` |
包管理器:**pnpm**(不要用 npm / yarn)。
## 准备
```bash
pnpm install
```
## 启动(两种)
在仓库根目录执行:
```bash
# 1)佛山铂尔曼 —— 读 .env.brm(标题 / Logo / 品牌色)
pnpm dev:brm
# 2)维伦家具 —— 读 .env.wl
pnpm dev:wl
```
默认开发端口见 `apps/web-antd/vite.config.ts`(当前 **14002**)。
接口代理:`/api` → 本地后端 `http://127.0.0.1:18004/api/`。
> 仅调试、不区分品牌时可用 `pnpm dev`(`development` 模式,默认品牌仍是铂尔曼)。
## 打包(两种)
```bash
# 1)佛山铂尔曼 → apps/web-antd/dist-brm(并可能产出 zip)
pnpm build:brm
# 2)维伦家具 → apps/web-antd/dist-wl
pnpm build:wl
```
一次打两个品牌:
```bash
pnpm build:brands
```
两个品牌 **outDir 必须分开**,否则会互相覆盖。上线前按品牌分别回归。
## 环境文件
| 文件 | 用途 |
|---|---|
| `apps/web-antd/.env.brm` | 铂尔曼生产构建 / `dev:brm` |
| `apps/web-antd/.env.wl` | 维伦生产构建 / `dev:wl` |
| `apps/web-antd/.env.development` | 通用本地开发(`pnpm dev`) |
品牌相关变量:`VITE_APP_BRAND`、`VITE_APP_TITLE`、`VITE_APP_FAVICON`、`VITE_GLOB_API_URL`。
## 后端
配套 API:`lgp-admin-plus-api`(Laravel 13)。
库表变更走 `database/sql/<YYYY-MM-DD>/01_名字.sql`,不要新建 PHP Migration。

View File

@@ -114,7 +114,7 @@ pnpm build
## 浏览器支持
本地开发推荐使用 `Chrome 80+` 浏览器
Tailwind CSS v4.0 is designed for Safari 16.4+, Chrome 111+, and Firefox 128+
支持现代浏览器,不支持 IE
@@ -140,8 +140,12 @@ pnpm build
## 贡献者
<a href="https://openomy.app/github/vbenjs/vue-vben-admin" target="_blank" style="display: block; width: 100%;" align="center">
<img src="https://openomy.app/svg?repo=vbenjs/vue-vben-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
</a>
<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://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
</a>
## Discord

View File

@@ -1,5 +1,7 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
import { MOCK_CODES } from '~/utils/mock-data';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);

View File

@@ -1,9 +1,15 @@
import { defineEventHandler, readBody, setResponseStatus } from 'h3';
import {
clearRefreshTokenCookie,
setRefreshTokenCookie,
} from '~/utils/cookie-utils';
import { generateAccessToken, generateRefreshToken } from '~/utils/jwt-utils';
import { forbiddenResponse } from '~/utils/response';
import { MOCK_USERS } from '~/utils/mock-data';
import {
forbiddenResponse,
useResponseError,
useResponseSuccess,
} from '~/utils/response';
export default defineEventHandler(async (event) => {
const { password, username } = await readBody(event);

View File

@@ -1,7 +1,9 @@
import { defineEventHandler } from 'h3';
import {
clearRefreshTokenCookie,
getRefreshTokenFromCookie,
} from '~/utils/cookie-utils';
import { useResponseSuccess } from '~/utils/response';
export default defineEventHandler(async (event) => {
const refreshToken = getRefreshTokenFromCookie(event);

View File

@@ -1,9 +1,11 @@
import { defineEventHandler } from 'h3';
import {
clearRefreshTokenCookie,
getRefreshTokenFromCookie,
setRefreshTokenCookie,
} from '~/utils/cookie-utils';
import { verifyRefreshToken } from '~/utils/jwt-utils';
import { generateAccessToken, verifyRefreshToken } from '~/utils/jwt-utils';
import { MOCK_USERS } from '~/utils/mock-data';
import { forbiddenResponse } from '~/utils/response';
export default defineEventHandler(async (event) => {

View File

@@ -0,0 +1,32 @@
import { eventHandler, setHeader } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
export default eventHandler(async (event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const data = `
{
"code": 0,
"message": "success",
"data": [
{
"id": 123456789012345678901234567890123456789012345678901234567890,
"name": "John Doe",
"age": 30,
"email": "john-doe@demo.com"
},
{
"id": 987654321098765432109876543210987654321098765432109876543210,
"name": "Jane Smith",
"age": 25,
"email": "jane@demo.com"
}
]
}
`;
setHeader(event, 'Content-Type', 'application/json');
return data;
});

View File

@@ -1,5 +1,7 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
import { MOCK_MENUS } from '~/utils/mock-data';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
export default eventHandler(async (event) => {
const userinfo = verifyAccessToken(event);

View File

@@ -1,3 +1,6 @@
import { eventHandler, getQuery, setResponseStatus } from 'h3';
import { useResponseError } from '~/utils/response';
export default eventHandler((event) => {
const { status } = getQuery(event);
setResponseStatus(event, Number(status));

View File

@@ -1,3 +1,4 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import {
sleep,

View File

@@ -1,3 +1,4 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import {
sleep,

View File

@@ -1,3 +1,4 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import {
sleep,

View File

@@ -1,4 +1,5 @@
import { faker } from '@faker-js/faker';
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';

View File

@@ -1,3 +1,4 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { MOCK_MENU_LIST } from '~/utils/mock-data';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';

View File

@@ -1,6 +1,7 @@
import { eventHandler, getQuery } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { MOCK_MENU_LIST } from '~/utils/mock-data';
import { unAuthorizedResponse } from '~/utils/response';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
const namesMap: Record<string, any> = {};

View File

@@ -1,6 +1,7 @@
import { eventHandler, getQuery } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { MOCK_MENU_LIST } from '~/utils/mock-data';
import { unAuthorizedResponse } from '~/utils/response';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
const pathMap: Record<string, any> = { '/': 0 };

View File

@@ -1,4 +1,5 @@
import { faker } from '@faker-js/faker';
import { eventHandler, getQuery } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { getMenuIds, MOCK_MENU_LIST } from '~/utils/mock-data';
import { unAuthorizedResponse, usePageResponseSuccess } from '~/utils/response';

View File

@@ -0,0 +1,85 @@
import { faker } from '@faker-js/faker';
import { eventHandler, getQuery } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse, usePageResponseSuccess } from '~/utils/response';
const formatterCN = new Intl.DateTimeFormat('zh-CN', {
timeZone: 'Asia/Shanghai',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
function generateMockDataList(count: number) {
const dataList = [];
for (let i = 0; i < count; i++) {
const dataItem: Record<string, any> = {
id: faker.string.uuid(),
name: faker.commerce.product(),
status: faker.helpers.arrayElement([0, 1]),
createTime: formatterCN.format(
faker.date.between({ from: '2022-01-01', to: '2025-01-01' }),
),
deptId: faker.string.uuid(),
remark: faker.lorem.sentence(),
};
dataList.push(dataItem);
}
return dataList;
}
const mockData = generateMockDataList(100);
export default eventHandler(async (event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const {
page = 1,
pageSize = 20,
name,
id,
remark,
startTime,
endTime,
deptId,
status,
} = getQuery(event);
let listData = structuredClone(mockData);
if (name) {
listData = listData.filter((item) =>
item.name.toLowerCase().includes(String(name).toLowerCase()),
);
}
if (id) {
listData = listData.filter((item) =>
item.id.toLowerCase().includes(String(id).toLowerCase()),
);
}
if (remark) {
listData = listData.filter((item) =>
item.remark?.toLowerCase()?.includes(String(remark).toLowerCase()),
);
}
if (startTime) {
listData = listData.filter((item) => item.createTime >= startTime);
}
if (endTime) {
listData = listData.filter((item) => item.createTime <= endTime);
}
if (['0', '1'].includes(status as string)) {
listData = listData.filter((item) => item.status === Number(status));
}
if (deptId) {
listData = listData.filter((item) => item.deptId === deptId);
}
return usePageResponseSuccess(page as string, pageSize as string, listData);
});

View File

@@ -1,6 +1,11 @@
import { faker } from '@faker-js/faker';
import { eventHandler, getQuery } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse, usePageResponseSuccess } from '~/utils/response';
import {
sleep,
unAuthorizedResponse,
usePageResponseSuccess,
} from '~/utils/response';
function generateMockDataList(count: number) {
const dataList = [];
@@ -44,30 +49,69 @@ export default eventHandler(async (event) => {
await sleep(600);
const { page, pageSize, sortBy, sortOrder } = getQuery(event);
// 规范化分页参数,处理 string[]
const pageRaw = Array.isArray(page) ? page[0] : page;
const pageSizeRaw = Array.isArray(pageSize) ? pageSize[0] : pageSize;
const pageNumber = Math.max(
1,
Number.parseInt(String(pageRaw ?? '1'), 10) || 1,
);
const pageSizeNumber = Math.min(
100,
Math.max(1, Number.parseInt(String(pageSizeRaw ?? '10'), 10) || 10),
);
const listData = structuredClone(mockData);
if (sortBy && Reflect.has(listData[0], sortBy as string)) {
// 规范化 query 入参,兼容 string[]
const sortKeyRaw = Array.isArray(sortBy) ? sortBy[0] : sortBy;
const sortOrderRaw = Array.isArray(sortOrder) ? sortOrder[0] : sortOrder;
// 检查 sortBy 是否是 listData 元素的合法属性键
if (
typeof sortKeyRaw === 'string' &&
listData[0] &&
Object.prototype.hasOwnProperty.call(listData[0], sortKeyRaw)
) {
// 定义数组元素的类型
type ItemType = (typeof listData)[0];
const sortKey = sortKeyRaw as keyof ItemType; // 将 sortBy 断言为合法键
const isDesc = sortOrderRaw === 'desc';
listData.sort((a, b) => {
if (sortOrder === 'asc') {
if (sortBy === 'price') {
return (
Number.parseFloat(a[sortBy as string]) -
Number.parseFloat(b[sortBy as string])
);
const aValue = a[sortKey] as unknown;
const bValue = b[sortKey] as unknown;
let result: number;
if (typeof aValue === 'number' && typeof bValue === 'number') {
result = aValue - bValue;
} else if (aValue instanceof Date && bValue instanceof Date) {
result = aValue.getTime() - bValue.getTime();
} else if (typeof aValue === 'boolean' && typeof bValue === 'boolean') {
if (aValue === bValue) {
result = 0;
} else {
return a[sortBy as string] > b[sortBy as string] ? 1 : -1;
result = aValue ? 1 : -1;
}
} else {
if (sortBy === 'price') {
return (
Number.parseFloat(b[sortBy as string]) -
Number.parseFloat(a[sortBy as string])
);
} else {
return a[sortBy as string] < b[sortBy as string] ? 1 : -1;
}
const aStr = String(aValue);
const bStr = String(bValue);
const aNum = Number(aStr);
const bNum = Number(bStr);
result =
Number.isFinite(aNum) && Number.isFinite(bNum)
? aNum - bNum
: aStr.localeCompare(bStr, undefined, {
numeric: true,
sensitivity: 'base',
});
}
return isDesc ? -result : result;
});
}
return usePageResponseSuccess(page as string, pageSize as string, listData);
return usePageResponseSuccess(
String(pageNumber),
String(pageSizeNumber),
listData,
);
});

View File

@@ -1 +1,3 @@
import { defineEventHandler } from 'h3';
export default defineEventHandler(() => 'Test get handler');

View File

@@ -1 +1,3 @@
import { defineEventHandler } from 'h3';
export default defineEventHandler(() => 'Test post handler');

View File

@@ -0,0 +1,12 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
import { getTimezone } from '~/utils/timezone-utils';
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
return useResponseSuccess(getTimezone());
});

View File

@@ -0,0 +1,11 @@
import { eventHandler } from 'h3';
import { TIME_ZONE_OPTIONS } from '~/utils/mock-data';
import { useResponseSuccess } from '~/utils/response';
export default eventHandler(() => {
const data = TIME_ZONE_OPTIONS.map((o) => ({
label: `${o.timezone} (GMT${o.offset >= 0 ? `+${o.offset}` : o.offset})`,
value: o.timezone,
}));
return useResponseSuccess(data);
});

View File

@@ -0,0 +1,26 @@
import { eventHandler, readBody, setResponseStatus } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { TIME_ZONE_OPTIONS } from '~/utils/mock-data';
import {
unAuthorizedResponse,
useResponseError,
useResponseSuccess,
} from '~/utils/response';
import { setTimezone } from '~/utils/timezone-utils';
export default eventHandler(async (event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}
const body = await readBody<{ timezone?: unknown }>(event);
const timezone =
typeof body?.timezone === 'string' ? body.timezone : undefined;
const allowed = TIME_ZONE_OPTIONS.some((o) => o.timezone === timezone);
if (!timezone || !allowed) {
setResponseStatus(event, 400);
return useResponseError('Bad Request', 'Invalid timezone');
}
setTimezone(timezone);
return useResponseSuccess({});
});

View File

@@ -1,5 +1,6 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);

View File

@@ -1,5 +1,6 @@
import { eventHandler } from 'h3';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';
import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response';
export default eventHandler((event) => {
const userinfo = verifyAccessToken(event);

View File

@@ -1,3 +1,4 @@
import { defineEventHandler } from 'h3';
import { forbiddenResponse, sleep } from '~/utils/response';
export default defineEventHandler(async (event) => {

View File

@@ -1,3 +1,5 @@
import { defineNitroConfig } from 'nitropack/config';
import errorHandler from './error';
process.env.COMPATIBILITY_DATE = new Date().toISOString();

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/backend-mock",
"version": "0.0.1",
"version": "5.7.0",
"description": "",
"private": true,
"license": "MIT",

View File

@@ -1,13 +1,15 @@
import { defineEventHandler } from 'h3';
export default defineEventHandler(() => {
return `
<h1>Hello Vben Admin</h1>
<h2>Mock service is starting</h2>
<h2>Mock service is running</h2>
<ul>
<li><a href="/api/user">/api/user/info</a></li>
<li><a href="/api/menu">/api/menu/all</a></li>
<li><a href="/api/auth/codes">/api/auth/codes</a></li>
<li><a href="/api/auth/login">/api/auth/login</a></li>
<li><a href="/api/upload">/api/upload</a></li>
<li><a href="/api/auth/codes">/api/auth/codes</a></li>
<li><a href="/api/user/info">/api/user/info</a></li>
<li><a href="/api/menu/all">/api/menu/all</a></li>
<li><a href="/api/auth/logout">/api/auth/logout</a></li>
</ul>
`;
});

View File

@@ -1,3 +1,11 @@
{
"extends": "./.nitro/types/tsconfig.json"
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"compilerOptions": {
"paths": {
"~/*": ["./*"]
}
},
"include": ["**/*.ts", "**/.*.ts"],
"exclude": ["node_modules", "dist", ".nitro"]
}

View File

@@ -1,5 +1,7 @@
import type { EventHandlerRequest, H3Event } from 'h3';
import { deleteCookie, getCookie, setCookie } from 'h3';
export function clearRefreshTokenCookie(event: H3Event<EventHandlerRequest>) {
deleteCookie(event, 'jwt', {
httpOnly: true,

View File

@@ -1,8 +1,11 @@
import type { EventHandlerRequest, H3Event } from 'h3';
import type { UserInfo } from './mock-data';
import { getHeader } from 'h3';
import jwt from 'jsonwebtoken';
import { UserInfo } from './mock-data';
import { MOCK_USERS } from './mock-data';
// TODO: Replace with your own secret key
const ACCESS_TOKEN_SECRET = 'access_token_secret';
@@ -31,12 +34,22 @@ export function verifyAccessToken(
return null;
}
const token = authHeader.split(' ')[1];
const tokenParts = authHeader.split(' ');
if (tokenParts.length !== 2) {
return null;
}
const token = tokenParts[1] as string;
try {
const decoded = jwt.verify(token, ACCESS_TOKEN_SECRET) as UserPayload;
const decoded = jwt.verify(
token,
ACCESS_TOKEN_SECRET,
) as unknown as UserPayload;
const username = decoded.username;
const user = MOCK_USERS.find((item) => item.username === username);
if (!user) {
return null;
}
const { password: _pwd, ...userinfo } = user;
return userinfo;
} catch {
@@ -50,7 +63,12 @@ export function verifyRefreshToken(
try {
const decoded = jwt.verify(token, REFRESH_TOKEN_SECRET) as UserPayload;
const username = decoded.username;
const user = MOCK_USERS.find((item) => item.username === username);
const user = MOCK_USERS.find(
(item) => item.username === username,
) as UserInfo;
if (!user) {
return null;
}
const { password: _pwd, ...userinfo } = user;
return userinfo;
} catch {

View File

@@ -7,6 +7,11 @@ export interface UserInfo {
homePath?: string;
}
export interface TimezoneOption {
offset: number;
timezone: string;
}
export const MOCK_USERS: UserInfo[] = [
{
id: 0,
@@ -14,6 +19,7 @@ export const MOCK_USERS: UserInfo[] = [
realName: 'Vben',
roles: ['super'],
username: 'vben',
homePath: '/dashboard/workspace',
},
{
id: 1,
@@ -21,7 +27,7 @@ export const MOCK_USERS: UserInfo[] = [
realName: 'Admin',
roles: ['admin'],
username: 'admin',
homePath: '/workspace',
homePath: '/dashboard/workspace',
},
{
id: 2,
@@ -29,7 +35,7 @@ export const MOCK_USERS: UserInfo[] = [
realName: 'Jack',
roles: ['user'],
username: 'jack',
homePath: '/analytics',
homePath: '/dashboard/analytics',
},
];
@@ -59,11 +65,11 @@ const dashboardMenus = [
},
name: 'Dashboard',
path: '/dashboard',
redirect: '/analytics',
redirect: '/dashboard/analytics',
children: [
{
name: 'Analytics',
path: '/analytics',
path: 'analytics',
component: '/dashboard/analytics/index',
meta: {
affixTab: true,
@@ -72,7 +78,7 @@ const dashboardMenus = [
},
{
name: 'Workspace',
path: '/workspace',
path: 'workspace',
component: '/dashboard/workspace/index',
meta: {
title: 'page.dashboard.workspace',
@@ -91,7 +97,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
title: 'demos.access.adminVisible',
},
name: 'AccessAdminVisibleDemo',
path: '/demos/access/admin-visible',
path: 'admin-visible',
},
super: {
component: '/demos/access/super-visible',
@@ -100,7 +106,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
title: 'demos.access.superVisible',
},
name: 'AccessSuperVisibleDemo',
path: '/demos/access/super-visible',
path: 'super-visible',
},
user: {
component: '/demos/access/user-visible',
@@ -109,7 +115,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
title: 'demos.access.userVisible',
},
name: 'AccessUserVisibleDemo',
path: '/demos/access/user-visible',
path: 'user-visible',
},
};
@@ -127,7 +133,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
children: [
{
name: 'AccessDemos',
path: '/demosaccess',
path: 'access',
meta: {
icon: 'mdi:cloud-key-outline',
title: 'demos.access.backendPermissions',
@@ -136,7 +142,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
children: [
{
name: 'AccessPageControlDemo',
path: '/demos/access/page-control',
path: 'page-control',
component: '/demos/access/index',
meta: {
icon: 'mdi:page-previous-outline',
@@ -145,7 +151,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
},
{
name: 'AccessButtonControlDemo',
path: '/demos/access/button-control',
path: 'button-control',
component: '/demos/access/button-control',
meta: {
icon: 'mdi:button-cursor',
@@ -154,7 +160,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
},
{
name: 'AccessMenuVisible403Demo',
path: '/demos/access/menu-visible-403',
path: 'menu-visible-403',
component: '/demos/access/menu-visible-403',
meta: {
authority: ['no-body'],
@@ -189,18 +195,46 @@ export const MOCK_MENUS = [
export const MOCK_MENU_LIST = [
{
id: 1,
name: 'Workspace',
name: 'Dashboard',
status: 1,
type: 'menu',
icon: 'mdi:dashboard',
path: '/workspace',
component: '/dashboard/workspace/index',
type: 'catalog',
icon: 'lucide:layout-dashboard',
path: '/dashboard',
meta: {
icon: 'carbon:workspace',
title: 'page.dashboard.workspace',
affixTab: true,
order: 0,
icon: 'lucide:layout-dashboard',
order: -1,
title: 'page.dashboard.title',
},
children: [
{
id: 101,
pid: 1,
status: 1,
type: 'menu',
name: 'Analytics',
path: 'analytics',
component: '/dashboard/analytics/index',
meta: {
affixTab: true,
icon: 'lucide:area-chart',
title: 'page.dashboard.analytics',
keepAlive: true,
},
},
{
id: 102,
pid: 1,
status: 1,
type: 'menu',
name: 'Workspace',
path: 'workspace',
component: '/views/dashboard/workspace/index',
meta: {
icon: 'carbon:workspace',
title: 'page.dashboard.workspace',
},
},
],
},
{
id: 2,
@@ -276,7 +310,7 @@ export const MOCK_MENU_LIST = [
children: [
{
id: 20_401,
pid: 201,
pid: 202,
name: 'SystemDeptCreate',
status: 1,
type: 'button',
@@ -285,7 +319,7 @@ export const MOCK_MENU_LIST = [
},
{
id: 20_402,
pid: 201,
pid: 202,
name: 'SystemDeptEdit',
status: 1,
type: 'button',
@@ -294,7 +328,7 @@ export const MOCK_MENU_LIST = [
},
{
id: 20_403,
pid: 201,
pid: 202,
name: 'SystemDeptDelete',
status: 1,
type: 'button',
@@ -388,3 +422,29 @@ export function getMenuIds(menus: any[]) {
});
return ids;
}
/**
* 时区选项
*/
export const TIME_ZONE_OPTIONS: TimezoneOption[] = [
{
offset: -5,
timezone: 'America/New_York',
},
{
offset: 0,
timezone: 'Europe/London',
},
{
offset: 8,
timezone: 'Asia/Shanghai',
},
{
offset: 9,
timezone: 'Asia/Tokyo',
},
{
offset: 9,
timezone: 'Asia/Seoul',
},
];

View File

@@ -1,5 +1,7 @@
import type { EventHandlerRequest, H3Event } from 'h3';
import { setResponseStatus } from 'h3';
export function useResponseSuccess<T = any>(data: T) {
return {
code: 0,

View File

@@ -0,0 +1,9 @@
let mockTimeZone: null | string = null;
export const setTimezone = (timeZone: string) => {
mockTimeZone = timeZone;
};
export const getTimezone = () => {
return mockTimeZone;
};

View File

@@ -0,0 +1,6 @@
# ????????????
# ?????pnpm build:desktop:dev?electron-vite build --mode development?? electron-vite dev
# MAIN_VITE_ ?? = ???????electron-vite ???
# /api ?????????????nl-admin-api????????????
MAIN_VITE_API_UPSTREAM=http://127.0.0.1:18006/api

View File

@@ -0,0 +1,6 @@
# ????????????
# ?????pnpm build:desktop?electron-vite build ?? production ???
# TODO(???)??? /api ??????????????????????
# ????????????????????????
MAIN_VITE_API_UPSTREAM=http://127.0.0.1:18006/api

View File

@@ -0,0 +1,76 @@
# electron-builder 打包配置(Windows + macOS 双平台)
#
# 签名/公证完全由环境变量驱动,本文件不写死任何证书:
# - 配置了 CSC_LINK + CSC_KEY_PASSWORD(或 mac 钥匙串里有 Developer ID 证书)→ 自动签名;
# 没配置则 electron-builder 自动跳过签名,只告警不报错(出未签名包)
# - APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD + APPLE_TEAM_ID 三者齐全 → 自动公证;缺任一则跳过
# - 未签名 mac 包首次打开需右键「打开」,自动更新由 updater.ts 降级为手动下载引导
#
# 注意:mac 包必须在 macOS 机器上构建(不支持从 Windows 交叉编译),命令同一条 pnpm build:desktop
# 必须与 src/main/config.ts 的 APP_ID 一致(Windows 通知 AUMID 对齐)
appId: com.nladmin.desktop
productName: Nl Admin
directories:
output: release
buildResources: resources
# 只打 electron-vite 产物:运行时依赖已全部打进 out/,asar 里无需 node_modules
files:
- out/**
extraResources:
# web-antd 生产 dist → resources/web(app:// 协议的静态根;不进 asar,为后续渲染层热替换留路)
- from: ../web-antd/dist
to: web
# 应用图标供运行时使用(托盘 / 通知 / 窗口图标)
- from: resources/icon.png
to: icon.png
asar: true
# dependencies 为空(依赖全部打进 out/),跳过原生依赖重建
npmRebuild: false
# 产物名不带空格,避免更新托管 URL 转义问题
artifactName: nl-admin-desktop-${version}-${os}-${arch}.${ext}
win:
# 提供 ≥512px 的 png,electron-builder 自动转 .ico
icon: resources/icon.png
target:
- target: nsis
arch:
- x64
nsis:
# 非一键安装:允许用户选择安装目录
oneClick: false
allowToChangeInstallationDirectory: true
# 开始菜单快捷方式是 Windows 通知(AUMID)生效的前提,必须保留
createDesktopShortcut: always
createStartMenuShortcut: true
shortcutName: Nl Admin
mac:
# 同一张 png 自动转 .icns
icon: resources/icon.png
category: public.app-category.business
# 公证的前置要求;配合基础 entitlements(无摄像头/麦克风,本项目无音视频)
hardenedRuntime: true
gatekeeperAssess: false
entitlements: resources/entitlements.mac.plist
entitlementsInherit: resources/entitlements.mac.plist
target:
# zip 是 mac 自动更新(latest-mac.yml)的必需格式,dmg 用于人工分发安装
- target: dmg
arch:
- x64
- arm64
- target: zip
arch:
- x64
- arm64
dmg:
# dmg 容器本身不签名(zip 内的 .app 已按环境变量策略签名),减少无证书时的干扰告警
sign: false
publish:
# generic 静态托管:目录里放 latest.yml / latest-mac.yml / 安装包 / blockmap 即可
# TODO(待确认):与 src/main/config.ts 的 UPDATE_URL 保持一致
provider: generic
url: https://updates.example.com/nl-desktop/

View File

@@ -0,0 +1,34 @@
import { defineConfig } from 'electron-vite';
/**
* electron-vite 构建配置
*
* 为什么不配置 renderer:
* 渲染层不由本工程构建——开发期直接加载 web-antd 的 vite dev server(http://localhost:14002),
* 生产期通过 app:// 自定义协议加载 web-antd 的生产 dist(electron-builder extraResources 拷入)。
*
* 为什么不用 externalizeDepsPlugin:
* 故意把 electron-updater / electron-log / electron-store 等运行时依赖全部打进 out/ 产物,
* 使应用的 dependencies 为空,electron-builder 无需收集 node_modules,
* 从而规避 pnpm 软链目录结构在打包期的兼容问题(asar 里只有 out/ 与 package.json)。
*/
export default defineConfig({
main: {
build: {
outDir: 'out/main',
},
},
preload: {
build: {
outDir: 'out/preload',
rollupOptions: {
output: {
// sandbox: true 的 preload 必须是 CommonJS(Electron 硬性限制),
// 这里锁定输出为 index.cjs,主进程按该文件名引用
format: 'cjs',
entryFileNames: '[name].cjs',
},
},
},
},
});

26913
apps/desktop/out/main/index.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
//#region \0rolldown/runtime.js
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
//#endregion
//#region src/preload/index.ts
var import_electron = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
var { spawnSync } = require("child_process");
var fs = require("fs");
var path = require("path");
var pathFile = path.join(__dirname, "path.txt");
function downloadElectron() {
console.log("Downloading Electron binary...");
if (spawnSync(process.execPath, [path.join(__dirname, "install.js")], { stdio: "inherit" }).status !== 0) throw new Error("Electron failed to install correctly. Please delete `node_modules/electron` and run \"npx install-electron --no\" manually.");
}
/**
* Fetches the path to the Electron executable to use in development mode.
* If the executable is missing, attempt to download it first.
*
* @returns the path to the Electron executable to run
*/
function getElectronPath() {
let executablePath;
if (fs.existsSync(pathFile)) executablePath = fs.readFileSync(pathFile, "utf-8");
if (process.env.ELECTRON_OVERRIDE_DIST_PATH) return path.join(process.env.ELECTRON_OVERRIDE_DIST_PATH, executablePath || "electron");
if (executablePath) {
const fullPath = path.join(__dirname, "dist", executablePath);
if (!fs.existsSync(fullPath)) downloadElectron();
return fullPath;
} else {
try {
downloadElectron();
} catch {
throw new Error("Electron failed to install correctly. Please delete `node_modules/electron` and run \"npx install-electron --no\" manually.");
}
executablePath = fs.readFileSync(pathFile, "utf-8");
return path.join(__dirname, "dist", executablePath);
}
}
module.exports = getElectronPath();
})))();
/**
* 用 canvas 绘制 Windows 任务栏角标覆盖图(红底白字数字),返回 dataURL
* 为什么在 preload 画:主进程没有 DOM canvas,nativeImage 也不能绘制文字;
* preload 跑在渲染进程里有完整 DOM 能力,画完把 dataURL 交给主进程 setOverlayIcon
*/
function drawBadgeDataURL(count) {
const size = 32;
const canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext("2d");
if (!ctx) return "";
const text = count > 99 ? "99+" : String(count);
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
ctx.fillStyle = "#f5222d";
ctx.fill();
ctx.fillStyle = "#ffffff";
ctx.font = `bold ${text.length > 2 ? 13 : 18}px sans-serif`;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, size / 2, 17);
return canvas.toDataURL("image/png");
}
/** 订阅主进程推送事件的通用封装,返回取消订阅函数(组件卸载时记得调用防止泄漏) */
function subscribe(channel, callback) {
const listener = (_event, payload) => callback(payload);
import_electron.ipcRenderer.on(channel, listener);
return () => import_electron.ipcRenderer.removeListener(channel, listener);
}
var desktopAPI = {
/** 恒为 true,web 侧用它判断是否运行在 Electron 壳内 */
isElectron: true,
/** 当前平台:win32 / darwin / linux(渲染层做平台差异 UI 时用) */
platform: process.platform,
/** 应用版本号(package.json version,用于「关于」展示) */
getVersion: () => import_electron.ipcRenderer.invoke("desktop:get-version"),
/**
* 发系统通知;route 传入站内路由(如 /notice/list)时点击通知会唤起窗口并跳转
* flash 默认 true:窗口未聚焦时同时闪烁任务栏(mac 表现为 Dock 弹跳)
*/
notify: (options) => import_electron.ipcRenderer.invoke("desktop:notify", options),
/** 设置未读角标数,0 清除;mac 用 Dock 原生数字,Windows 用 canvas 画的覆盖图 */
setBadge: (count) => {
const dataUrl = count > 0 && process.platform === "win32" ? drawBadgeDataURL(count) : "";
return import_electron.ipcRenderer.invoke("desktop:set-badge", count, dataUrl);
},
/** 手动控制任务栏闪烁(一般用不到,notify 已内置) */
flashFrame: (flag = true) => import_electron.ipcRenderer.invoke("desktop:flash-frame", flag),
/** 读取开机自启状态 */
getAutoLaunch: () => import_electron.ipcRenderer.invoke("desktop:get-auto-launch"),
/** 设置开机自启(--hidden 静默启动进托盘) */
setAutoLaunch: (enabled) => import_electron.ipcRenderer.invoke("desktop:set-auto-launch", enabled),
/** 枚举系统打印机列表 */
getPrinters: () => import_electron.ipcRenderer.invoke("desktop:get-printers"),
/**
* 打印一段完整 HTML:不传 deviceName 时读持久化的默认打印机;
* silent=true 静默打印,false 弹系统打印对话框
*/
printHTML: (options) => import_electron.ipcRenderer.invoke("desktop:print-html", options),
/** 读桌面端本地设置(如默认打印机) */
getSetting: (key) => import_electron.ipcRenderer.invoke("desktop:get-setting", key),
/** 写桌面端本地设置 */
setSetting: (key, value) => import_electron.ipcRenderer.invoke("desktop:set-setting", key, value),
/** 手动检查更新(托盘菜单也有同款入口) */
checkUpdate: () => import_electron.ipcRenderer.invoke("desktop:check-update"),
/** 更新下载完成后立即重启安装 */
quitAndInstall: () => import_electron.ipcRenderer.invoke("desktop:quit-and-install"),
/** 订阅「点击通知要求跳转路由」事件,web 侧收到后自行 router.push */
onNavigate: (callback) => subscribe("desktop:navigate", callback),
/** 订阅更新流程事件(checking / available / progress / downloaded 等),用于展示进度 */
onUpdateEvent: (callback) => subscribe("desktop:update-event", callback)
};
import_electron.contextBridge.exposeInMainWorld("desktopAPI", desktopAPI);
//#endregion

29
apps/desktop/package.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "@vben/desktop",
"version": "1.0.0",
"private": true,
"description": "Nl Admin 桌面端壳工程:app:// 协议复用 web-antd 生产 dist,主进程转发 /api 到后端",
"productName": "Nl Admin",
"author": "nl-admin",
"type": "module",
"main": "out/main/index.js",
"scripts": {
"dev": "electron-vite dev --watch",
"build": "electron-vite build && electron-builder --config electron-builder.yml --publish never",
"build:dev": "electron-vite build --mode development && electron-builder --config electron-builder.yml --publish never -c.artifactName=nl-admin-desktop-${version}-${os}-${arch}-dev.${ext}",
"build:dir": "electron-vite build && electron-builder --dir --config electron-builder.yml",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/node": "catalog:",
"@vben/web-antd": "workspace:*",
"electron": "catalog:",
"electron-builder": "catalog:",
"electron-log": "catalog:",
"electron-store": "catalog:",
"electron-updater": "catalog:",
"electron-vite": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -0,0 +1,228 @@
x64:
firstOrDefaultFilePatterns:
- '!**/node_modules/**'
- '!resources{,/**/*}'
- '!release{,/**/*}'
- out/**
- package.json
- '!**/*.{iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts,mk,a,o,obj,forge-meta,pdb}'
- '!**/._*'
- '!**/electron-builder.{yaml,yml,json,json5,toml,ts}'
- '!**/{.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,.DS_Store,thumbs.db,.gitignore,.gitkeep,.gitattributes,.npmignore,.idea,.vs,.flowconfig,.jshintrc,.eslintrc,.circleci,.yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log,pnpm-lock.yaml,bun.lock,bun.lockb,appveyor.yml,.travis.yml,circle.yml,.nyc_output,.husky,.github,electron-builder.env}'
- '!.yarn{,/**/*}'
- '!.editorconfig'
- '!.yarnrc.yml'
nodeModuleFilePatterns:
- '**/*'
- out/**
nsis:
script: |-
!include "D:\myCode\nl-admin\nl-admin-view\node_modules\.pnpm\app-builder-lib@26.15.3_dmg_ed407063d9219dada699e6fa1d0a9e89\node_modules\app-builder-lib\templates\nsis\include\StdUtils.nsh"
!addincludedir "D:\myCode\nl-admin\nl-admin-view\node_modules\.pnpm\app-builder-lib@26.15.3_dmg_ed407063d9219dada699e6fa1d0a9e89\node_modules\app-builder-lib\templates\nsis\include"
!macro _isUpdated _a _b _t _f
${StdUtils.TestParameter} $R9 "updated"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isUpdated `"" isUpdated ""`
!macro _isForceRun _a _b _t _f
${StdUtils.TestParameter} $R9 "force-run"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isForceRun `"" isForceRun ""`
!macro _isKeepShortcuts _a _b _t _f
${StdUtils.TestParameter} $R9 "keep-shortcuts"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isKeepShortcuts `"" isKeepShortcuts ""`
!macro _isNoDesktopShortcut _a _b _t _f
${StdUtils.TestParameter} $R9 "no-desktop-shortcut"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isNoDesktopShortcut `"" isNoDesktopShortcut ""`
!macro _isDeleteAppData _a _b _t _f
${StdUtils.TestParameter} $R9 "delete-app-data"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isDeleteAppData `"" isDeleteAppData ""`
!macro _isForAllUsers _a _b _t _f
${StdUtils.TestParameter} $R9 "allusers"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isForAllUsers `"" isForAllUsers ""`
!macro _isForCurrentUser _a _b _t _f
${StdUtils.TestParameter} $R9 "currentuser"
StrCmp "$R9" "true" `${_t}` `${_f}`
!macroend
!define isForCurrentUser `"" isForCurrentUser ""`
!macro addLangs
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "SpanishInternational"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "TradChinese"
!insertmacro MUI_LANGUAGE "Japanese"
!insertmacro MUI_LANGUAGE "Korean"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "Danish"
!insertmacro MUI_LANGUAGE "Swedish"
!insertmacro MUI_LANGUAGE "Norwegian"
!insertmacro MUI_LANGUAGE "Finnish"
!insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "PortugueseBR"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Ukrainian"
!insertmacro MUI_LANGUAGE "Czech"
!insertmacro MUI_LANGUAGE "Slovak"
!insertmacro MUI_LANGUAGE "Hungarian"
!insertmacro MUI_LANGUAGE "Arabic"
!insertmacro MUI_LANGUAGE "Turkish"
!insertmacro MUI_LANGUAGE "Thai"
!insertmacro MUI_LANGUAGE "Vietnamese"
!macroend
!include "C:\Users\admin\AppData\Local\Temp\t-T8jq5r\3-messages.nsh"
!include "C:\Users\admin\AppData\Local\Temp\t-T8jq5r\4-messages.nsh"
!addplugindir /x86-unicode "C:\Users\admin\AppData\Local\Temp\electron-builder-cache\nsis-resources-3.4.1\nsis-resources-3.4.1-2jx2y\plugins\x86-unicode"
Var newStartMenuLink
Var oldStartMenuLink
Var newDesktopLink
Var oldDesktopLink
Var oldShortcutName
Var oldMenuDirectory
!include "common.nsh"
!include "MUI2.nsh"
!include "multiUser.nsh"
!include "allowOnlyOneInstallerInstance.nsh"
!ifdef BUILD_UNINSTALLER
!ifmacrodef customUnInstallSection
!define MUI_COMPONENTSPAGE_NODESC
!insertmacro MUI_UNPAGE_COMPONENTS
!endif
!endif
!ifdef INSTALL_MODE_PER_ALL_USERS
!ifdef BUILD_UNINSTALLER
RequestExecutionLevel user
!else
RequestExecutionLevel admin
!endif
!else
RequestExecutionLevel user
!endif
!ifdef BUILD_UNINSTALLER
SilentInstall silent
!else
Var appExe
Var launchLink
!endif
!ifdef ONE_CLICK
!include "oneClick.nsh"
!else
!include "assistedInstaller.nsh"
!endif
!insertmacro addLangs
!ifmacrodef customHeader
!insertmacro customHeader
!endif
Function .onInit
Call setInstallSectionSpaceRequired
SetOutPath $INSTDIR
${LogSet} on
!ifmacrodef preInit
!insertmacro preInit
!endif
!ifdef DISPLAY_LANG_SELECTOR
!insertmacro MUI_LANGDLL_DISPLAY
!endif
!ifdef BUILD_UNINSTALLER
WriteUninstaller "${UNINSTALLER_OUT_FILE}"
!insertmacro quitSuccess
!else
!insertmacro check64BitAndSetRegView
!ifdef ONE_CLICK
!insertmacro ALLOW_ONLY_ONE_INSTALLER_INSTANCE
!else
${IfNot} ${UAC_IsInnerInstance}
!insertmacro ALLOW_ONLY_ONE_INSTALLER_INSTANCE
${EndIf}
!endif
!insertmacro initMultiUser
!ifmacrodef customInit
!insertmacro customInit
!endif
!ifmacrodef addLicenseFiles
InitPluginsDir
!insertmacro addLicenseFiles
!endif
!endif
FunctionEnd
!ifndef BUILD_UNINSTALLER
!include "installUtil.nsh"
!endif
Section "install" INSTALL_SECTION_ID
!ifndef BUILD_UNINSTALLER
# If we're running a silent upgrade of a per-machine installation, elevate so extracting the new app will succeed.
# For a non-silent install, the elevation will be triggered when the install mode is selected in the UI,
# but that won't be executed when silent.
!ifndef INSTALL_MODE_PER_ALL_USERS
!ifndef ONE_CLICK
${if} $hasPerMachineInstallation == "1" # set in onInit by initMultiUser
${andIf} ${Silent}
${ifNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${Break}
${Case} 1223 ;user aborted
${Break}
${Default}
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0"
${Break}
${EndSwitch}
Quit
${else}
!insertmacro setInstallModePerAllUsers
${endIf}
${endIf}
!endif
!endif
!include "installSection.nsh"
!endif
SectionEnd
Function setInstallSectionSpaceRequired
!insertmacro setSpaceRequired ${INSTALL_SECTION_ID}
FunctionEnd
!ifdef BUILD_UNINSTALLER
!include "uninstaller.nsh"
!endif

View File

@@ -0,0 +1,8 @@
version: 1.0.0
files:
- url: nl-admin-desktop-1.0.0-win-x64-dev.exe
sha512: XlRSHvc+DBg0UFayyyQjKf3Mv/6CpGz8XGEVRPb9Dx7OXVSotIA5uL85Kq2cU4IqtBsLQRBGrGiqc1b9yHL0lQ==
size: 102116616
path: nl-admin-desktop-1.0.0-win-x64-dev.exe
sha512: XlRSHvc+DBg0UFayyyQjKf3Mv/6CpGz8XGEVRPb9Dx7OXVSotIA5uL85Kq2cU4IqtBsLQRBGrGiqc1b9yHL0lQ==
releaseDate: '2026-08-12T10:14:59.294Z'

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<!--
macOS hardenedRuntime 基础 entitlements(Electron 运行必需的三件套)。
本项目无 IM 音视频业务,故不包含摄像头/麦克风条目;
后续若派生项目需要 getUserMedia,再补 com.apple.security.device.camera / audio-input。
-->
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

12
apps/desktop/src/env.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
/**
* electron-vite 构建期注入的环境变量类型声明
* 值来源见 apps/desktop/.env.development / .env.production
*/
interface ImportMetaEnv {
/** /api 转发上游地址(MAIN_VITE_ 前缀 = 仅主进程可见) */
readonly MAIN_VITE_API_UPSTREAM?: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}

View File

@@ -0,0 +1,54 @@
/**
* 桌面端全局配置常量
*
* 所有「待确认占位项」集中在本文件(TODO 标注),后续对齐生产环境后只需改这里,
* 不要把这些常量散落到其它模块(避免上线前漏改)。
*/
/**
* 应用唯一标识
* 必须与 electron-builder.yml 的 appId 完全一致:
* Windows 通知依赖 AppUserModelID(AUMID)与安装包快捷方式的 appId 对齐,不一致通知不弹
*/
export const APP_ID = 'com.nladmin.desktop';
/** 产品名:窗口标题、托盘 tooltip、通知标题兜底 */
export const PRODUCT_NAME = 'Nl Admin';
/** app:// 自定义协议的 scheme 与 host,生产环境渲染层 Origin 固定为 app://local */
export const APP_SCHEME = 'app';
export const APP_HOST = 'local';
/**
* /api 上游地址:按构建模式从 env 文件注入(electron-vite 构建期替换)
* - 联调包 pnpm build:desktop:dev → .env.development(固定本地后端)
* - 正式包 pnpm build:desktop → .env.production(TODO:生产域名确认后改该文件)
* 转发语义与 apps/web-antd/vite.config.ts 的 dev 代理完全一致:
* 渲染层请求 /api/xxx → 剥掉 /api 前缀 → 转发到 `${API_UPSTREAM}/xxx`
* 兜底本地后端,保证 env 缺失时包仍可用
*/
export const API_UPSTREAM =
import.meta.env.MAIN_VITE_API_UPSTREAM ?? 'http://127.0.0.1:18006/api';
/** 渲染层请求统一前缀:与桌面端动态下发的 _app.config.js 中 VITE_GLOB_API_URL 保持一致 */
export const API_PREFIX = '/api';
/**
* TODO(待确认):自动更新托管地址(1panel 加一个静态站点即可)
* 目录内需存放 electron-builder 产物:
* Windows:latest.yml + exe + blockmap;mac:latest-mac.yml + dmg + zip + blockmap
*/
export const UPDATE_URL = 'https://updates.example.com/nl-desktop/';
/** TODO(待确认):mac 未签名时自动更新降级提示跳转的手动下载页,默认复用更新托管地址 */
export const DOWNLOAD_PAGE_URL = UPDATE_URL;
/**
* 开发模式渲染层地址:web-antd 的 vite dev server
* 注意端口是 14002(apps/web-antd/vite.config.ts 的 server.port 覆盖了 .env.development 的 5666)
*/
export const DEV_SERVER_URL =
process.env.ELECTRON_RENDERER_URL ?? 'http://localhost:14002';
/** 全局快捷键:切换主窗口显示/隐藏(CommandOrControl 自动映射 Windows=Ctrl / mac=Cmd) */
export const GLOBAL_SHORTCUT = 'CommandOrControl+Alt+N';

View File

@@ -0,0 +1,66 @@
/**
* 主进程入口:装配协议、窗口、托盘、IPC、快捷键、更新器
* 启动顺序有讲究:协议特权注册必须在 app ready 之前,其余都在 whenReady 之后
*/
import { app } from 'electron';
import log from 'electron-log/main';
import { APP_ID, PRODUCT_NAME } from './config';
import { registerIpcHandlers } from './ipc';
import {
installAppProtocolHandler,
registerAppSchemePrivileges,
} from './protocol';
import { registerGlobalShortcut } from './shortcut';
import { appState } from './state';
import { createTray } from './tray';
import { initUpdater } from './updater';
import {
createMainWindow,
setupSessionSecurity,
showMainWindow,
} from './window';
// 日志落盘到 userData/logs,线上问题靠它排查
log.initialize();
log.transports.file.level = 'info';
// Windows 通知/任务栏分组依赖 AUMID,必须与 electron-builder.yml 的 appId 完全一致
app.setAppUserModelId(APP_ID);
// app:// 特权协议注册(Electron 要求必须在 ready 之前)
registerAppSchemePrivileges();
// 单实例锁:重复启动时唤起已有窗口而不是开第二个实例
const gotSingleInstanceLock = app.requestSingleInstanceLock();
if (gotSingleInstanceLock) {
app.on('second-instance', () => showMainWindow());
app.whenReady().then(async () => {
setupSessionSecurity();
installAppProtocolHandler();
registerIpcHandlers();
// --hidden 由开机自启注入(见 utils.setAutoLaunchEnabled):创建窗口但静默待在托盘
const startHidden = process.argv.includes('--hidden');
await createMainWindow({ startHidden });
createTray();
registerGlobalShortcut();
initUpdater();
log.info(`[main] ${PRODUCT_NAME} 启动完成 hidden=${startHidden}`);
});
// mac:点击 Dock 图标恢复窗口(关窗只是隐藏,窗口实例一直存活)
app.on('activate', () => showMainWindow());
// 所有窗口关闭也不退出:应用常驻托盘,真正退出走托盘菜单 / Cmd+Q
app.on('window-all-closed', () => {
// 故意留空:覆盖 Electron 默认的「非 mac 全关即退出」行为
});
// Cmd+Q / app.quit() 都会先经过这里:放行窗口 close(不再拦截为隐藏)
app.on('before-quit', () => {
appState.quitting = true;
});
} else {
app.quit();
}

View File

@@ -0,0 +1,223 @@
/**
* IPC 通道注册:渲染层 window.desktopAPI 各能力的主进程实现
* 安全约定:所有 handler 统一先校验 sender 来源(app://local 或本地 dev server),
* 防止意外加载的第三方页面调用桌面能力
*/
import type { IpcMainInvokeEvent } from 'electron';
import {
app,
BrowserWindow,
ipcMain,
nativeImage,
Notification,
} from 'electron';
import log from 'electron-log/main';
import { PRODUCT_NAME } from './config';
import { SETTING_KEYS, settingsStore } from './store';
import { refreshTrayMenu } from './tray';
import { checkUpdateManually, quitAndInstallNow } from './updater';
import {
getAutoLaunchEnabled,
getResourcePath,
setAutoLaunchEnabled,
} from './utils';
import {
getMainWindow,
isTrustedWebContentsUrl,
showMainWindow,
} from './window';
/** 渲染层 notify() 的入参结构(与 preload 保持同步) */
interface NotifyOptions {
body?: string;
flash?: boolean;
route?: string;
silent?: boolean;
title: string;
}
/** 渲染层 printHTML() 的入参结构(与 preload 保持同步) */
interface PrintHTMLOptions {
deviceName?: string;
html: string;
landscape?: boolean;
silent?: boolean;
}
/**
* 带来源校验的 ipcMain.handle 包装
* 为什么不用裸 ipcMain.handle:每个通道都要校验 sender,包一层避免每处复制粘贴校验代码
*/
function handle(
channel: string,
handler: (event: IpcMainInvokeEvent, ...args: any[]) => unknown,
): void {
ipcMain.handle(channel, (event, ...args) => {
const senderUrl = event.senderFrame?.url ?? '';
if (!isTrustedWebContentsUrl(senderUrl)) {
log.warn('[ipc] 拒绝不可信来源的 IPC 调用:', channel, senderUrl);
throw new Error('IPC 调用来源不可信');
}
return handler(event, ...args);
});
}
/** 注册全部 IPC 通道,应用启动时调用一次 */
export function registerIpcHandlers(): void {
handle('desktop:get-version', () => app.getVersion());
// ---- 系统通知 ----
handle('desktop:notify', (_event, options: NotifyOptions) => {
showNotification(options);
});
// ---- 未读角标(dataUrl 由 preload 的 canvas 绘制,仅 Windows 用到) ----
handle('desktop:set-badge', (_event, count: number, dataUrl: string) => {
setBadge(count, dataUrl);
});
// ---- 任务栏闪烁 ----
handle('desktop:flash-frame', (_event, flag: boolean) => {
const win = getMainWindow();
if (!win) return;
// 已聚焦时闪烁没有意义(还会造成任务栏图标闪一下的视觉bug)
if (flag && win.isFocused()) return;
win.flashFrame(!!flag);
});
// ---- 开机自启 ----
handle('desktop:get-auto-launch', () => getAutoLaunchEnabled());
handle('desktop:set-auto-launch', (_event, enabled: boolean) => {
const result = setAutoLaunchEnabled(!!enabled);
// 渲染层改了自启后,托盘菜单的勾选状态要同步
refreshTrayMenu();
return result;
});
// ---- 静默打印 ----
handle('desktop:get-printers', async () => {
const win = getMainWindow();
return win ? await win.webContents.getPrintersAsync() : [];
});
handle('desktop:print-html', (_event, options: PrintHTMLOptions) =>
printHTML(options),
);
// ---- 桌面端本地设置 ----
handle('desktop:get-setting', (_event, key: string) => settingsStore.get(key));
handle('desktop:set-setting', (_event, key: string, value: unknown) => {
settingsStore.set(key, value);
});
// ---- 更新 ----
handle('desktop:check-update', () => checkUpdateManually());
handle('desktop:quit-and-install', () => quitAndInstallNow());
}
/**
* 弹系统通知:点击唤起主窗口,携带 route 时再通知渲染层跳转站内路由
* Windows 能弹的前提:app.setAppUserModelId 与安装包 appId 一致(入口处已设置)
*/
function showNotification(options: NotifyOptions): void {
if (!Notification.isSupported()) {
log.warn('[ipc] 当前系统不支持通知');
return;
}
const notification = new Notification({
body: options.body ?? '',
icon: nativeImage.createFromPath(getResourcePath('icon.png')),
silent: options.silent ?? false,
title: options.title || PRODUCT_NAME,
});
notification.on('click', () => {
showMainWindow();
if (options.route) {
getMainWindow()?.webContents.send('desktop:navigate', options.route);
}
});
notification.show();
// 默认行为:窗口未聚焦时同步闪烁任务栏(mac 表现为 Dock 弹跳),聚焦后自动清除
const win = getMainWindow();
if ((options.flash ?? true) && win && !win.isFocused()) {
win.flashFrame(true);
}
}
/**
* 设置未读角标,按平台分支:
* mac 用 Dock 原生数字角标;Windows 用 preload 画好的红底数字图做任务栏覆盖图;
* Linux 尽力而为走 setBadgeCount(仅部分桌面环境支持)
*/
function setBadge(count: number, dataUrl: string): void {
const normalized = Math.max(0, Math.floor(count) || 0);
if (process.platform === 'darwin') {
app.dock?.setBadge(normalized > 0 ? String(normalized) : '');
return;
}
if (process.platform === 'win32') {
const win = getMainWindow();
if (!win) return;
if (normalized > 0 && dataUrl) {
win.setOverlayIcon(
nativeImage.createFromDataURL(dataUrl),
`${normalized} 条未读`,
);
} else {
win.setOverlayIcon(null, '');
}
return;
}
app.setBadgeCount(normalized);
}
/**
* 打印一段完整 HTML
* 实现:隐藏窗口加载 HTML(base64 data URL 避免特殊字符截断)→ webContents.print
* 静默打印必须有明确的打印机名(入参或本地设置),否则自动降级为弹系统打印对话框
*/
async function printHTML(
options: PrintHTMLOptions,
): Promise<{ message?: string; success: boolean }> {
const deviceName =
options.deviceName ||
(settingsStore.get(SETTING_KEYS.printerDeviceName) as string | undefined);
const silent = (options.silent ?? true) && !!deviceName;
const printWindow = new BrowserWindow({
show: false,
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
},
});
try {
const dataUrl = `data:text/html;charset=utf-8;base64,${Buffer.from(
options.html,
'utf8',
).toString('base64')}`;
await printWindow.loadURL(dataUrl);
return await new Promise((resolvePrint) => {
printWindow.webContents.print(
{
deviceName: silent ? deviceName : undefined,
landscape: options.landscape ?? false,
printBackground: true,
silent,
},
(success, failureReason) => {
resolvePrint({
message: success ? undefined : failureReason,
success,
});
},
);
});
} catch (error) {
log.error('[ipc] 打印失败:', error);
return { message: String(error), success: false };
} finally {
if (!printWindow.isDestroyed()) printWindow.destroy();
}
}

View File

@@ -0,0 +1,223 @@
/**
* app:// 自定义协议层——桌面端的「内置 nginx」
*
* 生产环境渲染进程加载 app://local/,本模块负责三件事:
* 1. 静态文件服务:把 web-antd 的生产 dist(extraResources 拷入 resources/web)按路径吐出,
* 并做 SPA fallback(等价 nginx try_files;本项目生产是 hash 路由,fallback 仅兜底)
* 2. 动态覆盖 /_app.config.js:利用 vben 的运行时配置机制,把 VITE_GLOB_API_URL 改写为 /api,
* 使桌面端 API 指向与网页端部署解耦(网页端 .env.production 完全不用动)
* 3. 转发 /api/*:用主进程 net.fetch 转发到后端上游(剥掉 /api 前缀,语义与
* apps/web-antd/vite.config.ts 的 dev 代理 rewrite 一致),因为是主进程发起、
* 与页面同源(app://local),所以后端无需配置 CORS
*/
import { readFile, stat } from 'node:fs/promises';
import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:path';
import { app, net, protocol } from 'electron';
import log from 'electron-log/main';
import { API_PREFIX, API_UPSTREAM, APP_HOST, APP_SCHEME } from './config';
/** 常见静态资源的 MIME 映射(dist 内实际会出现的类型) */
const MIME_TYPES: Record<string, string> = {
'.avif': 'image/avif',
'.css': 'text/css; charset=utf-8',
'.eot': 'application/vnd.ms-fontobject',
'.gif': 'image/gif',
'.html': 'text/html; charset=utf-8',
'.ico': 'image/x-icon',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.js': 'text/javascript; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.map': 'application/json; charset=utf-8',
'.mjs': 'text/javascript; charset=utf-8',
'.mp3': 'audio/mpeg',
'.mp4': 'video/mp4',
'.otf': 'font/otf',
'.png': 'image/png',
'.svg': 'image/svg+xml',
'.ttf': 'font/ttf',
'.txt': 'text/plain; charset=utf-8',
'.wasm': 'application/wasm',
'.webp': 'image/webp',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.xml': 'application/xml; charset=utf-8',
};
/**
* vben 运行时配置文件的路径模式
* vben 5.x 产出 `_app-config-{version}-{hash}.js`(本仓库实测),历史版本为 `_app.config.js`,
* 用模式匹配兼容两种命名,避免升级 vben 后改写逻辑悄悄失效
*/
const APP_CONFIG_FILE_RE = /^\/_app[.-]config[^/]*\.js$/;
/**
* 注册 app:// 为特权协议
* 必须在 app ready 之前调用(Electron 硬性要求),否则协议没有 standard/secure 等特权:
* - standard:拥有标准 Origin 语义,localStorage / IndexedDB 才可用(登录态依赖)
* - secure:视为 Secure Context,clipboard 等现代 Web 能力才可用
* - supportFetchAPI + corsEnabled:允许渲染层 fetch/XHR 请求本协议(axios 调 /api 必需)
* - stream:允许流式响应;codeCache:v8 代码缓存加速二次启动
*/
export function registerAppSchemePrivileges(): void {
protocol.registerSchemesAsPrivileged([
{
scheme: APP_SCHEME,
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
corsEnabled: true,
stream: true,
codeCache: true,
},
},
]);
}
/**
* 计算 web 静态资源根目录
* 打包后:resources/web(electron-builder extraResources 从 ../web-antd/dist 拷入)
* 开发态:直接指向 apps/web-antd/dist(用于本地不打包也能验证 app:// 生产链路)
*/
function getWebRoot(): string {
return app.isPackaged
? join(process.resourcesPath, 'web')
: resolve(app.getAppPath(), '../web-antd/dist');
}
/**
* 安装 app:// 协议处理器,必须在 app ready 之后调用
*/
export function installAppProtocolHandler(): void {
protocol.handle(APP_SCHEME, async (request) => {
try {
const url = new URL(request.url);
// 只认 app://local,其它 host 一律 404,避免协议被意外扩散使用
if (url.host !== APP_HOST) {
return new Response('Not Found', { status: 404 });
}
const pathname = decodeURIComponent(url.pathname);
// 1) /api 前缀 → 转发到后端上游
if (pathname === API_PREFIX || pathname.startsWith(`${API_PREFIX}/`)) {
return await forwardApiRequest(request, url);
}
// 2) vben 运行时配置文件 → 动态改写 API 地址后下发
if (APP_CONFIG_FILE_RE.test(pathname)) {
return await serveAppConfigOverride(pathname);
}
// 3) 其余走静态文件服务 + SPA fallback
return await serveStatic(pathname);
} catch (error) {
log.error('[protocol] 处理请求异常:', request.url, error);
return new Response('Internal Error', { status: 500 });
}
});
}
/**
* 转发 /api/* 请求到后端上游
* 为什么整体缓冲 body 再转发:管理后台的上传体量可控(几 MB 级),
* 缓冲比流式转发(需处理 duplex half 兼容性)简单可靠得多
*/
async function forwardApiRequest(request: Request, url: URL): Promise<Response> {
// 剥掉 /api 前缀,保留其后的路径与查询串
const restPath = url.pathname.slice(API_PREFIX.length) || '/';
const upstream = API_UPSTREAM.replace(/\/+$/, '');
const target = `${upstream}${restPath}${url.search}`;
const headers = new Headers(request.headers);
// Origin/Referer 是 app://local,对上游没有意义,转发时移除避免干扰后端框架的来源判断
headers.delete('origin');
headers.delete('referer');
try {
const hasBody = !['GET', 'HEAD'].includes(request.method.toUpperCase());
return await net.fetch(target, {
method: request.method,
headers,
body: hasBody ? await request.arrayBuffer() : undefined,
redirect: 'follow',
});
} catch (error) {
log.error('[protocol] API 转发失败:', target, error);
// 返回 vben 响应拦截器可识别的结构,前端会用 message 弹错误提示
return new Response(
JSON.stringify({ code: 502, message: '无法连接后端服务,请检查网络后重试' }),
{
status: 502,
headers: { 'content-type': 'application/json; charset=utf-8' },
},
);
}
}
/**
* 动态下发 vben 运行时配置文件
* vben 生产构建会产出该文件定义 window._VBEN_ADMIN_PRO_APP_CONF_(含 VITE_GLOB_API_URL),
* 桌面端读取 dist 里的原文件、只把 VITE_GLOB_API_URL 改写为 /api(其余运行时配置键原样保留),
* 这样 axios 的 baseURL 变成同源相对路径,全部命中上面的 /api 转发
*/
async function serveAppConfigOverride(pathname: string): Promise<Response> {
const filePath = join(getWebRoot(), pathname.replace(/^\/+/, ''));
let content: string;
try {
const raw = await readFile(filePath, 'utf8');
content = raw.replace(
/("VITE_GLOB_API_URL"\s*:\s*")[^"]*(")/,
`$1${API_PREFIX}$2`,
);
log.info('[protocol] 运行时配置已改写 VITE_GLOB_API_URL → /api:', pathname);
} catch {
// 文件读不到时兜底生成最小可用配置(理论上 vben 构建一定会产出)
log.warn('[protocol] 运行时配置文件缺失,使用兜底配置:', pathname);
content = `window._VBEN_ADMIN_PRO_APP_CONF_={"VITE_GLOB_API_URL":"${API_PREFIX}"};Object.freeze(window._VBEN_ADMIN_PRO_APP_CONF_);`;
}
return new Response(content, {
headers: {
'content-type': 'text/javascript; charset=utf-8',
// 运行时配置不缓存,保证改上游地址后重启即生效
'cache-control': 'no-cache',
},
});
}
/**
* 静态文件服务 + SPA fallback
* 带目录穿越防护:解析后的物理路径必须仍在 webRoot 内
*/
async function serveStatic(pathname: string): Promise<Response> {
const webRoot = normalize(getWebRoot());
const relPath = pathname === '/' ? 'index.html' : pathname.replace(/^\/+/, '');
let filePath = normalize(join(webRoot, relPath));
// 目录穿越防护:必须用 path.relative 判断真实包含关系。
// 不能用 filePath.startsWith(webRoot) —— 那样 `resources\web` 的同级目录
// `resources\website` 也会命中前缀,从而逃出 web 根读到相邻目录文件
const rel = relative(webRoot, filePath);
if (rel.startsWith('..') || isAbsolute(rel)) {
return new Response('Forbidden', { status: 403 });
}
// 文件不存在或是目录时回退 index.html(等价 nginx try_files $uri /index.html)
const fileStat = await stat(filePath).catch(() => null);
if (!fileStat || fileStat.isDirectory()) {
filePath = join(webRoot, 'index.html');
}
try {
const data = await readFile(filePath);
const mime =
MIME_TYPES[extname(filePath).toLowerCase()] ?? 'application/octet-stream';
return new Response(data as unknown as BodyInit, {
headers: { 'content-type': mime },
});
} catch (error) {
// 连 index.html 都没有:一般是没先构建 web-antd,给出可读的提示页
log.error('[protocol] 静态资源读取失败:', filePath, error);
return new Response(
'<h3>未找到 web 构建产物</h3><p>请先在仓库根目录执行 <code>pnpm build</code> 生成 apps/web-antd/dist 后重试。</p>',
{
status: 404,
headers: { 'content-type': 'text/html; charset=utf-8' },
},
);
}
}

View File

@@ -0,0 +1,33 @@
/**
* 全局快捷键:一键唤起/隐藏主窗口(默认 CommandOrControl+Alt+N,见 config.ts)
*/
import { app, globalShortcut } from 'electron';
import log from 'electron-log/main';
import { GLOBAL_SHORTCUT } from './config';
import { getMainWindow, showMainWindow } from './window';
/**
* 注册全局快捷键
* 快捷键可能被其它程序占用:注册失败只记录告警,绝不影响应用启动
*/
export function registerGlobalShortcut(): void {
const ok = globalShortcut.register(GLOBAL_SHORTCUT, () => {
const win = getMainWindow();
if (!win) return;
// 可见且聚焦 → 隐藏;否则(隐藏/最小化/失焦)→ 唤起到前台
if (win.isVisible() && win.isFocused()) {
win.hide();
} else {
showMainWindow();
}
});
if (!ok) {
log.warn(
'[shortcut] 全局快捷键注册失败(可能被其它程序占用):',
GLOBAL_SHORTCUT,
);
}
// 退出前必须注销,否则某些平台会残留系统级占用
app.on('will-quit', () => globalShortcut.unregisterAll());
}

View File

@@ -0,0 +1,11 @@
/**
* 主进程共享运行时状态
* 单独成模块是为了避免 window.ts / tray.ts / updater.ts 之间互相 import 造成循环依赖
*/
export const appState = {
/**
* 是否处于「真正退出」流程(托盘菜单退出 / mac Cmd+Q / 更新重启安装)
* false 时点击窗口关闭按钮只隐藏到托盘,不退出应用
*/
quitting: false,
};

View File

@@ -0,0 +1,16 @@
/**
* 桌面端本地设置持久化(electron-store,落盘到 userData/settings.json)
* 存放:静默打印选中的打印机、托盘首次隐藏提示标记等轻量配置
* 统一从这里取单例,禁止各模块自行 new Store 造成多份文件
*/
import Store from 'electron-store';
/** 设置项的键值约定(集中声明避免魔法字符串散落) */
export const SETTING_KEYS = {
/** 静默打印默认打印机名称 */
printerDeviceName: 'printer.deviceName',
/** Windows 关闭进托盘的首次提示是否已展示 */
closeHintShown: 'tray.closeHintShown',
} as const;
export const settingsStore = new Store({ name: 'settings' });

View File

@@ -0,0 +1,66 @@
/**
* 系统托盘:应用常驻入口
* Windows:关闭窗口后靠托盘活着,单击托盘还原窗口
* mac:托盘(菜单栏图标)仅提供快捷菜单,窗口恢复主要靠 Dock 的 activate 事件
*/
import { app, Menu, nativeImage, Tray } from 'electron';
import { PRODUCT_NAME } from './config';
import { appState } from './state';
import { checkUpdateManually } from './updater';
import { getAutoLaunchEnabled, getResourcePath, setAutoLaunchEnabled } from './utils';
import { showMainWindow } from './window';
/** 托盘单例(必须持有引用,否则会被 GC 导致图标消失) */
let tray: null | Tray = null;
/**
* 创建托盘图标与菜单
* 托盘直接用品牌应用图标缩小(resources/icon.png,年糕猫+奶酪)
*/
export function createTray(): Tray {
// TODO(待确认):mac 后续可换 Template 单色托盘图(setTemplateImage 随菜单栏深浅色自动反色)
const icon = nativeImage
.createFromPath(getResourcePath('icon.png'))
.resize({ height: 16, width: 16 });
tray = new Tray(icon);
tray.setToolTip(PRODUCT_NAME);
refreshTrayMenu();
// Windows 惯例:单击托盘直接还原主窗口;mac 惯例是单击弹菜单,不抢行为
if (process.platform !== 'darwin') {
tray.on('click', () => showMainWindow());
}
return tray;
}
/**
* 重建托盘右键菜单
* 单独导出是因为「开机自启」勾选状态可能被渲染层(desktopAPI.setAutoLaunch)改掉,
* 改完需要同步刷新菜单勾选态
*/
export function refreshTrayMenu(): void {
if (!tray) return;
const menu = Menu.buildFromTemplate([
{ click: () => showMainWindow(), label: '显示主窗口' },
{ type: 'separator' },
{
checked: getAutoLaunchEnabled(),
click: (item) => {
setAutoLaunchEnabled(item.checked);
},
label: '开机自启',
type: 'checkbox',
},
{ click: () => checkUpdateManually(), label: '检查更新' },
{ type: 'separator' },
{
click: () => {
// 标记真正退出,绕过窗口 close 事件里的「隐藏到托盘」拦截
appState.quitting = true;
app.quit();
},
label: '退出',
},
]);
tray.setContextMenu(menu);
}

View File

@@ -0,0 +1,154 @@
/**
* 自动更新:electron-updater(generic provider,消费静态托管的 latest*.yml + 安装包)
* Windows 消费 latest.yml + exe;mac 消费 latest-mac.yml + zip
* mac 未签名包无法通过更新签名校验:捕获后降级为「前往下载页手动安装」提示
*/
import type { UpdateInfo } from 'electron-updater';
import { app, dialog, shell } from 'electron';
import log from 'electron-log/main';
import electronUpdater from 'electron-updater';
import { DOWNLOAD_PAGE_URL, PRODUCT_NAME } from './config';
import { appState } from './state';
import { getMainWindow } from './window';
// electron-updater 是 CJS 包,ESM 下先整体导入再解构(named import 在部分打包场景会失败)
const { autoUpdater } = electronUpdater;
/** 是否用户手动触发的检查:手动才弹「已是最新/失败」反馈,启动时的静默检查不打扰用户 */
let manualCheck = false;
/** 防止重复初始化事件监听 */
let initialized = false;
/** 把更新流程事件转发给渲染层(web 侧可用 desktopAPI.onUpdateEvent 展示下载进度) */
function sendUpdateEvent(type: string, payload?: unknown): void {
getMainWindow()?.webContents.send('desktop:update-event', { payload, type });
}
/**
* 初始化更新器:注册事件 + 启动延时静默检查
* 只在打包环境生效(开发态没有 app-update.yml,检查必然报错)
*/
export function initUpdater(): void {
if (!app.isPackaged || initialized) return;
initialized = true;
autoUpdater.logger = log;
autoUpdater.autoDownload = true;
// 用户选「退出时安装」时靠这个兜底自动装
autoUpdater.autoInstallOnAppQuit = true;
autoUpdater.on('checking-for-update', () => sendUpdateEvent('checking'));
autoUpdater.on('update-available', (info: UpdateInfo) =>
sendUpdateEvent('available', { version: info.version }),
);
autoUpdater.on('update-not-available', () => {
sendUpdateEvent('not-available');
if (manualCheck) {
dialog.showMessageBox({
message: '当前已是最新版本',
title: PRODUCT_NAME,
type: 'info',
});
}
manualCheck = false;
});
autoUpdater.on('download-progress', (progress) =>
sendUpdateEvent('progress', {
percent: progress.percent,
transferred: progress.transferred,
total: progress.total,
}),
);
autoUpdater.on('update-downloaded', (info: UpdateInfo) => {
sendUpdateEvent('downloaded', { version: info.version });
void promptInstall(info);
});
autoUpdater.on('error', (error) => {
const message = String(error?.message ?? error);
sendUpdateEvent('error', { message });
log.error('[updater] 更新出错:', message);
// mac 未签名包的签名校验失败:降级为手动下载引导
const isMacSignatureIssue =
process.platform === 'darwin' &&
/code signature|codesign|not signed/i.test(message);
if (isMacSignatureIssue) {
void promptManualDownload();
} else if (manualCheck) {
dialog.showMessageBox({
detail: message,
message: '检查更新失败',
title: PRODUCT_NAME,
type: 'warning',
});
}
manualCheck = false;
});
// 启动 8 秒后静默检查:等窗口/协议就绪,也避免抢启动期资源
setTimeout(() => {
autoUpdater
.checkForUpdates()
.catch((error) => log.warn('[updater] 启动静默检查失败:', error));
}, 8000);
}
/** 手动检查更新(托盘菜单 / desktopAPI.checkUpdate 共用入口) */
export function checkUpdateManually(): void {
if (!app.isPackaged) {
dialog.showMessageBox({
message: '开发模式不支持检查更新',
title: PRODUCT_NAME,
type: 'info',
});
return;
}
manualCheck = true;
autoUpdater
.checkForUpdates()
.catch((error) => log.warn('[updater] 手动检查失败:', error));
}
/** 立即重启安装(更新属于真正退出,先置 quitting 绕过「关闭进托盘」拦截) */
export function quitAndInstallNow(): void {
appState.quitting = true;
// isSilent=false 走正常安装界面;isForceRunAfter=true 装完自动拉起新版本
autoUpdater.quitAndInstall(false, true);
}
/** 下载完成后的安装确认弹窗 */
async function promptInstall(info: UpdateInfo): Promise<void> {
const options = {
buttons: ['立即重启安装', '退出时安装'],
cancelId: 1,
defaultId: 0,
detail: '选择「退出时安装」则下次退出应用时自动完成升级。',
message: `新版本 ${info.version} 已下载完成,是否立即重启安装?`,
title: PRODUCT_NAME,
type: 'info' as const,
};
const win = getMainWindow();
const { response } = win
? await dialog.showMessageBox(win, options)
: await dialog.showMessageBox(options);
if (response === 0) {
quitAndInstallNow();
}
}
/** mac 未签名降级:引导用户去下载页手动装新版本 */
async function promptManualDownload(): Promise<void> {
const { response } = await dialog.showMessageBox({
buttons: ['打开下载页', '取消'],
cancelId: 1,
defaultId: 0,
detail: '当前安装包未进行代码签名,无法自动更新,请前往下载页手动安装最新版本。',
message: '检测到新版本',
title: PRODUCT_NAME,
type: 'info',
});
if (response === 0) {
void shell.openExternal(DOWNLOAD_PAGE_URL);
}
}

View File

@@ -0,0 +1,35 @@
/**
* 主进程通用小工具
*/
import { join } from 'node:path';
import { app } from 'electron';
/**
* 取运行时资源文件的绝对路径(图标等)
* 打包后:resources/ 下(electron-builder extraResources 拷入)
* 开发态:apps/desktop/resources/ 源目录
*/
export function getResourcePath(rel: string): string {
return app.isPackaged
? join(process.resourcesPath, rel)
: join(app.getAppPath(), 'resources', rel);
}
/** 读取开机自启状态(Windows 读注册表,mac 读系统「登录项」) */
export function getAutoLaunchEnabled(): boolean {
return app.getLoginItemSettings().openAtLogin;
}
/**
* 设置开机自启
* args --hidden 仅 Windows 生效:自启时静默进托盘不弹主窗口(入口处解析该参数);
* mac 走 SMAppService(系统设置 → 登录项 可见),不支持自定义参数,自启后正常显示窗口
*/
export function setAutoLaunchEnabled(enabled: boolean): boolean {
app.setLoginItemSettings({
openAtLogin: enabled,
args: enabled ? ['--hidden'] : [],
});
return getAutoLaunchEnabled();
}

View File

@@ -0,0 +1,187 @@
/**
* 主窗口管理:创建、加载策略、安全基线、关闭行为
*/
import { join } from 'node:path';
import {
app,
BrowserWindow,
nativeImage,
Notification,
session,
shell,
} from 'electron';
import log from 'electron-log/main';
import {
APP_HOST,
APP_SCHEME,
DEV_SERVER_URL,
PRODUCT_NAME,
} from './config';
import { appState } from './state';
import { SETTING_KEYS, settingsStore } from './store';
import { getResourcePath } from './utils';
/** 主窗口单例引用(应用生命周期内只有一个主窗口) */
let mainWindow: BrowserWindow | null = null;
/** 取主窗口(已销毁则返回 null,调用方需自行兜底) */
export function getMainWindow(): BrowserWindow | null {
return mainWindow && !mainWindow.isDestroyed() ? mainWindow : null;
}
/** 显示并聚焦主窗口(托盘单击 / 通知点击 / 二次启动 / mac Dock 激活共用) */
export function showMainWindow(): void {
const win = getMainWindow();
if (!win) return;
if (win.isMinimized()) win.restore();
win.show();
win.focus();
}
/**
* 判断某个 URL 是否属于「自己人」页面
* 用途:will-navigate 导航拦截、IPC sender 来源校验
* 生产只信 app://local,开发态额外放行本地 vite dev server(localhost 与 127.0.0.1 等价)
*/
export function isTrustedWebContentsUrl(url: string): boolean {
if (url.startsWith(`${APP_SCHEME}://${APP_HOST}`)) return true;
if (!app.isPackaged) {
return (
url.startsWith(DEV_SERVER_URL) ||
url.startsWith(DEV_SERVER_URL.replace('localhost', '127.0.0.1'))
);
}
return false;
}
/**
* 会话级安全设置:权限请求默认拒绝,仅放行白名单
* 本项目无 IM 音视频,media(摄像头/麦克风)一律拒绝;派生项目需要时再把 'media' 加进白名单
*/
export function setupSessionSecurity(): void {
const allowedPermissions = new Set([
'clipboard-read',
'clipboard-sanitized-write',
'fullscreen',
'notifications',
]);
session.defaultSession.setPermissionRequestHandler(
(_webContents, permission, callback) => {
callback(allowedPermissions.has(permission));
},
);
}
/**
* 创建主窗口
* @param options.startHidden 开机自启(--hidden)时为 true:创建后不显示、静默待在托盘
*/
export async function createMainWindow(options: {
startHidden: boolean;
}): Promise<BrowserWindow> {
const win = new BrowserWindow({
title: PRODUCT_NAME,
width: 1440,
height: 900,
minWidth: 1024,
minHeight: 680,
// 先隐藏,ready-to-show 再展示,避免加载期白屏闪烁
show: false,
autoHideMenuBar: true,
// mac 的应用图标由打包配置决定,这里只给 Windows/Linux 的窗口图标
icon:
process.platform === 'darwin'
? undefined
: nativeImage.createFromPath(getResourcePath('icon.png')),
backgroundColor: '#f5f5f5',
webPreferences: {
// 安全基线:隔离 + 沙箱 + 禁 node,一律不许放开(渲染层是可热替换的 web 产物)
preload: join(import.meta.dirname, '../preload/index.cjs'),
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
spellcheck: false,
},
});
mainWindow = win;
win.on('ready-to-show', () => {
if (!options.startHidden) win.show();
});
// 渲染层 window.open 的外链统一交给系统浏览器,壳内不开新窗口
win.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('http://') || url.startsWith('https://')) {
shell.openExternal(url);
}
return { action: 'deny' };
});
// 页面内直接跳转外部地址也拦下来走系统浏览器,防止壳被当成通用浏览器用
win.webContents.on('will-navigate', (event, url) => {
if (!isTrustedWebContentsUrl(url)) {
event.preventDefault();
// 与 setWindowOpenHandler 保持一致:只把 http(s) 交给系统浏览器,
// file:// / 自定义协议等一律仅拦截不外开,避免被诱导打开危险协议
if (url.startsWith('http://') || url.startsWith('https://')) {
shell.openExternal(url);
}
}
});
// 关闭按钮 = 隐藏到托盘(双平台一致;真正退出走托盘菜单/Cmd+Q,见 state.quitting)
win.on('close', (event) => {
if (appState.quitting) return;
event.preventDefault();
win.hide();
showFirstHideHint();
});
// 拿到焦点时清掉任务栏闪烁提醒
win.on('focus', () => win.flashFrame(false));
if (app.isPackaged) {
// 生产:走 app:// 协议加载 web-antd 的 dist(hash 路由,入口固定 index.html)
await win.loadURL(`${APP_SCHEME}://${APP_HOST}/index.html`);
} else {
// 开发:连 web-antd 的 vite dev server,起得比 vite 快时自动重试等它就绪
loadDevServerWithRetry(win);
}
return win;
}
/**
* 开发模式加载 dev server,失败每秒重试(dev:desktop 并行启动时 electron 通常比 vite 先就绪)
*/
function loadDevServerWithRetry(win: BrowserWindow, attempt = 0): void {
if (win.isDestroyed()) return;
win.webContents.once('did-fail-load', (_event, code, desc) => {
if (attempt >= 120) {
log.error('[window] 连接 dev server 失败已放弃:', DEV_SERVER_URL, code, desc);
return;
}
setTimeout(() => loadDevServerWithRetry(win, attempt + 1), 1000);
});
win.loadURL(DEV_SERVER_URL).catch(() => {
// loadURL 的 promise 失败与 did-fail-load 重复,重试统一由上面的事件驱动
});
}
/**
* Windows 首次「关闭进托盘」时弹一条系统通知告知用户,只提示一次(标记持久化)
* mac 关窗隐藏是系统惯例,无需提示
*/
function showFirstHideHint(): void {
if (process.platform !== 'win32') return;
if (settingsStore.get(SETTING_KEYS.closeHintShown)) return;
settingsStore.set(SETTING_KEYS.closeHintShown, true);
if (Notification.isSupported()) {
new Notification({
title: PRODUCT_NAME,
body: '已最小化到系统托盘,单击托盘图标可恢复窗口',
icon: nativeImage.createFromPath(getResourcePath('icon.png')),
}).show();
}
}

View File

@@ -0,0 +1,121 @@
/**
* preload:通过 contextBridge 向渲染层暴露 window.desktopAPI
*
* 运行在 sandbox 沙箱中(只能使用 electron 受限模块 + DOM),
* 所有能力都走 ipcRenderer.invoke 白名单通道,渲染层拿不到任何 Node 能力。
* web 侧的类型声明见 apps/web-antd/src/types/desktop.d.ts(两边字段需保持同步)。
*/
import type { IpcRendererEvent } from 'electron';
import { contextBridge, ipcRenderer } from 'electron';
/**
* 用 canvas 绘制 Windows 任务栏角标覆盖图(红底白字数字),返回 dataURL
* 为什么在 preload 画:主进程没有 DOM canvas,nativeImage 也不能绘制文字;
* preload 跑在渲染进程里有完整 DOM 能力,画完把 dataURL 交给主进程 setOverlayIcon
*/
function drawBadgeDataURL(count: number): string {
const size = 32;
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
if (!ctx) return '';
const text = count > 99 ? '99+' : String(count);
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
ctx.fillStyle = '#f5222d';
ctx.fill();
ctx.fillStyle = '#ffffff';
ctx.font = `bold ${text.length > 2 ? 13 : 18}px sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text, size / 2, size / 2 + 1);
return canvas.toDataURL('image/png');
}
/** 订阅主进程推送事件的通用封装,返回取消订阅函数(组件卸载时记得调用防止泄漏) */
function subscribe<T>(
channel: string,
callback: (payload: T) => void,
): () => void {
const listener = (_event: IpcRendererEvent, payload: T) => callback(payload);
ipcRenderer.on(channel, listener);
return () => ipcRenderer.removeListener(channel, listener);
}
const desktopAPI = {
/** 恒为 true,web 侧用它判断是否运行在 Electron 壳内 */
isElectron: true as const,
/** 当前平台:win32 / darwin / linux(渲染层做平台差异 UI 时用) */
platform: process.platform,
/** 应用版本号(package.json version,用于「关于」展示) */
getVersion: (): Promise<string> => ipcRenderer.invoke('desktop:get-version'),
/**
* 发系统通知;route 传入站内路由(如 /notice/list)时点击通知会唤起窗口并跳转
* flash 默认 true:窗口未聚焦时同时闪烁任务栏(mac 表现为 Dock 弹跳)
*/
notify: (options: {
title: string;
body?: string;
route?: string;
silent?: boolean;
flash?: boolean;
}): Promise<void> => ipcRenderer.invoke('desktop:notify', options),
/** 设置未读角标数,0 清除;mac 用 Dock 原生数字,Windows 用 canvas 画的覆盖图 */
setBadge: (count: number): Promise<void> => {
const dataUrl =
count > 0 && process.platform === 'win32' ? drawBadgeDataURL(count) : '';
return ipcRenderer.invoke('desktop:set-badge', count, dataUrl);
},
/** 手动控制任务栏闪烁(一般用不到,notify 已内置) */
flashFrame: (flag = true): Promise<void> =>
ipcRenderer.invoke('desktop:flash-frame', flag),
/** 读取开机自启状态 */
getAutoLaunch: (): Promise<boolean> =>
ipcRenderer.invoke('desktop:get-auto-launch'),
/** 设置开机自启(--hidden 静默启动进托盘) */
setAutoLaunch: (enabled: boolean): Promise<boolean> =>
ipcRenderer.invoke('desktop:set-auto-launch', enabled),
/** 枚举系统打印机列表 */
getPrinters: (): Promise<unknown[]> =>
ipcRenderer.invoke('desktop:get-printers'),
/**
* 打印一段完整 HTML:不传 deviceName 时读持久化的默认打印机;
* silent=true 静默打印,false 弹系统打印对话框
*/
printHTML: (options: {
html: string;
deviceName?: string;
silent?: boolean;
landscape?: boolean;
}): Promise<{ message?: string; success: boolean }> =>
ipcRenderer.invoke('desktop:print-html', options),
/** 读桌面端本地设置(如默认打印机) */
getSetting: (key: string): Promise<unknown> =>
ipcRenderer.invoke('desktop:get-setting', key),
/** 写桌面端本地设置 */
setSetting: (key: string, value: unknown): Promise<void> =>
ipcRenderer.invoke('desktop:set-setting', key, value),
/** 手动检查更新(托盘菜单也有同款入口) */
checkUpdate: (): Promise<void> => ipcRenderer.invoke('desktop:check-update'),
/** 更新下载完成后立即重启安装 */
quitAndInstall: (): Promise<void> =>
ipcRenderer.invoke('desktop:quit-and-install'),
/** 订阅「点击通知要求跳转路由」事件,web 侧收到后自行 router.push */
onNavigate: (callback: (route: string) => void): (() => void) =>
subscribe<string>('desktop:navigate', callback),
/** 订阅更新流程事件(checking / available / progress / downloaded 等),用于展示进度 */
onUpdateEvent: (
callback: (event: { payload?: unknown; type: string }) => void,
): (() => void) =>
subscribe<{ payload?: unknown; type: string }>(
'desktop:update-event',
callback,
),
};
contextBridge.exposeInMainWorld('desktopAPI', desktopAPI);
/** 导出类型供主进程侧引用(仅类型层面,运行时无依赖) */
export type DesktopAPI = typeof desktopAPI;

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2023",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"types": ["node"],
"strict": true,
"noEmit": true,
"skipLibCheck": true,
"esModuleInterop": true,
"isolatedModules": true,
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src", "electron.vite.config.ts"]
}

View File

@@ -1,5 +1,11 @@
# 应用标题
VITE_APP_TITLE=Nl Admin
VITE_APP_TITLE=佛山铂尔曼
# 品牌:brm 佛山铂尔曼 / wl 维伦家具,由 build:brm、build:wl 覆盖
VITE_APP_BRAND=brm
# 浏览器标签图标,index.html 里按此变量注入
VITE_APP_FAVICON=/brand/brm-favicon.svg
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
VITE_APP_NAMESPACE=vben-web-antd

27
apps/web-antd/.env.brm Normal file
View File

@@ -0,0 +1,27 @@
# 佛山铂尔曼(小程序 AppID wx679d36842570cea7)
#
# --mode brm 不会再去加载 .env.production,所以生产变量必须在这份文件里写全。
# VITE_ARCHIVER 会产出 dist.zip,两个品牌必须分开 outDir,否则互相覆盖。
VITE_APP_TITLE=佛山铂尔曼
VITE_APP_BRAND=brm
VITE_APP_FAVICON=/brand/brm-favicon.svg
VITE_BASE=/
# 接口地址
VITE_GLOB_API_URL=https://api.borman.top/api
# 是否开启压缩,可以设置为 none, brotli, gzip
VITE_COMPRESS=gzip
# 是否开启 PWA
VITE_PWA=false
# vue-router 的模式
VITE_ROUTER_HISTORY=hash
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true

27
apps/web-antd/.env.wl Normal file
View File

@@ -0,0 +1,27 @@
# 维伦家具(小程序 AppID wx57b54060a579c31a)
#
# --mode wl 不会再去加载 .env.production,所以生产变量必须在这份文件里写全。
# VITE_ARCHIVER 会产出 dist.zip,两个品牌必须分开 outDir,否则互相覆盖。
VITE_APP_TITLE=维伦家具
VITE_APP_BRAND=wl
VITE_APP_FAVICON=/brand/wl-favicon.svg
VITE_BASE=/
# 接口地址
VITE_GLOB_API_URL=https://api.weilun.top/api
# 是否开启压缩,可以设置为 none, brotli, gzip
VITE_COMPRESS=gzip
# 是否开启 PWA
VITE_PWA=false
# vue-router 的模式
VITE_ROUTER_HISTORY=hash
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true

View File

@@ -12,8 +12,10 @@
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
<title><%= VITE_APP_TITLE %></title>
<link rel="icon" href="/favicon.ico" />
<title>%VITE_APP_TITLE%</title>
<!-- 品牌 favicon 由 VITE_APP_FAVICON 注入,.env 里给了默认值保证各 mode 都能替换 -->
<link rel="icon" href="/favicon.ico" sizes="32x32" />
<link rel="icon" type="image/svg+xml" href="%VITE_APP_FAVICON%" />
<script>
// 生产环境下注入百度统计
if (window._VBEN_ADMIN_PRO_APP_CONF_) {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben/web-antd",
"version": "5.5.6",
"version": "5.7.0",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@@ -18,7 +18,11 @@
"scripts": {
"build": "pnpm vite build --mode production",
"build:analyze": "pnpm vite build --mode analyze",
"build:brm": "pnpm vite build --mode brm --outDir dist-brm",
"build:wl": "pnpm vite build --mode wl --outDir dist-wl",
"dev": "pnpm vite --mode development",
"dev:brm": "pnpm vite --mode brm",
"dev:wl": "pnpm vite --mode wl",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit --skipLibCheck"
},
@@ -43,8 +47,13 @@
"@vueuse/core": "catalog:",
"ant-design-vue": "catalog:",
"dayjs": "catalog:",
"jszip": "^3.10.1",
"markdown-it": "^15.0.0",
"pinia": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
},
"devDependencies": {
"@types/markdown-it": "^14.1.2"
}
}

View File

@@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="BORMAN">
<title>BORMAN favicon</title>
<g fill="none" stroke="#B8924A" stroke-linecap="round" stroke-linejoin="round">
<rect x="5" y="5" width="54" height="54" rx="14" stroke-width="2"/>
<path d="M18 52V18c0-4.5 3.5-7 8-7h4c3.5 0 5.5 2.5 5.5 6.5V36" stroke-width="2.2"/>
<path d="M35.5 37h16c3 0 5.5 2 5.5 5.5V46H25" stroke-width="2.2"/>
<path d="M35.5 28h12c2.5 0 4 1.5 4 4" stroke-width="2"/>
<path d="M28 46v8M50 46v8" stroke-width="2.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128" role="img" aria-label="BORMAN">
<title>BORMAN Dark</title>
<defs>
<linearGradient id="brmDarkStroke" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#F0E6D2"/>
<stop offset="55%" stop-color="#D4B56A"/>
<stop offset="100%" stop-color="#E8D9B0"/>
</linearGradient>
</defs>
<style type="text/css"><![CDATA[
.frame-outer,.frame-inner,.mark{fill:none;stroke:url(#brmDarkStroke);stroke-linecap:round;stroke-linejoin:round}
.frame-outer{stroke-width:2.5;animation:breath 5s ease-in-out infinite}
.frame-inner{stroke-width:1;opacity:.5}
.mark{stroke-width:3.1;animation:breath 5s ease-in-out .4s infinite}
@keyframes breath{0%,100%{opacity:1}50%{opacity:.84}}
@media (prefers-reduced-motion:reduce){
.frame-outer,.mark{animation:none}
}
]]></style>
<rect class="frame-outer" x="10" y="10" width="108" height="108" rx="28"/>
<rect class="frame-inner" x="18" y="18" width="92" height="92" rx="22"/>
<g class="mark">
<path d="M40 102V36c0-9 7-14 16-14h8c7 0 11 5 11 13v39"/>
<path d="M75 74h30c6 0 11 4 11 11v7H52"/>
<path d="M75 56h24c5 0 8 3 8 8"/>
<path d="M56 92v14M98 92v14"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 80" width="320" height="80" role="img" aria-label="BORMAN">
<title>BORMAN Dark</title>
<defs>
<linearGradient id="brmHDark" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#F0E6D2"/>
<stop offset="55%" stop-color="#D4B56A"/>
<stop offset="100%" stop-color="#E8D9B0"/>
</linearGradient>
</defs>
<style type="text/css"><![CDATA[
.ico .frame-outer,.ico .frame-inner,.ico .mark{fill:none;stroke:url(#brmHDark);stroke-linecap:round;stroke-linejoin:round}
.ico .frame-outer{stroke-width:2.5;animation:breath 5s ease-in-out infinite}
.ico .frame-inner{stroke-width:1;opacity:.5}
.ico .mark{stroke-width:3.1}
.wm{fill:#F2ECE1;font-family:'Source Han Serif SC','Noto Serif SC','Songti SC',STSong,serif}
.sub{fill:#C9BDA8;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif}
.rule{stroke:#D4B56A;opacity:.55}
.shine{stroke:#F5E9C8;stroke-width:2;opacity:0;pointer-events:none}
svg:hover .shine{animation:shine-run .65s ease-out}
@keyframes breath{0%,100%{opacity:1}50%{opacity:.84}}
@keyframes shine-run{0%{opacity:0;stroke-dasharray:8 240;stroke-dashoffset:0}30%{opacity:.9}100%{opacity:0;stroke-dashoffset:-180}}
@media (prefers-reduced-motion:reduce){
.ico .frame-outer,.shine{animation:none!important}
}
]]></style>
<g class="ico" transform="translate(4 8) scale(0.8125)">
<rect class="frame-outer" x="10" y="10" width="108" height="108" rx="28"/>
<rect class="frame-inner" x="18" y="18" width="92" height="92" rx="22"/>
<rect class="shine" x="10" y="10" width="108" height="108" rx="28" fill="none"/>
<g class="mark">
<path d="M40 102V36c0-9 7-14 16-14h8c7 0 11 5 11 13v39"/>
<path d="M75 74h30c6 0 11 4 11 11v7H52"/>
<path d="M75 56h24c5 0 8 3 8 8"/>
<path d="M56 92v14M98 92v14"/>
</g>
</g>
<path class="rule" d="M92 22V58" fill="none" stroke-width="1"/>
<text class="wm" x="108" y="40" font-size="26" letter-spacing="2.2">&#x4F5B;&#x5C71;&#x94C2;&#x5C14;&#x66FC;</text>
<text class="sub" x="110" y="58" font-size="10" letter-spacing="4.2">BORMAN FURNITURE</text>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

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