<template> <div class="form-table" ref="scFormTable"> <el-table :data="data" ref="table" border stripe :cell-style="{ textAlign: 'center' }" :header-cell-style="{ textAlign: 'center', background: 'var(--el-table-row-hover-bg-color)', color: 'var(--el-text-color-primary)', }" > <el-table-column type="index" width="50" fixed="left"> <template #header> <el-button v-if="!hideAdd" type="primary" icon="el-icon-plus" size="small" circle @click="rowAdd"></el-button> <el-tooltip v-else content="序号" placement="top"> # </el-tooltip> </template> <template #default="scope"> <div :class="['form-table-handle', { 'form-table-handle-delete': !hideDelete }]"> <span>{{ scope.$index + 1 }}</span> <el-button v-if="!hideDelete" type="danger" icon="el-icon-delete" size="small" plain circle @click="rowDel(scope.row, scope.$index)" ></el-button> </div> </template> </el-table-column> <el-table-column label="" width="50" v-if="dragSort"> <template #header> <el-icon> <el-tooltip content="拖动排序" placement="top"> <WarningFilled /> </el-tooltip> </el-icon> </template> <template #default> <div class="move" style="cursor: move"> <el-icon> <Sort /> </el-icon> </div> </template> </el-table-column> <slot></slot> <template #empty> {{ placeholder }} </template> </el-table> </div> </template> <script> import Sortable from 'sortablejs'; export default { props: { /** * 表格数据 */ modelValue: { type: Array, default: () => [] }, /** * 新增行模板 */ addTemplate: { type: Object, default: () => {} }, /** * 无数据时的提示语 */ placeholder: { type: String, default: '暂无数据' }, /** * 是否启用拖拽排序 */ dragSort: { type: Boolean, default: false }, /** * 是否隐藏新增按钮 */ hideAdd: { type: Boolean, default: false }, /** * 是否隐藏删除按钮 */ hideDelete: { type: Boolean, default: false }, }, data() { return { /** * 表格数据 */ data: [], }; }, mounted() { this.data = this.modelValue; if (this.dragSort) { this.rowDrop(); } }, watch: { modelValue() { this.data = this.modelValue; }, data: { handler() { /** * 更新表格数据 * @event update:modelValue * @type {Array} */ this.$emit('update:modelValue', this.data); }, deep: true, }, }, methods: { /** * 启用表格行拖拽排序 */ rowDrop() { const _this = this; const tbody = this.$refs.table.$el.querySelector('.el-table__body-wrapper tbody'); Sortable.create(tbody, { handle: '.move', animation: 300, ghostClass: 'ghost', onEnd({ newIndex, oldIndex }) { _this.data.splice(newIndex, 0, _this.data.splice(oldIndex, 1)[0]); const newArray = _this.data.slice(0); const tmpHeight = _this.$refs.scFormTable.offsetHeight; _this.$refs.scFormTable.style.setProperty('height', tmpHeight + 'px'); _this.data = []; _this.$nextTick(() => { _this.data = newArray; _this.$nextTick(() => { _this.$refs.scFormTable.style.removeProperty('height'); }); }); }, }); }, /** * 新增一行 */ rowAdd() { const temp = JSON.parse(JSON.stringify(this.addTemplate)); this.data.push(temp); }, /** * 删除一行 * @param {Object} row - 要删除的行数据 * @param {number} index - 要删除的行的索引 */ rowDel(row, index) { this.data.splice(index, 1); this.$emit('delete', row); }, /** * 插入一行 * @param {Object} row - 要插入的行数据,默认为新增行模板 */ pushRow(row) { const temp = row || JSON.parse(JSON.stringify(this.addTemplate)); this.data.push(temp); }, /** * 根据索引删除一行 * @param {number} index - 要删除的行的索引 */ deleteRow(index) { this.data.splice(index, 1); }, }, }; </script> <style scoped> .form-table { width: 100%; } .form-table .form-table-handle { text-align: center; } .form-table .form-table-handle span { display: inline-block; } .form-table .form-table-handle button { display: none; } .form-table .hover-row .form-table-handle-delete span { display: none; } .form-table .hover-row .form-table-handle-delete button { display: inline-block; } .form-table .move { text-align: center; font-size: 14px; margin-top: 3px; } </style>