|
|
|
|
@ -16,7 +16,12 @@
|
|
|
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
@row-click="handleRowClick"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="55" reserve-selection />
|
|
|
|
|
<el-table-column
|
|
|
|
|
type="selection"
|
|
|
|
|
width="55"
|
|
|
|
|
reserve-selection
|
|
|
|
|
:selectable="isSelectionColumnSelectable"
|
|
|
|
|
/>
|
|
|
|
|
<el-table-column
|
|
|
|
|
v-for="column in columns"
|
|
|
|
|
:key="column.prop || column.slotName"
|
|
|
|
|
@ -71,6 +76,7 @@ const props = withDefaults(
|
|
|
|
|
pageSize?: number
|
|
|
|
|
initialRows?: any[]
|
|
|
|
|
queryParams?: Record<string, any> // 新增
|
|
|
|
|
selectable?: (row: any, index: number) => boolean
|
|
|
|
|
/** ✅ 新增 */
|
|
|
|
|
defaultSelectedKeys?: (string | number)[]
|
|
|
|
|
}>(),
|
|
|
|
|
@ -102,6 +108,18 @@ const syncingSelection = ref(false)
|
|
|
|
|
const isSingleSelect = computed(() => props.selectionType === 'single')
|
|
|
|
|
|
|
|
|
|
const resolveRowKey = (row: Record<string, any>) => row[props.rowKey]
|
|
|
|
|
const isRowSelectable = (row: any, index = list.value.findIndex((item) => resolveRowKey(item) === resolveRowKey(row))) => {
|
|
|
|
|
return props.selectable ? props.selectable(row, index) : true
|
|
|
|
|
}
|
|
|
|
|
const isSelectionColumnSelectable = (row: any, index: number) => isRowSelectable(row, index)
|
|
|
|
|
|
|
|
|
|
const removeUnselectableSelections = () => {
|
|
|
|
|
list.value.forEach((row, index) => {
|
|
|
|
|
if (!isRowSelectable(row, index)) {
|
|
|
|
|
selectedMap.value.delete(resolveRowKey(row))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const refreshSelectionOnTable = async () => {
|
|
|
|
|
await nextTick()
|
|
|
|
|
@ -111,9 +129,9 @@ const refreshSelectionOnTable = async () => {
|
|
|
|
|
try {
|
|
|
|
|
table.clearSelection()
|
|
|
|
|
const selectedIds = selectedMap.value
|
|
|
|
|
list.value.forEach((row) => {
|
|
|
|
|
list.value.forEach((row, index) => {
|
|
|
|
|
const rowId = resolveRowKey(row)
|
|
|
|
|
if (selectedIds.has(rowId)) {
|
|
|
|
|
if (selectedIds.has(rowId) && isRowSelectable(row, index)) {
|
|
|
|
|
table.toggleRowSelection(row, true)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
@ -139,6 +157,7 @@ const getList = async () => {
|
|
|
|
|
const data = await props.fetchApi(params)
|
|
|
|
|
list.value = data.list || []
|
|
|
|
|
total.value = data.total || 0
|
|
|
|
|
removeUnselectableSelections()
|
|
|
|
|
await refreshSelectionOnTable()
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
@ -147,9 +166,10 @@ const getList = async () => {
|
|
|
|
|
|
|
|
|
|
const handleSelectionChange = (rows: any[]) => {
|
|
|
|
|
if (syncingSelection.value) return
|
|
|
|
|
const selectableRows = rows.filter((row) => isRowSelectable(row))
|
|
|
|
|
if (isSingleSelect.value) {
|
|
|
|
|
selectedMap.value.clear()
|
|
|
|
|
const latestRow = rows.length ? rows[rows.length - 1] : undefined
|
|
|
|
|
const latestRow = selectableRows.length ? selectableRows[selectableRows.length - 1] : undefined
|
|
|
|
|
if (latestRow) {
|
|
|
|
|
selectedMap.value.set(resolveRowKey(latestRow), latestRow)
|
|
|
|
|
}
|
|
|
|
|
@ -160,13 +180,14 @@ const handleSelectionChange = (rows: any[]) => {
|
|
|
|
|
pageIdSet.forEach((id) => {
|
|
|
|
|
selectedMap.value.delete(id)
|
|
|
|
|
})
|
|
|
|
|
rows.forEach((row) => {
|
|
|
|
|
selectableRows.forEach((row) => {
|
|
|
|
|
selectedMap.value.set(resolveRowKey(row), row)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleRowClick = (row: any) => {
|
|
|
|
|
if (!isSingleSelect.value) return
|
|
|
|
|
if (!isRowSelectable(row)) return
|
|
|
|
|
const table = tableRef.value
|
|
|
|
|
if (!table) return
|
|
|
|
|
syncingSelection.value = true
|
|
|
|
|
|