yn_digital_gadgets_web/src/components/ComTable/index.vue

232 lines
5.7 KiB
Vue

<template>
<div class="com-table-container">
<!-- 查询表单 -->
<ComSearchForm
v-if="showSearch"
ref="searchFormRef"
:form-columns="formColumns"
:show-search="showSearch"
:default-form-data="defaultFormData"
:size="size"
@search="handleSearch"
@reset="handleReset"
/>
<!-- 数据表格 -->
<ComDataTable
ref="dataTableRef"
:table-data="tableData"
:table-columns="tableColumns"
:loading="loading"
:pagination="pagination"
:show-selection="showSelection"
:show-index="showIndex"
:show-toolbar="showToolbar"
:show-action="showAction"
:action-columns="actionColumns"
@selection-change="handleSelectionChange"
@refresh="handleRefresh"
@pagination-change="handlePaginationChange"
@action="handleAction"
>
<!-- 工具栏插槽 -->
<template #toolbar>
<slot
name="toolbar"
:formData="
Object.assign({}, searchFormRef?.getFormData() || {}, {
pageNum: pagination.page,
pageSize: pagination.limit,
}) || {}
"
/>
</template>
<!-- 自定义列插槽 -->
<template
v-for="column in tableColumns"
:key="column.prop"
#[column.slot]="{ row, index, prop }"
>
<slot :name="column.slot" :row="row" :index="index" :prop="prop" />
</template>
<!-- 操作列插槽 -->
<template #action="{ row, index }">
<slot name="action" :row="row" :index="index" />
</template>
</ComDataTable>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import ComSearchForm from '@/components/ComSearchForm/index.vue'
import ComDataTable from '@/components/ComDataTable/index.vue'
const props = defineProps({
// 表单配置
formColumns: {
type: Array,
default: () => [],
},
// 表格配置
tableColumns: {
type: Array,
default: () => [],
},
// 显示搜索表单
showSearch: {
type: Boolean,
default: true,
},
// 表单大小
size: {
type: String,
default: 'default',
},
// 默认表单数据
defaultFormData: {
type: Object,
default: () => ({}),
},
// 表格功能开关
showSelection: {
type: Boolean,
default: false,
},
showIndex: {
type: Boolean,
default: true,
},
showToolbar: {
type: Boolean,
default: false,
},
showAction: {
type: Boolean,
default: false,
},
// 操作列配置
actionColumns: {
type: Array,
default: () => [],
},
// 数据加载函数
loadData: {
type: Function,
default: null,
},
// 初始化默认查询参数
defaultQueryParams: {
type: Object,
default: () => ({}),
},
})
const emit = defineEmits(['search', 'reset', 'selection-change', 'action'])
const searchFormRef = ref(null)
const dataTableRef = ref(null)
const loading = ref(false)
const tableData = ref([])
const pagination = reactive({
page: 1,
limit: 10,
total: 0,
})
// 搜索
const handleSearch = (formData) => {
pagination.page = 1
fetchData(formData)
emit('search', formData)
}
// 重置
const handleReset = (formData) => {
pagination.page = 1
fetchData(formData)
emit('reset', formData)
}
// 选择变化
const handleSelectionChange = (selection) => {
emit('selection-change', selection)
}
// 刷新
const handleRefresh = () => {
const formData = searchFormRef.value?.getFormData() || {}
fetchData(formData)
}
// 分页变化
const handlePaginationChange = (newPagination) => {
Object.assign(pagination, newPagination)
const formData = searchFormRef.value?.getFormData() || {}
fetchData(formData)
}
// 操作
const handleAction = (action, row, index) => {
emit('action', action, row, index)
}
// 获取数据
const fetchData = async (formData = {}) => {
if (!props.loadData) {
console.warn('ComTable: loadData function is not provided')
return
}
loading.value = true
try {
const params = {
...formData,
...props.defaultQueryParams,
pageNum: pagination.page, // 后端可能需要pageNum
pageSize: pagination.limit, // 后端可能需要pageSize
}
const response = await props.loadData(params)
// 假设返回格式:{ rows: [], total: 0 } 或 { data: { rows: [], total: 0 } }
if (response) {
const data = response.rows || response.data?.rows || response.data || []
const total = response.total || response.data?.total || 0
tableData.value = data
pagination.total = total
}
} catch (error) {
console.error('ComTable: fetchData error', error)
tableData.value = []
pagination.total = 0
} finally {
loading.value = false
}
}
onMounted(() => {
fetchData()
})
// 暴露方法
defineExpose({
searchFormRef,
dataTableRef,
refresh: handleRefresh,
getFormData: () => searchFormRef.value?.getFormData() || {},
resetForm: () => searchFormRef.value?.resetForm(),
clearSelection: () => dataTableRef.value?.clearSelection(),
})
</script>
<style scoped>
.com-table-container {
width: 100%;
}
</style>