emis-frontend/src/components/XdTable/index.vue
2024-05-07 12:53:25 +08:00

385 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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: ''
}
}
},
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>