This commit is contained in:
linfso 2024-05-13 05:27:54 +08:00
parent 28ff754fcf
commit 7f4ac99bbe

View File

@ -0,0 +1,391 @@
<template>
<div class="xd-table">
<div class="table-operate-btn-content" v-show="showOperateButton">
<!-- toolbar -->
<slot name="operateBtnContent">
<div class="operate-btn-content">
<slot name="toolbar">
<div />
</slot>
<div class="top-right-btn" v-show="showRightButton">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="间距" placement="top">
<el-dropdown size="mini" @command="(command) => handleAdjustTableSize(command)">
<el-button size="mini" circle style="margin-left: 10px;" class="icon iconfont icon-hangjianju" />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="small" >中等</el-dropdown-item>
<el-dropdown-item command="mini" >紧凑</el-dropdown-item>
<el-dropdown-item command="medium" >宽松</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="canHideColumns">
<el-popover
placement="bottom-end"
popper-class="table-cloumn-setting-popper"
trigger="click"
:show-arrow="false"
>
<div class="setting-row-content">
<div style="text-align:right;display: inline-flex;width:180px;border-bottom: 1px solid #d5d4d438;padding: 0px 0px 10px 0px;">
<!-- <el-button @click="delAllStorage">恢复系统表格设置</el-button>
<el-button @click="delStorage">恢复当前表格设置</el-button> -->
<div style="text-align: left;width: 50%;line-height: 30px;">显示列</div>
<div style="text-align: right;width: 50%;"><el-button type="text" size="mini" plain @click="delAllStorage" >重置</el-button></div>
</div>
<draggable v-model="storageList"
ghostClass="drag-ghost"
chosenClass="drag-chosen"
:animation="500"
handle=".el-icon-s-operation"
@end="updateTable">
<div v-for="clo in storageList" :key="clo.label" class="setting-row">
<!-- <i class="el-icon-s-operation" /> -->
<i class="el-icon-s-operation icon iconfont icon-ui_drag_horizontally" />
<el-checkbox v-model="clo.show" class="label" @change="showOrHidden($event,clo)">{{ clo.label }}</el-checkbox>
<!-- <el-button
class="btn"
size="mini"
:type="clo.fixed === 'left' ? 'primary' : 'default'"
@click="setFixed('left',clo)"
>K</el-button> -->
<!-- <el-button
class="btn"
size="mini"
:type="clo.fixed === 'right' ? 'primary' : 'default'"
@click="setFixed('right',clo)"
>固定在右侧</el-button> -->
</div>
</draggable>
</div>
<el-button style="margin-left: 10px;" slot="reference" size="mini" circle icon="el-icon-menu" />
</el-popover>
</el-tooltip>
<!-- <el-tooltip class="item" effect="dark" content="导出" placement="top" v-if="download!=null">
<el-button size="mini" circle icon="el-icon-download" @click="download()" />
</el-tooltip> -->
</el-row>
</div>
</div>
</slot>
</div>
<div>
<orig-table ref="table"
:config="config" />
<pagination
v-show="total>0"
:total="total"
:page-sizes="[10,20,50,100,300,500,1000,2000,5000]"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
:page-size="queryParams.pageSize"
@pagination="queryTable"
/>
</div>
</div>
</template>
<script>
import Sortable from 'sortablejs'
import draggable from 'vuedraggable'
import origTable from './table.jsx'
// import setHeight from '@/mixins/setHeight'
const components = { origTable, draggable }
export default {
name: 'XadvTable',
components,
// mixins: [setHeight],
props: {
showSearch: {
type: Boolean,
default: true,
},
canHideColumns: {
type: Boolean,
default: true,
},
storageName: {
type: String,
required: false
},
queryParams:{
type: Object,
default: {},
},
total:{
type: Number,
default: 0,
},
showRightButton:{
type: Boolean,
default: true,
},
showOperateButton:{
type: Boolean,
default: true,
},
},
data() {
return {
// 弹出层标题
title: "显示/隐藏",
// 是否显示弹出层
open: false,
showTable: false,
popVisible:false,
storageList: [],
tbSize:"",
name: '',
config: {
children: [],
attrs: {size:"small"},
listeners: {},
key: ''
},
selection: [],
startX: null,
startY: null,
endX: null,
endY: null,
}
},
watch: {
'$attrs': {
handler(newV) {
this.$set(this.config, 'attrs', newV)
},
deep: true,
immediate: true
}
},
mounted() {
this.initStorage()
this.updateTable()
this.initSort();
},
methods: {
// 动态列渲染表格时,需要在列渲染完成后重新渲染一下表格
reload() {
this.$nextTick(() => {
this.initStorage()
this.updateTable()
this.initSort();
})
},
download(){
this.$emit("download");
},
initSort() {
},
// 查询
queryTable(){
this.$emit("queryTable");
},
// 显示搜索
toggleSearch() {
this.$emit("update:showSearch", !this.showSearch);
},
// 刷新
refresh() {
this.$emit("queryTable");
},
// 打开显隐列
showColumn() {
this.open = true;
},
getInstance() {
// const ref = this.$children.find(i => i.$options._componentTag === 'el-table')
// return ref
return this.$refs.table.$refs?.elTable
},
delStorage() {
// this.$confirm('恢复当前表格设置将清除当前表格设置并刷新页面是否继续?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
// storage[this.storageName] = []
// window.localStorage.setItem('tableStorage', JSON.stringify(storage))
// location.reload()
// })
},
delAllStorage() {
// this.$confirm('恢复系统表格设置将清除当前表格设置并刷新页面是否继续?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// window.localStorage.removeItem('tableStorage')
// location.reload()
// })
window.localStorage.removeItem('tableStorage');
this.reload();
},
showOrHidden(val, clo) {
if (!val && this.storageList.filter(i => i.show).length === 0) {
this.$message.warning('列表最少显示一列')
this.$nextTick(() => {
clo.show = true
})
return
}
this.updateTable()
},
setFixed(value, clo) {
if (clo.fixed === value) {
clo.fixed = false
} else {
clo.fixed = value
}
this.updateTable()
},
// 更多操作触发
handleAdjustTableSize(command) {
//size:mini/small/medium;
// console.log(this.config);
switch (command) {
case "small":
this.config.attrs.size='small';
break;
case "mini":
this.config.attrs.size='mini';
break;
case "medium":
this.config.attrs.size='medium';
break;
default:
break;
}
this.updateTable();
},
// 初始化缓存配置
initStorage() {
this.storageList = []
let list = [];
const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
// 不管是否初次还是要做一下处理,万一页面有修改,做一下更新,以最新的node节点数组为准
if(this.storageName!=undefined && this.storageName!=''){
list = storage[this.storageName] ? storage[this.storageName] : []
}
// let list = storage[this.storageName] ? storage[this.storageName] : []
this.$vnode.componentOptions.children.forEach(node => {
// 以label为准,因为可能会改文本
if (!(!node.componentOptions || node.componentOptions.propsData.type) && list.findIndex(i => i.label === node.componentOptions.propsData.label) < 0) {
// 非插槽且 不是特殊类型的 找不到就加上
const propsData = JSON.parse(JSON.stringify(node.componentOptions.propsData))
if (propsData.fixed === undefined || propsData.fixed === false) {
propsData.fixed = false
} else {
propsData.fixed = propsData.fixed ? propsData.fixed : 'left'
}
list.push({
fixed: false, // 默认新增的都是不固定
show: true, // 默认新增的都是显示的
...propsData
})
}
})
// 必须在节点数组存在的才有意义
list = list.filter(item => this.$vnode.componentOptions.children.find(n => {
return n.componentOptions && item.label === n.componentOptions.propsData.label
}))
this.storageList = list
},
// 根据缓存的数组进行渲染表格
updateTable() {
// 特殊类型
const childrenNodes = this.$vnode.componentOptions.children.filter(node => node.componentOptions && node.componentOptions.propsData.type)
this.storageList.forEach(item => {
if (item.show) {
const node = this.$vnode.componentOptions.children.find(n => n.componentOptions && n.componentOptions.propsData.label === item.label)
if (node) {
node.componentOptions.propsData.fixed = item.fixed
childrenNodes.push(node)
}
}
})
this.config.children = childrenNodes
this.config.attrs = this.$attrs
this.config.listeners = this.$listeners
// 通过key值触发表格刷新,避免拖拽由于数组长度一致导致diff算法无法识别
this.config.key = Math.random() + ''
// 控制下表格重新刷新
// this.getInstance()?.doLayout()
const storage = window.localStorage.getItem('tableStorage') ? JSON.parse(window.localStorage.getItem('tableStorage')) : {}
storage[this.storageName] = this.storageList
window.localStorage.setItem('tableStorage', JSON.stringify(storage))
}
}
}
</script>
<style lang="scss" scoped>
.table-cloumn-setting-popper{
.setting-row-content{
max-height: 600px;
overflow-y: auto;
.setting-row{
height: 30px;
line-height: 30px;
.el-icon-s-operation{
cursor: move;
font-size: 16px;
margin-right: 8px;
}
.label{
margin-right: 8px;
}
.btn{
padding: 4px!important;
}
}
}
}
.xd-table{
width:100%;
height:100%;
position: relative;
.el-icon-setting{
position: absolute;
right: 7px;
top: 5px;
cursor: pointer;
}
.table-operate-btn-content{
// width: calc(100% - 40px);
width: 100%;
// min-height: 28px; // 给一个最低的高度,防止没有插槽,右侧icon被吞
min-height: 40px; // 给一个最低的高度,防止没有插槽,右侧icon被吞
.operate-btn-content {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 28px;
padding-bottom: 6px;
}
}
}
.drag-ghost { background-color: #e7e7e77d; }
.drag-chosen { background-color: #e7e7e77d; }
.pagination-container{
padding: 0px 20px !important;
}
</style>