232 lines
5.7 KiB
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>
|