Files
school-developer/src/components/FormTable/index.vue
吴红兵 1f645dad3e init
2025-12-02 10:37:49 +08:00

188 lines
4.1 KiB
Vue

<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)',
}"
style="width: 100%"
:table-layout="'auto'"
>
<el-table-column type="index" width="50" fixed="left">
<template #header>
<el-button v-if="!hideAdd" type="primary" 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="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%;
overflow-x: auto;
}
</style>