From 0c3edb10b06006b8745e626a330d5efdf0b22d0e Mon Sep 17 00:00:00 2001 From: Netfan Date: Wed, 21 May 2025 14:48:51 +0800 Subject: [PATCH 01/11] fix: getFieldComponentRef will return actual ref within AsyncComponentWrapper (#6252) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复异步加载组件时,表单的getFieldComponentRef方法没能获取到正确的组件实例 --- packages/@core/ui-kit/form-ui/src/form-api.ts | 23 ++++++++++++++++--- playground/src/views/examples/form/api.vue | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/@core/ui-kit/form-ui/src/form-api.ts b/packages/@core/ui-kit/form-ui/src/form-api.ts index 0ae8ed77a..e097a4654 100644 --- a/packages/@core/ui-kit/form-ui/src/form-api.ts +++ b/packages/@core/ui-kit/form-ui/src/form-api.ts @@ -11,7 +11,7 @@ import type { Recordable } from '@vben-core/typings'; import type { FormActions, FormSchema, VbenFormProps } from './types'; -import { toRaw } from 'vue'; +import { isRef, toRaw } from 'vue'; import { Store } from '@vben-core/shared/store'; import { @@ -100,9 +100,26 @@ export class FormApi { getFieldComponentRef( fieldName: string, ): T | undefined { - return this.componentRefMap.has(fieldName) - ? (this.componentRefMap.get(fieldName) as T) + let target = this.componentRefMap.has(fieldName) + ? (this.componentRefMap.get(fieldName) as ComponentPublicInstance) : undefined; + if ( + target && + target.$.type.name === 'AsyncComponentWrapper' && + target.$.subTree.ref + ) { + if (Array.isArray(target.$.subTree.ref)) { + if ( + target.$.subTree.ref.length > 0 && + isRef(target.$.subTree.ref[0]?.r) + ) { + target = target.$.subTree.ref[0]?.r.value as ComponentPublicInstance; + } + } else if (isRef(target.$.subTree.ref.r)) { + target = target.$.subTree.ref.r.value as ComponentPublicInstance; + } + } + return target as T; } /** diff --git a/playground/src/views/examples/form/api.vue b/playground/src/views/examples/form/api.vue index e367cb852..a7e15a08b 100644 --- a/playground/src/views/examples/form/api.vue +++ b/playground/src/views/examples/form/api.vue @@ -134,7 +134,7 @@ function handleClick( } case 'componentRef': { // 获取下拉组件的实例,并调用它的focus方法 - formApi.getFieldComponentRef('fieldOptions')?.focus(); + formApi.getFieldComponentRef('fieldOptions')?.focus?.(); break; } case 'disabled': { From ebef2c91e250c30c76bbd80f2e75ba9caae35d52 Mon Sep 17 00:00:00 2001 From: LinaBell <15891557205@163.com> Date: Thu, 22 May 2025 09:04:40 +0800 Subject: [PATCH 02/11] fix: tab cannot be displayed correctly after browser refresh (#6256) --- packages/stores/src/modules/tabbar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stores/src/modules/tabbar.ts b/packages/stores/src/modules/tabbar.ts index 17215a5ea..5b892b666 100644 --- a/packages/stores/src/modules/tabbar.ts +++ b/packages/stores/src/modules/tabbar.ts @@ -208,7 +208,7 @@ export const useTabbarStore = defineStore('core-tabbar', { const keys: string[] = []; for (const key of closeKeys) { - if (key !== tab.key) { + if (key !== getTabKeyFromTab(tab)) { const closeTab = this.tabs.find( (item) => getTabKeyFromTab(item) === key, ); From 11b2b5bcc2068c7e05699e6e5295e380b45dc5b8 Mon Sep 17 00:00:00 2001 From: ali-pay Date: Thu, 22 May 2025 09:09:31 +0800 Subject: [PATCH 03/11] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E7=AE=A1=E7=90=86=E4=B8=AD=E6=8C=89=E9=92=AE=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=80=BC=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#6255)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playground/src/views/system/menu/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/src/views/system/menu/data.ts b/playground/src/views/system/menu/data.ts index ee787e503..75190b4ac 100644 --- a/playground/src/views/system/menu/data.ts +++ b/playground/src/views/system/menu/data.ts @@ -11,7 +11,7 @@ export function getMenuTypeOptions() { value: 'catalog', }, { color: 'default', label: $t('system.menu.typeMenu'), value: 'menu' }, - { color: 'error', label: $t('system.menu.typeButton'), value: 'action' }, + { color: 'error', label: $t('system.menu.typeButton'), value: 'button' }, { color: 'success', label: $t('system.menu.typeEmbedded'), From a2bdcd6e49ada83c9caa30c4dba2c1077db63ba9 Mon Sep 17 00:00:00 2001 From: panda7 Date: Fri, 23 May 2025 15:20:38 +0800 Subject: [PATCH 04/11] 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 --- .../common-ui/vben-ellipsis-text.md | 8 ++ .../vben-ellipsis-text/auto-display/index.vue | 16 ++++ .../ellipsis-text/ellipsis-text.vue | 88 ++++++++++++++++++- 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 docs/src/demos/vben-ellipsis-text/auto-display/index.vue diff --git a/docs/src/components/common-ui/vben-ellipsis-text.md b/docs/src/components/common-ui/vben-ellipsis-text.md index 109f1161c..ce6c0334a 100644 --- a/docs/src/components/common-ui/vben-ellipsis-text.md +++ b/docs/src/components/common-ui/vben-ellipsis-text.md @@ -26,6 +26,12 @@ outline: deep +## 自动显示 tooltip + +通过`tooltip-when-ellipsis`设置,仅在文本长度超出导致省略号出现时才触发 tooltip。 + + + ## API ### Props @@ -37,6 +43,8 @@ outline: deep | maxWidth | 文本区域最大宽度 | `number \| string` | `'100%'` | | placement | 提示浮层的位置 | `'bottom'\|'left'\|'right'\|'top'` | `'top'` | | tooltip | 启用文本提示 | `boolean` | `true` | +| tooltipWhenEllipsis | 内容超出,自动启用文本提示 | `boolean` | `false` | +| ellipsisThreshold | 设置 tooltipWhenEllipsis 后才生效,文本截断检测的像素差异阈值,越大则判断越严格,如果碰见异常情况可以自己设置阈值 | `number` | `3` | | tooltipBackgroundColor | 提示文本的背景颜色 | `string` | - | | tooltipColor | 提示文本的颜色 | `string` | - | | tooltipFontSize | 提示文本的大小 | `string` | - | diff --git a/docs/src/demos/vben-ellipsis-text/auto-display/index.vue b/docs/src/demos/vben-ellipsis-text/auto-display/index.vue new file mode 100644 index 000000000..fb5a32a50 --- /dev/null +++ b/docs/src/demos/vben-ellipsis-text/auto-display/index.vue @@ -0,0 +1,16 @@ + + diff --git a/packages/effects/common-ui/src/components/ellipsis-text/ellipsis-text.vue b/packages/effects/common-ui/src/components/ellipsis-text/ellipsis-text.vue index b32c5dfa6..12f44bdb6 100644 --- a/packages/effects/common-ui/src/components/ellipsis-text/ellipsis-text.vue +++ b/packages/effects/common-ui/src/components/ellipsis-text/ellipsis-text.vue @@ -1,7 +1,14 @@ + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa50ca938..57789eb42 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,9 @@ catalogs: '@types/html-minifier-terser': specifier: ^7.0.2 version: 7.0.2 + '@types/json-bigint': + specifier: ^1.0.4 + version: 1.0.4 '@types/jsonwebtoken': specifier: ^9.0.9 version: 9.0.9 @@ -291,6 +294,9 @@ catalogs: is-ci: specifier: ^4.1.0 version: 4.1.0 + json-bigint: + specifier: ^1.0.0 + version: 1.0.0 jsonc-eslint-parser: specifier: ^2.4.0 version: 2.4.0 @@ -1877,6 +1883,9 @@ importers: dayjs: specifier: 'catalog:' version: 1.11.13 + json-bigint: + specifier: 'catalog:' + version: 1.0.0 pinia: specifier: ^3.0.2 version: 3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) @@ -1886,6 +1895,10 @@ importers: vue-router: specifier: 'catalog:' version: 4.5.1(vue@3.5.13(typescript@5.8.3)) + devDependencies: + '@types/json-bigint': + specifier: 'catalog:' + version: 1.0.4 scripts/turbo-run: dependencies: @@ -4341,6 +4354,9 @@ packages: '@types/html-minifier-terser@7.0.2': resolution: {integrity: sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==} + '@types/json-bigint@1.0.4': + resolution: {integrity: sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -5253,6 +5269,9 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + bignumber.js@9.3.0: + resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -7643,6 +7662,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -14045,6 +14067,8 @@ snapshots: '@types/html-minifier-terser@7.0.2': {} + '@types/json-bigint@1.0.4': {} + '@types/json-schema@7.0.15': {} '@types/jsonwebtoken@9.0.9': @@ -15115,6 +15139,8 @@ snapshots: dependencies: is-windows: 1.0.2 + bignumber.js@9.3.0: {} + binary-extensions@2.3.0: {} bindings@1.5.0: @@ -17775,6 +17801,10 @@ snapshots: jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.0 + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 00c384ef6..98cd5e464 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -41,6 +41,7 @@ catalog: '@types/archiver': ^6.0.3 '@types/eslint': ^9.6.1 '@types/html-minifier-terser': ^7.0.2 + '@types/json-bigint': ^1.0.4 '@types/jsonwebtoken': ^9.0.9 '@types/lodash.clonedeep': ^4.5.9 '@types/lodash.get': ^4.4.9 @@ -112,6 +113,7 @@ catalog: happy-dom: ^17.4.6 html-minifier-terser: ^7.2.0 is-ci: ^4.1.0 + json-bigint: ^1.0.0 jsonc-eslint-parser: ^2.4.0 jsonwebtoken: ^9.0.2 lefthook: ^1.11.12 From 48d70182b41aff8b88d63d18bee773adbf02e824 Mon Sep 17 00:00:00 2001 From: yingzi2019 <54906337+yingzi2019@users.noreply.github.com> Date: Fri, 23 May 2025 15:23:06 +0800 Subject: [PATCH 07/11] feat: improve check updates (#6257) Co-authored-by: monkey --- .../layouts/src/widgets/check-updates/check-updates.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/effects/layouts/src/widgets/check-updates/check-updates.vue b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue index 661604d8b..4f3082f39 100644 --- a/packages/effects/layouts/src/widgets/check-updates/check-updates.vue +++ b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue @@ -6,7 +6,7 @@ import { $t } from '@vben/locales'; import { useVbenModal } from '@vben-core/popup-ui'; interface Props { - // 轮训时间,分钟 + // 轮询时间,分钟 checkUpdatesInterval?: number; // 检查更新的地址 checkUpdateUrl?: string; @@ -46,6 +46,7 @@ async function getVersionTag() { const response = await fetch(props.checkUpdateUrl, { cache: 'no-cache', method: 'HEAD', + redirect: 'manual', }); return ( From 97894a940e246f1eef26a9493e0291be7d9b8482 Mon Sep 17 00:00:00 2001 From: wyc001122 <498040880@qq.com> Date: Fri, 23 May 2025 15:24:01 +0800 Subject: [PATCH 08/11] 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 --- docs/src/en/guide/essentials/settings.md | 3 +++ docs/src/guide/essentials/settings.md | 3 +++ .../__tests__/__snapshots__/config.test.ts.snap | 1 + packages/@core/preferences/src/config.ts | 1 + packages/@core/preferences/src/types.ts | 2 ++ .../shadcn-ui/src/components/avatar/avatar.vue | 14 +++++++++++++- .../ui-kit/shadcn-ui/src/components/logo/logo.vue | 6 ++++++ packages/effects/layouts/src/basic/layout.vue | 2 ++ 8 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/src/en/guide/essentials/settings.md b/docs/src/en/guide/essentials/settings.md index b7cb3a2de..e5aa71a83 100644 --- a/docs/src/en/guide/essentials/settings.md +++ b/docs/src/en/guide/essentials/settings.md @@ -238,6 +238,7 @@ const defaultPreferences: Preferences = { }, logo: { enable: true, + fit: 'contain', source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', }, navigation: { @@ -431,6 +432,8 @@ interface HeaderPreferences { interface LogoPreferences { /** Whether the logo is visible */ enable: boolean; + /** Logo image fitting method */ + fit: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'; /** Logo URL */ source: string; } diff --git a/docs/src/guide/essentials/settings.md b/docs/src/guide/essentials/settings.md index cd7c9380d..cca572d86 100644 --- a/docs/src/guide/essentials/settings.md +++ b/docs/src/guide/essentials/settings.md @@ -237,6 +237,7 @@ const defaultPreferences: Preferences = { }, logo: { enable: true, + fit: 'contain', source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', }, navigation: { @@ -431,6 +432,8 @@ interface HeaderPreferences { interface LogoPreferences { /** logo是否可见 */ enable: boolean; + /** logo图片适应方式 */ + fit: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'; /** logo地址 */ source: string; } diff --git a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap index df20b55d6..1cccbbb27 100644 --- a/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap @@ -61,6 +61,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj }, "logo": { "enable": true, + "fit": "contain", "source": "https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp", }, "navigation": { diff --git a/packages/@core/preferences/src/config.ts b/packages/@core/preferences/src/config.ts index 70d15c3e3..835eed557 100644 --- a/packages/@core/preferences/src/config.ts +++ b/packages/@core/preferences/src/config.ts @@ -62,6 +62,7 @@ const defaultPreferences: Preferences = { logo: { enable: true, + fit: 'contain', source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', }, navigation: { diff --git a/packages/@core/preferences/src/types.ts b/packages/@core/preferences/src/types.ts index cc0fefe31..e640edb5c 100644 --- a/packages/@core/preferences/src/types.ts +++ b/packages/@core/preferences/src/types.ts @@ -134,6 +134,8 @@ interface HeaderPreferences { interface LogoPreferences { /** logo是否可见 */ enable: boolean; + /** logo图片适应方式 */ + fit: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'; /** logo地址 */ source: string; } diff --git a/packages/@core/ui-kit/shadcn-ui/src/components/avatar/avatar.vue b/packages/@core/ui-kit/shadcn-ui/src/components/avatar/avatar.vue index 4f630e196..a63f349c3 100644 --- a/packages/@core/ui-kit/shadcn-ui/src/components/avatar/avatar.vue +++ b/packages/@core/ui-kit/shadcn-ui/src/components/avatar/avatar.vue @@ -5,6 +5,8 @@ import type { AvatarRootProps, } from 'radix-vue'; +import type { CSSProperties } from 'vue'; + import type { ClassType } from '@vben-core/typings'; import { computed } from 'vue'; @@ -16,6 +18,7 @@ interface Props extends AvatarFallbackProps, AvatarImageProps, AvatarRootProps { class?: ClassType; dot?: boolean; dotClass?: ClassType; + fit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'; size?: number; } @@ -28,6 +31,15 @@ const props = withDefaults(defineProps(), { as: 'button', dot: false, dotClass: 'bg-green-500', + fit: 'cover', +}); + +const imageStyle = computed(() => { + const { fit } = props; + if (fit) { + return { objectFit: fit }; + } + return {}; }); const text = computed(() => { @@ -51,7 +63,7 @@ const rootStyle = computed(() => { class="relative flex flex-shrink-0 items-center" > - + {{ text }} (), { logoSize: 32, src: '', theme: 'light', + fit: 'cover', }); @@ -53,6 +58,7 @@ withDefaults(defineProps(), { :alt="text" :src="src" :size="logoSize" + :fit="fit" class="relative rounded-none bg-transparent" />