refactor: 优化viewed实例初始化,rowStyle rowClassName 从最新的配置中读取
parent
28905b0bec
commit
9c49f4bb1e
|
|
@ -6,6 +6,7 @@ import type {
|
||||||
} from '@vben-core/form-ui';
|
} from '@vben-core/form-ui';
|
||||||
|
|
||||||
import type { VxeGridProps } from './types';
|
import type { VxeGridProps } from './types';
|
||||||
|
import type {ViewedRowHelper} from './use-viewed-row';
|
||||||
|
|
||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue';
|
||||||
|
|
||||||
|
|
@ -42,20 +43,15 @@ export class VxeGridApi<
|
||||||
|
|
||||||
public store: Store<VxeGridProps<T, D, P>>;
|
public store: Store<VxeGridProps<T, D, P>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已读行 helper(在 mount 中初始化,业务能力全部封装在 useViewedRow 中)
|
||||||
|
*/
|
||||||
|
public viewedRowHelper: null | ViewedRowHelper<T> = null;
|
||||||
|
|
||||||
private isMounted = false;
|
private isMounted = false;
|
||||||
|
|
||||||
private stateHandler: StateHandler;
|
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>) {
|
constructor(options: VxeGridProps<T, D, P> = {} as VxeGridProps<T, D, P>) {
|
||||||
const storeState = { ...options };
|
const storeState = { ...options };
|
||||||
|
|
||||||
|
|
@ -82,7 +78,7 @@ export class VxeGridApi<
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有已读的 key 集合
|
* 获取所有已读的 key 集合(返回副本,避免外部修改内部状态)
|
||||||
*/
|
*/
|
||||||
getViewedKeys(): Set<number | string> {
|
getViewedKeys(): Set<number | string> {
|
||||||
const raw = this.viewedRowHelper?.viewedSet.value;
|
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) {
|
toggleSearchForm(show?: boolean) {
|
||||||
this.setState({
|
this.setState({
|
||||||
showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm,
|
showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm,
|
||||||
|
|
@ -191,5 +179,6 @@ export class VxeGridApi<
|
||||||
unmount() {
|
unmount() {
|
||||||
this.isMounted = false;
|
this.isMounted = false;
|
||||||
this.stateHandler.reset();
|
this.stateHandler.reset();
|
||||||
|
this.viewedRowHelper = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ export interface VxeGridProps<
|
||||||
/**
|
/**
|
||||||
* 已读行功能
|
* 已读行功能
|
||||||
*/
|
*/
|
||||||
viewedRow?: boolean | ViewedRowOptions<T>;
|
viewedRowOptions?: boolean | ViewedRowOptions<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ExtendedVxeGridApi<
|
export type ExtendedVxeGridApi<
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,8 @@ export function useViewedRow<T = any>(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ViewedRowHelper<T = any> = ReturnType<typeof useViewedRow<T>>;
|
||||||
|
|
||||||
// ========== 工具函数 ==========
|
// ========== 工具函数 ==========
|
||||||
|
|
||||||
function normalizeClassName(value: any): string {
|
function normalizeClassName(value: any): string {
|
||||||
|
|
@ -445,24 +447,64 @@ export function applyViewedRowOptions(
|
||||||
viewedRowConfig: boolean | ViewedRowOptions,
|
viewedRowConfig: boolean | ViewedRowOptions,
|
||||||
helper: ReturnType<typeof useViewedRow>,
|
helper: ReturnType<typeof useViewedRow>,
|
||||||
) {
|
) {
|
||||||
|
// 从最新的配置中读取 rowClassName 和 rowStyle(支持运行时修改)
|
||||||
|
const viewedRowClassName = isBoolean(viewedRowConfig)
|
||||||
|
? undefined
|
||||||
|
: viewedRowConfig.rowClassName;
|
||||||
|
const viewedRowStyle = isBoolean(viewedRowConfig)
|
||||||
|
? undefined
|
||||||
|
: viewedRowConfig.rowStyle;
|
||||||
|
|
||||||
// 注入 rowClassName
|
// 注入 rowClassName
|
||||||
const originalRowClassName = mergedOptions.rowClassName;
|
const originalRowClassName = mergedOptions.rowClassName;
|
||||||
mergedOptions.rowClassName = (params: any) => {
|
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(
|
return mergeClassNames(
|
||||||
isFunction(originalRowClassName)
|
isFunction(originalRowClassName)
|
||||||
? originalRowClassName(params)
|
? originalRowClassName(params)
|
||||||
: originalRowClassName,
|
: originalRowClassName,
|
||||||
helper.getRowClassName(params),
|
viewedClass,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 注入 rowStyle
|
// 注入 rowStyle
|
||||||
const originalRowStyle = mergedOptions.rowStyle;
|
const originalRowStyle = mergedOptions.rowStyle;
|
||||||
mergedOptions.rowStyle = (params: any) => {
|
mergedOptions.rowStyle = (params: any) => {
|
||||||
const viewedStyle = helper.getRowStyle(params);
|
|
||||||
const originalStyle = isFunction(originalRowStyle)
|
const originalStyle = isFunction(originalRowStyle)
|
||||||
? originalRowStyle(params)
|
? originalRowStyle(params)
|
||||||
: originalRowStyle;
|
: 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 (!viewedStyle && !originalStyle) return undefined;
|
||||||
if (!originalStyle) return viewedStyle;
|
if (!originalStyle) return viewedStyle;
|
||||||
if (!viewedStyle) return originalStyle;
|
if (!viewedStyle) return originalStyle;
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,10 @@ import {
|
||||||
nextTick,
|
nextTick,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
shallowRef,
|
|
||||||
toRaw,
|
toRaw,
|
||||||
useSlots,
|
useSlots,
|
||||||
useTemplateRef,
|
useTemplateRef,
|
||||||
watch,
|
watch,
|
||||||
watchEffect,
|
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
import { usePriorityValues } from '@vben/hooks';
|
import { usePriorityValues } from '@vben/hooks';
|
||||||
|
|
@ -79,45 +77,31 @@ const {
|
||||||
tableTitleHelp,
|
tableTitleHelp,
|
||||||
showSearchForm,
|
showSearchForm,
|
||||||
separator,
|
separator,
|
||||||
viewedRow,
|
viewedRowOptions,
|
||||||
} = usePriorityValues(props, state);
|
} = usePriorityValues(props, state);
|
||||||
|
|
||||||
// ========== 已读行:响应 viewedRow 配置变化 ==========
|
// viewedRowOptions:helper 只创建一次(persist/keyField 不支持运行时切换)
|
||||||
const defaultKeyField = (gridOptions.value?.rowConfig as any)?.keyField || 'id';
|
// actionCodes、rowClassName、rowStyle、viewedKeys 的变化通过 options computed 自然响应
|
||||||
|
const gridApi = props.api;
|
||||||
|
|
||||||
const viewedRowHelper = shallowRef<null | ReturnType<typeof useViewedRow>>(
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 初始化 + 监听配置变化时重建 helper
|
|
||||||
watch(
|
watch(
|
||||||
viewedRow,
|
viewedRowOptions,
|
||||||
(cfg) => {
|
(cfg) => {
|
||||||
if (!cfg) {
|
// helper 已存在则不重建
|
||||||
viewedRowHelper.value = null;
|
if (gridApi.viewedRowHelper) return;
|
||||||
props.api?.setViewedRowHelper?.(null);
|
|
||||||
return;
|
if (!cfg) return;
|
||||||
}
|
|
||||||
const resolvedOptions = isBoolean(cfg)
|
const keyField =
|
||||||
? {keyField: defaultKeyField}
|
(gridOptions.value?.rowConfig as any)?.keyField || 'id';
|
||||||
: {keyField: defaultKeyField, ...cfg};
|
const resolved = isBoolean(cfg)
|
||||||
viewedRowHelper.value = useViewedRow(resolvedOptions);
|
? {keyField}
|
||||||
// 同步更新 API 中的 helper 引用
|
: {keyField, ...cfg};
|
||||||
if (props.api?.setViewedRowHelper) {
|
gridApi.viewedRowHelper = useViewedRow(resolved);
|
||||||
props.api.setViewedRowHelper(viewedRowHelper.value);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{immediate: true},
|
{immediate: true},
|
||||||
);
|
);
|
||||||
|
|
||||||
// viewedSet 变化时,主动刷新 grid 行样式
|
|
||||||
watchEffect(() => {
|
|
||||||
const helper = viewedRowHelper.value;
|
|
||||||
if (!helper) return;
|
|
||||||
// 访问 viewedSet.value 建立依赖追踪
|
|
||||||
void helper.viewedSet.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { isMobile } = usePreferences();
|
const { isMobile } = usePreferences();
|
||||||
const isSeparator = computed(() => {
|
const isSeparator = computed(() => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -276,11 +260,11 @@ const options = computed(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注入已读行功能(rowClassName、rowStyle、columns 拦截)
|
// 注入已读行功能(rowClassName、rowStyle、columns 拦截)
|
||||||
if (viewedRow.value && viewedRowHelper.value) {
|
if (viewedRowOptions.value && gridApi.viewedRowHelper) {
|
||||||
applyViewedRowOptions(
|
applyViewedRowOptions(
|
||||||
mergedOptions,
|
mergedOptions,
|
||||||
viewedRow.value,
|
viewedRowOptions.value,
|
||||||
viewedRowHelper.value,
|
gridApi.viewedRowHelper,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions,
|
gridOptions,
|
||||||
viewedRow: {
|
viewedRowOptions: {
|
||||||
// 触发已读的操作码
|
// 触发已读的操作码
|
||||||
actionCodes: ['view'],
|
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() {
|
function onCustomSet() {
|
||||||
const tableData = gridApi.grid.getData();
|
const tableData = gridApi.grid.getData();
|
||||||
const keys = tableData.slice(0, 2).map((row) => row.id);
|
const keys = tableData.slice(0, 2).map((row) => row.id);
|
||||||
|
|
@ -168,7 +195,13 @@ function onClearViewed() {
|
||||||
<Grid table-title="已查看行标记" table-title-help="提示">
|
<Grid table-title="已查看行标记" table-title-help="提示">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button class="mr-2" type="primary" @click="onCustomSet">
|
<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>
|
||||||
<Button type="primary" @click="onClearViewed"> 清空缓存</Button>
|
<Button type="primary" @click="onClearViewed"> 清空缓存</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue