review:【bpm 工作流】流程打印

This commit is contained in:
YunaiV
2025-09-03 13:25:05 +08:00
parent 1c6e6eb24e
commit be964a6287
13 changed files with 139 additions and 126 deletions

View File

@ -42,8 +42,8 @@ import Logger from '@/utils/Logger'
import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患 import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患
// wangeditor插件注册 // wangeditor 插件注册
import {setupWangeditorPlugin} from "@/views/bpm/model/form/PrintTemplate"; import { setupWangeditorPlugin } from '@/views/bpm/model/form/PrintTemplate'
import print from 'vue3-print-nb' // 打印插件 import print from 'vue3-print-nb' // 打印插件
@ -67,12 +67,14 @@ const setupAll = async () => {
setupAuth(app) setupAuth(app)
setupMountedFocus(app) setupMountedFocus(app)
// wangeditor 插件注册
setupWangeditorPlugin() setupWangeditorPlugin()
await router.isReady() await router.isReady()
app.use(VueDOMPurifyHTML) app.use(VueDOMPurifyHTML)
// 打印
app.use(print) app.use(print)
app.mount('#app') app.mount('#app')

View File

@ -254,7 +254,7 @@
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
<print-template ref="printTemplateRef" @confirm="confirmPrintTemplate"/> <print-template ref="printTemplateRef" @confirm="confirmPrintTemplate" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -491,8 +491,9 @@ watch(
{ immediate: true } { immediate: true }
) )
// TODO defaultTemplate 是否需要放到 infra_config // TODO defaultTemplate 是否需要放到 infra_config TODO @lesan就先 default 这里好了。
const defaultTemplate = '<p style="text-align: center;"><span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="流程名称" data-info="%7B%22id%22%3A%22processName%22%7D">@流程名称</span></p><p style="text-align: right;">打印人:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="打印人" data-info="%7B%22id%22%3A%22printUser%22%7D">@打印人</span></p><p style="text-align: right;">流程编号:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="流程编号" data-info="%7B%22id%22%3A%22processNum%22%7D">@流程编号</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;打印时间:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="打印时间" data-info="%7B%22id%22%3A%22printTime%22%7D">@打印时间</span></p><table style="width: 100%;"><tbody><tr><td colSpan="1" rowSpan="1" width="auto">发起人</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起人" data-info="%7B%22id%22%3A%22startUser%22%7D">@发起人</span></td><td colSpan="1" rowSpan="1" width="auto">发起时间</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起时间" data-info="%7B%22id%22%3A%22startTime%22%7D">@发起时间</span></td></tr><tr><td colSpan="1" rowSpan="1" width="auto">所属部门</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起人部门" data-info="%7B%22id%22%3A%22startUserDept%22%7D">@发起人部门</span></td><td colSpan="1" rowSpan="1" width="auto">流程状态</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="流程状态" data-info="%7B%22id%22%3A%22processStatus%22%7D">@流程状态</span></td></tr></tbody></table><p><span data-w-e-type="process-record" data-w-e-is-void data-w-e-is-inline>流程记录</span></p>' const defaultTemplate =
'<p style="text-align: center;"><span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="流程名称" data-info="%7B%22id%22%3A%22processName%22%7D">@流程名称</span></p><p style="text-align: right;">打印人:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="打印人" data-info="%7B%22id%22%3A%22printUser%22%7D">@打印人</span></p><p style="text-align: right;">流程编号:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="流程编号" data-info="%7B%22id%22%3A%22processNum%22%7D">@流程编号</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;打印时间:<span data-w-e-type="mention" data-w-e-is-void="" data-w-e-is-inline="" data-value="打印时间" data-info="%7B%22id%22%3A%22printTime%22%7D">@打印时间</span></p><table style="width: 100%;"><tbody><tr><td colSpan="1" rowSpan="1" width="auto">发起人</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起人" data-info="%7B%22id%22%3A%22startUser%22%7D">@发起人</span></td><td colSpan="1" rowSpan="1" width="auto">发起时间</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起时间" data-info="%7B%22id%22%3A%22startTime%22%7D">@发起时间</span></td></tr><tr><td colSpan="1" rowSpan="1" width="auto">所属部门</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="发起人部门" data-info="%7B%22id%22%3A%22startUserDept%22%7D">@发起人部门</span></td><td colSpan="1" rowSpan="1" width="auto">流程状态</td><td colSpan="1" rowSpan="1" width="auto"><span data-w-e-type="mention" data-w-e-is-void data-w-e-is-inline data-value="流程状态" data-info="%7B%22id%22%3A%22processStatus%22%7D">@流程状态</span></td></tr></tbody></table><p><span data-w-e-type="process-record" data-w-e-is-void data-w-e-is-inline>流程记录</span></p>'
const handlePrintTemplateEnableChange = (val: boolean) => { const handlePrintTemplateEnableChange = (val: boolean) => {
if (val) { if (val) {
if (!modelData.value.printTemplateSetting.template) { if (!modelData.value.printTemplateSetting.template) {
@ -504,7 +505,7 @@ const printTemplateRef = ref()
const handleEditPrintTemplate = () => { const handleEditPrintTemplate = () => {
printTemplateRef.value.open(modelData.value.printTemplateSetting.template) printTemplateRef.value.open(modelData.value.printTemplateSetting.template)
} }
const confirmPrintTemplate = (template) => { const confirmPrintTemplate = (template: any) => {
modelData.value.printTemplateSetting.template = template modelData.value.printTemplateSetting.template = template
} }
</script> </script>

View File

@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import {Editor, Toolbar} from '@wangeditor/editor-for-vue' import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import {IDomEditor} from '@wangeditor/editor' import { IDomEditor } from '@wangeditor/editor'
import MentionModal from "./MentionModal.vue"; import MentionModal from './MentionModal.vue'
const emit = defineEmits(['confirm']) const emit = defineEmits(['confirm'])
// mention // @mention 相关
const isShowModal = ref(false) const isShowModal = ref(false)
const showModal = () => { const showModal = () => {
isShowModal.value = true isShowModal.value = true
@ -13,12 +13,12 @@ const showModal = () => {
const hideModal = () => { const hideModal = () => {
isShowModal.value = false isShowModal.value = false
} }
const insertMention = (id, name) => { const insertMention = (id: any, name: any) => {
const mentionNode = { const mentionNode = {
type: 'mention', type: 'mention',
value: name, value: name,
info: {id}, info: { id },
children: [{text: ''}], children: [{ text: '' }]
} }
const editor = editorRef.value const editor = editorRef.value
if (editor) { if (editor) {
@ -29,20 +29,19 @@ const insertMention = (id, name) => {
} }
} }
// Dialog // Dialog 相关
const dialogVisible = ref(false) const dialogVisible = ref(false)
const open = async (template) => { const open = async (template: string) => {
dialogVisible.value = true dialogVisible.value = true
valueHtml.value = template valueHtml.value = template
console.log(template)
} }
defineExpose({open}) defineExpose({ open })
const handleConfirm = () => { const handleConfirm = () => {
emit('confirm', valueHtml.value) emit('confirm', valueHtml.value)
dialogVisible.value = false dialogVisible.value = false
} }
// Editor // Editor 相关
const editorRef = shallowRef<IDomEditor>() const editorRef = shallowRef<IDomEditor>()
const editorId = ref('wangeEditor-1') const editorId = ref('wangeEditor-1')
const toolbarConfig = { const toolbarConfig = {
@ -57,41 +56,45 @@ const editorConfig = {
EXTEND_CONF: { EXTEND_CONF: {
mentionConfig: { mentionConfig: {
showModal, showModal,
hideModal, hideModal
}, }
}, }
} }
const valueHtml = ref() const valueHtml = ref()
const handleCreated = (editor: IDomEditor) => { const handleCreated = (editor: IDomEditor) => {
editorRef.value = editor editorRef.value = editor
} }
// onBeforeUnmount /** 初始化 */
onBeforeUnmount(() => { onBeforeUnmount(() => {
const editor = editorRef.value const editor = editorRef.value
if (editor == null) return if (editor == null) {
return
}
editor.destroy() editor.destroy()
}) })
</script> </script>
<template> <template>
<el-dialog v-model="dialogVisible" title="自定义模板" fullscreen> <el-dialog v-model="dialogVisible" title="自定义模板" fullscreen>
<div style="margin: 0 10px;"> <div style="margin: 0 10px">
<el-alert <el-alert
title="输入 @ 可选择插入流程表单选项和默认选项" title="输入 @ 可选择插入流程表单选项和默认选项"
type="info" type="info"
show-icon show-icon
:closable="false"/> :closable="false"
/>
</div> </div>
<div style="border: 1px solid #ccc;margin: 10px;"> <!-- TODO @unocss 简化 style -->
<div style="border: 1px solid #ccc; margin: 10px">
<Toolbar <Toolbar
style="border-bottom: 1px solid #ccc;" style="border-bottom: 1px solid #ccc"
:editor="editorRef" :editor="editorRef"
:editorId="editorId" :editorId="editorId"
:defaultConfig="toolbarConfig" :defaultConfig="toolbarConfig"
/> />
<Editor <Editor
style="height: 500px; overflow-y: hidden;" style="height: 500px; overflow-y: hidden"
v-model="valueHtml" v-model="valueHtml"
:defaultConfig="editorConfig" :defaultConfig="editorConfig"
:editorId="editorId" :editorId="editorId"
@ -100,9 +103,10 @@ onBeforeUnmount(() => {
<MentionModal <MentionModal
v-if="isShowModal" v-if="isShowModal"
@hide-mention-modal="hideModal" @hide-mention-modal="hideModal"
@insert-mention="insertMention"/> @insert-mention="insertMention"
/>
</div> </div>
<div style="margin-right: 10px;float: right;"> <div style="margin-right: 10px; float: right">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleConfirm"> </el-button> <el-button type="primary" @click="handleConfirm"> </el-button>
</div> </div>

View File

@ -6,47 +6,48 @@ const top = ref('')
const left = ref('') const left = ref('')
const searchVal = ref('') const searchVal = ref('')
const list = ref([ const list = ref([
{id: 'startUser', name: '发起人'}, { id: 'startUser', name: '发起人' },
{id: 'startUserDept', name: '发起人部门'}, { id: 'startUserDept', name: '发起人部门' },
{id: 'processName', name: '流程名称'}, { id: 'processName', name: '流程名称' },
{id: 'processNum', name: '流程编号'}, { id: 'processNum', name: '流程编号' },
{id: 'startTime', name: '发起时间'}, { id: 'startTime', name: '发起时间' },
{id: 'endTime', name: '发起时间'}, { id: 'endTime', name: '发起时间' },
{id: 'processStatus', name: '流程状态'}, { id: 'processStatus', name: '流程状态' },
{id: 'processResult', name: '流程结果'}, { id: 'processResult', name: '流程结果' },
{id: 'printUser', name: '打印人'}, { id: 'printUser', name: '打印人' },
{id: 'printTime', name: '打印时间'}, { id: 'printTime', name: '打印时间' }
]) ])
const searchedList = computed(() => { const searchedList = computed(() => {
const searchValStr = searchVal.value.trim().toLowerCase() const searchValStr = searchVal.value.trim().toLowerCase()
return list.value.filter(item => { return list.value.filter((item) => {
const name = item.name.toLowerCase() const name = item.name.toLowerCase()
return name.indexOf(searchValStr) >= 0; return name.indexOf(searchValStr) >= 0
}) })
}) })
const inputKeyupHandler = (event) => { const inputKeyupHandler = (event: any) => {
if (event.key === 'Escape') { if (event.key === 'Escape') {
emit('hideMentionModal') emit('hideMentionModal')
} }
if (event.key === 'Enter') { if (event.key === 'Enter') {
const firstOne = searchedList.value[0] const firstOne = searchedList.value[0]
if (firstOne) { if (firstOne) {
const {id, name} = firstOne const { id, name } = firstOne
insertMentionHandler(id, name) insertMentionHandler(id, name)
} }
} }
} }
const insertMentionHandler = (id, name) => { const insertMentionHandler = (id: any, name: any) => {
emit('insertMention', id, name) emit('insertMention', id, name)
emit('hideMentionModal') emit('hideMentionModal')
} }
const formFields = inject('formFieldsObj') const formFields = inject('formFieldsObj')
onMounted(()=> { onMounted(() => {
// TODO @lesan这里 idea 会爆红,看看能不能处理下;
if (formFields.value && formFields.value.length > 0) { if (formFields.value && formFields.value.length > 0) {
const cloneFormField = formFields.value.map((item) => { const cloneFormField = formFields.value.map((item) => {
return { return {
name: '[表单]'+item.title, name: '[表单]' + item.title,
id: item.field id: item.field
} }
}) })
@ -66,13 +67,15 @@ onMounted(()=> {
<template> <template>
<div id="mention-modal" :style="{ top: top, left: left }"> <div id="mention-modal" :style="{ top: top, left: left }">
<!-- TODO @lesancss 可以用 unocss -->
<input id="mention-input" v-model="searchVal" ref="inputRef" @keyup="inputKeyupHandler" /> <input id="mention-input" v-model="searchVal" ref="inputRef" @keyup="inputKeyupHandler" />
<ul id="mention-list"> <ul id="mention-list">
<li <li
v-for="item in searchedList" v-for="item in searchedList"
:key="item.id" :key="item.id"
@click="insertMentionHandler(item.id, item.name)" @click="insertMentionHandler(item.id, item.name)"
>{{ item.name }} >
{{ item.name }}
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -1,8 +1,9 @@
import {Boot} from '@wangeditor/editor' import { Boot } from '@wangeditor/editor'
import processRecordModule from "./module"; import processRecordModule from './module'
import mentionModule from "@wangeditor/plugin-mention"; import mentionModule from '@wangeditor/plugin-mention'
// 注册要在创建编辑器之前注册,且只能注册一次,不可重复注册 // 注册要在创建编辑器之前注册,且只能注册一次,不可重复注册
// TODO @lesanWangEditor 拼写
export const setupWangeditorPlugin = () => { export const setupWangeditorPlugin = () => {
Boot.registerModule(processRecordModule) Boot.registerModule(processRecordModule)
Boot.registerModule(mentionModule) Boot.registerModule(mentionModule)

View File

@ -1,12 +1,12 @@
import { SlateElement } from '@wangeditor/editor' import { SlateElement } from '@wangeditor/editor'
function processRecordToHtml(elem: SlateElement, childrenHtml: string): string { function processRecordToHtml(_elem: SlateElement, _childrenHtml: string): string {
return `<span data-w-e-type="process-record" data-w-e-is-void data-w-e-is-inline>流程记录</span>` return `<span data-w-e-type="process-record" data-w-e-is-void data-w-e-is-inline>流程记录</span>`
} }
const conf = { const conf = {
type: 'process-record', type: 'process-record',
elemToHtml: processRecordToHtml, elemToHtml: processRecordToHtml
} }
export default conf export default conf

View File

@ -1,16 +1,17 @@
import {IModuleConf} from '@wangeditor/editor' import { IModuleConf } from '@wangeditor/editor'
import withProcessRecord from './plugin' import withProcessRecord from './plugin'
import renderElemConf from './render-elem' import renderElemConf from './render-elem'
import elemToHtmlConf from './elem-to-html' import elemToHtmlConf from './elem-to-html'
import parseHtmlConf from './parse-elem-html' import parseHtmlConf from './parse-elem-html'
import processRecordMenu from "./menu/ProcessRecordMenu" import processRecordMenu from './menu/ProcessRecordMenu'
// TODO @lesanPrintTemplate 是参考了哪些文档哇?要不要在 index.ts 稍微写点注释,方便大家理解;
const module: Partial<IModuleConf> = { const module: Partial<IModuleConf> = {
editorPlugin: withProcessRecord, editorPlugin: withProcessRecord,
renderElems: [renderElemConf], renderElems: [renderElemConf],
elemsToHtml: [elemToHtmlConf], elemsToHtml: [elemToHtmlConf],
parseElemsHtml: [parseHtmlConf], parseElemsHtml: [parseHtmlConf],
menus: [processRecordMenu], menus: [processRecordMenu]
} }
export default module export default module

View File

@ -1,31 +1,31 @@
import { IButtonMenu, IDomEditor } from '@wangeditor/editor' import { IButtonMenu, IDomEditor } from '@wangeditor/editor'
class ProcessRecordMenu implements IButtonMenu { class ProcessRecordMenu implements IButtonMenu {
readonly tag: string; readonly tag: string
readonly title: string; readonly title: string
constructor() { constructor() {
this.title = '流程记录' this.title = '流程记录'
this.tag = 'button' this.tag = 'button'
} }
getValue(editor: IDomEditor): string { getValue(_editor: IDomEditor): string {
return '' return ''
} }
isActive(editor: IDomEditor): boolean { isActive(_editor: IDomEditor): boolean {
return false return false
} }
isDisabled(editor: IDomEditor): boolean { isDisabled(_editor: IDomEditor): boolean {
return false return false
} }
exec(editor: IDomEditor, value: string) { exec(editor: IDomEditor, _value: string) {
if (this.isDisabled(editor)) return if (this.isDisabled(editor)) return
const processRecordElem = { const processRecordElem = {
type: 'process-record', type: 'process-record',
children: [{ text: '' }], children: [{ text: '' }]
} }
editor.insertNode(processRecordElem) editor.insertNode(processRecordElem)
editor.move(1) editor.move(1)

View File

@ -2,19 +2,20 @@ import { DOMElement } from './utils/dom'
import { IDomEditor, SlateDescendant, SlateElement } from '@wangeditor/editor' import { IDomEditor, SlateDescendant, SlateElement } from '@wangeditor/editor'
function parseHtml( function parseHtml(
elem: DOMElement, _elem: DOMElement,
children: SlateDescendant[], _children: SlateDescendant[],
editor: IDomEditor _editor: IDomEditor
): SlateElement { ): SlateElement {
return { return {
// TODO @lesan这里有个红色告警可以去掉哇
type: 'process-record', type: 'process-record',
children: [{ text: '' }], children: [{ text: '' }]
} }
} }
const parseHtmlConf = { const parseHtmlConf = {
selector: 'span[data-w-e-type="process-record"]', selector: 'span[data-w-e-type="process-record"]',
parseElemHtml: parseHtml, parseElemHtml: parseHtml
} }
export default parseHtmlConf export default parseHtmlConf

View File

@ -4,7 +4,7 @@ function withProcessRecord<T extends IDomEditor>(editor: T) {
const { isInline, isVoid } = editor const { isInline, isVoid } = editor
const newEditor = editor const newEditor = editor
newEditor.isInline = elem => { newEditor.isInline = (elem) => {
const type = DomEditor.getNodeType(elem) const type = DomEditor.getNodeType(elem)
if (type === 'process-record') { if (type === 'process-record') {
return true return true
@ -13,7 +13,7 @@ function withProcessRecord<T extends IDomEditor>(editor: T) {
return isInline(elem) return isInline(elem)
} }
newEditor.isVoid = elem => { newEditor.isVoid = (elem) => {
const type = DomEditor.getNodeType(elem) const type = DomEditor.getNodeType(elem)
if (type === 'process-record') { if (type === 'process-record') {
return true return true

View File

@ -1,58 +1,60 @@
import {h, VNode} from 'snabbdom' import { h, VNode } from 'snabbdom'
import {DomEditor, IDomEditor, SlateElement} from '@wangeditor/editor' import { DomEditor, IDomEditor, SlateElement } from '@wangeditor/editor'
function renderProcessRecord(elem: SlateElement, children: VNode[] | null, editor: IDomEditor): VNode { function renderProcessRecord(
elem: SlateElement,
_children: VNode[] | null,
editor: IDomEditor
): VNode {
const selected = DomEditor.isNodeSelected(editor, elem) const selected = DomEditor.isNodeSelected(editor, elem)
const vnode = h( return h(
'table', 'table',
{ {
props: { props: {
contentEditable: false, contentEditable: false
}, },
style: { style: {
width: '100%', width: '100%',
border: selected border: selected ? '2px solid var(--w-e-textarea-selected-border-color)' : ''
? '2px solid var(--w-e-textarea-selected-border-color)' }
: '',
},
}, },
[ [
h('thead', [ h('thead', [h('tr', [h('th', { attrs: { colSpan: 3 } }, '流程记录')])]),
h('tr', [h('th', {attrs: {colSpan: 3}}, '流程记录')])
]),
h('tbody', [ h('tbody', [
h('tr', [ h('tr', [
h('td', [h( h('td', [
h(
'span', 'span',
{ {
props: { props: {
contentEditable: false, contentEditable: false
}, },
style: { style: {
marginLeft: '3px', marginLeft: '3px',
marginRight: '3px', marginRight: '3px',
backgroundColor: 'var(--w-e-textarea-slight-bg-color)', backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
borderRadius: '3px', borderRadius: '3px',
padding: '0 3px', padding: '0 3px'
}, }
}, },
`节点` `节点`
) )
]), ]),
h('td', [h( h('td', [
h(
'span', 'span',
{ {
props: { props: {
contentEditable: false, contentEditable: false
}, },
style: { style: {
marginLeft: '3px', marginLeft: '3px',
marginRight: '3px', marginRight: '3px',
backgroundColor: 'var(--w-e-textarea-slight-bg-color)', backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
borderRadius: '3px', borderRadius: '3px',
padding: '0 3px', padding: '0 3px'
}, }
}, },
`操作` `操作`
) )
@ -61,12 +63,11 @@ function renderProcessRecord(elem: SlateElement, children: VNode[] | null, edito
]) ])
] ]
) )
return vnode
} }
const conf = { const conf = {
type: 'process-record', type: 'process-record',
renderElem: renderProcessRecord, renderElem: renderProcessRecord
} }
export default conf export default conf

View File

@ -12,7 +12,7 @@ const printData = ref()
const userName = computed(() => userStore.user.nickname ?? '') const userName = computed(() => userStore.user.nickname ?? '')
const printTime = ref(formatDate(new Date(), 'YYYY-MM-DD HH:mm')) const printTime = ref(formatDate(new Date(), 'YYYY-MM-DD HH:mm'))
const open = async (id) => { const open = async (id: string) => {
loading.value = true loading.value = true
try { try {
printData.value = await ProcessInstanceApi.getProcessInstancePrintData(id) printData.value = await ProcessInstanceApi.getProcessInstancePrintData(id)
@ -98,6 +98,7 @@ const printObj = ref({
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- TODO @lesan最下面的 table 央视可以去掉么 -->
</template> </template>
<style lang="scss"> <style lang="scss">

View File

@ -10,7 +10,7 @@
/> />
<div class="flex"> <div class="flex">
<div class="text-#878c93 h-15px">编号{{ id }}</div> <div class="text-#878c93 h-15px">编号{{ id }}</div>
<Icon icon="ep:printer" class="ml-15px cursor-pointer" @click="handlePrint"/> <Icon icon="ep:printer" class="ml-15px cursor-pointer" @click="handlePrint" />
</div> </div>
<el-divider class="!my-8px" /> <el-divider class="!my-8px" />
<div class="flex items-center gap-5 mb-10px h-40px"> <div class="flex items-center gap-5 mb-10px h-40px">
@ -128,6 +128,8 @@
</el-scrollbar> </el-scrollbar>
</div> </div>
</ContentWrap> </ContentWrap>
<!-- 打印预览弹窗 -->
<PrintDialog ref="printRef" /> <PrintDialog ref="printRef" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -192,6 +194,7 @@ const getDetail = () => {
/** 加载流程实例 */ /** 加载流程实例 */
const BusinessFormComponent = ref<any>(null) // 异步组件 const BusinessFormComponent = ref<any>(null) // 异步组件
/** 获取审批详情 */ /** 获取审批详情 */
const activityNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([]) // 审批节点信息
const getApprovalDetail = async () => { const getApprovalDetail = async () => {
processInstanceLoading.value = true processInstanceLoading.value = true
try { try {
@ -270,11 +273,7 @@ const getProcessModelView = async () => {
} }
} }
// 审批节点信息 /** 设置表单权限 */
const activityNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([])
/**
* 设置表单权限
*/
const setFieldPermission = (field: string, permission: string) => { const setFieldPermission = (field: string, permission: string) => {
if (permission === FieldPermissionType.READ) { if (permission === FieldPermissionType.READ) {
//@ts-ignore //@ts-ignore
@ -292,20 +291,19 @@ const setFieldPermission = (field: string, permission: string) => {
} }
} }
/** /** 操作成功后刷新 */
* 操作成功后刷新
*/
const refresh = () => { const refresh = () => {
// 重新获取详情 // 重新获取详情
getDetail() getDetail()
} }
/** 处理打印 */
const printRef = ref() const printRef = ref()
const handlePrint = async () => { const handlePrint = async () => {
printRef.value.open(props.id) printRef.value.open(props.id)
} }
/** 当前的Tab */ /** 当前的 Tab */
const activeTab = ref('form') const activeTab = ref('form')
/** 初始化 */ /** 初始化 */