Przeglądaj źródła

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

YunaiV 5 miesięcy temu
rodzic
commit
be964a6287

+ 4 - 2
src/main.ts

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

Plik diff jest za duży
+ 5 - 4
src/views/bpm/model/form/ExtraSettings.vue


+ 28 - 24
src/views/bpm/model/form/PrintTemplate/Index.vue

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

+ 21 - 18
src/views/bpm/model/form/PrintTemplate/MentionModal.vue

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

+ 5 - 4
src/views/bpm/model/form/PrintTemplate/index.ts

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

+ 2 - 2
src/views/bpm/model/form/PrintTemplate/module/elem-to-html.ts

@@ -1,12 +1,12 @@
 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>`
 }
 
 const conf = {
   type: 'process-record',
-  elemToHtml: processRecordToHtml,
+  elemToHtml: processRecordToHtml
 }
 
 export default conf

+ 4 - 3
src/views/bpm/model/form/PrintTemplate/module/index.ts

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

+ 7 - 7
src/views/bpm/model/form/PrintTemplate/module/menu/ProcessRecordMenu.ts

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

+ 6 - 5
src/views/bpm/model/form/PrintTemplate/module/parse-elem-html.ts

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

+ 2 - 2
src/views/bpm/model/form/PrintTemplate/module/plugin.ts

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

+ 45 - 44
src/views/bpm/model/form/PrintTemplate/module/render-elem.ts

@@ -1,72 +1,73 @@
-import {h, VNode} from 'snabbdom'
-import {DomEditor, IDomEditor, SlateElement} from '@wangeditor/editor'
+import { h, VNode } from 'snabbdom'
+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 vnode = h(
+  return h(
     'table',
     {
       props: {
-        contentEditable: false,
+        contentEditable: false
       },
       style: {
         width: '100%',
-        border: selected
-          ? '2px solid var(--w-e-textarea-selected-border-color)'
-          : '',
-      },
+        border: selected ? '2px solid var(--w-e-textarea-selected-border-color)' : ''
+      }
     },
     [
-      h('thead', [
-        h('tr', [h('th', {attrs: {colSpan: 3}}, '流程记录')])
-      ]),
+      h('thead', [h('tr', [h('th', { attrs: { colSpan: 3 } }, '流程记录')])]),
       h('tbody', [
         h('tr', [
-          h('td', [h(
-            'span',
-            {
-              props: {
-                contentEditable: false,
-              },
-              style: {
-                marginLeft: '3px',
-                marginRight: '3px',
-                backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
-                borderRadius: '3px',
-                padding: '0 3px',
+          h('td', [
+            h(
+              'span',
+              {
+                props: {
+                  contentEditable: false
+                },
+                style: {
+                  marginLeft: '3px',
+                  marginRight: '3px',
+                  backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
+                  borderRadius: '3px',
+                  padding: '0 3px'
+                }
               },
-            },
-            `节点`
-          )
+              `节点`
+            )
           ]),
-          h('td', [h(
-            'span',
-            {
-              props: {
-                contentEditable: false,
-              },
-              style: {
-                marginLeft: '3px',
-                marginRight: '3px',
-                backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
-                borderRadius: '3px',
-                padding: '0 3px',
+          h('td', [
+            h(
+              'span',
+              {
+                props: {
+                  contentEditable: false
+                },
+                style: {
+                  marginLeft: '3px',
+                  marginRight: '3px',
+                  backgroundColor: 'var(--w-e-textarea-slight-bg-color)',
+                  borderRadius: '3px',
+                  padding: '0 3px'
+                }
               },
-            },
-            `操作`
-          )
+              `操作`
+            )
           ])
         ])
       ])
     ]
   )
-  return vnode
 }
 
 const conf = {
   type: 'process-record',
-  renderElem: renderProcessRecord,
+  renderElem: renderProcessRecord
 }
 
 export default conf

+ 2 - 1
src/views/bpm/processInstance/detail/PrintDialog.vue

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

+ 8 - 10
src/views/bpm/processInstance/detail/index.vue

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