vue3中实现给pdf加盖公章(手动拖拽公章确认位置)

开发项目时,碰到了一个这样的需求:需要前端从服务器获取到一个pdf文件,然后用户通过手动拖拽公章的方式确认公章应该加盖的位置,然后将位置信息传递给服务器。代码并不是非常完美,仅供大家参考。

引用的两个包版本为

js 复制代码
"vue-pdf-embed": "^1.1.5",
"vue3-pdfjs": "^0.1.6",

全部代码实现如下:(为了方便大家查看效果,pdf由用户手动上传得到)

javascript 复制代码
<template>
  <div>
    <!-- 本地上传一个pdf文件用于测试 -->
    <input type="file" id="file-input" multiple  />

    <div style="position: relative; margin: 0 auto">
      <div class="control">
        <span>共{{ numPages }}页</span>
        <el-pagination
          v-model:current-page="pageNum"
          :page-size="1"
          background
          layout="prev, pager, next, jumper"
          :total="numPages"
        />
      </div>
      <div class="all" id="wrap">
        <!-- 给拖拽存放区添加拖拽存放区事件 -->
        <div class="drag" @drop="drop" @dragover.prevent ref="vuepdf">
          <vue-pdf-embed
            :source="source"
            class="vue-pdf-embed"
            width="700"
            :style="scaleFun"
            :page="pageNum"
          />
          <div
            :class="['box', item.selectName]"
            @mousedown="move($event, item)"
            @contextmenu.prevent="deleteModel(index)"
            @click="getModel(item)"
            v-for="(item, index) in dropData"
            :key="index"
            :style="{ left: item.left + 'px', top: item.top + 'px' }"
          >
            {{ item.name }}
            {{ item.model }}
          </div>
        </div>
      </div>
    </div>
    <div>
      <el-button
        type="success"
        draggable="true"
        @dragstart="dragstart($event, item)"
        @dragend="dragend"
        v-for="(item, index) in dragList"
        :key="index"
        >盖章</el-button
      >
      <el-button type="primary" @click="submit">保存</el-button>
      <p>请拖拽《盖章》按钮到合同区域,然后移动公章至合适位置,点击《保存》后盖章成功。</p>
    </div>
  </div>
</template>

<script setup>
/**
 *@date: 2024-08-16
 *@description: 合同签署-签章
 **/
import VuePdfEmbed from 'vue-pdf-embed'
import { createLoadingTask } from 'vue3-pdfjs/esm' // 获得总页数
import { getCurrentInstance, ref, computed, onMounted } from 'vue'
import { ElButton } from 'element-plus'

const { proxy } = getCurrentInstance()

let dropData = ref([])
let dragList = ref([
  {
    name: '公章处1',
    width: 50,
    height: 50,
    left: 0,
    top: 0,
    type: 4,
    model: ''
  }
])

let currentItem = ref({})
let x = ref('')
let y = ref('')
let height = ref(0)

// 内部移动事件
const move = (e, item) => {
  const odiv = e.target
  const disX = e.clientX - odiv.offsetLeft
  const disY = e.clientY - odiv.offsetTop
  document.onmousemove = (e) => {
    let left = e.clientX - disX
    let top = e.clientY - disY
    if (top <= 0) {
      top = 0
    }
    if (top >= height.value - 100) {
      top = height.value - 100
    }
    if (left >= 700 - 100) {
      left = 700 - 100
    }
    if (left <= 0) {
      left = 0
    }
    // 拖拽位置设定
    item.left = left
    item.top = top
    // 获取位置
    // 500 容器高度 50 印章一半距离
    x.value = left + 50
    y.value = top + 50
  }
  document.onmouseup = (e) => {
    document.onmousemove = null
    document.onmouseup = null
  }
}
const dragstart = (e, item) => {
  e.dataTransfer.setData('item', JSON.stringify(item))
  if (height.value === 0) {
    height.value = proxy.$refs['vuepdf'].offsetHeight
  }
}
const dragend = (e) => {
  e.dataTransfer.clearData()
}
// 拖拽事件,获取参数
const drop = (e) => {
  // 获取拖拽对象的参数
  let data = e.dataTransfer.getData('item')
  data = JSON.parse(data)
  // 鼠标落点位置相对于当前拖拽存放地的 x y
  data.left = e.layerX - 50
  data.top = e.layerY - 50
  // data.top = document.querySelector("#wrap").scrollTop;
  // 存放到当前拖拽对象生成的列表中
  // dropData.value.push(data)
  dropData.value[0] = data //只允许存在一个公章,每次拖拽后都顶替掉第一个章
}
const deleteModel = (index) => {
  dropData.value.splice(index, 1)
}
// 获取参数
const getModel = (item) => {
  dropData.value = dropData.value.map((item) => {
    item.selectName = ''
    return item
  })
  item.selectName = 'select'
  currentItem.value = item
}

//合同初始化,页数
let source = ref('')
let scale = ref(1)
let pageNum = ref(1)
let numPages = ref(0)
const scaleFun = computed(() => {
  return `transform:scale(${scale.value})`
})

const submit = () => {
  console.log(x.value, y.value)
}

const init = () => {
  document.getElementById('file-input').addEventListener('change', function (e) {
    let fileList = e.target.files
    let file = fileList[0]
    source.value = URL.createObjectURL(file)
    //获取pdf总页数
    const loadingTask = createLoadingTask(source.value)
    loadingTask.promise.then((pdf) => {
      numPages.value = pdf.numPages
    })
  })
}

onMounted(() => {
  init()
})
</script>

<style lang="scss" scoped>
.div {
  bottom: 20px;
  position: absolute;
  left: 50%;
  margin-left: -152px;
}
.vue-pdf-embed {
  text-align: center;
}
.all {
  overflow-y: scroll;
  height: 650px;
}
.drag {
  overflow: hidden;
  width: 700px;
  height: auto;
  margin: 0 auto;
  position: relative;
  .box {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-size: 100% 100%;
    border: 3px solid red;
    user-select: none;
    cursor: pointer;
    text-align: center;
    line-height: 94px;
    color: red;
    font-weight: bolder;
  }
  .select {
    border-color: red;
  }
}
p {
  font-size: 13px;
  color: red;
  margin: 2px 0 0 0;
}
.control {
  display: flex;
  justify-content: center;
  span {
    line-height: 36px;
  }
}
</style>
相关推荐
AirDroid_cn3 小时前
PDF转图片需要用到什么技术?苹果手机怎样将PDF转为jpg?
pdf·iphone·ipad·快捷指令
拓端研究室10 小时前
专题:2025全球消费趋势与中国市场洞察报告|附300+份报告PDF、原数据表汇总下载
大数据·信息可视化·pdf
Kyln.Wu2 天前
【python实用小脚本-190】Python一键删除PDF任意页:输入页码秒出干净文件——再也不用在线裁剪排队
服务器·python·pdf
阿幸软件杂货间2 天前
免费万能电子书格式转换器!Neat Converter支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的相互转换。
pdf·格式转换
星马梦缘3 天前
CSDN转PDF【无水印且免费!!!】
pdf·免费·pandoc·转pdf·无水印·csdn转pdf·wkhtmlpdf
画月的亮3 天前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf
伊织code4 天前
pdfminer.six
python·pdf·图片·提取·文本·pdfminer·pdfminer.six
HAPPY酷4 天前
给纯小白的Python操作 PDF 笔记
开发语言·python·pdf
代码AI弗森5 天前
PDF OCR + 大模型:让文档理解不止停留在识字
pdf·ocr
小周同学:6 天前
在 Vue2 中使用 pdf.js + pdf-lib 实现 PDF 预览、手写签名、文字批注与高保真导出
开发语言·前端·javascript·vue.js·pdf