You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="page">
<div class="box" ref="box">
<div class="container" ref="container" :style="transform">
<div class="no">
序列号{{ info.shouquanshubianhao }}
</div>
<div class="qrcode">
<div ref="qrcode"></div>
<div style="padding-top: 2px;text-shadow: 1px 1px #ddd;">扫码核验</div>
</div>
<div class="title">
<span style="padding-right: 20px;"></span><span></span>
</div>
<div class="text">
兹有<span>{{ info.name }}</span>身份证号<span>{{ info.idcard }}</span>经苏州市总工会审核评定为{{ new Date().getFullYear() }}年度苏州市总工会<span>{{ info.kunnanleixing }}</span>
<template v-if="showChild">
<span>{{ printChild.name }}</span>身份证号码<span>{{ printChild.idcard }}</span>系其家庭成员
</template>
<br>
<p>特此证明</p>
<div class="stay">
<p>苏州市总工会权益保障部</p>
<p>{{ $moment(new Date()).format('YYYY年M月DD日') }}</p>
</div>
<img class="seal" :src="require('@/assets/seal.gif')" alt="">
</div>
</div>
</div>
<Button v-show="isReduction" class="reduction" size="small" type="info" @click="reduction">还原</Button>
<div class="bottom-panel">
<Button type="info" icon="md-download" @click="download">下载</Button>
<Button type="info" icon="md-print" @click="print">打印</Button>
</div>
</div>
</template>
<script>
import "jspdf/dist/polyfills.es"
import QRCode from 'qrcodejs2';
import html2canvas from "html2canvas";
import Jspdf from "jspdf";
import printJS from "print-js";
import { saveAs } from 'file-saver';
import { updateLog, userInfo } from "@/api/h5";
export default {
data() {
return {
info: {},
printChild: {},
container: {
w: 0,
h: 0,
offsetX: 0,
offsetY: 0,
lastX: 0,
lastY: 0,
scale: 1
},
isToImg: false,
type: new Map([
[1,'特别困难'],
[2,'深度困难'],
[3,'相对困难'],
[4,'意外至困']
])
}
},
methods: {
reduction () {
this.container.offsetY = 0;
this.container.offsetX = 0;
this.container.scale = 1;
},
creatQrCode() {
let { href } = this.$router.resolve({
path: this.$route.fullPath,
query: {
isQr: 1
}
});
let w = this.$refs['box']?.getBoundingClientRect()?.width;
new QRCode(this.$refs.qrcode, {
text: `${window.location.origin}${window.location.pathname}${href}`, // 二维码的内容
width: (w * 0.14) || 74,
height: (w * 0.14) || 74,
colorDark: '#000',
colorLight: '#fff',
correctLevel: QRCode.CorrectLevel.H
});
},
setFontSize () {
const box = this.$refs['box'];
const container = this.$refs['container'];
const baseSize = 15;
const scale = box.getBoundingClientRect().width / 600;
container.style.fontSize = baseSize * Math.min(scale, 2) + "px";
},
init () {
const box = this.$refs['box'];
const container = this.$refs['container'];
const { width,height } = box.getBoundingClientRect();
this.container.w = width;
this.container.h = height;
this.setFontSize();
//
box.ontouchstart = box.onmousedown = event => {
event.preventDefault();
if (event.type === 'touchstart') {
let touch = event.touches[0];
this.container.lastX = touch.clientX;
this.container.lastY = touch.clientY;
} else {
this.container.lastX = event.clientX;
this.container.lastY = event.clientY;
}
box.ontouchmove = box.onmousemove = e => {
let currentX,currentY;
if (e.type === 'touchmove') {
let touch = e.touches[0];
currentX = touch.clientX;
currentY = touch.clientY;
} else {
currentX = e.clientX;
currentY = e.clientY;
}
this.container.offsetX += currentX - this.container.lastX;
this.container.offsetY += currentY - this.container.lastY;
this.container.lastX = currentX;
this.container.lastY = currentY;
}
}
box.ontouchend = box.onmouseup = e => {
box.ontouchmove = box.onmousemove = null;
}
box.onwheel = e => {
e.preventDefault();
this.container.scale *= Math.exp(e.deltaY / -100);
}
},
download () {
this.isToImg = true;
html2canvas(this.$refs['container'],{
backgroundColor: '#ffffff',
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
dpi: window.devicePixelRatio || 1,
scale: 3 // 按比例增加分辨率
}).then(cnv => {
this.isToImg = false;
const pdf = new Jspdf('p','mm','a4');
const ctx = cnv.getContext('2d');
let a4w = 190;
let a4h = 277; // A4大小210mm x 297mm四边各保留10mm的边距显示区域190x277
let imgHeight = Math.floor(a4h * cnv.width / a4w); // 按A4显示比例换算一页图像的像素高度
let renderedHeight = 0;
while (renderedHeight < cnv.height) {
let page = document.createElement('canvas');
page.width = cnv.width;
page.height = Math.min(imgHeight, cnv.height - renderedHeight);// 可能内容不足一页
// 用getImageData剪裁指定区域并画到前面创建的canvas对象中
page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, cnv.width, Math.min(imgHeight, cnv.height - renderedHeight)), 0, 0);
pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面保留10mm边距
renderedHeight += imgHeight;
if (renderedHeight < cnv.height) {
pdf.addPage();// 如果后面还有内容,添加一个空页
}
// delete page;
}
// 保存文件
//pdf.save(`困难职工证明-${this.info.name}.pdf`);
let file = pdf.output('blob',{
filename: `困难职工证明-${this.info.name}.pdf`,
type: 'application/pdf;charset=utf-8'
})
let blob = new Blob([file], {type: 'application/pdf'});
let reader = new FileReader();
let filename = `困难职工证明-${this.info.name}.pdf`
reader.onloadend = function() {
let a = document.createElement('a');
a.href = reader.result;
a.download = filename;
a.click();
}
reader.readAsDataURL(blob);
// console.log(file)
// saveAs(file,`困难职工证明-${this.info.name}.pdf`)
// let a = document.createElement('a');
// a.href = window.URL.createObjectURL(file);
// a.download = `困难职工证明-${this.info.name}.pdf`;
// a.click();
}).catch(err => {
this.isToImg = false;
})
},
print () {
this.isToImg = true;
html2canvas(this.$refs['container'],{
backgroundColor: null,
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
dpi: window.devicePixelRatio || 1,
scale: 3 // 按比例增加分辨率
}).then(cnv => {
this.isToImg = false;
printJS({
printable: cnv.toDataURL(),
type: 'image',
documentTitle: `困难职工证明-${this.info.name}`,
style: '@page{margin: 0 10mm;}'
})
updateLog({
bianma: window.atob(this.$route.query.bm),
type: window.atob(this.$route.query.isChild) == 0 ? 1 : 2
})
}).catch(err => this.isToImg = true)
},
getPrintChild (childrens) {
const childId = window.atob(this.$route.query.isChild);
this.printChild = childrens.find(i => i.id == childId);
}
},
computed: {
transform () {
if (this.isToImg) return {};
return { 'transform': `translate(${this.container.offsetX}px,${this.container.offsetY}px) scale(${this.container.scale},${this.container.scale})` }
},
isReduction () {
return this.container.offsetX !== 0 || this.container.offsetY !== 0 || this.container.scale !== 1
},
showChild () {
return window.atob(this.$route.query.isChild) != 0
}
},
created() {
if (this.$route.query.isQr && this.$route.query.bm) {
updateLog({
bianma: window.atob(this.$route.query.bm),
type: 3
})
}
},
mounted() {
if (this.$route.query.bm) {
userInfo({
bianma: window.atob(this.$route.query.bm)
}).then(res => {
console.log(res)
this.info = res.user;
this.getPrintChild(res.childrens);
this.init();
this.creatQrCode();
})
}
}
}
</script>
<style scoped lang="scss">
.page {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background: rgb(80,80,80);
}
.box {
width: 100vw;
height: 100vh;
max-width: 600px;
max-height: 800px;
background: #eee;
overflow: hidden;
margin: auto;
.container {
width: 100%;
height: 100%;
background: #fff;
position: relative;
&-border {
border: .5px solid #333;
}
@mixin h1 {
font-weight: 900;
font-size: 2em;
text-align: center;
text-shadow: 1px 1px #ddd;
}
@mixin h2 {
font-weight: 500;
font-size: 1.2em;
text-align: center;
text-shadow: 1px 1px #ddd;
}
@mixin text {
text-shadow: 1px 1px #ddd;
font-size: 1.1em;
}
& > div {
position: absolute;
}
.no {
@include h2;
transform: translate(20px,20px);
}
.qrcode {
transform: translate(0px,20px);
right: 20px;
text-align: center;
}
.title {
@include h1;
transform: translate(-50%,0);
left: 50%;
top: 22.5%;
}
.text {
@include text;
word-spacing: 4px;
letter-spacing: 1px;
top: 35%;
padding: 0 5em;
text-indent: 2em;
line-height: 2.6;
word-break: break-all;
& > span {
text-decoration: underline;
}
}
.stay {
@include text;
line-height: 1.8;
text-align: right;
padding-top: 1em;
padding-right: 1em;
position: relative;
z-index: 1;
}
.seal {
right: 14%;
width: 7vw;
min-width: 50px;
object-fit: cover;
filter: saturate(1);
transform: translate(-1em,-4em);
z-index: 0;
position: absolute;
}
}
}
.reduction {
transform: translateX(-50%);
position: fixed;
left: 50%;
bottom: 60px;
}
.bottom-panel {
height: 50px;
background: rgba(55,55,55,.6);
display: flex;
justify-content: space-evenly;
align-items: center;
transition: all .2s;
position: fixed;
left: 0;
right: 0;
bottom: 0;
& > Button {
min-width: 90px;
max-width: 150px;
width: 16%;
}
}
</style>