mirror of
https://gitee.com/myxzgzs/boyue-ui-admin-vue3
synced 2025-08-09 08:52:41 +08:00
feat: 完善UserTask审批签名
This commit is contained in:
parent
dd72d35fe4
commit
04f4f630ad
@ -36,6 +36,7 @@ export type ApprovalTaskInfo = {
|
|||||||
assigneeUser: User
|
assigneeUser: User
|
||||||
status: number
|
status: number
|
||||||
reason: string
|
reason: string
|
||||||
|
sign: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 审批节点信息
|
// 审批节点信息
|
||||||
|
@ -44,6 +44,12 @@
|
|||||||
:rows="4"
|
:rows="4"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="runningTask.signEnable" label="签名" prop="sign" ref="approveSignFormRef">
|
||||||
|
<el-button @click="signRef.open()">点击签名</el-button>
|
||||||
|
<el-image class="w-90px h-40px ml-5px" v-if="approveReasonForm.sign"
|
||||||
|
:src="approveReasonForm.sign"
|
||||||
|
:preview-src-list="[approveReasonForm.sign]"/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button :disabled="formLoading" type="success" @click="handleAudit(true, approveFormRef)">
|
<el-button :disabled="formLoading" type="success" @click="handleAudit(true, approveFormRef)">
|
||||||
{{ getButtonDisplayName(OperationButtonType.APPROVE) }}
|
{{ getButtonDisplayName(OperationButtonType.APPROVE) }}
|
||||||
@ -471,6 +477,8 @@
|
|||||||
<Icon :size="14" icon="ep:refresh" /> 再次提交
|
<Icon :size="14" icon="ep:refresh" /> 再次提交
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<SignDialog ref="signRef" @success="handleSignFinish"/>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||||
@ -484,6 +492,7 @@ import {
|
|||||||
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
||||||
import { BpmProcessInstanceStatus, BpmModelFormType } from '@/utils/constants'
|
import { BpmProcessInstanceStatus, BpmModelFormType } from '@/utils/constants'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
import SignDialog from "./SignDialog.vue";
|
||||||
defineOptions({ name: 'ProcessInstanceBtnContainer' })
|
defineOptions({ name: 'ProcessInstanceBtnContainer' })
|
||||||
|
|
||||||
const router = useRouter() // 路由
|
const router = useRouter() // 路由
|
||||||
@ -522,11 +531,15 @@ const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
|
|||||||
|
|
||||||
// 审批通过意见表单
|
// 审批通过意见表单
|
||||||
const approveFormRef = ref<FormInstance>()
|
const approveFormRef = ref<FormInstance>()
|
||||||
|
const signRef = ref()
|
||||||
|
const approveSignFormRef = ref()
|
||||||
const approveReasonForm = reactive({
|
const approveReasonForm = reactive({
|
||||||
reason: ''
|
reason: '',
|
||||||
|
sign: ''
|
||||||
})
|
})
|
||||||
const approveReasonRule = reactive<FormRules<typeof approveReasonForm>>({
|
const approveReasonRule = reactive<FormRules<typeof approveReasonForm>>({
|
||||||
reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
||||||
|
sign: [{ required: true, message: '签名不能为空', trigger: 'change' }]
|
||||||
})
|
})
|
||||||
// 拒绝表单
|
// 拒绝表单
|
||||||
const rejectFormRef = ref<FormInstance>()
|
const rejectFormRef = ref<FormInstance>()
|
||||||
@ -672,6 +685,10 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) =>
|
|||||||
reason: approveReasonForm.reason,
|
reason: approveReasonForm.reason,
|
||||||
variables // 审批通过, 把修改的字段值赋于流程实例变量
|
variables // 审批通过, 把修改的字段值赋于流程实例变量
|
||||||
}
|
}
|
||||||
|
// 签名
|
||||||
|
if (runningTask.value.signEnable) {
|
||||||
|
data.sign = approveReasonForm.sign
|
||||||
|
}
|
||||||
// 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
|
// 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
|
||||||
// TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
|
// TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
|
||||||
const formCreateApi = approveFormFApi.value
|
const formCreateApi = approveFormFApi.value
|
||||||
@ -966,6 +983,11 @@ const getUpdatedProcessInstanceVaiables = ()=> {
|
|||||||
return variables
|
return variables
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSignFinish = (url) => {
|
||||||
|
approveReasonForm.sign = url
|
||||||
|
approveSignFormRef.value.validate('change')
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({ loadTodoTask })
|
defineExpose({ loadTodoTask })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -123,6 +123,15 @@
|
|||||||
>
|
>
|
||||||
审批意见:{{ task.reason }}
|
审批意见:{{ task.reason }}
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="task.sign && activity.nodeType === NodeType.USER_TASK_NODE"
|
||||||
|
class="text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
|
||||||
|
>
|
||||||
|
签名:
|
||||||
|
<el-image class="w-90px h-40px ml-5px"
|
||||||
|
:src="task.sign"
|
||||||
|
:preview-src-list="[task.sign]"/>
|
||||||
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
<!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
|
<!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
|
||||||
|
84
src/views/bpm/processInstance/detail/SignDialog.vue
Normal file
84
src/views/bpm/processInstance/detail/SignDialog.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="signDialogVisible"
|
||||||
|
title="签名"
|
||||||
|
width="935"
|
||||||
|
>
|
||||||
|
<div class="position-relative">
|
||||||
|
<Vue3Signature class="b b-solid b-gray" ref="signature" w="900px" h="400px"/>
|
||||||
|
<el-button
|
||||||
|
style="position: absolute; bottom: 20px; right: 10px"
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
size="small"
|
||||||
|
@click="signature.clear()"
|
||||||
|
>
|
||||||
|
<Icon icon="ep:delete" class="mr-5px"/>
|
||||||
|
清除
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="signDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submit">
|
||||||
|
提交
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Vue3Signature from "vue3-signature"
|
||||||
|
import * as FileApi from '@/api/infra/file'
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const signDialogVisible = ref(false)
|
||||||
|
const signature = ref()
|
||||||
|
|
||||||
|
const open = async () => {
|
||||||
|
signDialogVisible.value = true
|
||||||
|
}
|
||||||
|
defineExpose({open})
|
||||||
|
|
||||||
|
const emits = defineEmits(['success'])
|
||||||
|
const submit = async () => {
|
||||||
|
message.success('签名上传中请稍等。。。')
|
||||||
|
const res = await FileApi.updateFile({file: base64ToFile(signature.value.save('image/png'), '签名')})
|
||||||
|
emits('success', res.data)
|
||||||
|
signDialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const base64ToFile = (base64, fileName) => {
|
||||||
|
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
|
||||||
|
let data = base64.split(',');
|
||||||
|
// 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
|
||||||
|
let type = data[0].match(/:(.*?);/)[1];
|
||||||
|
// 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
|
||||||
|
let suffix = type.split('/')[1];
|
||||||
|
// 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
|
||||||
|
const bstr = window.atob(data[1]);
|
||||||
|
// 获取解码结果字符串的长度
|
||||||
|
let n = bstr.length
|
||||||
|
// 根据解码结果字符串的长度创建一个等长的整形数字数组
|
||||||
|
// 但在创建时 所有元素初始值都为 0
|
||||||
|
const u8arr = new Uint8Array(n)
|
||||||
|
// 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
|
||||||
|
while (n--) {
|
||||||
|
// charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
|
||||||
|
u8arr[n] = bstr.charCodeAt(n)
|
||||||
|
}
|
||||||
|
// 利用构造函数创建File文件对象
|
||||||
|
// new File(bits, name, options)
|
||||||
|
const file = new File([u8arr], `${fileName}.${suffix}`, {
|
||||||
|
type: type
|
||||||
|
})
|
||||||
|
// 将File文件对象返回给方法的调用者
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user