vue-excel不规则表格编写且可以打印预览
效果图:一、打印预览引入两个依赖文件ref=“exportPdf” 指向只能指向div这些dom原生元素,不然会报Element is not attached to aDocument错误。npm install html2canvas --savenpm install print-js --save二、封装一个组件 excel(不规格表格 粗暴方法实现)<template><
·
效果图:
一、打印预览引入两个依赖文件
ref=“exportPdf” 指向只能指向div这些dom原生元素,不然会报Element is not attached to a
Document错误。
npm install html2canvas --save
npm install print-js --save
二、封装一个组件 excel(不规格表格 粗暴方法实现)
<template>
<div>
<div class="title">{{title}}</div>
<div class="cont">
<!-- 第一行表格 五列 -->
<div class="table">
<div class="lump" v-for="(item, index) in tableArr" :key="index">
<div class="box">
<div class="content1">{{ item.key }}</div>
<el-tooltip v-if="item.value.length > 11" class="item" :content="item.value" placement="top">
<div :class="item.border !== 'none' ? 'content2' : 'content_border'">{{ item.value}}</div>
</el-tooltip>
<div v-else :class="item.border !== 'none' ? 'content2' : 'content_border'">{{ item.value}}</div>
</div>
</div>
</div>
<!-- 第二行表格 三列 2-4 -->
<div class="table">
<div class="lump2" v-for="(item, index) in tableArr2" :key="index">
<div class="box">
<div class="content1" :style="'width:'+ item.width">{{ item.key }}</div>
<el-tooltip v-if="item.value.length > 11" class="item" :content="item.value" placement="top">
<div :class="item.border !== 'none' ? 'content2' : 'content_border'" :style="'width:'+ item._width">{{ item.value}}</div>
</el-tooltip>
<div v-else :class="item.border !== 'none' ? 'content2' : 'content_border'" :style="'width:'+ item._width">{{ item.value}}</div>
</div>
</div>
</div>
<!-- 第三行表格 一列-->
<div class="table">
<div class="content3">现场处理情况信息</div>
</div>
<!-- 第四行表格 二列 -->
<div class="table">
<template v-for="(item, index) in tableArr4">
<div class="lump4" :key="index">
<div :key="'info'+ index" :class="item.type == 2 ? 'conttent4' : 'conttent6'">
<!-- 不是3隐藏 -->
<template v-if="item.type !== 3">
<div :class="item.type == 1 ? 'conttent6-title' : 'conttent4-title'">{{item.key+ ':'}}</div>
<el-tooltip v-if="item.value.length > 20" class="item" :content="item.value" placement="top">
<div :class="item.type == 1 ? 'conttent6-txt' : 'conttent4-txt'">{{item.value}}</div>
</el-tooltip>
<div v-else :class="item.type == 1 ? 'conttent6-txt' : 'conttent4-txt'">{{item.value}}</div>
</template>
<!-- 评价 -->
<template v-if="item.type == 3">
<div class="conttent6-score">
<div class="conttent6-score-title">{{item.key+ ':'}}</div>
<el-row class="conttent6-score-affirm">
<el-col>维保工程师是否按约定时间上门:是</el-col>
<el-col>是否主动出示上岗工作牌:是</el-col>
<el-col>维护完毕是否逐项检验正常:是</el-col>
<el-col>维护完毕后是否清洁设备和现场:是</el-col>
<el-col>满意度:非常满意</el-col>
</el-row>
</div>
</template>
</div>
<div :key="index" :class="item.type == 2 ? 'conttent5' : 'conttent7'">
<template v-if="item.type !== 3">
<div :class="item.type == 1 ? 'conttent7-title' : 'conttent5-title'">{{item.key2+ ':'}}</div>
<el-tooltip v-if="item.value2.length > 20" class="item" :content="item.value2" placement="top">
<div :class="item.type == 1 ? 'conttent7-txt' : 'conttent5-txt'">{{item.value2}}</div>
</el-tooltip>
<div v-else :class="item.type == 1 ? 'conttent7-txt' : 'conttent5-txt'">{{item.value2}}</div>
</template>
<!-- 签名 -->
<template v-if="item.type == 3">
<div class="conttent7-sign">
<div class="conttent7-sign-title">{{item.key2+ ':'}}</div>
<div class="conttent7-sign-txt">{{item.value2}}</div>
</div>
<img
v-if="item.type == 3"
src="http://t13.baidu.com/it/u=1883019352,930630496&fm=224&app=112&f=JPEG?w=500&h=500&s=4B843862418D69E3567530C60000E0B1"
style="padding-left: 25%; width:200px; height:150px"
alt
/>
</template>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
},
tableArr: {
type: Array,
default: () => {
return []
}
},
tableArr2: {
type: Array,
default: () => {
return []
}
},
tableArr4: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {}
},
computed: {},
created() {},
mounted() {},
watch: {},
methods: {},
components: {}
}
</script>
<style scoped lang="scss">
$titleColor: rgb(117, 117, 117);
$borderColor: 1px solid #e9e9e9;
.title {
width: 100%; // 1200px
margin: 0 auto;
margin-top: 30px;
padding: 20px 0;
font-size: 18px;
font-weight: 600;
background-color: #e1e1e1;
// border: 1px solid #e1e1e1;
}
.cont {
border-right: $borderColor;
}
.table {
width: 100%; // 1200px
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.lump {
width: 20%;
}
.lump2 {
width: 40%;
}
.lump2:nth-child(3),
.lump2:nth-child(6),
.lump2:last-child {
width: 20%;
}
.box {
width: 100%;
height: 40px;
display: flex;
border-top: $borderColor;
.content1 {
width: 40%;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #fafafa;
border-left: $borderColor;
border-bottom: $borderColor;
color: $titleColor;
font-size: 14px;
}
.content2 {
width: 60%;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #fff;
border-left: $borderColor;
border-bottom: $borderColor;
color: 000;
font-size: 14px;
cursor: pointer;
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap; //溢出不换行
}
// .content2:last-child {
// border-right: $borderColor;
// }
.content_border {
width: 60%;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #fff;
border-left: $borderColor;
border-bottom: $borderColor;
color: 000;
font-size: 14px;
cursor: pointer;
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap; //溢出不换行
}
}
// 三列样式
.content3 {
width: 100%;
height: 40px;
display: inline-block;
line-height: 40px;
text-align: center;
background-color: #fff;
border: $borderColor;
border-right: none;
color: 000;
font-size: 14px;
font-weight: 600;
}
// 四列样式
.lump4 {
width: 100%;
display: flex;
// align-items: center;
flex-wrap: wrap;
box-sizing: border-box;
border: $borderColor;
border-top: none;
border-right: none;
.conttent4 {
display: flex;
align-items: center;
width: calc(48% - 1px);
height: 40px;
line-height: 40px;
border-right: $borderColor;
background-color: #fff;
text-align: left;
cursor: pointer;
white-space: nowrap; //溢出不换行
&-title {
color: $titleColor;
padding-left: 12px;
}
&-txt {
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap; //溢出不换行
}
}
.conttent5 {
display: flex;
align-items: center;
width: 52%;
height: 40px;
line-height: 40px;
text-align: left;
background-color: #fff;
cursor: pointer;
white-space: nowrap;
&-title {
padding-left: 12px;
color: $titleColor;
}
&-txt {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.conttent6 {
width: calc(48% - 1px);
min-height: 100px;
text-align: left;
// border-right: $borderColor;
background: #fff;
border-top: none;
cursor: pointer;
// white-space: nowrap;
&-title {
color: $titleColor;
padding: 12px;
}
&-txt {
padding: 0 12px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
// 评价
&-score {
padding: 12px;
&-title {
color: $titleColor;
}
&-affirm {
padding: 12px;
padding-left: 0;
::v-deep .el-col {
padding-bottom: 12px;
}
::v-deep .el-col:last-child {
padding-bottom: 0;
}
}
}
}
.conttent7 {
width: calc(52% - 30px);
min-height: 100px;
text-align: left;
background: #fff;
border-left: $borderColor;
cursor: pointer;
&-title {
color: $titleColor;
padding: 12px;
}
&-txt {
padding: 0 12px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
// 签名
&-sign {
display: flex;
align-items: center;
padding: 12px;
&-title {
color: $titleColor;
}
}
}
}
</style>
三、父组件调用
<template>
<div>
<el-dialog title="工单详情" :visible.sync="detailsVisible" :width="dialogWidth" @close="handleClose">
<!-- 卡片试图区域 -->
<el-card class="box-card">
<template>
<div class="steps-cont">
<div
class="date"
v-show="item != ''"
:style="{'left': `${index*((timeList.length==3 ? number*2 :timeList.length==4 ? number*3:number)/(timeList.length-1))+ percentum}%`}"
v-for="(item, index) in timeList"
ref="refTime"
:key="index"
>
<div>{{item.year}}</div>
<div class="date-time">{{item.time}}</div>
</div>
<el-steps :active="2" align-center>
<el-step title="待接单" description="派遣到维修人员 黄某"></el-step>
<el-step title="已接单" description="维修接单 李某"></el-step>
<el-step title="执行中" description="执行中 王某"></el-step>
<el-step title="已结单" description="已完成 王某"></el-step>
</el-steps>
</div>
</template>
<!-- 打印预览 print-->
<el-main class="main">
<div ref="exportPdf" id="exportPdf">
<!-- 表格 -->
<Excel ref="refExcel" :title="excel_title" :tableArr="tableArr" :tableArr2="tableArr2" :tableArr4="tableArr4" />
</div>
</el-main>
<div>
<el-button type="primary" size="mini" @click="printHandle">打印预览</el-button>
</div>
<el-footer class="table" style="padding-top:10px">
<el-descriptions title="其他信息">
<template v-for="(item, index) in otherList">
<el-descriptions-item :key="index" :label="item.label">{{item.value}}</el-descriptions-item>
</template>
</el-descriptions>
</el-footer>
</el-card>
</el-dialog>
</div>
</template>
<script>
import html2canvas from 'html2canvas' // 转为图片
import printJS from 'print-js' // 打印
import Excel from './excel'
export default {
name: 'OrderDetails',
components: { Excel },
props: {
orderVisible: {
type: Boolean,
default: false
}
},
data() {
return {
dialogWidth: '1500px',
// 订单时间线
timeList: [
{ year: '2022', time: '03-01 15:25:13' },
{ year: '2022', time: '04-01 15:25:13' }
// { year: '2022', time: '05-01 15:25:13' }
// { year: '2022', time: '06-01 15:25:13' }
],
number: 25, // 平均偏移位置
percentum: '', // 初始位置百分比
// 悬浮显示
isShowTooltip: true,
// 表格数据
excel_title: '云南XXX服务XX单',
tableArr: [
{
key: '订单号',
value: 'wb-2022-03-1801',
border: 'none'
},
{
key: '客户名称',
value: '大理市政府',
border: 'none'
},
{
key: '办公室地址',
value: '923',
border: 'none'
},
{
key: '联系电话',
value: '13511112222',
border: 'none'
},
{
key: '维修工程师',
value: '张飞'
}
],
// 第二列表格
tableArr2: [
{
key: '保修时间',
value: '2022-03-18 12:00',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '预计时间',
value: '2小时',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '报修人',
value: '关羽',
width: '101.44px',
_width: '152.3px'
},
// ------------------
{
key: '服务内容',
value: '打印机连不上',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '服务方式',
value: '上门服务',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '报修方式',
value: '在线报修',
width: '101.44px',
_width: '152.3px'
},
// --------------------
{
key: '影响范围',
value: '一般',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '紧急程度',
value: '一般',
width: '101.44px',
_width: '383.8px',
border: 'none'
},
{
key: '其他',
value: '',
width: '101.44px',
_width: '152.3px'
}
],
// 第四列
tableArr4: [
{
key: '故障原因',
value: '经排查,网络断开,内网故障',
key2: '维修处理情况',
value2: '国产电脑连接共享打印机,已处理完成',
type: 1
},
{
key: '注:若需要重装系统, 数据请客户提前备份。客户确认签字',
value: '',
key2: '修复时间',
value2: '2022-03-08 11:00',
type: 2
},
{
key: '客户填写部分',
value: '',
key2: '客户签字及日期',
value2: '2022-03-08 12:00',
type: 3
}
],
otherList: [
{ label: '工单状态', value: '已结单' },
{ label: '工单耗时', value: '0分钟' },
{ label: '工单来源', value: '小程序' },
{ label: '收费项目', value: '无收费项目' },
{ label: '收费金额', value: '000000' },
{ label: '到场时间', value: '2022-03-12 09:45:25' }
],
// 窗口变化
screenWidth: document.body.clientWidth
}
},
created() {
if (this.screenWidth > 1700) {
this.dialogWidth = '1500px'
this.percentum = 7
} else {
this.dialogWidth = '1050px'
this.percentum = 4.2
}
},
mounted() {
// 获取窗口变化
const that = this
window.onresize = () => {
return (() => {
window.screenWidth = document.body.clientWidth
that.screenWidth = window.screenWidth
this.$nextTick(() => {
// console.log(this.$refs.refTime.width, 'ref')
})
})()
}
},
watch: {
// 监听窗口变化
screenWidth(val) {
// 为了避免频繁触发resize函数导致页面卡顿,使用定时器
if (!this.timer) {
// 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
this.screenWidth = val
this.timer = true
let that = this
if (this.screenWidth > 1700) {
that.dialogWidth = '1500px'
that.percentum = 7
} else {
that.dialogWidth = '1050px'
that.percentum = 4.2
}
setTimeout(function () {
// 打印screenWidth变化的值
console.log(that.screenWidth)
that.timer = false
}, 400)
}
}
},
computed: {
detailsVisible: {
get() {
return this.orderVisible
},
set(val) {
console.log(val)
this.$emit('update:orderVisible', val) // detailsVisible改变的时候通知父组件
}
}
},
methods: {
// 关闭弹框
handleClose() {
// this.orderVisible = false
},
//转图片打印
printHandle() {
html2canvas(this.$refs.exportPdf, {
backgroundColor: null,
useCORS: true,
windowHeight: document.body.scrollHeight
}).then(canvas => {
const url = canvas.toDataURL()
this.img = url
printJS({
printable: url,
type: 'image',
documentTitle: ''
})
})
},
printContext() {
this.$print(this.$refs.print)
}
}
}
</script>
<style lang="scss" scoped>
$titleColor: rgb(117, 117, 117);
$borderColor: 1px solid #e9e9e9;
.steps-cont {
// width: 80%;
margin: 0 auto;
position: relative;
padding-top: 22px;
}
.date {
position: absolute;
top: -50px;
left: 5.5%;
padding: 8px 30px;
color: #fff;
background: $nav-bg;
border-radius: 35px;
&-time {
font-size: 12px;
}
}
.date:after {
content: ''; /*CSS伪类用法*/
position: absolute; /*定位背景横线的位置*/
top: 52px;
left: 49%;
background: $nav-bg; /*宽和高做出来的背景横线*/
width: 4px;
height: 22px;
}
.box-card {
padding-top: 20px;
width: 100%;
min-height: 100vh;
box-sizing: border-box;
padding: 50px;
}
.table {
width: 100%; // 1200px
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
</style>
更多推荐
已为社区贡献5条内容
所有评论(0)