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

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

"vue-pdf-embed": "^1.1.5",
"vue3-pdfjs": "^0.1.6",

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

<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>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值