101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
export interface SortableColumn {
|
|
key?: string;
|
|
slot?: string;
|
|
prop?: string | ((index: number) => number);
|
|
name?: string; // 列的显示名称
|
|
sortable?: boolean; // 是否可排序
|
|
zeroAsNull?: boolean; // 是否将 0 视为 null 值处理
|
|
[key: string]: any;
|
|
}
|
|
|
|
// 可排序表格的函数
|
|
export const useSortableTable = <T>(
|
|
dataRef: Ref<T[]>,
|
|
defaultSortColumn: MaybeRefOrGetter<string> = "", // 默认排序列的key值,可以让某一列默认排序
|
|
defaultSortDirection: MaybeRefOrGetter<"asc" | "desc" | ""> = "asc", // 为空表示不排序
|
|
columnsRef?: Ref<SortableColumn[]> // 列配置,用于获取 zeroAsNull 等配置
|
|
) => {
|
|
// 排序状态
|
|
const sortColumn = ref<string>(toValue(defaultSortColumn));
|
|
const sortDirection = ref<"asc" | "desc" | "">(
|
|
toValue(defaultSortColumn) ? toValue(defaultSortDirection) : ""
|
|
);
|
|
|
|
// 监听默认排序参数的变化
|
|
watchEffect(() => {
|
|
const newColumn = toValue(defaultSortColumn);
|
|
sortColumn.value = newColumn;
|
|
sortDirection.value = newColumn ? toValue(defaultSortDirection) : "";
|
|
});
|
|
|
|
// 排序处理函数
|
|
const handleSort = (column: SortableColumn) => {
|
|
if (!column.sortable) return;
|
|
|
|
const columnKey = column.key || column.slot || column.prop;
|
|
if (!columnKey || typeof columnKey !== "string") return;
|
|
|
|
if (sortColumn.value === columnKey) {
|
|
// 当前列被点击:升序 -> 降序 -> 取消排序
|
|
if (sortDirection.value === "asc") {
|
|
// 如果是升序,改为降序
|
|
sortDirection.value = "desc";
|
|
} else if (sortDirection.value === "desc") {
|
|
// 如果是降序,取消排序
|
|
sortColumn.value = "";
|
|
sortDirection.value = "";
|
|
} else {
|
|
// 如果是不排序,设置为升序
|
|
sortDirection.value = "asc";
|
|
}
|
|
} else {
|
|
// 如果点击的是新列,设置为升序
|
|
sortColumn.value = columnKey;
|
|
sortDirection.value = "asc";
|
|
}
|
|
};
|
|
|
|
// 计算排序后的数据
|
|
const getSortedData = computed(() => {
|
|
const data = dataRef.value || [];
|
|
if (!sortColumn.value || !sortDirection.value) return data;
|
|
|
|
// 查找当前排序列的配置
|
|
const currentColumn = columnsRef?.value?.find(
|
|
(col) => (col.key || col.slot || col.prop) === sortColumn.value
|
|
);
|
|
|
|
return [...data].sort((a: any, b: any) => {
|
|
let aValue = a[sortColumn.value];
|
|
let bValue = b[sortColumn.value];
|
|
const factor = sortDirection.value === "asc" ? 1 : -1;
|
|
|
|
// 如果配置了 zeroAsNull,将 0 视为 null
|
|
if (currentColumn?.zeroAsNull) {
|
|
if (aValue === 0) aValue = null;
|
|
if (bValue === 0) bValue = null;
|
|
}
|
|
|
|
// 处理 null 和 undefined 值
|
|
if (aValue == null && bValue == null) return 0;
|
|
if (aValue == null) return 1;
|
|
if (bValue == null) return -1;
|
|
|
|
// 根据数据类型进行排序
|
|
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
return (aValue - bValue) * factor;
|
|
} else {
|
|
// 字符串或其他类型
|
|
return String(aValue).localeCompare(String(bValue)) * factor;
|
|
}
|
|
});
|
|
});
|
|
|
|
return {
|
|
sortColumn,
|
|
sortDirection,
|
|
handleSort,
|
|
sortedData: getSortedData
|
|
};
|
|
};
|