From 01508d5e42f929e18ed4cd697bafc2c0283a305c Mon Sep 17 00:00:00 2001 From: Jin Mao Date: Thu, 26 Feb 2026 05:45:36 +0800 Subject: [PATCH 1/4] fix: fix lint --- packages/stores/src/modules/tabbar.ts | 58 ++++++++++++++++++++------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/packages/stores/src/modules/tabbar.ts b/packages/stores/src/modules/tabbar.ts index 8d18d442..66a3758b 100644 --- a/packages/stores/src/modules/tabbar.ts +++ b/packages/stores/src/modules/tabbar.ts @@ -1,5 +1,9 @@ import type { ComputedRef } from 'vue'; -import type { RouteLocationNormalized, Router, RouteRecordNormalized } from 'vue-router'; +import type { + RouteLocationNormalized, + Router, + RouteRecordNormalized, +} from 'vue-router'; import type { TabDefinition } from '@vben-core/typings'; @@ -66,7 +70,9 @@ export const useTabbarStore = defineStore('core-tabbar', { */ async _bulkCloseByKeys(keys: string[]) { const keySet = new Set(keys); - this.tabs = this.tabs.filter((item) => !keySet.has(getTabKeyFromTab(item))); + this.tabs = this.tabs.filter( + (item) => !keySet.has(getTabKeyFromTab(item)), + ); if (isVisitHistory()) { this.visitHistory.remove(...keys); } @@ -130,20 +136,25 @@ export const useTabbarStore = defineStore('core-tabbar', { if (tabIndex === -1) { const maxCount = preferences.tabbar.maxCount; // 获取动态路由打开数,超过 0 即代表需要控制打开数 - const maxNumOfOpenTab = (routeTab?.meta?.maxNumOfOpenTab ?? -1) as number; + const maxNumOfOpenTab = (routeTab?.meta?.maxNumOfOpenTab ?? + -1) as number; // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 // 获取到已经打开的动态路由数, 判断是否大于某一个值 if ( maxNumOfOpenTab > 0 && - this.tabs.filter((tab) => tab.name === routeTab.name).length >= maxNumOfOpenTab + this.tabs.filter((tab) => tab.name === routeTab.name).length >= + maxNumOfOpenTab ) { // 关闭第一个 - const index = this.tabs.findIndex((item) => item.name === routeTab.name); + const index = this.tabs.findIndex( + (item) => item.name === routeTab.name, + ); index !== -1 && this.tabs.splice(index, 1); } else if (maxCount > 0 && this.tabs.length >= maxCount) { // 关闭第一个 const index = this.tabs.findIndex( - (item) => !Reflect.has(item.meta, 'affixTab') || !item.meta.affixTab + (item) => + !Reflect.has(item.meta, 'affixTab') || !item.meta.affixTab, ); index !== -1 && this.tabs.splice(index, 1); } @@ -183,7 +194,9 @@ export const useTabbarStore = defineStore('core-tabbar', { this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1); // 设置访问历史记录 if (isVisitHistory()) { - this.visitHistory.retain(this.tabs.map((item) => getTabKeyFromTab(item))); + this.visitHistory.retain( + this.tabs.map((item) => getTabKeyFromTab(item)), + ); } await this._goToDefaultTab(router); this.updateCacheTabs(); @@ -220,7 +233,9 @@ export const useTabbarStore = defineStore('core-tabbar', { for (const key of closeKeys) { if (key !== getTabKeyFromTab(tab)) { - const closeTab = this.tabs.find((item) => getTabKeyFromTab(item) === key); + const closeTab = this.tabs.find( + (item) => getTabKeyFromTab(item) === key, + ); if (!closeTab) { continue; } @@ -290,12 +305,14 @@ export const useTabbarStore = defineStore('core-tabbar', { break; } } - await (previousTab ? this._goToTab(previousTab, router) : this._goToDefaultTab(router)); + await (previousTab + ? this._goToTab(previousTab, router) + : this._goToDefaultTab(router)); return; } // 未开启访问历史记录,直接跳转下一个或上一个tab const index = this.getTabs.findIndex( - (item) => getTabKeyFromTab(item) === getTabKey(currentRoute.value) + (item) => getTabKeyFromTab(item) === getTabKey(currentRoute.value), ); const before = this.getTabs[index - 1]; @@ -319,7 +336,9 @@ export const useTabbarStore = defineStore('core-tabbar', { */ async closeTabByKey(key: string, router: Router) { const originKey = decodeURIComponent(key); - const index = this.tabs.findIndex((item) => getTabKeyFromTab(item) === originKey); + const index = this.tabs.findIndex( + (item) => getTabKeyFromTab(item) === originKey, + ); if (index === -1) { return; } @@ -335,7 +354,9 @@ export const useTabbarStore = defineStore('core-tabbar', { * @param key */ getTabByKey(key: string) { - return this.getTabs.find((item) => getTabKeyFromTab(item) === key) as TabDefinition; + return this.getTabs.find( + (item) => getTabKeyFromTab(item) === key, + ) as TabDefinition; }, /** * @zh_CN 新窗口打开标签页 @@ -656,14 +677,21 @@ function isTabShown(tab: TabDefinition) { * @param tab */ function getTabKey(tab: RouteLocationNormalized | RouteRecordNormalized) { - const { fullPath, path, meta: { fullPathKey } = {}, query = {} } = tab as RouteLocationNormalized; + const { + fullPath, + path, + meta: { fullPathKey } = {}, + query = {}, + } = tab as RouteLocationNormalized; // pageKey可能是数组(查询参数重复时可能出现) - const pageKey = Array.isArray(query.pageKey) ? query.pageKey[0] : query.pageKey; + const pageKey = Array.isArray(query.pageKey) + ? query.pageKey[0] + : query.pageKey; let rawKey; if (pageKey) { rawKey = pageKey; } else { - rawKey = fullPathKey === false ? path : fullPath ?? path; + rawKey = fullPathKey === false ? path : (fullPath ?? path); } try { return decodeURIComponent(rawKey); From 05920cd66d447198680590f8e6dc143d6f941d83 Mon Sep 17 00:00:00 2001 From: moil-xm <64048303+moil-xm@users.noreply.github.com> Date: Thu, 26 Feb 2026 06:14:12 +0800 Subject: [PATCH 2/4] 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> --- internal/vite-config/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/vite-config/src/index.ts b/internal/vite-config/src/index.ts index 352a3235..c9c2b20d 100644 --- a/internal/vite-config/src/index.ts +++ b/internal/vite-config/src/index.ts @@ -1,4 +1,5 @@ export * from './config'; export * from './options'; export * from './plugins'; +export type * from './typing'; export { loadAndConvertEnv } from './utils/env'; From 191fd90f0695c4227291398c3511da96315dec00 Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Thu, 26 Feb 2026 06:17:04 +0800 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E6=8F=8F=E8=BF=B0=E6=98=BE=E7=A4=BA=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=20(#6938)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../@core/ui-kit/form-ui/src/form-render/form-field.vue | 6 +++--- playground/src/views/examples/form/basic.vue | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/@core/ui-kit/form-ui/src/form-render/form-field.vue b/packages/@core/ui-kit/form-ui/src/form-render/form-field.vue index 53c731e7..cc610d59 100644 --- a/packages/@core/ui-kit/form-ui/src/form-render/form-field.vue +++ b/packages/@core/ui-kit/form-ui/src/form-render/form-field.vue @@ -381,10 +381,10 @@ onUnmounted(() => {
- - - + + + diff --git a/playground/src/views/examples/form/basic.vue b/playground/src/views/examples/form/basic.vue index 52d04319..05be1f3a 100644 --- a/playground/src/views/examples/form/basic.vue +++ b/playground/src/views/examples/form/basic.vue @@ -67,6 +67,13 @@ const [BaseForm, baseFormApi] = useVbenForm({ label: '字符串', rules: 'required', }, + { + component: 'Input', + fieldName: 'desc', + // 界面显示的description + description: '这是表单描述', + label: '字符串(带描述)', + }, { // 组件需要在 #/adapter.ts内注册,并加上类型 component: 'ApiSelect', From 45b843f3441b3b45cae6192981f5422ff1310831 Mon Sep 17 00:00:00 2001 From: ming4762 Date: Thu, 26 Feb 2026 06:21:08 +0800 Subject: [PATCH 4/4] fix: fix bug where `renderEcharts` gets stuck in a dead loop (#7561) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 触发条件:echart所在页面开启keepalive 在其他页面切换颜色模式 --- .../plugins/src/echarts/use-echarts.ts | 27 ++++++++++++++++--- .../src/router/routes/modules/dashboard.ts | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts index dc74fd46..4f1989ce 100644 --- a/packages/effects/plugins/src/echarts/use-echarts.ts +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -6,7 +6,17 @@ import type { Nullable } from '@vben/types'; import type EchartsUI from './echarts-ui.vue'; -import { computed, nextTick, watch } from 'vue'; +import { + computed, + nextTick, + onActivated, + onBeforeUnmount, + onDeactivated, + onMounted, + ref, + unref, + watch, +} from 'vue'; import { usePreferences } from '@vben/preferences'; @@ -27,6 +37,8 @@ type EchartsThemeType = 'dark' | 'light' | null; function useEcharts(chartRef: Ref) { let chartInstance: echarts.ECharts | null = null; let cacheOptions: EChartsOption = {}; + // echart是否处于激活状态 + const isActiveRef = ref(false); const { isDark } = usePreferences(); const { height, width } = useWindowSize(); @@ -42,6 +54,11 @@ function useEcharts(chartRef: Ref) { return maybeComponent.$el ?? null; }; + onMounted(() => (isActiveRef.value = true)); + onActivated(() => (isActiveRef.value = true)); + onDeactivated(() => (isActiveRef.value = false)); + onBeforeUnmount(() => (isActiveRef.value = false)); + const isElHidden = (el: HTMLElement | null): boolean => { if (!el) return true; return el.offsetHeight === 0 || el.offsetWidth === 0; @@ -71,6 +88,9 @@ function useEcharts(chartRef: Ref) { options: EChartsOption, clear = true, ): Promise> => { + if (!unref(isActiveRef)) { + return Promise.resolve(null); + } cacheOptions = options; const currentOptions = { ...options, @@ -154,8 +174,8 @@ function useEcharts(chartRef: Ref) { useResizeObserver(chartRef as never, resizeHandler); - watch(isDark, () => { - if (chartInstance) { + watch([isDark, isActiveRef], () => { + if (chartInstance && unref(isActiveRef)) { chartInstance.dispose(); initCharts(); renderEcharts(cacheOptions); @@ -168,6 +188,7 @@ function useEcharts(chartRef: Ref) { chartInstance?.dispose(); }); return { + isActive: isActiveRef, renderEcharts, resize, updateData, diff --git a/playground/src/router/routes/modules/dashboard.ts b/playground/src/router/routes/modules/dashboard.ts index 5254dc65..7ef3cfb6 100644 --- a/playground/src/router/routes/modules/dashboard.ts +++ b/playground/src/router/routes/modules/dashboard.ts @@ -20,6 +20,7 @@ const routes: RouteRecordRaw[] = [ affixTab: true, icon: 'lucide:area-chart', title: $t('page.dashboard.analytics'), + keepAlive: true, }, }, {