From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/bpm/processInstance/detail/PrintDialog.vue |  234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/src/views/bpm/processInstance/detail/PrintDialog.vue b/src/views/bpm/processInstance/detail/PrintDialog.vue
new file mode 100644
index 0000000..fb8cd8b
--- /dev/null
+++ b/src/views/bpm/processInstance/detail/PrintDialog.vue
@@ -0,0 +1,234 @@
+<script setup lang="ts">
+import * as ProcessInstanceApi from '@/api/bpm/processInstance'
+import { useUserStore } from '@/store/modules/user'
+import { formatDate } from '@/utils/formatTime'
+import { DICT_TYPE, getDictLabel } from '@/utils/dict'
+import { decodeFields } from '@/utils/formCreate'
+
+const userStore = useUserStore()
+
+const visible = ref(false)
+const loading = ref(false)
+
+const printData = ref()
+const userName = computed(() => userStore.user.nickname ?? '')
+const printTime = ref(formatDate(new Date(), 'YYYY-MM-DD HH:mm'))
+const formFields = ref()
+const printDataMap = ref({})
+
+const open = async (id: string) => {
+  loading.value = true
+  try {
+    printData.value = await ProcessInstanceApi.getProcessInstancePrintData(id)
+    initPrintDataMap()
+    parseFormFields()
+  } finally {
+    loading.value = false
+  }
+  visible.value = true
+}
+defineExpose({ open })
+
+const parseFormFields = () => {
+  if (!printData.value) return
+
+  const formFieldsObj = decodeFields(
+    printData.value.processInstance.processDefinition?.formFields || []
+  )
+  const processVariables = printData.value.processInstance.formVariables
+  let res: any = []
+  for (const item of formFieldsObj) {
+    const id = item['field']
+    const name = item['title']
+    const variable = processVariables[item['field']]
+    let html = variable
+    switch (item['type']) {
+      case 'UploadImg': {
+        let imgEl = document.createElement('img')
+        imgEl.setAttribute('src', variable)
+        imgEl.setAttribute('style', 'max-width: 600px;')
+        html = imgEl.outerHTML
+        break
+      }
+      case 'radio':
+      case 'checkbox':
+      case 'select': {
+        const options = item['options'] || []
+        const temp: any = []
+        if (Array.isArray(variable)) {
+          const labels = options.filter((o) => variable.includes(o.value)).map((o) => o.label)
+          temp.push(...labels)
+        } else {
+          const opt = options.find((o) => o.value === variable)
+          temp.push(opt.label)
+        }
+        html = temp.join(',')
+      }
+      // TODO 鏇村琛ㄥ崟鎵撳嵃灞曠ず
+    }
+    printDataMap.value[item['field']] = html
+    res.push({ id, name, html })
+  }
+  formFields.value = res
+}
+
+const initPrintDataMap = () => {
+  printDataMap.value['startUser'] = printData.value.processInstance.startUser.nickname
+  printDataMap.value['startUserDept'] = printData.value.processInstance.startUser.deptName
+  printDataMap.value['processName'] = printData.value.processInstance.name
+  printDataMap.value['processNum'] = printData.value.processInstance.id
+  printDataMap.value['startTime'] = formatDate(printData.value.processInstance.startTime)
+  printDataMap.value['endTime'] = formatDate(printData.value.processInstance.endTime)
+  printDataMap.value['processStatus'] = getDictLabel(
+    DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
+    printData.value.processInstance.status
+  )
+  printDataMap.value['printUser'] = userName.value
+  printDataMap.value['printTime'] = printTime.value
+}
+
+const getPrintTemplateHTML = () => {
+  const parser = new DOMParser()
+  let doc = parser.parseFromString(printData.value.printTemplateHtml, 'text/html')
+  // table 娣诲姞border
+  let tables = doc.querySelectorAll('table')
+  tables.forEach((item) => {
+    item.setAttribute('border', '1')
+    item.setAttribute('style', (item.getAttribute('style') || '') + 'border-collapse:collapse;')
+  })
+  // 鏇挎崲 mentions
+  let mentions = doc.querySelectorAll('[data-w-e-type="mention"]')
+  mentions.forEach((item) => {
+    const mentionId = JSON.parse(decodeURIComponent(item.getAttribute('data-info') ?? ''))['id']
+    item.innerHTML = printDataMap.value[mentionId] ?? ''
+  })
+  // 鏇挎崲娴佺▼璁板綍
+  let processRecords = doc.querySelectorAll('[data-w-e-type="process-record"]')
+  let processRecordTable: Element = document.createElement('table')
+  if (processRecords.length > 0) {
+    // 鏋勫缓娴佺▼璁板綍html
+    processRecordTable.setAttribute('border', '1')
+    processRecordTable.setAttribute('style', 'width:100%;border-collapse:collapse;')
+    const headTr = document.createElement('tr')
+    const headTd = document.createElement('td')
+    headTd.setAttribute('colspan', '2')
+    headTd.setAttribute('width', 'auto')
+    headTd.setAttribute('style', 'text-align: center;')
+    headTd.innerHTML = '娴佺▼鑺傜偣'
+    headTr.appendChild(headTd)
+    processRecordTable.appendChild(headTr)
+    printData.value.tasks.forEach((item) => {
+      const tr = document.createElement('tr')
+      const td1 = document.createElement('td')
+      td1.innerHTML = item.name
+      const td2 = document.createElement('td')
+      td2.innerHTML = item.description
+      tr.appendChild(td1)
+      tr.appendChild(td2)
+      processRecordTable.appendChild(tr)
+    })
+  }
+  processRecords.forEach((item) => {
+    item.innerHTML = processRecordTable.outerHTML
+  })
+  // 杩斿洖 html
+  return doc.body.innerHTML
+}
+
+const printObj = ref({
+  id: 'printDivTag',
+  popTitle: '&nbsp',
+  extraCss: '/print.css',
+  extraHead: '',
+  zIndex: 20003
+})
+</script>
+
+<template>
+  <el-dialog v-loading="loading" v-model="visible" :show-close="false">
+    <div id="printDivTag" style="word-break: break-all">
+      <div v-if="printData.printTemplateEnable" v-html="getPrintTemplateHTML()"></div>
+      <div v-else>
+        <h2 class="text-center">{{ printData.processInstance.name }}</h2>
+        <div class="text-right text-15px">{{ '鎵撳嵃浜哄憳: ' + userName }}</div>
+        <div class="flex justify-between">
+          <div class="text-15px">{{ '娴佺▼缂栧彿: ' + printData.processInstance.id }}</div>
+          <div class="text-15px">{{ '鎵撳嵃鏃堕棿: ' + printTime }}</div>
+        </div>
+        <table class="mt-20px w-100%" border="1" style="border-collapse: collapse">
+          <tbody>
+            <tr>
+              <td class="p-5px w-25%">鍙戣捣浜�</td>
+              <td class="p-5px w-25%">{{ printData.processInstance.startUser.nickname }}</td>
+              <td class="p-5px w-25%">鍙戣捣鏃堕棿</td>
+              <td class="p-5px w-25%">{{ formatDate(printData.processInstance.startTime) }}</td>
+            </tr>
+            <tr>
+              <td class="p-5px w-25%">鎵�灞為儴闂�</td>
+              <td class="p-5px w-25%">{{ printData.processInstance.startUser.deptName }}</td>
+              <td class="p-5px w-25%">娴佺▼鐘舵��</td>
+              <td class="p-5px w-25%">
+                {{
+                  getDictLabel(
+                    DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
+                    printData.processInstance.status
+                  )
+                }}
+              </td>
+            </tr>
+            <tr>
+              <td class="p-5px w-100% text-center" colspan="4">
+                <h4>琛ㄥ崟鍐呭</h4>
+              </td>
+            </tr>
+            <tr v-for="item in formFields" :key="item.id">
+              <td class="p-5px w-20%">
+                {{ item.name }}
+              </td>
+              <td class="p-5px w-80%" colspan="3">
+                <div v-html="item.html"></div>
+              </td>
+            </tr>
+            <tr>
+              <td class="p-5px w-100% text-center" colspan="4">
+                <h4>娴佺▼鑺傜偣</h4>
+              </td>
+            </tr>
+            <tr v-for="item in printData.tasks" :key="item.id">
+              <td class="p-5px w-20%">
+                {{ item.name }}
+              </td>
+              <td class="p-5px w-80%" colspan="3">
+                {{ item.description }}
+                <div v-if="item.signPicUrl && item.signPicUrl.length > 0">
+                  <img class="w-90px h-40px" :src="item.signPicUrl" alt="" />
+                </div>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="visible = false">鍙� 娑�</el-button>
+        <el-button type="primary" v-print="printObj"> 鎵� 鍗�</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<style>
+/* 淇鎵撳嵃鍙樉绀轰竴椤� */
+@media print {
+  @page {
+    size: auto;
+  }
+
+  body,
+  html,
+  div {
+    height: auto !important;
+  }
+}
+</style>

--
Gitblit v1.8.0