页面
div class="ant-alert ant-alert-info">
<div class="float-right">
<ColumnsByOrder
@onColSettingsChange="onColSettingsChange"
@draggableChange="draggableChange"
:columnsByOrder.sync="columnsByOrder"
:settingColumns.sync="settingColumns"
/>
</div>
</div>
<p-table ref="table" rowKey="id" :loading="loading" :data-source="tableData" bordered :columns="columns" :pagination="pagination" @change="handleTableChange" :scroll="{ x: 1000 }" :components="components">
<template slot="no" slot-scope="text, record, index">
<div>{{ index - 0 + 1 }}</div>
</template>
<template slot="returnMessage" slot-scope="text, record, index">
<div class="text-eclipse" @click="showDetail(text,'json')">{{ text }}</div>
</template>
<template slot="messageBody" slot-scope="text, record, index">
<div class="text-eclipse" @click="showDetail(text,'json')">{{ text }}</div>
</template>
</p-table>
ColumnsByOrder组件
<template>
<p-popover
trigger="click"
placement="bottomRight"
:overlayStyle="{minWidth: '300px'}"
>
<template slot="title">
<p-row class="f-modal-title-rank" type="flex">
<p-col class="left">
<slot name="title">自定义列</slot>
</p-col>
<p-col class="right">
<p-dropdown>
<p class="poros-dropdown-link">
<p-icon type="unordered-list" />
</p>
<p-menu slot="overlay">
<p-menu-item>
<div @click="rankBtn">{{ titleRank }}</div>
</p-menu-item>
<p-menu-item>
<div @click="checkAll">全选</div>
</p-menu-item>
</p-menu>
</p-dropdown>
</p-col>
</p-row>
</template>
<template slot="content">
<p-checkbox-group
@change="onColSettingsChange"
v-model="settingColumnsNew"
:defaultValue="settingColumnsNew"
>
<p-row>
<template v-for="(item, index) in columnsByOrderNew">
<template
v-if="item.fixed == 'left'"
>
<p-col :span="spanWidth" :key="item.dataIndex">
<p-checkbox :value="item.dataIndex"
>{{ index }}:{{ item.title }}</p-checkbox
>
</p-col>
</template>
</template>
<draggable
ghost-class="chosenClass"
v-model="columnsByOrderNew"
@change="draggableChange"
filter=".unmover"
>
<template v-for="(item, index) in columnsByOrderNew">
<template
v-if="item.key != 'rowIndex' && item.dataIndex != 'action'&& item.fixed != 'left'"
>
<p-col :span="spanWidth" :key="item.dataIndex" :class="{'unmover':item.fixed=='left'}">
<p-checkbox :value="item.dataIndex"
>{{ index }}:{{ item.title }}</p-checkbox
>
</p-col>
</template>
</template>
</draggable>
</p-row>
</p-checkbox-group>
</template>
<a> <p-icon type="setting" />自定义列</a>
</p-popover>
</template>
<script>
import draggable from 'vuedraggable'
export default {
components: { draggable },
props: {
getWidth: {
type: Object,
default: () => ({}),
},
settingColumns: {
type: Array,
default: () => [],
},
columnsByOrder: {
type: Array,
default: () => [],
},
},
data() {
return {
spanWidth: 12,
titleRank: '一列',
}
},
computed: {
settingColumnsNew: {
get() {
return this.settingColumns
},
set(val) {
this.$emit('update:settingColumns', val)
},
},
columnsByOrderNew: {
get() {
return this.columnsByOrder
},
set(val) {
this.$emit('update:columnsByOrder', val)
},
},
},
methods: {
rankBtn() {
if (this.spanWidth === 12) {
this.spanWidth = 24
this.titleRank = '两列'
} else {
this.spanWidth = 12
this.titleRank = '一列'
}
},
checkAll() {
let arr = []
this.$emit('onColSettingsChange', this.columnsByOrder.map(item=>item.dataIndex))
},
onColSettingsChange(val) {
this.$emit('onColSettingsChange', val)
},
draggableChange(val) {
this.$emit('draggableChange', val)
},
},
}
</script>
<style scoped lang="less">
.f-modal-title-rank {
justify-content: space-between;
}
.f-modal-title-rank .right {
cursor: pointer;
}
.chosenClass {
box-shadow: 1px 1px 8px 1px rgba(0, 0, 0, 0.2);
}
.list-group-item {
cursor: pointer;
}
</style>
mixinjs
import $ from 'jquery'
import Vue from 'vue'
import ColumnsByOrder from '@/components/ColumnsByOrder'
import VueDraggableResizable from 'vue-draggable-resizable'
Vue.component('vue-draggable-resizable', VueDraggableResizable);
//defColumns 为默认的列
//columns 为当前的列
export const PageListMixin = {
components: { ColumnsByOrder },
data() {
this.components = {
header: {
cell: (h, props, children) => {
const { key, ...restProps } = props
// const col = this.columns.find((col) => {
// const k = col.dataIndex || col.key
// return k === key
// })
let col = null
if (key === "selection-column") {
// 当前column为全选的时候,要返回全选的 th ,否则无法出现全选
return <th {...restProps} class={props.class} width="50">{children}</th>
} else {
col = this.columns.find((item) => {
const k = item.dataIndex || item.key;
return k === key;
});
}
if (key === 'action'|| key === 'operation') {
return h('th', { ...restProps }, [...children])
}
if (!col || !col.width ) {
return <th {...restProps} class={props.class} width="180">{children}</th>;
}
const dragProps = {
key: col.dataIndex || col.key,
class: 'table-draggable-handle',
attrs: {
w: 10,
x: col.width,
z: 10,
axis: 'x',
draggable: true,
resizable: false,
},
on: {
dragging: (x, y) => {
col.width = Math.max(x, 1) < 100 ? 100 : Math.max(x, 1)
// if (
// this.columns
// .slice(0, this.columns.length - 1)
// .map((item) => item.width || 0)
// .reduce((x, y) => x + y) >=
// document.querySelector('.poros-table-scroll').offsetWidth -
// 130
// ) {
// this.columns[this.columns.length - 1].width = 130
// } else {
// delete this.columns[this.columns.length - 1].width
// }
$('tbody td').css('user-select', 'none')
this.$forceUpdate()
this.$nextTick(()=>{
this.setFixedWidth()
})
},
dragstop: (x, y) => {
$('tbody td').css('user-select', 'auto')
}
},
}
const drag = h('vue-draggable-resizable', { ...dragProps })
return h('th', { ...restProps, class: 'resize-table-th' }, [
...children,
drag,
])
},
},
}
return {
columnsByOrder: [],
settingColumns: [],
}
},
created () {
if(this.columns) {
this.defColumns = JSON.parse(JSON.stringify(this.columns))
}
},
mounted() {
this.initColumns()
this.draggableInit()
// this.setdefColumns()
this.$nextTick(() => {
// 为了解决拖拽时,点击事件失效的问题
let eles = document.querySelectorAll('.table-draggable-handle')
for (let i = 0; i < eles.length; i++) {
eles[i].onclick = function(e) {
var ev = e || window.event
if (ev && ev.stopPropagation) {
ev.stopPropagation()
} else {
ev.cancelBubble = true
}
}
}
})
},
computed: {
},
methods: {
update() {
this.$forceUpdate()
},
throttle(fn) {
let canRun = true
return function() {
if (!canRun) {
return
}
canRun = false
setTimeout(() => {
fn.call(this, arguments)
canRun = true
}, 100)
}
},
// 计算table前后fiexed的宽度
setFixedWidth() {
if(this.$refs.table) {
let arrLength = this.columns.length - 1
if(this.columns[arrLength]['dataIndex'] == 'action'|| this.columns[arrLength]['dataIndex'] == 'operation') {
let lastThWidth = this.$refs.table.$el.querySelector('.poros-table-row-cell-last')?.offsetWidth
this.$refs.table.$el.querySelector('.poros-table-fixed-right .poros-table-fixed').style.width = lastThWidth + 'px'
}
if(this.columns[0]['fixed'] == 'left') {
const firstThWidth = this.$refs.table.$el.querySelector('.poros-table-scroll .poros-table-thead .resize-table-th')?.offsetWidth
this.$refs.table.$el.querySelector('.poros-table-fixed-left .poros-table-fixed').style.width = firstThWidth + 'px'
}
this.$forceUpdate()
}
},
arrayIsEqual(objArr1, objArr2, key, isString = true) {
let arrFlag = false
let arr1 = objArr1.map((item) =>
isString ? item[key].trim() : item[key]
)
let arr2 = objArr2.map((item) =>
isString ? item[key].trim() : item[key]
)
if (arr1.length != arr2.length) {
return arrFlag
}
arr1.forEach((element, index) => {
if (arr1.indexOf(arr2[index]) != -1 && arr2.indexOf(element) != -1) {
arrFlag = true
}
})
return arrFlag
},
//初始化列设置
initColumns(customerName) {
if(!this.defColumns) return
let allSettingColumns = []
this.defColumns.forEach(function(item, i, array) {
allSettingColumns.push(item.dataIndex)
})
this.settingColumns = allSettingColumns
this.columns = this.defColumns
},
draggableInit(customerName) {
if(!this.defColumns) return
this.columnsByOrder = this.defColumns.filter(
(item) => item.key != 'rowIndex'&& item.dataIndex != 'action'&& item.dataIndex != 'operation'
)
},
draggableChange(rest, customerName) {
if (rest.moved) {
const { newIndex, oldIndex } = rest.moved
this.onOrderChange(customerName)
}
},
//列设置更改事件
onColSettingsChange(checkedValues, customerName) {
this.settingColumns = checkedValues
this.completeColumns()
},
onOrderChange(customerName) {
// 自定义列排序
this.completeColumns()
},
completeColumns() {
const columns = this.columnsByOrder.filter((item) => {
if (this.settingColumns.includes(item.dataIndex)) {
return true
}
return false
})
let indexColumn = this.defColumns.find((item) => item.key == 'rowIndex')
let actionColumn = this.defColumns.find(
(item) => item.dataIndex == 'action' || item.dataIndex == 'operation'
)
indexColumn && columns.unshift(indexColumn)
actionColumn && columns.push(actionColumn)
this.columns = columns
this.$nextTick(() => {
this.setFixedWidth()
})
// this.setdefColumns && this.setdefColumns()
},
setdefColumns() {
if (
this.columns.map((item) => item.width || 0).reduce((x, y) => x + y) >
window.innerWidth - 220
) {
let arrLength = this.columns.length - 1
this.columns.forEach((item, index) => {
item['ellipsis'] = true
item['field'] = item['dataIndex']
if (
!['action', 'rowIndex'].includes(item['key']) &&
item['title'] != '操作' &&
item['title'] != '操作内容'
) {
item['sorter'] = item['unSorter'] ? false : true
}
delete item['fixed']
if (item['key'] === 'rowIndex') {
item['width'] = 60
} else {
item['width'] = item['width'] || 140
}
})
this.columns[0]['fixed'] = 'left'
this.columns[1]['fixed'] = 'left'
if (
this.columns[arrLength]['key'] == 'action' ||
this.columns[arrLength]['title'] == '操作' ||
this.columns[arrLength]['title'] == '操作内容'
) {
this.columns[arrLength]['fixed'] = 'right'
}
} else {
this.columns.forEach((item, index) => {
item['ellipsis'] = true
item['field'] = item['dataIndex']
delete item['fixed']
if (
!['action', 'rowIndex'].includes(item['key']) &&
item['title'] != '操作' &&
item['title'] != '操作内容'
) {
item['sorter'] = item['unSorter'] ? false : true
item['width'] = item['width'] || 140
} else {
item['width'] = 60
}
})
this.columns.map((item) => item.width || 0).reduce((x, y) => x + y) <
window.innerWidth - 220 &&
delete this.columns[this.columns.length - 1].width
}
},
},
}
