From ec0518f36a6c79e3777387c6b17ea8e696f79325 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 15 Nov 2025 21:52:09 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20[bpm][antd]=20=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/modules/custom-print-template.vue | 127 ++++++++++++++++++ .../bpm/model/form/modules/extra-setting.vue | 123 ++++++++++++++++- .../bpm/model/form/modules/tinymce-plugin.ts | 78 +++++++++++ .../bpm/processInstance/detail/index.vue | 2 +- .../{processs-print.vue => process-print.vue} | 66 ++++----- 5 files changed, 349 insertions(+), 47 deletions(-) create mode 100644 apps/web-antd/src/views/bpm/model/form/modules/custom-print-template.vue create mode 100644 apps/web-antd/src/views/bpm/model/form/modules/tinymce-plugin.ts rename apps/web-antd/src/views/bpm/processInstance/detail/modules/{processs-print.vue => process-print.vue} (80%) diff --git a/apps/web-antd/src/views/bpm/model/form/modules/custom-print-template.vue b/apps/web-antd/src/views/bpm/model/form/modules/custom-print-template.vue new file mode 100644 index 000000000..d4b26c391 --- /dev/null +++ b/apps/web-antd/src/views/bpm/model/form/modules/custom-print-template.vue @@ -0,0 +1,127 @@ + + + diff --git a/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue b/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue index 1e64b37c7..af3d6bfa9 100644 --- a/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue +++ b/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue @@ -1,6 +1,7 @@ diff --git a/apps/web-antd/src/views/bpm/model/form/modules/tinymce-plugin.ts b/apps/web-antd/src/views/bpm/model/form/modules/tinymce-plugin.ts new file mode 100644 index 000000000..145dc894b --- /dev/null +++ b/apps/web-antd/src/views/bpm/model/form/modules/tinymce-plugin.ts @@ -0,0 +1,78 @@ +/** TinyMCE 自定义功能: + * - processrecord 按钮:插入流程记录占位元素 + * - @ 自动补全:插入 mention 占位元素 + */ + +// @ts-ignore TinyMCE 全局或通过打包器提供 +import type { Editor } from 'tinymce'; + +export interface MentionItem { + id: string; + name: string; +} + +/** 在编辑器 setup 回调中注册流程记录按钮和 @ 自动补全 */ +export function setupTinyPlugins( + editor: Editor, + getMentionList: () => MentionItem[], +) { + // 按钮:流程记录 + editor.ui.registry.addButton('processrecord', { + text: '流程记录', + tooltip: '插入流程记录占位', + onAction: () => { + // 流程记录占位显示, 仅用于显示。process-print.vue 组件中会替换掉 + editor.insertContent( + [ + '
', + '', + '', + '', + '', + '', + '', + '
流程记录
节点操作
', + '
', + ].join(''), + ); + }, + }); + + // @ 自动补全 + editor.ui.registry.addAutocompleter('bpmMention', { + trigger: '@', + minChars: 0, + columns: 1, + fetch: ( + pattern: string, + _maxResults: number, + _fetchOptions: Record, + ) => { + const list = getMentionList(); + const keyword = (pattern || '').toLowerCase().trim(); + const data = list + .filter((i) => i.name.toLowerCase().includes(keyword)) + .map((i) => ({ + value: i.id, + text: i.name, + })); + return Promise.resolve(data); + }, + onAction: ( + autocompleteApi: any, + rng: Range, + value: string, + _meta: Record, + ) => { + const list = getMentionList(); + const item = list.find((i) => i.id === value); + const name = item ? item.name : value; + const info = encodeURIComponent(JSON.stringify({ id: value })); + editor.selection.setRng(rng); + editor.insertContent( + `@${name}`, + ); + autocompleteApi.hide(); + }, + }); +} diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/index.vue b/apps/web-antd/src/views/bpm/processInstance/detail/index.vue index 6c0c1b47e..064c45858 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/index.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/index.vue @@ -34,7 +34,7 @@ import { registerComponent } from '#/utils'; import ProcessInstanceBpmnViewer from './modules/bpm-viewer.vue'; import ProcessInstanceOperationButton from './modules/operation-button.vue'; -import ProcessssPrint from './modules/processs-print.vue'; +import ProcessssPrint from './modules/process-print.vue'; import ProcessInstanceSimpleViewer from './modules/simple-bpm-viewer.vue'; import BpmProcessInstanceTaskList from './modules/task-list.vue'; import ProcessInstanceTimeline from './modules/time-line.vue'; diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/modules/processs-print.vue b/apps/web-antd/src/views/bpm/processInstance/detail/modules/process-print.vue similarity index 80% rename from apps/web-antd/src/views/bpm/processInstance/detail/modules/processs-print.vue rename to apps/web-antd/src/views/bpm/processInstance/detail/modules/process-print.vue index e4e87e14e..504db968a 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/modules/processs-print.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/modules/process-print.vue @@ -143,7 +143,7 @@ function initPrintDataMap() { printDataMap.value.printTime = printTime.value; } -/** 获取打印模板 HTML (TODO 需求实现配置打印模板) */ +/** 获取打印模板 HTML */ function getPrintTemplateHTML() { if (!printData.value?.printTemplateHtml) return ''; @@ -153,16 +153,6 @@ function getPrintTemplateHTML() { 'text/html', ); - // table 添加 border - const tables = doc.querySelectorAll('table'); - tables.forEach((item) => { - item.setAttribute('border', '1'); - item.setAttribute( - 'style', - `${item.getAttribute('style') || ''}border-collapse:collapse;`, - ); - }); - // 替换 mentions const mentions = doc.querySelectorAll('[data-w-e-type="mention"]'); mentions.forEach((item) => { @@ -181,26 +171,23 @@ function getPrintTemplateHTML() { if (processRecords.length > 0) { // 构建流程记录 html - processRecordTable.setAttribute('border', '1'); - processRecordTable.setAttribute( - 'style', - 'width:100%;border-collapse:collapse;', - ); + processRecordTable.setAttribute('class', 'w-full border-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 = '流程节点'; + headTd.setAttribute('class', 'border border-black p-1.5 text-center'); + headTd.innerHTML = '流程记录'; headTr.append(headTd); processRecordTable.append(headTr); printData.value?.tasks.forEach((item) => { const tr = document.createElement('tr'); const td1 = document.createElement('td'); + td1.setAttribute('class', 'border border-black p-1.5'); td1.innerHTML = item.name; const td2 = document.createElement('td'); + td2.setAttribute('class', 'border border-black p-1.5'); td2.innerHTML = item.description; tr.append(td1); tr.append(td2); @@ -229,35 +216,34 @@ function getPrintTemplateHTML() {

{{ printData.processInstance.name }}

-
- {{ `打印人员: ${userName}` }} -
{{ `流程编号: ${printData.processInstance.id}` }}
-
{{ `打印时间: ${printTime}` }}
+
+ {{ `打印人员: ${userName}` }} +
- +
- - + - - + - - + - - + - - - -
发起人 + 发起人 {{ printData.processInstance.startUser?.nickname }} 发起时间 - + 发起时间 + {{ formatDate(printData.processInstance.startTime) }}
所属部门 + 所属部门 {{ printData.processInstance.startUser?.deptName }} 流程状态 + 流程状态 {{ getDictLabel( DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, @@ -268,33 +254,33 @@ function getPrintTemplateHTML() {

表单内容

+ {{ item.name }} +
-

流程节点

+

流程记录

+ {{ item.name }} + {{ item.description }}
From 22c1d5b2ec2a46ac8a1104cba28ee680051544ce Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 15 Nov 2025 22:01:27 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20[bpm][antd]=20todo=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/bpm/components/bpmn-process-designer/package/index.ts | 2 -- .../web-antd/src/views/bpm/model/form/modules/extra-setting.vue | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/index.ts b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/index.ts index 39f7f7f4d..483d5fb4d 100644 --- a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/index.ts +++ b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/index.ts @@ -9,5 +9,3 @@ export { default as MyProcessDesigner } from './designer'; // TODO @puhui999:流程发起时,预览相关的,需要使用; export { default as MyProcessViewer } from './designer/index2'; export { default as MyProcessPenal } from './penal'; - -// TODO @jason:【有个迁移的打印】【新增】流程打印,由 [@Lesan](https://gitee.com/LesanOuO) 贡献 [#816](https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/816/)、[#1418](https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1418/)、[#817](https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/817/)、[#1419](https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1419/)、[#1424](https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1424)、[#819](https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/819)、[#821](https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/821/) diff --git a/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue b/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue index af3d6bfa9..6ce0b15fa 100644 --- a/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue +++ b/apps/web-antd/src/views/bpm/model/form/modules/extra-setting.vue @@ -267,7 +267,7 @@ const [PrintTemplateModal, printTemplateModalApi] = useVbenModal({ connectedComponent: PrintTemplate, destroyOnClose: true, onConfirm() { - /** 从 modalApi 获取确认的数据 */ + // 会在内部模态框中设置数据,这里获取数据, 内部模态框中不能有 onConfirm 方法 const { confirmedTemplate } = printTemplateModalApi.getData<{ confirmedTemplate: string; }>();