router.js
// 签订承诺书
{
path: "/signPromise",
name: "signPromise",
component: () => import("../views/vehicle/signPromise/index"),
meta: {
name: "wechat:vehicle:signPromise",
},
},
request.js
if (response.status === 200 && response.config.responseType === "blob") {
// 文件类型特殊处理
const blob = new Blob([res.data], {
type: res.data.type
});
const fileName = res.config.fileName
if (!fileName.endsWith('.png')) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, fileName);
} else {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click(); // 释放内存
window.URL.revokeObjectURL(link.href);
}
}
return res;
}
Pakage
npm下载vue-esign
"vue-esign": "^1.1.4",
vue页面html
<template>
<div class="signPromise">
<van-nav-bar title="签订承诺书" left-arrow text-color="#000" background-color="#fff" @click-left="onClickLeft">
<template #right>
<van-icon name="ellipsis" @click="showShare=true" />
</template>
</van-nav-bar>
<div class="content">
<div class="scrollbar">
<div v-for="item in 30" :key="item">
{{ item }}
</div>
<div class="signName" @click="openSignDialog">
<p>签字:</p>
<div v-if="resultImg" class="nameBox">
<!-- <img src="~@/assets/image/editIcon.png" alt="" style="width: 150px;height: 60px;"> -->
<img :src="resultImg" alt="" style="width: 150px;height: 60px;">
</div>
<div v-else style="width: 150px;height: 60px;" />
</div>
</div>
</div>
<!-- dialog -->
<!--全答对退出 -->
<van-dialog v-model="dialogVisible1" :before-close="handleClose" :show-cancel-button="false"
:show-confirm-button="false">
<!-- <van-icon name="cross" class="close" @click="cancel" /> -->
<template #title>
<div class="diatitle">
<!-- <van-icon name="checked" color='#2ab165' /> -->
<span> 签字</span>
</div>
</template>
<div class="dialogcntent">
<div class="canvas">
<vue-esign ref="esign" :height="800" :is-crop="isCrop" :line-width="lineWidth" :line-color="lineColor"
:bg-color.sync="bgColor" />
</div>
<button @click="handleReset">
清除
</button>
<button @click="handleGenerate">
保存
</button>
</div>
</van-dialog>
<a href="path/to/your/pdf/file.pdf" download="filename.pdf" style="display: none;">下载 PDF</a>
<van-share-sheet
v-model="showShare"
title=""
:options="options"
@select="onSelect"
/>
<iframe
src="@/assets/image/1.pdf"
width="300"
height="200" />
</div>
</template>
<script>
import vueEsign from 'vue-esign'
import { Toast } from 'vant'
export default {
name: 'SignPromise',
components: { vueEsign },
data () {
return {
dialogVisible1: false,
isCrop: false,
lineWidth: 6,
lineColor: '#000000',
bgColor: '',
resultImg: '',
showShare: false,
options: [
// { name: '微信', icon: 'wechat' },
{ name: '保存PDF到本地', icon: 'link', id: 1 },
{ name: '保存图片到本地', icon: 'poster', id: 2 }
// { name: '复制链接', icon: 'link' },
// { name: '二维码', icon: 'qrcode' },
]
}
},
methods: {
onSelect (option) {
// console.log(option, option.name);
// 保存pdf到本地
if (option.id == 1) {
Toast("请点击右上角的菜单,选择 '在浏览器中打开',然后再点击 '下载'")
// 1.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// fetch('path/to/your/pdf/file.pdf')
// .then(response => response.blob())
// .then(blob => {
// // 创建 URL 对象
// const url = window.URL.createObjectURL(new Blob([blob]));
// // 创建一个 <a> 标签并模拟点击进行下载
// const link = document.createElement('a');
// link.href = url;
// link.setAttribute('download', 'filename.pdf');
// document.body.appendChild(link);
// link.click();
// // 释放 URL 对象
// window.URL.revokeObjectURL(url);
// })
// .catch(error => console.error('下载 PDF 出错:', error));
// 2.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 调用 downloadPDF 函数
// this.downloadPDF();
// 3.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
this.exportPDF()
}
this.showShare = false
},
// 下载pdf
exportPDF () {
// const Url = "path/to/your/pdf/file.pdf"
const a = document.createElement('a')
// a.href = Url
// a.download = "filename.pdf"
a.click()
},
// 下载pdf
downloadPDF () {
// 替换为你的 PDF 文件路径
const pdfUrl = 'path/to/your/pdf/file.pdf'
// 创建一个隐藏的 iframe 元素
const iframe = document.createElement('iframe')
iframe.style.display = 'none'
// 设置 iframe 的 src 为 PDF 文件路径
iframe.src = pdfUrl
// 将 iframe 添加到页面中
document.body.appendChild(iframe)
// 移除 iframe 元素,防止页面上出现多余的元素
setTimeout(() => {
document.body.removeChild(iframe)
}, 5000) // 5 秒后删除 iframe,可以根据需要调整这个时间
},
// 清除
handleReset () {
this.$refs.esign.reset()
},
// 保存canvas图片
handleGenerate () {
this.$refs.esign.generate().then(res => {
this.resultImg = res
console.log(res)
// 将图片发请求给后端保存到pdf
this.handleClose()
}).catch(err => {
alert(err) // 画布没有签字时会执行这里 'Not Signned'
})
},
openSignDialog () {
this.dialogVisible1 = true
},
// 返回
onClickLeft () {
this.$router.go(-1)
},
handleClose () {
this.dialogVisible1 = false
},
cancel () {
this.handleClose()
}
}
}
</script>
<style lang="less" scoped>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
::v-deep {
.van-dialog {
border-radius: 12px !important;
background: linear-gradient(180deg, #DDE6F3 0%, #F6FBFC 26%, #FFFFFF 43%, #FFFFFF 100%);
}}
.signName{
position: fixed;
right: 60px;
bottom: 60px;
display: flex;
}
.nameBox{
border-bottom: 2px solid #000;
}
::v-deep{
.van-nav-bar__content {
background-color: #fff !important;
}
.van-nav-bar__content .van-nav-bar__title {
color: #000;
font-weight: 700;
}
.van-nav-bar .van-icon {
color: #000;
}
}
.signPromise {
height: 100vh;
position: relative;
}
.content{
// height: 100%;
// overflow: hidden;
padding: 15px 30px;
height: calc(100% - 100px) ;
}
.scrollbar {
background-color: #2870dbc2;
height: 100%;
overflow: auto;
padding-bottom: 100px;
}
/* 滚动条样式 */
.scrollbar::-webkit-scrollbar {
width: 5px;
/* 滚动条宽度 */
}
/* 滚动条轨道样式 */
.scrollbar::-webkit-scrollbar-track {
background: #f1f1f1;
/* 滚动条轨道的背景色 */
}
/* 滚动条滑块样式 */
.scrollbar::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #bfbfbf;
/* 滚动条滑块的背景色 */
}
/* 滚动条滑块悬停样式 */
.scrollbar::-webkit-scrollbar-thumb:hover {
border-radius: 5px;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: #555;
/* 滚动条滑块悬停时的背景色 */
}
/*IE滚动条颜色*/
html {
scrollbar-face-color: #bfbfbf;
/*滚动条颜色*/
scrollbar-highlight-color: #bfbfbf;
scrollbar-3dlight-color: #bfbfbf;
scrollbar-darkshadow-color: #bfbfbf;
scrollbar-shadow-color: #adadad;
/*滑块边色*/
scrollbar-arrow-color: rgba(0, 0, 0, 0.4);
/*箭头颜色*/
scrollbar-track-color: #eeeeee;
/*背景颜色*/
}
</style>