refactor: 优化viewed实例初始化,rowStyle rowClassName 从最新的配置中读取

master^2
layhuts 2026-05-09 18:27:09 +08:00
parent 28905b0bec
commit 9c49f4bb1e
5 changed files with 107 additions and 59 deletions

View File

@ -6,6 +6,7 @@ import type {
} from '@vben-core/form-ui';
import type { VxeGridProps } from './types';
import type {ViewedRowHelper} from './use-viewed-row';
import { toRaw } from 'vue';
@ -42,20 +43,15 @@ export class VxeGridApi<
public store: Store<VxeGridProps<T, D, P>>;
/**
* helper mount useViewedRow
*/
public viewedRowHelper: null | ViewedRowHelper<T> = null;
private isMounted = false;
private stateHandler: StateHandler;
// 已读行相关方法(由 use-vxe-grid.vue 注入)
private viewedRowHelper: null | {
clearViewed: () => void;
isViewed: (record: T) => boolean;
markAsViewed: (record: T) => void;
markKeysAsViewed: (keys: Array<number | string>) => void;
removeKeys: (keys: Array<number | string>) => void;
viewedSet: { value: Set<number | string> };
} = null;
constructor(options: VxeGridProps<T, D, P> = {} as VxeGridProps<T, D, P>) {
const storeState = { ...options };
@ -82,7 +78,7 @@ export class VxeGridApi<
}
/**
* key
* key
*/
getViewedKeys(): Set<number | string> {
const raw = this.viewedRowHelper?.viewedSet.value;
@ -170,14 +166,6 @@ export class VxeGridApi<
}
}
/**
* helper
* @internal
*/
setViewedRowHelper(helper: VxeGridApi<T, D, P>['viewedRowHelper']) {
this.viewedRowHelper = helper;
}
toggleSearchForm(show?: boolean) {
this.setState({
showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm,
@ -191,5 +179,6 @@ export class VxeGridApi<
unmount() {
this.isMounted = false;
this.stateHandler.reset();
this.viewedRowHelper = null;
}
}

View File

@ -168,7 +168,7 @@ export interface VxeGridProps<
/**
*
*/
viewedRow?: boolean | ViewedRowOptions<T>;
viewedRowOptions?: boolean | ViewedRowOptions<T>;
}
export type ExtendedVxeGridApi<

View File

@ -373,6 +373,8 @@ export function useViewedRow<T = any>(
};
}
export type ViewedRowHelper<T = any> = ReturnType<typeof useViewedRow<T>>;
// ========== 工具函数 ==========
function normalizeClassName(value: any): string {
@ -445,24 +447,64 @@ export function applyViewedRowOptions(
viewedRowConfig: boolean | ViewedRowOptions,
helper: ReturnType<typeof useViewedRow>,
) {
// 从最新的配置中读取 rowClassName 和 rowStyle支持运行时修改
const viewedRowClassName = isBoolean(viewedRowConfig)
? undefined
: viewedRowConfig.rowClassName;
const viewedRowStyle = isBoolean(viewedRowConfig)
? undefined
: viewedRowConfig.rowStyle;
// 注入 rowClassName
const originalRowClassName = mergedOptions.rowClassName;
mergedOptions.rowClassName = (params: any) => {
if (!helper.isViewed(params.row)) {
return normalizeClassName(
isFunction(originalRowClassName)
? originalRowClassName(params)
: originalRowClassName,
);
}
let viewedClass: string;
if (viewedRowClassName === undefined || viewedRowClassName === null) {
viewedClass = DEFAULT_VIEWED_CLASS;
} else if (typeof viewedRowClassName === 'string') {
viewedClass = viewedRowClassName;
} else if (isFunction(viewedRowClassName)) {
viewedClass = normalizeClassName(viewedRowClassName(params));
} else {
viewedClass = DEFAULT_VIEWED_CLASS;
}
return mergeClassNames(
isFunction(originalRowClassName)
? originalRowClassName(params)
: originalRowClassName,
helper.getRowClassName(params),
viewedClass,
);
};
// 注入 rowStyle
const originalRowStyle = mergedOptions.rowStyle;
mergedOptions.rowStyle = (params: any) => {
const viewedStyle = helper.getRowStyle(params);
const originalStyle = isFunction(originalRowStyle)
? originalRowStyle(params)
: originalRowStyle;
if (!helper.isViewed(params.row)) {
return originalStyle || undefined;
}
let viewedStyle: any;
if (viewedRowStyle === undefined || viewedRowStyle === null) {
viewedStyle = undefined;
} else if (isFunction(viewedRowStyle)) {
viewedStyle = viewedRowStyle(params);
} else {
viewedStyle = viewedRowStyle;
}
if (!viewedStyle && !originalStyle) return undefined;
if (!originalStyle) return viewedStyle;
if (!viewedStyle) return originalStyle;

View File

@ -19,12 +19,10 @@ import {
nextTick,
onMounted,
onUnmounted,
shallowRef,
toRaw,
useSlots,
useTemplateRef,
watch,
watchEffect,
} from 'vue';
import { usePriorityValues } from '@vben/hooks';
@ -79,45 +77,31 @@ const {
tableTitleHelp,
showSearchForm,
separator,
viewedRow,
viewedRowOptions,
} = usePriorityValues(props, state);
// ========== viewedRow ==========
const defaultKeyField = (gridOptions.value?.rowConfig as any)?.keyField || 'id';
// viewedRowOptionshelper persist/keyField
// actionCodesrowClassNamerowStyleviewedKeys options computed
const gridApi = props.api;
const viewedRowHelper = shallowRef<null | ReturnType<typeof useViewedRow>>(
null,
);
// + helper
watch(
viewedRow,
viewedRowOptions,
(cfg) => {
if (!cfg) {
viewedRowHelper.value = null;
props.api?.setViewedRowHelper?.(null);
return;
}
const resolvedOptions = isBoolean(cfg)
? {keyField: defaultKeyField}
: {keyField: defaultKeyField, ...cfg};
viewedRowHelper.value = useViewedRow(resolvedOptions);
// API helper
if (props.api?.setViewedRowHelper) {
props.api.setViewedRowHelper(viewedRowHelper.value);
}
// helper
if (gridApi.viewedRowHelper) return;
if (!cfg) return;
const keyField =
(gridOptions.value?.rowConfig as any)?.keyField || 'id';
const resolved = isBoolean(cfg)
? {keyField}
: {keyField, ...cfg};
gridApi.viewedRowHelper = useViewedRow(resolved);
},
{immediate: true},
);
// viewedSet grid
watchEffect(() => {
const helper = viewedRowHelper.value;
if (!helper) return;
// 访 viewedSet.value
void helper.viewedSet.value;
});
const { isMobile } = usePreferences();
const isSeparator = computed(() => {
if (
@ -276,11 +260,11 @@ const options = computed(() => {
}
// rowClassNamerowStylecolumns
if (viewedRow.value && viewedRowHelper.value) {
if (viewedRowOptions.value && gridApi.viewedRowHelper) {
applyViewedRowOptions(
mergedOptions,
viewedRow.value,
viewedRowHelper.value,
viewedRowOptions.value,
gridApi.viewedRowHelper,
);
}

View File

@ -87,7 +87,7 @@ const gridOptions: VxeGridProps<RowType> = {
const [Grid, gridApi] = useVbenVxeGrid({
gridOptions,
viewedRow: {
viewedRowOptions: {
//
actionCodes: ['view'],
//
@ -144,6 +144,33 @@ function onView(row: RowType) {
});
}
const isStyle = ref(false);
function onStyleSet() {
isStyle.value = !isStyle.value;
gridApi.setState({
viewedRowOptions: {
rowStyle: () => {
return isStyle.value ? {backgroundColor: 'gray'} : '';
},
},
});
}
const isClassName = ref(false);
function onClassNameSet() {
isClassName.value = !isClassName.value;
gridApi.setState({
viewedRowOptions: {
rowClassName: () => {
return isClassName.value ? 'bg-red-100 vxe-row--viewed' : 'vxe-row--viewed';
},
},
});
}
function onCustomSet() {
const tableData = gridApi.grid.getData();
const keys = tableData.slice(0, 2).map((row) => row.id);
@ -168,7 +195,13 @@ function onClearViewed() {
<Grid table-title="" table-title-help="">
<template #toolbar-tools>
<Button class="mr-2" type="primary" @click="onCustomSet">
手动设置
手动标记
</Button>
<Button class="mr-2" type="primary" @click="onStyleSet">
设置Style
</Button>
<Button class="mr-2" type="primary" @click="onClassNameSet">
设置ClassName
</Button>
<Button type="primary" @click="onClearViewed"> </Button>
</template>