拖拽打印等功能
功能概述
- 我要表头能拖拽排序
- 我要表头能自定义显示隐藏
- 我要调整好表格能打印
- 每一项我都可能要加排序,是后台排序
你安排我我就做呗
效果展示
思路分析
拖拽
拖拽大概有两种(onmousemove,ondrag),简单的具体思路都是,记录下开始点,再获取到结束点,交换完事
表头自定义
在表头右边加个自定义下拉按钮
打印
打印浏览器不是有么,调用print()就可以,打印表格估计就是把表格这块抠出来,弄到个新文档,打印
排序
是后台排序,那我就只要监听个事件回调,调后台就可以了
参考
由于老衲过于菜鸡,保守起见,还是先来查查别人是怎么弄的吧
参考(fuzhi)地址
实现
打印
- 扣出需要打印的区域innerHTML到新建的一个iframe页面里面
- 获取到样式怼进去
- print()打印
<template>
<div>
<div ref="template">
<slot>
</slot>
</div>
<button v-if="buttonShow" @click="print" type="button" :class="buttonClass">
<span>开始打印</span>
</button>
</div>
</template>
export default {
props: {
// 是否显示默认的打印按钮
buttonShow: {
type: Boolean,
default: false
},
buttonClass: {
type: String,
default: 'el-button el-button--default'
}
},
mounted () {
this.init()
},
methods: {
init () {
let printI = document.getElementById('easyPrintIframe')
if (!printI) {
printI = document.createElement('iframe')
printI.id = 'easyPrintIframe'
printI.style.position = 'fixed'
printI.style.width = '0'
printI.style.height = '0'
printI.style.top = '-100px'
// 兼容ie
if (
window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)
) {
printI.src = 'javascript:document.write("<head><script>document.domain="' + document.domain + '";</s' + 'cript></head><body></body>")'
}
printI.onload = () => {
this.getStyle()
}
document.body.appendChild(printI)
} else {
this.getStyle()
}
},
print () {
if (typeof this.beforeCopy === 'function') {
// 检测到有复制前需要执行的功能
this.beforeCopy()
}
let $iframe = document.getElementById('easyPrintIframe')
// 复制body,打印内容
$iframe.contentDocument.body.innerHTML = this.$refs.template.innerHTML
if (typeof this.beforePrint === 'function') {
// 检测到有打印前需要执行的功能
// 比如有些二维码组件无法直接复制dom完成。
this.beforePrint()
}
setTimeout(() => {
$iframe.contentWindow.print()
}, 100)
},
getStyle () {
let mystyle = ``
let printI = document.getElementById('easyPrintIframe')
var str = ''
var styles1 = document.querySelectorAll('style')
for (var i = 0; i < styles1.length; i++) {
str += styles1[i].outerHTML
}
// console.log(str)
printI.contentDocument.head.innerHTML = str + mystyle
// 添加link引入
let styles = document.querySelectorAll('link')
for (let i = 0; i < styles.length; i++) {
// chrome 正常,firefox不正常,能执行到,但是添加没结果
let link = document.createElement('link')
link.setAttribute('rel', 'stylesheet')
if (styles[i].type) link.setAttribute('type', styles[i].type)
else link.setAttribute('type', 'text/css')
link.setAttribute('href', styles[i].href)
link.setAttribute('media', 'all')
printI.contentDocument.head.appendChild(link)
}
}
}
}
表头操作拖拽排序
- 表头元素都添加handleMouseMove事件,移动过程中,移到别的列上,交换位置
<template>
<div>
<div class="w-table" :class="{'w-table_moving': dragState.dragging}">
<div class="edit">
<el-dropdown type="primary" size="small" trigger="click">
<span class="el-dropdown-link">
<i class="el-icon-edit"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item, index) in tableHeaderBackup" :key="index">
<div>
<el-checkbox v-model="item.show" @change="init">{{item.label}}</el-checkbox>
</div>
</el-dropdown-item>
<el-dropdown-item style="padding:10px 15px 8px;">
<el-button @click="print" type="primary" style="width:100%;" icon="el-icon-download" size="small">打印</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<easy-print ref="print">
<el-table
ref="table"
row-key="id"
:data="tableData"
:header-cell-class-name="headerCellClassName"
:cell-class-name="cellClassName"
:style="`width: 100%`"
>
<template v-for="(col, index) in tableHeaderYes ">
<el-table-column
v-if="col.show"
:key="index"
:prop="col.prop"
:label="col.label"
:width="col.width"
:min-width="col.minWidth"
:type="col.type"
:header-align="col.headerAlign"
:column-key="index.toString()"
:render-header="renderHeader"
>
<template slot-scope="scope" >
<div v-if="col.format" v-html="col.format(scope.row[col.prop])"></div>
<div v-else>{{scope.row[col.prop]}}</div>
</template>
</el-table-column>
</template>
</el-table>
</easy-print>
</div>
</div>
</template>
export default {
data () {
return {
dragState: {
start: -9, // 起始元素的 index
end: -9, // 移动鼠标时所覆盖的元素 index
dragging: false, // 是否正在拖动
},
tableHeaderBackup: [], //备份完整的tableHeader
tableHeaderYes: [],// 需要在表头显示的
tableHeaderNo: [], // 暂时不显示的
tableHeader: [
{
prop: 'name',
label: '油站名称',
show: true,
minWidth: '120'
},
{
prop: 'address',
label: '油站地址',
sort: 1,
show: true,
minWidth: '120'
},
{
prop: 'header',
label: '油站负责人',
sort: 1,
show: true,
minWidth: '120'
},
{
prop: 'headerPhone',
label: '负责人电话',
sort: 1,
show: true,
minWidth: '120'
},
{
prop: 'updateTime',
label: '更新时间',
sort: 1,
show: true,
minWidth: '120'
}
],
tableData: []
}
},
mounted () {
this.tableHeaderBackup = this.$tool._deepCopy(this.tableHeader)
this.init()
},
methods: {
init () {
this.tableHeaderYes = this.tableHeaderBackup.filter(i => i.show)
this.tableHeaderNo = this.tableHeaderBackup.filter(i => !i.show)
},
renderHeader (createElement, { column, $index }) {
return createElement(
'div',
{
class: ['thead-cell-box'],
on: {
mousedown: $event => {},
mousemove: $event => {}
}
},
[
createElement(
'span',
{
class: ['thead-cell1']
},
column.label
),
createElement('span', {
class: ['thead-cell'],
on: {
mousedown: $event => {
this.handleMouseDown($event, column)
},
mousemove: $event => {
this.handleMouseMove($event, column)
}
}
}),
createElement(
'span',
{
class: {
'thead-cell2': true,
'caret-wrapper': true,
hidden: !this.tableHeaderYes[$index].sort,
ascending: this.tableHeaderYes[$index].sort === 2,
descending: this.tableHeaderYes[$index].sort === 3
},
on: {
click: $evnet => {
this.clickHandler($evnet, column, $index)
}
}
},
[
createElement(
'i',
{
class: ['sort-caret', 'ascending']
}
),
createElement(
'i',
{
class: ['sort-caret', 'descending']
}
)
]
)
]
)
},
handleMouseDown (e, column) {
this.dragState.dragging = true
this.dragState.start = parseInt(column.columnKey)
document.addEventListener('mouseup', this.handleMouseUp)
},
handleMouseUp () {
// 初始化拖动状态
this.dragState.start = -9
this.dragState.end = -9
this.dragState.dragging = false
document.removeEventListener('mouseup', this.handleMouseUp)
},
handleMouseMove (e, column) {
if (this.dragState.dragging) {
let index = parseInt(column.columnKey) // 记录起始列
if (index - this.dragState.start !== 0) {
this.dragState.end = parseInt(column.columnKey)
this.dragColumn(this.dragState) // 换位置
}
} else {
return false
}
},
dragColumn ({ start, end, direction }) {
const tableHeaderYes = this.$tool._deepCopy(this.tableHeaderYes)
//交换位置
const startObj = tableHeaderYes[start]
this.tableHeaderYes.splice(start, 1)
this.tableHeaderYes.splice(end, 0, startObj)
this.tableHeaderBackup = this.tableHeaderYes.concat(this.tableHeaderNo)//合并重新设置表头
this.dragState.dragging = false
this.$nextTick(() => {
this.dragState.dragging = true
this.dragState.start = end
this.dragState.end = start
})
},
// 拖拽样式的设置
headerCellClassName ({ column, columnIndex }) {
if (this.showSelection) columnIndex--
if (this.showExpand) columnIndex--
let active =
columnIndex === this.dragState.end
? `darg_active_${this.dragState.direction}`
: ''
let start = columnIndex === this.dragState.start ? `darg_start` : ''
return `${active} ${start}`
},
cellClassName ({ column, columnIndex }) {
if (this.showSelection) columnIndex--
if (this.showExpand) columnIndex--
return columnIndex === this.dragState.start ? `darg_start` : ''
},
//打印包住区域
print () {
this.$refs.print.print()
},
// 点击表头排序回调事件 1是默认,2升序,3降序
clickHandler (e, c, i) {
this.tableHeaderYes.map((item, index) => {
if (i === index) {
item.sort++
if (item.sort >= 4) {
item.sort = 1
}
} else if (item.sort) {
item.sort = 1
}
})
console.log(c.property, this.tableHeaderYes[i].sort)// 字段名,排序状态
}
}
}
.w-table {
position: relative;
.edit {
position: absolute;
right: 0;
top: 0;
z-index: 10;
.el-dropdown-link {
cursor: pointer;
background: #fff;
color: #1890ff;
font-size: 20px;
border: 1px solid #dfe6ec;
box-sizing: border-box;
height: 40px;
width: 40px;
display: flex;
justify-items: center;
align-content: center;
}
i {
margin: 0;
width: 40px;
text-align: center;
line-height: 40px;
}
}
.cell {
transition: all ease 0.2s;
}
.el-table {
thead {
th{
transition: all ease 0.2s;
&:hover{
background: #ddd;
}
}
.cell{
line-height: 40px;
}
.darg_start {
background: #999 !important;
cursor: move;
.cell{
color: #fff;
}
}
}
}
.el-table th {
padding: 0;
.thead-cell-box {
display: block;
position: relative;
white-space: normal;
}
.thead-cell {
cursor:copy;
position: absolute;
top: 0;
left: -10px;
bottom: 0;
right: 0;
}
.thead-cell2 {
width: 35px;
}
.thead-cell1 {
display: inline-block;
position: relative;
white-space: normal;
font-weight: 800;
line-height: 22px;
}
&.w-table_moving {
.el-table th .thead-cell {
cursor: move !important;
}
.el-table__fixed {
cursor: not-allowed;
}
}
}
搞完收工,200到手,下班下班,明天再来封装成组件
转载记录地址链接