From 75f6a814525dfd3b19e359a3dfa3de3e9226f32d Mon Sep 17 00:00:00 2001 From: 马宇豪 <978517621@qq.com> Date: 星期二, 26 十一月 2024 15:08:46 +0800 Subject: [PATCH] 更新 --- src/assets/styles/font/fangzhengKT.ttf | 0 src/permission.js | 2 src/views/safetyReview/expertManage/experts/index.vue | 26 ++--- src/utils/htmlToPdf.js | 50 ++++++++++ package.json | 2 src/views/safetyReview/expertManage/checkProgress/index.vue | 27 +++-- src/views/safetyReview/expertManage/checkProgress/components/certificatePdf.vue | 53 ++++++++++ src/views/certificatePdf.vue | 92 ++++++++++++++++++ src/assets/images/certBg.jpg | 0 src/router/index.js | 5 + 10 files changed, 230 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index fbc916a..6d172b9 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,11 @@ "element-plus": "2.2.27", "file-saver": "2.0.5", "fuse.js": "6.6.2", + "html2canvas": "^1.4.1", "js-base64": "^3.7.5", "js-cookie": "3.0.1", "jsencrypt": "3.3.1", + "jspdf": "^2.5.2", "nprogress": "0.2.0", "pinia": "2.0.22", "quill": "^2.0.0-dev.3", diff --git a/src/assets/images/certBg.jpg b/src/assets/images/certBg.jpg new file mode 100644 index 0000000..3847592 --- /dev/null +++ b/src/assets/images/certBg.jpg Binary files differ diff --git a/src/assets/styles/font/fangzhengKT.ttf b/src/assets/styles/font/fangzhengKT.ttf new file mode 100644 index 0000000..1ef7053 --- /dev/null +++ b/src/assets/styles/font/fangzhengKT.ttf Binary files differ diff --git a/src/permission.js b/src/permission.js index f8a49a3..eef296e 100644 --- a/src/permission.js +++ b/src/permission.js @@ -11,7 +11,7 @@ NProgress.configure({ showSpinner: false }); -const whiteList = ['/homePage','/fillForm','/checkProgress']; +const whiteList = ['/homePage','/fillForm','/checkProgress','/certPdf']; router.beforeEach((to, from, next) => { NProgress.start() diff --git a/src/router/index.js b/src/router/index.js index ebac8ec..e929a04 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -58,6 +58,11 @@ hidden: true }, { + path: '/certPdf', + component: () => import('@/views/certificatePdf'), + hidden: true + }, + { path: '/checkProgress', component: () => import('@/views/safetyReview/expertManage/checkProgress/index.vue'), hidden: true diff --git a/src/utils/htmlToPdf.js b/src/utils/htmlToPdf.js new file mode 100644 index 0000000..3dcb647 --- /dev/null +++ b/src/utils/htmlToPdf.js @@ -0,0 +1,50 @@ +// 导出页面为PDF格式 +import html2Canvas from 'html2canvas'; +import JsPDF from 'jspdf'; + +export default function htmlToPdf(title=new Date().getTime()) { + return html2Canvas(document.body, { + // useCORS:true, //保证跨域图片的显示 + // width:window.screen.availWidth, //显示canvas窗口的宽度 + // height:window.screen.availHeight, //显示canvas窗口的高度 + // windowHeight: document.body.scrollHeight, //获取y方向滚动条中的内容 + // windowWidth: document.body.scrollWidth,//获取x方向滚动条中的内容 + // x:0, //页面在水平方向上没有滚动,故设置为0 + // y: window.pageXOffset //页面在垂直方向的滚动距离 + }).then(function (canvas) { + let contentWidth = canvas.width; + let contentHeight = canvas.height; + let pageHeight = contentWidth / 592.28 * 841.89; + let leftHeight = contentHeight; + let position = 0; + // let imgWidth = 595.28; + // let imgHeight = 592.28 / contentWidth * contentHeight; + let imgWidth = 838.89; + let imgHeight = 835.89 / contentWidth * contentHeight; + + // 将图片转化为dataUrl + let pageData = canvas.toDataURL('image/jpeg', 1.0); + + // 三个参数,第一个方向(landscape横向?),第二个尺寸,第三个尺寸格式 + let PDF = new JsPDF('landscape', 'pt', 'a4'); + + //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度 (841.89) + //当内容未超过pdf一页显示的范围,无需分页 + if (leftHeight < pageHeight) { + // 0, 0, 控制文字距离左边,与上边的距离,后两个参数控制添加图片的尺寸,此处将页面高度按照 a4纸宽高比列进行压缩 + PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight); + } else { + while (leftHeight > 0) { + PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight); + leftHeight -= pageHeight; + position -= 841.89; + //避免添加空白页 + if (leftHeight > 0) { + PDF.addPage(); + } + } + } + PDF.save(title + '.pdf'); + }); + +} \ No newline at end of file diff --git a/src/views/certificatePdf.vue b/src/views/certificatePdf.vue new file mode 100644 index 0000000..f67bbc8 --- /dev/null +++ b/src/views/certificatePdf.vue @@ -0,0 +1,92 @@ +<template> + <div class="form-container"> + <div class="certContent" @click="getPdf()"> + <div class="main-content"> + 兹聘任{{info.name}}同志为自治区应急管理厅专家,聘任期为{{info.employmentDateStart?.substring(0,4)}}年{{info.employmentDateStart?.substring(5,7)}}月至{{info.employmentDateEnd?.substring(0,4)}}年{{info.employmentDateEnd?.substring(5,7)}}月。 + </div> + <div class="main-content"> + 特发此证! + </div> + <div class="footer-content"> + 自治区应急管理厅<br/> + {{info.updateTime?.substring(0,4)}}年{{info.updateTime?.substring(5,7)}}月 + </div> + </div> + </div> +</template> +<script setup> +import {reactive, ref, toRefs, onMounted, nextTick} from 'vue' +import {ElMessage, ElMessageBox} from "element-plus" +import htmlToPdf from '@/utils/htmlToPdf'; +import { useRoute } from 'vue-router' +const { proxy } = getCurrentInstance(); +const route = useRoute(); +const data = reactive({ + info: {} +}) +const {info} = toRefs(data) +onMounted(()=>{ + data.info = route.query + nextTick(()=>{ + getPdf() + }) +}) + +function getPdf() { + let title = data.info.name + '专家聘书' + htmlToPdf(title); +} + +onMounted(()=>{ + +}) + +defineExpose({ + getPdf +}) +</script> + +<style scoped lang="scss"> +@font-face { + font-family: "fangzhengKT"; + src: url("@/assets/styles/font/fangzhengKT.ttf"); + font-style: normal; + font-weight: normal; +} +.form-container{ + padding: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .certContent{ + width: 1920px; + height: 1280px; + background: url("@/assets/images/certBg.jpg") no-repeat center; + background-size: contain; + display: flex; + flex-direction: column; + align-items: center; + padding: 550px 380px 80px; + color: #9e0500; + + .main-content{ + width: 100%; + font-size: 50px; + text-align: left; + line-height: 1.8; + text-indent: 100px; + letter-spacing: 2px; + font-family: 'fangzhengKT'; + } + + .footer-content{ + font-size: 36px; + transform: translate(200px,120px); + text-align: center; + line-height: 1.8; + } + } +} +</style> diff --git a/src/views/safetyReview/expertManage/checkProgress/components/certificatePdf.vue b/src/views/safetyReview/expertManage/checkProgress/components/certificatePdf.vue new file mode 100644 index 0000000..4ada139 --- /dev/null +++ b/src/views/safetyReview/expertManage/checkProgress/components/certificatePdf.vue @@ -0,0 +1,53 @@ +<template> + <div class="form-container"> + <div class="certContent"> + <div></div> + </div> + </div> +</template> +<script setup> +import {reactive, ref, toRefs, onMounted} from 'vue' +import {ElMessage, ElMessageBox} from "element-plus" +import htmlToPdf from '@/utils/htmlToPdf'; +const { proxy } = getCurrentInstance(); + +const data = reactive({ + info: {} +}) + +const {info} = toRefs(data) +const deptList = ref([]); +onMounted(()=>{ + +}) + +function getPdf(info) { + console.log(info,'info') + htmlToPdf(); +} + +onMounted(()=>{ + +}) + +defineExpose({ + getPdf +}) +</script> + +<style scoped lang="scss"> +.form-container{ + padding: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .certContent{ + width: 1123px; + height: 794px; + background: url("@/assets/images/certBg.jpg") no-repeat; + background-size: contain; + } +} +</style> diff --git a/src/views/safetyReview/expertManage/checkProgress/index.vue b/src/views/safetyReview/expertManage/checkProgress/index.vue index b448ce7..be60b04 100644 --- a/src/views/safetyReview/expertManage/checkProgress/index.vue +++ b/src/views/safetyReview/expertManage/checkProgress/index.vue @@ -1,13 +1,13 @@ <template> <div class="form-container"> <el-form :model="queryParams" size="default" ref="formRef" inline :rules="formRules" label-width="110px" > - <el-form-item label="身份证号:" prop="idCard"> + <el-form-item label="身份证号:"> <el-input v-model.trim="queryParams.idCard" placeholder="请输入身份证号"></el-input> </el-form-item> - <el-form-item label="手机号:" prop="phone"> + <el-form-item label="手机号:"> <el-input v-model.trim="queryParams.phone" placeholder="请输入申报时预留的手机号"></el-input> </el-form-item> - <el-form-item label="业务处室:" prop="deptId"> + <el-form-item label="业务处室:"> <el-cascader clearable placeholder="请选择申请的业务处室" @@ -27,10 +27,10 @@ <span v-if="result.state == 3">评定不符合</span> <span v-if="result.state == 2">评定通过</span> </button> - <button :class="result.state == 4?'pro-btn-active':'pro-btn'"> + <button :class="result.state == 2?'pro-btn-active':'pro-btn'"> 专家入库 </button> - <button :class="result.state == 4?'pro-download-active':'pro-download'"> + <button :class="result.state == 2?'pro-download-active':'pro-download'" @click="downloadPdf(result)"> 专家证书下载 </button> </div> @@ -38,14 +38,15 @@ </template> <script setup> import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue' +import { useRouter } from 'vue-router' import {ElMessage, ElMessageBox} from "element-plus" import {verifyPhone, verifyIdCard} from "../../../../utils/validate" import { getToken } from "@/utils/auth" import {getExpertsList, queryApprove} from "@/api/form"; import {listOutDept} from "@/api/system/dept"; - +import CertificatePdf from './components/certificatePdf' const { proxy } = getCurrentInstance(); - +const router = useRouter() let validatePhone = (rule, value, callback)=>{ if(value === ''){ callback(new Error('请输入手机号')) @@ -76,9 +77,7 @@ deptId: null }, formRules:{ - idCard:[{ required: true, validator: verifyId, trigger: 'blur' }], - phone:[{ required: true, validator: validatePhone, trigger: 'blur' }], - deptId: [{ required: true, message: '请选择申请的业务处室', trigger: 'blur' }] + }, result: {} }) @@ -91,7 +90,6 @@ const showProgress = ref(false) const formRef = ref() - function getDepList() { listOutDept({}).then(response => { deptList.value = proxy.handleTree(response.data, "deptId",'parentId','children'); @@ -120,6 +118,13 @@ }) } +const downloadPdf=(info)=>{ + const routePath = '/certPdf'; + const resolvedRoute = router.resolve(routePath); + const queryString = new URLSearchParams(info).toString(); + const fullPath = `${resolvedRoute.href}?${queryString}`; + window.open(fullPath, '_blank'); +} const resetQuery = ()=>{ data.queryParams = { diff --git a/src/views/safetyReview/expertManage/experts/index.vue b/src/views/safetyReview/expertManage/experts/index.vue index 26a6f23..82cc3b7 100644 --- a/src/views/safetyReview/expertManage/experts/index.vue +++ b/src/views/safetyReview/expertManage/experts/index.vue @@ -89,19 +89,7 @@ </el-table-column> <el-table-column label="专家聘书" align="center" prop="expertCertificate"> <template #default="scope"> - <div class="demo-image__preview" v-if="scope.row.expertCertificate && scope.row.expertCertificate!==''"> - <el-image - style="width: 100px; height: 100px" - :src= "scope.row.expertCertificate" - :zoom-rate="1.2" - :max-scale="7" - :min-scale="0.2" - :preview-src-list="[scope.row.expertCertificate]" - :initial-index="0" - fit="cover" - :preview-teleported=true - /> - </div> + <el-button type="primary" link @click="viewCert(scope.row)">查看</el-button> </template> </el-table-column> <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> @@ -126,8 +114,8 @@ import {ElMessage, ElMessageBox} from "element-plus"; import ExpertForm from "../applyRecords/components/expertForm"; import {delExpert, getExpertsList, getExpertTypes} from "../../../../api/form"; -import { Plus } from '@element-plus/icons-vue' - +import {useRouter} from "vue-router"; +const router = useRouter(); const loading = ref(false); const data = reactive({ showSearch: true, @@ -222,6 +210,14 @@ return null; } +const viewCert=(info)=>{ + const routePath = '/certPdf'; + const resolvedRoute = router.resolve(routePath); + const queryString = new URLSearchParams(info).toString(); + const fullPath = `${resolvedRoute.href}?${queryString}`; + window.open(fullPath, '_blank'); +} + const getSupport =(safety,prevention,emergency)=>{ let str = [] let safeArr = safety?.split(',') -- Gitblit v1.9.2