<!-- 子组件 -->
<template>
<div>
<el-form inline :model="state.formData" :rules="state.formRules" ref="form">
<el-form-item v-for="item in formItems" :key="item.prop" :label="item.label" :prop="item.prop">
<template v-if="item.type === 'input'">
<el-input v-model="state.formData[item.prop]" :placeholder="item.placeholder" :disabled="item.disabled" :style="{width: item.width, marginLeft: item.marginLeft}" />
</template>
<template v-else-if="item.type === 'select'">
<el-select :style="{width: item.width}" v-model="state.formData[item.prop]" :value="'male'" :placeholder="item.placeholder" :disabled="item.disabled">
<el-option v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</template>
<template v-else-if="item.type === 'date'">
<el-date-picker
v-model="state.formData[item.prop]"
type="daterange"
range-separator="To"
start-placeholder="Start date"
end-placeholder="End date"
:style="{width: item.width, marginLeft: item.marginLeft}"
:default-value="[new Date('2023-00-00-00'), new Date('2023-10-00-00')]"
/>
</template>
<template v-else-if="item.type === 'btn'" >
<el-button v-for="(btn, i) in item.btnArr" :key="btn.id" size:small :type="btn.color" @click="formBtnClick(btn, i)">{{
btn.label }}</el-button>
</template>
</el-form-item>
</el-form>
<el-table border :data="tableData" :loading="loading" @selection-change="handleSelectionChange">
<el-table-column v-if="showCheckbox" type="selection" width="55">
</el-table-column>
<el-table-column v-for="(column, index) in columns" :key="column.prop" :label="column.label" :width="column.width">
<template #default="{ row }">
<template v-if="column.type === 'input'">
<el-input v-model="row[column.prop]" />
</template>
<template v-else-if="column.type === 'select'">
<el-select v-model="row[column.prop]">
<el-option v-for="option in column.options" :key="option.value" :label="option.label"
:value="option.value" />
</el-select>
</template>
<template v-else-if="column.type === 'btn'" >
<el-button style="width: 50px;" v-for="btn in column.btnArr" :key="btn.id" size:small text :type="btn.color" @click="tableBtnClick(btn, row)">{{
btn.label }}</el-button>
</template>
<template v-else>
{{ row[column.prop] }}
</template>
</template>
</el-table-column>
</el-table>
<el-pagination v-if="pagination" :current-page="pagination.currentPage" :page-size="pagination.pageSize"
:total="pagination.total" @current-change="handlePageChange" />
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
const props = defineProps(['columns', 'tableData', 'loading', 'pagination', 'showCheckbox', 'selectedRows', 'formItems'],
{
columns: {
type: Array,
required: true,
validator: (value) => {
return Array.isArray(value) && value.every(item => item.prop && item.label && (item.type === 'input' || item.type === 'select' || item.type === 'btn'))
}
},
tableData: {
type: Array,
required: true,
default: () => []
},
loading: {
type: Boolean,
default: false,
},
pagination: {
type: Object,
default: () => ({
currentPage: 1,
pageSize: 10,
total: 0,
}),
validator: (value) => {
return value.currentPage > 0 && value.pageSize > 0 && value.total >= 0
}
},
showCheckbox: {
type: Boolean,
default: false,
},
selectedRows: {
type: Array,
default: () => [],
validator: (value) => {
return Array.isArray(value) && value.every(item => typeof item === 'object' && item !== null)
}
}
}
)
const state = reactive({
formData: {},
formRules: {}
})
const formBtnClick = (item) => {
if (item.label === '提交') {
emit('formSubmit', state.formData);
} else {
onReset()
emit('formReset', state.formData);
}
};
const onReset = () => {
state.formData = {}
emit('reset');
};
for (const item of props.formItems) {
state.formData[item.prop] = item.value || '';
state.formRules[item.prop] = item.rules || [];
}
const emit = defineEmits()
const handlePageChange = (page) => {
emit('page-change', page)
}
const handleSelectionChange = (selectedRows) => {
emit('update:selected-rows', selectedRows)
}
const tableBtnClick = (btn, rowData) => {
emit('tableBtnClick', btn, rowData)
}
</script>
<!-- -->
<!-- 使用方法 -->
<template>
<div>
<TableComponent
:formItems="state.formItems"
:columns="state.colums"
:tableData="state.tableData"
:loading="state.loading"
:pagination="state.pagination"
:showCheckbox="state.showCheckbox"
:selectedRows="state.selectedRows"
@formSubmit="onSubmitHandler"
@formReset="onResetHandler"
@tableBtnClick="tableBtnClick"
@page-change="handlePageChange"
@update:selected-rows="handleSelectedRowsUpdate"
/>
</div>
</template>
<script setup>
import TableComponent from '@/components/table/table.vue';
import { reactive, onMounted } from 'vue';
const state = reactive({
formItems: [
{
type: 'select', prop: 'a', value: 0, options: [
{ label: 0, value: 0 },
{ label: 1, value: 1 }
],
width: '200px'
},
{ type: 'input', prop: 'a', marginLeft: '-12px' },
{
type: 'select', label: '1', prop: 'a', value: '', options: [
{ label: '全部', value: '' },
{ label: '1', value: 0 },
{ label: '2', value: 1 },
],
width: '200px'
},
{
type: 'select', prop: 'b', value: '', options: [
{ label: '1', value: '' },
{ label: '1', value: 1 }
],
width: '200px'
},
{
prop: 'date', type: 'date',
defaultValue: [new Date(2023, 0, 1), new Date(2023, 1, 1)], marginLeft: '-12px'
},
{
type: 'select', label: '1', prop: 'b1', value: '', options: [
{ label: '1', value: '' },
{ label: '2', value: 0 },
{ label: '3', value: 1 },
],
width: '200px'
},
{type: 'btn', btnArr: [
{label: '提交', color: 'primary', id: 0},
{label: '重置', color: 'primary', id: 1},
]}
],
colums: [
{ prop: 'name', label: '1', width: '120' },
{ prop: 'age', label: '1', width: '120' },
{ prop: 'age', label: '1', width: '120' },
{ prop: 'age', label: '1', width: '120' },
{ prop: 'age', label: '1111\n222', width: '120' },
{
prop: 'age', label: '操作', type: 'btn', width: '300', btnArr: [
{
label: '22',
color: 'primary',
id: 0
},
{
label: '22',
color: 'success',
id: 1
},
{
label: '11',
color: 'primary',
id: 2
},
]
},
],
tableData: [],
loding: false,
pagination: {
currentPage: 1,
pageSize: 1,
total: 0,
},
selectedRows: [],
dummyData: [
{ name: 'John Doe', age: 25, gender: 0 },
{ name: 'Jane Smith', age: 30, gender: 1 },
]
})
onMounted(() => {
loadData()
})
const onSubmitHandler = (formData) => {
console.log('Form submitted!', formData);
};
const onResetHandler = (formData) => {
console.log('Form reset!', formData);
};
const loadData = () => {
state.loading = true;
setTimeout(() => {
const startIndex = (state.pagination.currentPage - 1) * state.pagination.pageSize;
const endIndex = startIndex + state.pagination.pageSize;
const newData = state.dummyData.slice(startIndex, endIndex);
state.tableData = newData;
state.loading = false;
state.pagination.total = state.dummyData.length;
}, 1000);
};
const handlePageChange = (page) => {
state.pagination.currentPage = page;
loadData();
};
const tableBtnClick = item => {
console.log('当前点击的按钮', item);
}
const handleSelectedRowsUpdate = (selectedRows) => {
selectedRows = selectedRows;
console.log('选中的数据', selectedRows);
};
</script>