马宇豪
2024-11-26 75f6a814525dfd3b19e359a3dfa3de3e9226f32d
更新
已修改5个文件
已添加5个文件
257 ■■■■ 文件已修改
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/certBg.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/font/fangzhengKT.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/permission.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/htmlToPdf.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/certificatePdf.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/expertManage/checkProgress/components/certificatePdf.vue 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/expertManage/checkProgress/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/expertManage/experts/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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",
src/assets/images/certBg.jpg
src/assets/styles/font/fangzhengKT.ttf
Binary files differ
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()
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
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');
    });
}
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>
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>
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 = {
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(',')