import { ref } from 'vue' // 列表表头按字段排序。各页传一组「升序语义」的比较器,降序由这里统一取反; // 比较器里用 `||` 串一个兜底字段(一般是 id),值相等时顺序才稳定、不会每次渲染乱跳。 // // 用法: // const { toggleSort, sortMark, applySort } = useTableSort({ // id: (a, b) => a.id - b.id, // name: (a, b) => a.name.localeCompare(b.name, 'zh') || a.id - b.id, // }, 'id') // const viewRows = computed(() => applySort(rows.value.filter(...))) // 名称{{ sortMark('name') }} export type SortDir = 'asc' | 'desc' export type Comparator = (a: T, b: T) => number export function useTableSort( comparators: Record>, defaultKey: string, defaultDir: SortDir = 'asc' ) { const sortKey = ref(defaultKey) const sortDir = ref(defaultDir) function toggleSort(key: string) { if (!comparators[key]) return if (sortKey.value === key) sortDir.value = sortDir.value === 'asc' ? 'desc' : 'asc' else { sortKey.value = key; sortDir.value = 'asc' } } // 表头后缀的排序箭头;非当前排序列返回空串 function sortMark(key: string) { return sortKey.value === key ? (sortDir.value === 'asc' ? ' ↑' : ' ↓') : '' } // 返回新数组,不改原列表(原列表常是 ref 里的接口数据) function applySort(list: T[]): T[] { const cmp = comparators[sortKey.value] if (!cmp) return list const dir = sortDir.value === 'asc' ? 1 : -1 return [...list].sort((a, b) => cmp(a, b) * dir) } return { sortKey, sortDir, toggleSort, sortMark, applySort } }