refactor(ui): 统一复选框组件使用 defineModel 和 model-value 语法
- 在 BenchmarkTable.vue 中使用 defineModel 替代 props 和 emit 管理选中状态 - 统一所有复选框组件使用 model-value 属性替代 checked 属性 - 移除不必要的 class 样式和事件修饰符,简化代码逻辑 - 优化表格头部固定样式,提升滚动体验
This commit is contained in:
@@ -3,7 +3,6 @@ import { computed, ref } from 'vue'
|
||||
import { formatTime } from '../utils/benchmarkUtils'
|
||||
import GradientButton from '@/components/GradientButton.vue'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import {
|
||||
Table,
|
||||
@@ -14,18 +13,20 @@ import {
|
||||
TableRow,
|
||||
} from '@/components/ui/table'
|
||||
import { Spinner } from '@/components/ui/spinner'
|
||||
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
|
||||
// 使用 defineModel 正确定义 v-model
|
||||
const selectedRowKeys = defineModel('selectedRowKeys', { type: Array, default: () => [] })
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Array, required: true },
|
||||
selectedRowKeys: { type: Array, required: true },
|
||||
loading: { type: Boolean, default: false },
|
||||
loadingMore: { type: Boolean, default: false },
|
||||
hasMore: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:selectedRowKeys', 'export', 'loadMore', 'createAsyncTask'])
|
||||
const emit = defineEmits(['export', 'loadMore', 'createAsyncTask'])
|
||||
|
||||
// 列定义
|
||||
const columns = [
|
||||
@@ -45,13 +46,13 @@ const sortOrder = ref('desc')
|
||||
|
||||
// 全选状态
|
||||
const isAllSelected = computed(() => {
|
||||
return props.data.length > 0 && props.selectedRowKeys.length === props.data.length
|
||||
return props.data.length > 0 && selectedRowKeys.value.length === props.data.length
|
||||
})
|
||||
|
||||
// 半选状态(部分选中)
|
||||
// 半选状态
|
||||
const isIndeterminate = computed(() => {
|
||||
const selectedLen = props.selectedRowKeys.length
|
||||
return selectedLen > 0 && selectedLen < props.data.length
|
||||
const len = selectedRowKeys.value.length
|
||||
return len > 0 && len < props.data.length
|
||||
})
|
||||
|
||||
// 切换排序
|
||||
@@ -62,28 +63,25 @@ function handleSort(key) {
|
||||
sortKey.value = key
|
||||
sortOrder.value = 'desc'
|
||||
}
|
||||
emit('update:selectedRowKeys', [])
|
||||
selectedRowKeys.value = []
|
||||
}
|
||||
|
||||
// 选择切换
|
||||
// 全选切换
|
||||
function handleSelectAll(checked) {
|
||||
if (checked) {
|
||||
emit('update:selectedRowKeys', props.data.map(item => String(item.id)))
|
||||
} else {
|
||||
emit('update:selectedRowKeys', [])
|
||||
}
|
||||
selectedRowKeys.value = checked ? props.data.map(item => String(item.id)) : []
|
||||
}
|
||||
|
||||
// 单行选择
|
||||
function handleSelect(id) {
|
||||
const key = String(id)
|
||||
const newKeys = [...props.selectedRowKeys]
|
||||
const index = newKeys.indexOf(key)
|
||||
const keys = [...selectedRowKeys.value]
|
||||
const index = keys.indexOf(key)
|
||||
if (index > -1) {
|
||||
newKeys.splice(index, 1)
|
||||
keys.splice(index, 1)
|
||||
} else {
|
||||
newKeys.push(key)
|
||||
keys.push(key)
|
||||
}
|
||||
emit('update:selectedRowKeys', newKeys)
|
||||
selectedRowKeys.value = keys
|
||||
}
|
||||
|
||||
// 排序后的数据
|
||||
@@ -130,21 +128,20 @@ function formatNumber(value) {
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="overflow-x-auto max-h-[calc(100vh-400px)] overflow-y-auto
|
||||
<div class="overflow-x-auto max-h-[calc(100vh-400px)] overflow-y-auto relative
|
||||
[&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar]:h-1.5
|
||||
[&::-webkit-scrollbar-track]:bg-transparent
|
||||
[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30 [&::-webkit-scrollbar-thumb]:rounded"
|
||||
>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableRow class="sticky top-0 z-10 bg-card/95 backdrop-blur-sm">
|
||||
<TableHead class="w-[60px]">
|
||||
<div class="flex items-center gap-2">
|
||||
<Checkbox
|
||||
:checked="isAllSelected"
|
||||
:model-value="isAllSelected"
|
||||
:indeterminate="isIndeterminate"
|
||||
@update:checked="handleSelectAll"
|
||||
class="scale-110"
|
||||
@update:model-value="handleSelectAll"
|
||||
/>
|
||||
<span class="text-xs text-muted-foreground">全选</span>
|
||||
</div>
|
||||
@@ -186,9 +183,8 @@ function formatNumber(value) {
|
||||
>
|
||||
<TableCell class="w-[60px]">
|
||||
<Checkbox
|
||||
:checked="selectedRowKeys.includes(String(record.id))"
|
||||
@update:checked="handleSelect(record.id)"
|
||||
class="scale-110"
|
||||
:model-value="selectedRowKeys.includes(String(record.id))"
|
||||
@update:model-value="handleSelect(record.id)"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
||||
@@ -261,9 +261,9 @@
|
||||
<div class="flex items-center justify-between px-6 py-3 border-t border-border">
|
||||
<div class="flex items-center gap-4">
|
||||
<Checkbox
|
||||
:checked="selectedFileIds.length === fileList.length && fileList.length > 0"
|
||||
:model-value="selectedFileIds.length === fileList.length && fileList.length > 0"
|
||||
:indeterminate="selectedFileIds.length > 0 && selectedFileIds.length < fileList.length"
|
||||
@update:checked="handleSelectAll"
|
||||
@update:model-value="handleSelectAll"
|
||||
>
|
||||
全选
|
||||
</Checkbox>
|
||||
|
||||
@@ -89,8 +89,8 @@
|
||||
<TableRow>
|
||||
<TableHead class="w-[50px]">
|
||||
<Checkbox
|
||||
:checked="isAllSelected"
|
||||
@update:checked="handleSelectAll"
|
||||
:model-value="isAllSelected"
|
||||
@update:model-value="handleSelectAll"
|
||||
/>
|
||||
</TableHead>
|
||||
<TableHead class="w-[80px]">ID</TableHead>
|
||||
@@ -105,8 +105,8 @@
|
||||
<TableRow v-for="record in list" :key="record.id">
|
||||
<TableCell>
|
||||
<Checkbox
|
||||
:checked="selectedRowKeys.includes(record.id)"
|
||||
@update:checked="handleSelectRow(record.id)"
|
||||
:model-value="selectedRowKeys.includes(record.id)"
|
||||
@update:model-value="handleSelectRow(record.id)"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>{{ record.id }}</TableCell>
|
||||
|
||||
@@ -99,8 +99,8 @@
|
||||
<TableRow>
|
||||
<TableHead class="w-[50px]">
|
||||
<Checkbox
|
||||
:checked="isAllSelected"
|
||||
@update:checked="handleSelectAll"
|
||||
:model-value="isAllSelected"
|
||||
@update:model-value="handleSelectAll"
|
||||
/>
|
||||
</TableHead>
|
||||
<TableHead class="w-[70px]">ID</TableHead>
|
||||
@@ -120,8 +120,8 @@
|
||||
>
|
||||
<TableCell>
|
||||
<Checkbox
|
||||
:checked="selectedRowKeys.includes(record.id)"
|
||||
@update:checked.stop="handleSelectRow(record.id)"
|
||||
:model-value="selectedRowKeys.includes(record.id)"
|
||||
@update:model-value.stop="handleSelectRow(record.id)"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>{{ record.id }}</TableCell>
|
||||
|
||||
Reference in New Issue
Block a user