<template>
<div class="my-table">
<el-table v-bind="attrs" @row-dblclick="rowDblclick" :data="tableData" border>
<slot name="checkbox">
<el-table-column width="80px" v-if="showCheckbox">
<template #header>
<el-checkbox :indeterminate="checkboxMsg.isIndeterminate" v-model="checkboxMsg.checkAll"
@change="handleCheckAllChange">
</el-checkbox>
</template>
<template #default="scope">
<div class="inline-block" @click="clickCheckbox(scope.row)">
<el-checkbox :disabled="scope.row.disabled" v-model="scope.row.checked"
@change="handleCheckChange($event, scope.row)">
</el-checkbox>
</div>
</template>
</el-table-column>
</slot>
<el-table-column type="index" label="序号" width="80" v-if="!hideIndex" />
<el-table-column v-for="item in column" :key="item.prop" :show-overflow-tooltip="tooltip" :prop="item.prop"
:label="item.label" :width="item.width" v-bind="item.other" />
<slot name="handle">
<el-table-column v-if="!hideHandle" fixed="right" label="操作" :width="handleWidth">
<template #default="scope">
<my-btn v-if="!hideView" type="primary" size="small" @click="handleClick(scope, 'view')">查看</my-btn>
<my-btn v-if="!hideEdit" type="warning" size="small" @click="handleClick(scope, 'edit')">修改</my-btn>
<el-popconfirm v-if="!hideDel" title="确定要删除这个吗?" @confirm="handleClick(scope, 'del')">
<template #reference>
<my-btn type="danger" size="small">删除</my-btn> </template>
</el-popconfirm>
</template>
</el-table-column>
</slot>
</el-table>
<el-pagination v-if="!hidePagination" :current-page="pageNum" :page-size="pageSize" :page-sizes="pageSizes"
layout="sizes, prev, pager, next" :total="total" @size-change="sizeChange" @current-change="currentChange" />
</div>
</template>
<script setup >
const { proxy } = getCurrentInstance()
defineOptions({
name: "MyTable",
inheritAttrs: false,
})
const attrs = useAttrs();
console.log(attrs)
const prop = defineProps({
column: {
type: Array,
default: () => {
[
{
prop: "",
width: "",
label: "",
other: {},
},
];
},
},
tableData: {
type: Array,
default: () => [],
},
tooltip:{
type: Boolean,
default: true,
},
hideHandle: {
type: Boolean,
default: false,
},
hideView: {
type: Boolean,
default: false,
},
hideEdit: {
type: Boolean,
default: false,
},
hideDel: {
type: Boolean,
default: false,
},
hidePagination: {
type: Boolean,
default: false,
},
hideIndex: {
type: Boolean,
default: false,
},
showCheckbox: {
type: Boolean,
default: false,
},
pageNum: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 1,
},
pageSizes: {
type: Array,
default: () => [10, 20, 50, 100],
},
total: {
type: Number,
default: 1,
},
max: {
type: Number,
default: 0,
},
key: {
type: String,
default: 'id'
}
});
const {
column,
tableData,
hideHandle,
hideView,
hideEdit,
hideDel,
pageNum,
pageSize,
} = toRefs(prop);
let handleWidth = computed(() => {
let width = 200;
if (hideView.value) {
width -= 60;
}
if (hideEdit.value) {
width -= 60;
}
if (hideDel.value) {
width -= 60;
}
return Math.max(80, width);
});
const emits = defineEmits([
"handleEvent",
"dblclic",
"update:pageNum",
"update:pageSize",
"paginationChange"
]);
const handleClick = (value, type) => {
emits("handleEvent", { value, type });
};
const rowDblclick = (row, column) => {
emits("dblclic", { row, column });
}
const sizeChange = (value) => {
emits("update:pageSize", value);
emits("update:pageNum", 1);
emits("paginationChange");
};
const currentChange = (value) => {
emits("update:pageNum", value);
emits("paginationChange");
};
// 多选部分
const checkboxMsg = reactive({
isIndeterminate: false,
checkAll: false,
selectedList: []
})
const clickCheckbox = (item) => {
// 处理不可选的被选中的情况
let { disabled, checked } = item
if (disabled && checked) {
item.checked = false
handleCheckChange(false, item)
}
}
const handleCheckChange = (e, msg) => {
if (e && prop.max && checkboxMsg.selectedList.length >= prop.max) {
proxy.$message.warning(`最大可選為${prop.max}`);
nextTick(() => {
// // 同步赋值会导致e的值异常
msg.checked = false
})
return
}
const key = prop.key
let val = msg[key]
if (e) {
checkboxMsg.selectedList.push({
...msg
})
} else {
let index = checkboxMsg.selectedList.findIndex(item => {
return val === item[key]
})
if (~index) {
checkboxMsg.selectedList.splice(index, 1)
}
}
examineChecked()
}
const examineChecked = (init = false) => {
let checkedLength = 0
prop.tableData.forEach(item => {
if (item.checked) {
init && checkboxMsg.selectedList.push({
...item
})
checkedLength++
}
})
if (checkedLength == prop.tableData.length) {
checkboxMsg.checkAll = true
checkboxMsg.isIndeterminate = false
} else {
checkboxMsg.checkAll = false
if (checkedLength) {
checkboxMsg.isIndeterminate = true
} else {
checkboxMsg.isIndeterminate = false
}
}
}
const handleCheckAllChange = (e) => {
if (e && prop.max && checkboxMsg.selectedList.length >= prop.max) {
proxy.$message.warning(`最大可選為${prop.max}`);
checkboxMsg.checkAll = false
return
}
prop.tableData.forEach(item => {
if (!item.disabled && e != item.checked) {
item.checked = e
handleCheckChange(e, item)
}
})
}
defineExpose({
getSelectedList() {
return checkboxMsg.selectedList
},
examineChecked
})
</script>
<style scoped>
.my-table {
width: fit-content;
max-width: 100%;
}
.my-table :deep(td),
.my-table :deep(th) {
text-align: center;
}
.my-table .el-table {
margin-top: 10px;
margin-bottom: 10px;
}
.my-table .el-pagination {
justify-content: center;
}
</style>
vue3 elementPlus表格基础功封装
于 2023-06-14 17:31:06 首次发布