Files
yudao-ui-admin-vue3/src/views/bpm/processInstance/detail/PrintDialog.vue
2025-09-06 10:37:41 +08:00

267 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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, setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import formCreate from "@form-create/element-ui";
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 fApi = ref<ApiAttrs>()
const detailForm = ref({
rule: [],
option: {},
value: {}
})
const fApiH = ref<ApiAttrs>()
const detailFormH = ref({
rule: [],
option: {},
value: {}
})
const fcRef = 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 = () => {
const processInstance = printData.value.processInstance
const processDefinition = processInstance.processDefinition
setConfAndFields2(
detailForm,
processDefinition.formConf,
processDefinition.formFields,
processInstance.formVariables
)
detailForm.value.option = {
submitBtn: false,
resetBtn: false,
form: {
disabled: true
}
}
setConfAndFields2(
detailFormH,
processDefinition.formConf,
processDefinition.formFields,
processInstance.formVariables
)
detailFormH.value.option = {
submitBtn: false,
resetBtn: false,
form: {
disabled: true
}
}
return
// TODO @lesanform field 有可能基于 form-create 什么 api 生成么?好像也挺难的 = =
const formFieldsObj = decodeFields(printData.value.formFields)
const processVariables = printData.value.processInstance.formVariables
let res: any = []
for (const item of formFieldsObj) {
const id = item['field']
const name = item['title']
let html = '暂不支持此类型的表单展示'
// TODO 完善各类型表单的展示
// TODO @lesan要不 UploadImg、UploadFile 特殊处理下,其它就 else processVariables[item['field']]
// TODO @芋艿感觉很多都要处理一下select那些都要转为可读的label还有子表单那些都需要处理一下...
if (item['type'] === 'input') {
html = processVariables[item['field']]
} else if (item['type'] === 'UploadImg') {
html = `<img src="${processVariables[item['field']]}" style="max-width: 600px" />`
}
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['printUsername'] = 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 html = ref('')
const handleDialogOpened = async () => {
const processInstance = printData.value.processInstance
const processDefinition = processInstance.processDefinition
let fcData = {
rule: [],
option: {},
value: {}
}
setConfAndFields2(
fcData,
processDefinition.formConf,
processDefinition.formFields,
processInstance.formVariables
)
const api = formCreate.create(fcData.rule,fcData.option)
console.log(api)
}
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">
<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>
<td class="p-5px w-100% text-center" colspan="4">
<form-create
v-model="detailForm.value"
v-model:api="fApi"
:option="detailForm.option"
:rule="detailForm.rule"
/>
</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.signUrl !== ''">
<img class="w-90px h-40px" :src="item.signUrl" alt="" />
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleDialogOpened"> </el-button>
<el-button type="primary" v-print="printObj"> </el-button>
</div>
</template>
</el-dialog>
</template>