Main code:
html:
<template>
<div>
<div style="text-align: right; padding-bottom: 5px">
<a-popover title="请选择要展示的列" placement="topRight">
<template slot="content">
<a-checkbox
v-for="c in tHead"
:key="c.title"
@change="onCheckChange"
:defaultChecked="true"
:value="c.title"
>
{
{ c.title }}
</a-checkbox>
</template>
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
筛选列 <a-icon type="down" />
</a>
</a-popover>
</div>
<a-table
:loading="loading_"
class="tbBorder"
:rowSelection="rowSelection"
:rowKey="rowKey"
:pagination="pagination_"
:dataSource="dataSource_"
:components="components_"
v-bind="$props"
v-on="$listeners"
:columns="columns_"
@change="handleTableChange"
size="middle"
:scroll="{ x: scrollX || 0 }"
:rowClassName="
(record, index) => {
if (index % 2 != 0) return 'stripe';
}
"
>
<template
v-for="column in columns"
:slot="column.scopedSlots ? column.scopedSlots.customRender : ''"
slot-scope="text, record"
>
<slot
:name="column.scopedSlots ? column.scopedSlots.customRender : ''"
v-bind:scope="record"
></slot>
</template>
</a-table>
</div>
</template>
js:
<script>
import { Table } from "ant-design-vue";
import VueDraggableResizable from "vue-draggable-resizable";
import { mapState } from "vuex";
export default {
components_: {
VueDraggableResizable,
},
props: {
...Table.props,
api: { type: String },
queryParams: { type: Object },
get: { type: Boolean },
rowKey: { type: String },
scrollX: { type: Number },
rowSelection: { type: Object },
},
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;
});
if (!col || !col.width) {
return h("th", { ...restProps }, [...children]);
}
if (props.key == "operation") {
return h("th", { ...restProps, class: "operation" }, [...children]);
}
const dragProps = {
key: col.dataIndex || col.key,
class: "table-draggable-handle",
attrs: {
w: 10,
x: col.width,
z: 1,
axis: "x",
draggable: true,
resizable: false,
},
on: {
dragging: (x, y) => {
col.width = Math.max(x, 1);
},
},
};
const drag = h("vue-draggable-resizable", { ...dragProps });
return h("th", { ...restProps, class: "resize-table-th" }, [
...children,
drag,
]);
},
},
};
return {
selectedRowKeys: [],
selectedRows: [],
columns_: this.columns,
tHead: [],
dataSource_: [],
loading_: false,
pagination_: this.pagination || {
total: 0,
pageSizeOptions: ["10", "20", "30", "40", "100"],
current: 1,
defaultPageSize: 10,
showQuickJumper: false,
showSizeChanger: true,
showTotal: (total, range) =>
`显示 ${range[0]} ~ ${range[1]} 条记录,共 ${total} 条记录`,
},
};
},
mounted() {
this.tHeadCreat(this.columns);
this.fetch();
},
methods: {
tHeadCreat(columns) {
columns.forEach((ele) => {
if (columns.indexOf(ele) != columns.length - 1) {
ele.colSpan = 1;
this.tHead.push(ele);
}
});
},
//筛选列
onCheckChange(e) {
this.tHead.map((ele) => {
if (ele.title === e.target.value) {
ele.colSpan = e.target.checked ? 1 : 0;
this.changeColumns(e.target.value, e.target.checked);
}
});
},
changeColumns(title, checked) {
if (checked) {
let i = 0; //用来标记插入时的位置,从头开始找
this.tHead.forEach((ele, index) => {
if (ele.title != title) {
if (
this.columns_.some((item) => {
return item.title == ele.title;
})
) {
i++; //如果该元素已经存在则向后移动一位
}
} else {
this.columns_.splice(i, 0, ele);
}
});
} else {
this.columns_.map((ele, index) => {
if (ele.title == title) {
this.columns_.splice(index, 1);
}
});
}
},
//分页
handleTableChange(pagination, filters, sorter) {
this.pagination_ = pagination;
this.fetch();
},
resetPagination() {
this.pagination_.current = 1;
},
fetch(p) {
let param = p || this.queryParams;
this.loading_ = true;
if (this.get) {
this.$get(this.api, {
...param,
pageSize:
this.pagination_.pageSize || this.pagination_.defaultPageSize,
pageNum: this.pagination_.current,
})
.then((res) => {
console.log("res-get", res);
let data = res.data;
this.pagination_.total =
data.total == undefined ? data.length : data.total;
this.dataSource_ = data.rows.children || data.rows || data;
this.loading_ = false;
})
.catch((err) => {
console.warn(err);
});
} else {
this.$post(this.api, {
...param,
pageSize: this.pagination_.pageSize,
pageNum: this.pagination_.current,
})
.then((res) => {
console.log("dataTable-res", res);
let data = res.data;
this.pagination_.total =
data.total == undefined ? data.length : data.total;
if (data.rows) {
if (data.rows.children) this.dataSource_ = data.rows.children;
else this.dataSource_ = data.rows;
} else this.dataSource_ = data;
// this.dataSource_ = data.rows.children || data.rows || data;
this.loading_ = false;
})
.catch((err) => {
console.warn(err);
});
}
},
},
};
</script>
css style
<style lang="less">
.table-draggable-handle {
/* width: 10px !important; */
height: 100% !important;
left: auto !important;
right: -5px;
cursor: col-resize;
touch-action: none;
border: none;
position: absolute;
transform: none !important;
bottom: 0;
}
.resize-table-th {
position: relative;
}
.tbBorder {
border: 1px solid #ebebeb;
}
// .stripe {
// background-color: #fafafa;
// }
.ant-table-scroll {
.operation {
color: transparent;
}
}
</style>
Code when referenced by parent component:
<my-table
ref="dataTable"
api="user"
:get="true"
:rowKey="'userId'"
:columns="columns"
:queryParams="queryParams"
:rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:scrollX="1450"
>
<template slot="operation" slot-scope="record">
<a-button
type="link"
class="btn-operation"
v-hasPermission="'user:update'"
@click="edit(record.scope)"
>修改</a-button
>
<a-button
type="link"
class="btn-operation"
v-hasPermission="'user:update'"
@click="view(record.scope)"
>查看</a-button
>
<a-button
type="link"
class="btn-operation"
v-hasPermission="'user:update'"
@click="resetPassword(record.scope)"
>密码重置</a-button
>
</template>
</my-table>