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>
相关推荐
面包资料屋14 小时前
整理了 2009 - 2025 年的【199 管综真题 + 解析】PDF,全套共 34 份文件
开发语言·javascript·pdf
yk 坤帝15 小时前
用Python将 PDF 中的表格提取为 Excel/CSV
python·pdf·excel
赱向远方18 小时前
【软件推荐——pdf2docx】
python·pdf·开源软件·docx·软件推荐·doc·pdf2docx
IDRSolutions_CN18 小时前
PDF 合并测试:性能与内容完整性
java·经验分享·pdf·软件工程·团队开发
helloworld工程师18 小时前
Java实现PDF加水印功能:技术解析与实践指南
java·开发语言·pdf
__ocean20 小时前
编译Qt5.15.16并启用pdf模块
开发语言·qt·pdf
三少的笔记1 天前
Windows中PDF TXT Excel Word PPT等Office文件在预览窗格无法预览的终级解决方法大全
pdf·word·excel
SEO-狼术1 天前
Easily Add Pages to PDF Documents
pdf
weixin_628993851 天前
批量处理+权限加密编辑转换压缩全功能提升PDF管理效率
pdf·电脑·软件构建·开源软件
大强同学2 天前
Adobe DC 2025安装教程
windows·adobe·pdf