Files
yudao-ui-admin-vue3/src/views/bpm/processInstance/detail/PrintDialog.vue

267 lines
9.0 KiB
Vue
Raw Normal View History

2025-09-02 17:04:31 +08:00
<script setup lang="ts">
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import { useUserStore } from '@/store/modules/user'
import { formatDate } from '@/utils/formatTime'
2025-09-04 09:16:29 +08:00
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
2025-09-06 10:37:41 +08:00
import { decodeFields, setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import formCreate from "@form-create/element-ui";
2025-09-02 17:04:31 +08:00
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'))
2025-09-04 09:16:29 +08:00
const formFields = ref()
const printDataMap = ref({})
2025-09-02 17:04:31 +08:00
2025-09-06 10:37:41 +08:00
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) => {
2025-09-02 17:04:31 +08:00
loading.value = true
try {
printData.value = await ProcessInstanceApi.getProcessInstancePrintData(id)
2025-09-04 09:16:29 +08:00
initPrintDataMap()
parseFormFields()
2025-09-02 17:04:31 +08:00
} finally {
loading.value = false
}
visible.value = true
}
defineExpose({ open })
2025-09-04 09:16:29 +08:00
const parseFormFields = () => {
2025-09-06 10:37:41 +08:00
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 生成么?好像也挺难的 = =
2025-09-04 09:16:29 +08:00
const formFieldsObj = decodeFields(printData.value.formFields)
2025-09-06 10:37:41 +08:00
const processVariables = printData.value.processInstance.formVariables
2025-09-04 09:16:29 +08:00
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']]
2025-09-06 10:37:41 +08:00
// TODO @芋艿感觉很多都要处理一下select那些都要转为可读的label还有子表单那些都需要处理一下...
2025-09-04 09:16:29 +08:00
if (item['type'] === 'input') {
html = processVariables[item['field']]
} else if (item['type'] === 'UploadImg') {
2025-09-04 09:16:29 +08:00
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 = () => {
2025-09-06 10:37:41 +08:00
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)
2025-09-04 09:16:29 +08:00
printDataMap.value['processStatus'] = getDictLabel(
DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
2025-09-06 10:37:41 +08:00
printData.value.processInstance.status
2025-09-04 09:16:29 +08:00
)
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
2025-09-04 09:16:29 +08:00
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')
2025-09-04 09:16:29 +08:00
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)
2025-09-06 10:37:41 +08:00
printData.value.tasks.forEach((item) => {
2025-09-04 09:16:29 +08:00
const tr = document.createElement('tr')
const td1 = document.createElement('td')
2025-09-06 10:37:41 +08:00
td1.innerHTML = item.name
2025-09-04 09:16:29 +08:00
const td2 = document.createElement('td')
2025-09-06 10:37:41 +08:00
td2.innerHTML = item.description
2025-09-04 09:16:29 +08:00
tr.appendChild(td1)
tr.appendChild(td2)
processRecordTable.appendChild(tr)
})
}
processRecords.forEach((item) => {
2025-09-04 09:16:29 +08:00
item.innerHTML = processRecordTable.outerHTML
})
// 返回 html
2025-09-04 09:16:29 +08:00
return doc.body.innerHTML
}
2025-09-06 10:37:41 +08:00
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)
}
2025-09-02 17:04:31 +08:00
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">
2025-09-04 09:16:29 +08:00
<div v-if="printData.printTemplateEnable" v-html="getPrintTemplateHTML()"></div>
2025-09-02 17:04:31 +08:00
<div v-else>
2025-09-06 10:37:41 +08:00
<h2 class="text-center">{{ printData.processInstance.name }}</h2>
2025-09-02 17:04:31 +08:00
<div class="text-right text-15px">{{ '打印人员: ' + userName }}</div>
<div class="flex justify-between">
2025-09-06 10:37:41 +08:00
<div class="text-15px">{{ '流程编号: ' + printData.processInstance.id }}</div>
2025-09-02 17:04:31 +08:00
<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>
2025-09-06 10:37:41 +08:00
<td class="p-5px w-25%">{{ printData.processInstance.startUser.nickname }}</td>
2025-09-02 17:04:31 +08:00
<td class="p-5px w-25%">发起时间</td>
2025-09-06 10:37:41 +08:00
<td class="p-5px w-25%">{{ formatDate(printData.processInstance.startTime) }}</td>
2025-09-02 17:04:31 +08:00
</tr>
<tr>
<td class="p-5px w-25%">所属部门</td>
2025-09-06 10:37:41 +08:00
<td class="p-5px w-25%">{{ printData.processInstance.startUser.deptName }}</td>
2025-09-02 17:04:31 +08:00
<td class="p-5px w-25%">流程状态</td>
2025-09-04 09:16:29 +08:00
<td class="p-5px w-25%">
2025-09-06 10:37:41 +08:00
{{
getDictLabel(
DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
printData.processInstance.status
)
}}
2025-09-04 09:16:29 +08:00
</td>
2025-09-02 17:04:31 +08:00
</tr>
<tr>
<td class="p-5px w-100% text-center" colspan="4">
<h4>表单内容</h4>
</td>
</tr>
2025-09-06 10:37:41 +08:00
<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"
/>
2025-09-02 17:04:31 +08:00
</td>
</tr>
<tr>
<td class="p-5px w-100% text-center" colspan="4">
<h4>流程节点</h4>
</td>
</tr>
2025-09-06 10:37:41 +08:00
<tr v-for="item in printData.tasks" :key="item.id">
2025-09-02 17:04:31 +08:00
<td class="p-5px w-20%">
2025-09-06 10:37:41 +08:00
{{ item.name }}
2025-09-02 17:04:31 +08:00
</td>
<td class="p-5px w-80%" colspan="3">
2025-09-06 10:37:41 +08:00
{{ item.description }}
2025-09-02 17:04:31 +08:00
<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">
2025-09-06 10:37:41 +08:00
<el-button @click="handleDialogOpened"> </el-button>
2025-09-02 17:04:31 +08:00
<el-button type="primary" v-print="printObj"> </el-button>
</div>
</template>
</el-dialog>
</template>