<template>
<div>
<div class="table-box">
<div class="table-header">
<template v-for="columnItem in tableColumn" :key="columnItem.label">
<div>
<span>{{ columnItem.label }}</span>
<template v-if="columnItem.label === '标签序号'">
<el-tooltip class="box-item" effect="dark" :content="sortTip" placement="top">
<el-icon style="margin-left: 15px;">
<QuestionFilled />
</el-icon>
</el-tooltip>
</template>
</div>
</template>
</div>
<!-- 内容拖拽 -->
<draggable v-model="data" group="items" @change="logEvent" v-if="data?.length > 0">
<!-- 遍历表格数据-->
<div class="table-item" v-for="item in data" :key="item.id">
<!-- 遍历header数据 -->
<template v-for="columnItem in tableColumn" :key="columnItem.label">
<!-- 遍历一行中的每一列 -->
<template v-for="(value, key) of item" :key="key">
<p v-if="String(key) === columnItem.prop" style="display: flex; align-items: center;">
<!-- 值 -->
<span>{{ value }}</span>
<!-- slot -->
<slot v-if="columnItem.slot" :name="columnItem.slot" />
<!-- p标签排序编辑弹窗 -->
<template v-if="String(key) === 'tagNum'">
<el-popover :visible="popoverVisible === item.id" placement="bottom"
:show-arrow="false" :offset="3"
popper-style="padding:3px 5px; margin-left:18px;">
<!-- 按钮 -->
<template #reference>
<el-icon style="color: #409EFF;cursor: pointer; margin-left: 45px;"
@click="editSort(item)">
<Edit />
</el-icon>
</template>
<!-- 编辑 -->
<div class="sort-edit-box">
<el-input-number v-model="sortNumber" :min="0" :max="99" :controls="false"
style="width: 70px;height: 24px;" />
<span style="margin: 0 8px;color:#409EFF; "
@click="sortEditSubmit">确定</span>
<span style="color:#F56C6C;" @click="sortCancel">取消</span>
</div>
</el-popover>
</template>
</p>
</template>
<!--操作按钮 -->
<p class="btn-box" v-if="columnItem.prop === 'button'">
<el-button v-if="item?.appNumber <= 0" size="small" text @click="deleteBtn(item)"
type="danger">删除</el-button>
<el-tooltip v-else effect="dark" content="请先移除所有关联应用" placement="top">
<el-button :disabled="item?.appNumber > 0" size="small" text>删除</el-button>
</el-tooltip>
</p>
</template>
</div>
</draggable>
<div v-else style="text-align: center; min-height: 200px;">暂无数据</div>
</div>
<!-- 分页 -->
<div style="position: relative;padding-top: 15px;">
<el-pagination class="app-pagination" :current-page="pagination.page" :page-size="pagination.size"
:page-sizes="pageSizes" :total="total" @size-change="pageSizeChange" @current-change="pageNoChange"
layout="total, sizes, prev, pager, next" />
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue';
import { VueDraggableNext } from 'vue-draggable-next'
import { ElMessage, ElMessageBox } from 'element-plus'
const draggable = VueDraggableNext
const props = defineProps({
tableColumn: {
required: true,
type: Array<{ label: string, prop: string, slot?: string }>,
default: () => []
},
tableData: {
type: Array<any>,
default: () => []
},
pagination: {
required: true,
type: Object,
default: () => { page: 1; size: 20 }
},
total: {
required: true,
type: Number,
default: 0
},
pageSizes: {
type: Array,
default: () => [20, 50, 100]
},
hideOnSinglePage: { // 只有一页时是否隐藏
type: Boolean,
default: false
},
})
const data = ref([]) // 表格数据变量
const sortTip = ref('应用中心标签过滤器中,标签按照标签序号由大到小从左向右排列,序号相等按照创建时间由近到远排列')
const popoverVisible = ref('')
const sortNumber = ref(null)
const emit = defineEmits(['size-change', 'current-change', 'sort-change'])
// 生命周期
onMounted(() => {
data.value = props.tableData
})
// 监听
watch(data, (newValue, oldValue) => {
console.log('newValue', newValue[0])
})
/*** 声明方法 ****/
const pageSizeChange = (val: any) => {
emit('size-change', val)
}
const pageNoChange = (val: any) => {
emit('current-change', val)
}
// 拖拽结束
const logEvent = (event) => {
console.log('拖拽结束: ', event);
}
// 删除
const deleteBtn = (row) => {
console.log('删除')
ElMessageBox.confirm(
`您正在进行删除标签操作,是否确定要删除“${row.name}”?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
}
)
.then(() => {
ElMessage({
type: 'success',
message: '删除成功',
})
})
.catch(() => {
})
}
// 编辑排序
const editSort = (row) => {
// emit('sort-change', row)
console.log('编辑排序')
popoverVisible.value = row.id
sortNumber.value = row.num
}
const sortEditSubmit = () => {
emit('sort-change', sortNumber.value)
console.log('确定排序')
sortNumber.value = null
popoverVisible.value = ''
}
const sortCancel = () => {
console.log('取消编辑排序')
sortNumber.value = null
popoverVisible.value = ''
}
</script>
<style lang="scss" scoped>
.table-box {
width: 100%;
.table-header {
display: flex;
justify-content: space-between;
padding: 0 10px;
background-color: #eff2ff;
>div {
flex: 1;
text-align: left;
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
}
}
.table-item {
height: 40px;
line-height: 40px;
display: flex;
justify-content: space-between;
border-top: 1px solid rgba($color: #ccc, $alpha: 0.4);
padding: 0 10px;
>p {
flex: 1;
text-align: left;
}
&:last-child {
border-bottom: 1px solid rgba($color: #ccc, $alpha: 0.4);
}
}
}
// 标签排序编辑
.sort-edit-box {
background-color: #fff;
font-size: 12px;
display: flex;
align-items: center;
>span {
white-space: nowrap;
cursor: pointer;
}
}
</style>
vue3+ts表格拖拽实现
最新推荐文章于 2024-10-04 00:46:18 发布