Merge branch 'feature/bpm-n' of https://gitee.com/LesanOuO/yudao-ui-admin-vue3 into feature/bpm
# Conflicts: # src/components/SimpleProcessDesignerV2/src/consts.tspull/654/MERGE
commit
528ebf3ea3
|
@ -0,0 +1,3 @@
|
|||
import ESign from './src/ESign.vue'
|
||||
|
||||
export { ESign }
|
|
@ -0,0 +1,288 @@
|
|||
<template>
|
||||
<div style="position: relative">
|
||||
<canvas
|
||||
ref="canvasRef"
|
||||
@mousedown="mouseDown"
|
||||
@mousemove="mouseMove"
|
||||
@mouseup="mouseUp"
|
||||
@touchstart="touchStart"
|
||||
@touchmove="touchMove"
|
||||
@touchend="touchEnd"
|
||||
style="border: 1px solid lightgrey; max-width: 100%; display: block"
|
||||
>
|
||||
</canvas>
|
||||
|
||||
<el-button
|
||||
style="position: absolute; bottom: 20px; right: 10px"
|
||||
type="primary"
|
||||
text
|
||||
size="small"
|
||||
@click="reset"
|
||||
>
|
||||
<Icon icon="ep:delete" class="mr-5px" />清除
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
defineOptions({ name: 'ESign' })
|
||||
|
||||
const emits = defineEmits(['update:bgColor'])
|
||||
const props = defineProps({
|
||||
// 画布宽度,即导出图片的宽度
|
||||
width: propTypes.number.def(900),
|
||||
// 画布高度,即导出图片的高度
|
||||
height: propTypes.number.def(400),
|
||||
// 画笔粗细
|
||||
lineWidth: propTypes.number.def(10),
|
||||
// 画笔颜色
|
||||
lineColor: propTypes.string.def('#000000'),
|
||||
// 画布背景色,为空时画布背景透明
|
||||
bgColor: propTypes.string.def(''),
|
||||
// 是否裁剪,在画布设定尺寸基础上裁掉四周空白部分
|
||||
isCrop: propTypes.bool.def(false),
|
||||
// 清空画布时是否同时清空设置的背景色
|
||||
isClearBgColor: propTypes.bool.def(true),
|
||||
// 生成图片格式
|
||||
format: propTypes.string.def('image/png'),
|
||||
// 生成图片质量,0 到 1
|
||||
quality: propTypes.number.def(1)
|
||||
})
|
||||
const canvasRef = ref()
|
||||
const hasDrew = ref(false)
|
||||
const resultImg = ref('')
|
||||
const points = ref<any>([])
|
||||
const canvasTxt = ref()
|
||||
const startX = ref(0)
|
||||
const startY = ref(0)
|
||||
const isDrawing = ref(false)
|
||||
const sratio = ref(1)
|
||||
|
||||
const ratio = computed(() => {
|
||||
return props.height / props.width
|
||||
})
|
||||
const stageInfo = computed(() => {
|
||||
return canvasRef.value.getBoundingClientRect()
|
||||
})
|
||||
const bgColor = computed(() => {
|
||||
return props.bgColor ? props.bgColor : 'rgba(255, 255, 255, 0)'
|
||||
})
|
||||
|
||||
watch(
|
||||
() => bgColor.value,
|
||||
() => {
|
||||
if (canvasRef.value) {
|
||||
canvasRef.value.style.background = bgColor.value
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
const resizeHandler = () => {
|
||||
const canvas = canvasRef.value
|
||||
canvas.style.width = props.width + 'px'
|
||||
const realw = parseFloat(window.getComputedStyle(canvas).width)
|
||||
canvas.style.height = ratio.value * realw + 'px'
|
||||
canvasTxt.value = canvas.getContext('2d')
|
||||
canvasTxt.value.scale(1 * sratio.value, 1 * sratio.value)
|
||||
sratio.value = realw / props.width
|
||||
canvasTxt.value.scale(1 / sratio.value, 1 / sratio.value)
|
||||
}
|
||||
// For PC
|
||||
const mouseDown = (e) => {
|
||||
e.preventDefault()
|
||||
isDrawing.value = true
|
||||
hasDrew.value = true
|
||||
let obj = {
|
||||
x: e.offsetX,
|
||||
y: e.offsetY
|
||||
}
|
||||
drawStart(obj)
|
||||
}
|
||||
const mouseMove = (e) => {
|
||||
e.preventDefault()
|
||||
if (isDrawing.value) {
|
||||
let obj = {
|
||||
x: e.offsetX,
|
||||
y: e.offsetY
|
||||
}
|
||||
drawMove(obj)
|
||||
}
|
||||
}
|
||||
const mouseUp = (e) => {
|
||||
e.preventDefault()
|
||||
let obj = {
|
||||
x: e.offsetX,
|
||||
y: e.offsetY
|
||||
}
|
||||
drawEnd(obj)
|
||||
isDrawing.value = false
|
||||
}
|
||||
// For Mobile
|
||||
const touchStart = (e) => {
|
||||
e.preventDefault()
|
||||
hasDrew.value = true
|
||||
if (e.touches.length === 1) {
|
||||
let obj = {
|
||||
x: e.targetTouches[0].clientX - canvasRef.value.getBoundingClientRect().left,
|
||||
y: e.targetTouches[0].clientY - canvasRef.value.getBoundingClientRect().top
|
||||
}
|
||||
drawStart(obj)
|
||||
}
|
||||
}
|
||||
const touchMove = (e) => {
|
||||
e.preventDefault()
|
||||
if (e.touches.length === 1) {
|
||||
let obj = {
|
||||
x: e.targetTouches[0].clientX - canvasRef.value.getBoundingClientRect().left,
|
||||
y: e.targetTouches[0].clientY - canvasRef.value.getBoundingClientRect().top
|
||||
}
|
||||
drawMove(obj)
|
||||
}
|
||||
}
|
||||
const touchEnd = (e) => {
|
||||
e.preventDefault()
|
||||
if (e.touches.length === 1) {
|
||||
let obj = {
|
||||
x: e.targetTouches[0].clientX - canvasRef.value.getBoundingClientRect().left,
|
||||
y: e.targetTouches[0].clientY - canvasRef.value.getBoundingClientRect().top
|
||||
}
|
||||
drawEnd(obj)
|
||||
}
|
||||
}
|
||||
// 绘制
|
||||
const drawStart = (obj) => {
|
||||
startX.value = obj.x
|
||||
startY.value = obj.y
|
||||
canvasTxt.value.beginPath()
|
||||
canvasTxt.value.moveTo(startX.value, startY.value)
|
||||
canvasTxt.value.lineTo(obj.x, obj.y)
|
||||
canvasTxt.value.lineCap = 'round'
|
||||
canvasTxt.value.lineJoin = 'round'
|
||||
canvasTxt.value.lineWidth = props.lineWidth * sratio.value
|
||||
canvasTxt.value.stroke()
|
||||
canvasTxt.value.closePath()
|
||||
points.value.push(obj)
|
||||
}
|
||||
const drawMove = (obj) => {
|
||||
canvasTxt.value.beginPath()
|
||||
canvasTxt.value.moveTo(startX.value, startY.value)
|
||||
canvasTxt.value.lineTo(obj.x, obj.y)
|
||||
canvasTxt.value.strokeStyle = props.lineColor
|
||||
canvasTxt.value.lineWidth = props.lineWidth * sratio.value
|
||||
canvasTxt.value.lineCap = 'round'
|
||||
canvasTxt.value.lineJoin = 'round'
|
||||
canvasTxt.value.stroke()
|
||||
canvasTxt.value.closePath()
|
||||
startY.value = obj.y
|
||||
startX.value = obj.x
|
||||
points.value.push(obj)
|
||||
}
|
||||
const drawEnd = (obj) => {
|
||||
canvasTxt.value.beginPath()
|
||||
canvasTxt.value.moveTo(startX.value, startY.value)
|
||||
canvasTxt.value.lineTo(obj.x, obj.y)
|
||||
canvasTxt.value.lineCap = 'round'
|
||||
canvasTxt.value.lineJoin = 'round'
|
||||
canvasTxt.value.stroke()
|
||||
canvasTxt.value.closePath()
|
||||
points.value.push(obj)
|
||||
points.value.push({ x: -1, y: -1 })
|
||||
}
|
||||
// 生成
|
||||
const generate = (options) => {
|
||||
let imgFormat = options && options.format ? options.format : props.format
|
||||
let imgQuality = options && options.quality ? options.quality : props.quality
|
||||
const pm = new Promise((resolve, reject) => {
|
||||
if (!hasDrew.value) {
|
||||
reject(`Warning: Not Signned!`)
|
||||
return
|
||||
}
|
||||
let resImgData = canvasTxt.value.getImageData(
|
||||
0,
|
||||
0,
|
||||
canvasRef.value.width,
|
||||
canvasRef.value.height
|
||||
)
|
||||
canvasTxt.value.globalCompositeOperation = 'destination-over'
|
||||
canvasTxt.value.fillStyle = bgColor.value
|
||||
canvasTxt.value.fillRect(0, 0, canvasRef.value.width, canvasRef.value.height)
|
||||
resultImg.value = canvasRef.value.toDataURL(imgFormat, imgQuality)
|
||||
canvasTxt.value.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)
|
||||
canvasTxt.value.putImageData(resImgData, 0, 0)
|
||||
canvasTxt.value.globalCompositeOperation = 'source-over'
|
||||
if (props.isCrop) {
|
||||
const crop_area = getCropArea(resImgData.data)
|
||||
let crop_canvas = document.createElement('canvas')
|
||||
const crop_ctx = crop_canvas.getContext('2d')
|
||||
crop_canvas.width = crop_area[2] - crop_area[0]
|
||||
crop_canvas.height = crop_area[3] - crop_area[1]
|
||||
const crop_imgData = canvasTxt.value.getImageData(...crop_area)
|
||||
crop_ctx.globalCompositeOperation = 'destination-over'
|
||||
crop_ctx.putImageData(crop_imgData, 0, 0)
|
||||
crop_ctx.fillStyle = bgColor.value
|
||||
crop_ctx.fillRect(0, 0, crop_canvas.width, crop_canvas.height)
|
||||
resultImg.value = crop_canvas.toDataURL(imgFormat, imgQuality)
|
||||
}
|
||||
resolve(resultImg.value)
|
||||
})
|
||||
return pm
|
||||
}
|
||||
const reset = () => {
|
||||
canvasTxt.value.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)
|
||||
if (props.isClearBgColor) {
|
||||
emits('update:bgColor', '')
|
||||
canvasRef.value.style.background = 'rgba(255, 255, 255, 0)'
|
||||
}
|
||||
points.value = []
|
||||
hasDrew.value = false
|
||||
resultImg.value = ''
|
||||
}
|
||||
const getCropArea = (imgData) => {
|
||||
let topX = canvasRef.value.width
|
||||
let btmX = 0
|
||||
let topY = canvasRef.value.height
|
||||
let btnY = 0
|
||||
for (let i = 0; i < canvasRef.value.width; i++) {
|
||||
for (let j = 0; j < canvasRef.value.height; j++) {
|
||||
let pos = (i + canvasRef.value.width * j) * 4
|
||||
if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) {
|
||||
btnY = Math.max(j, btnY)
|
||||
btmX = Math.max(i, btmX)
|
||||
topY = Math.min(j, topY)
|
||||
topX = Math.min(i, topX)
|
||||
}
|
||||
}
|
||||
}
|
||||
topX++
|
||||
btmX++
|
||||
topY++
|
||||
btnY++
|
||||
const data = [topX, topY, btmX, btnY]
|
||||
return data
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
generate
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
})
|
||||
onMounted(() => {
|
||||
canvasRef.value.height = props.height
|
||||
canvasRef.value.width = props.width
|
||||
canvasRef.value.style.background = bgColor.value
|
||||
resizeHandler()
|
||||
// 在画板以外松开鼠标后冻结画笔
|
||||
document.onmouseup = () => {
|
||||
isDrawing.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -128,7 +128,13 @@ const addNode = (type: number) => {
|
|||
},
|
||||
assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT,
|
||||
childNode: props.childNode,
|
||||
createTaskListener: {
|
||||
taskCreateListener: {
|
||||
enable: false
|
||||
},
|
||||
taskAssignListener: {
|
||||
enable: false
|
||||
},
|
||||
taskCompleteListener: {
|
||||
enable: false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,11 @@ export interface SimpleFlowNode {
|
|||
// 审批节点的审批人与发起人相同时,对应的处理类型
|
||||
assignStartUserHandlerType?: number
|
||||
// 创建任务监听器
|
||||
createTaskListener?: ListenerHandler
|
||||
taskCreateListener?: ListenerHandler
|
||||
// 创建任务监听器
|
||||
taskAssignListener?: ListenerHandler
|
||||
// 创建任务监听器
|
||||
taskCompleteListener?: ListenerHandler
|
||||
// 条件类型
|
||||
conditionType?: ConditionType
|
||||
// 条件表达式
|
||||
|
@ -236,15 +240,25 @@ export type AssignEmptyHandler = {
|
|||
*/
|
||||
export type ListenerHandler = {
|
||||
enable: boolean
|
||||
path: string
|
||||
header: ListenerMap[]
|
||||
body: ListenerMap[]
|
||||
path?: string
|
||||
header?: ListenerMap[]
|
||||
body?: ListenerMap[]
|
||||
}
|
||||
export type ListenerMap = {
|
||||
key: string
|
||||
type: number
|
||||
value: string
|
||||
}
|
||||
export enum ListenerMapTypeEnum {
|
||||
/**
|
||||
* 固定值
|
||||
*/
|
||||
FIXED_VALUE = 1,
|
||||
/**
|
||||
* 表单
|
||||
*/
|
||||
FROM_FORM = 2
|
||||
}
|
||||
export const LISTENER_MAP_TYPES = [
|
||||
{
|
||||
value: 1,
|
||||
|
|
|
@ -14,7 +14,8 @@ import {
|
|||
NODE_DEFAULT_NAME,
|
||||
AssignStartUserHandlerType,
|
||||
AssignEmptyHandlerType,
|
||||
FieldPermissionType
|
||||
FieldPermissionType,
|
||||
ListenerMap
|
||||
} from './consts'
|
||||
import { parseFormFields } from '@/components/FormCreate/src/utils/index'
|
||||
export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
|
||||
|
@ -136,6 +137,18 @@ export type UserTaskFormType = {
|
|||
timeDuration?: number
|
||||
maxRemindCount?: number
|
||||
buttonsSetting: any[]
|
||||
taskCreateListenerEnable?: boolean
|
||||
taskCreateListenerPath?: string
|
||||
taskCreateListenerHeader?: ListenerMap[]
|
||||
taskCreateListenerBody?: ListenerMap[]
|
||||
taskAssignListenerEnable?: boolean
|
||||
taskAssignListenerPath?: string
|
||||
taskAssignListenerHeader?: ListenerMap[]
|
||||
taskAssignListenerBody?: ListenerMap[]
|
||||
taskCompleteListenerEnable?: boolean
|
||||
taskCompleteListenerPath?: string
|
||||
taskCompleteListenerHeader?: ListenerMap[]
|
||||
taskCompleteListenerBody?: ListenerMap[]
|
||||
}
|
||||
|
||||
export type CopyTaskFormType = {
|
||||
|
|
|
@ -436,133 +436,153 @@
|
|||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="监听器" name="listener">
|
||||
<div>
|
||||
<div v-for="(listener, listenerIdx) in taskListener" :key="listenerIdx">
|
||||
<el-form label-position="top">
|
||||
<el-divider content-position="left">
|
||||
<el-text tag="b" size="large">创建任务</el-text>
|
||||
</el-divider>
|
||||
<!-- TODO @lesan:createTaskListenerEnable、createTaskListenerPath 等 idea 红色的告警! -->
|
||||
<el-form-item prop="createTaskListenerEnable">
|
||||
<el-switch
|
||||
v-model="configForm.createTaskListenerEnable"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-if="configForm.createTaskListenerEnable">
|
||||
<div>
|
||||
<el-divider content-position="left">
|
||||
<el-text tag="b" size="large">{{ listener.name }}</el-text>
|
||||
</el-divider>
|
||||
<el-form-item>
|
||||
<el-alert
|
||||
title="仅支持 POST 请求,以请求体方式接收参数"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
<el-switch
|
||||
v-model="configForm[`task${listener.type}ListenerEnable`]"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求地址" prop="createTaskListenerPath">
|
||||
<el-input v-model="configForm.createTaskListenerPath" />
|
||||
</el-form-item>
|
||||
<el-form-item label="请求头" prop="createTaskListenerHeader">
|
||||
<div
|
||||
class="flex pt-2"
|
||||
v-for="(item, index) in configForm.createTaskListenerHeader"
|
||||
:key="index"
|
||||
>
|
||||
<!-- TODO @lesan:css 尽量用 unocss 哈 -->
|
||||
<div class="mr-2">
|
||||
<el-input v-model="item.key" style="width: 160px" />
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-select v-model="item.type" style="width: 100px">
|
||||
<el-option
|
||||
v-for="types in LISTENER_MAP_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
<div v-if="configForm[`task${listener.type}ListenerEnable`]">
|
||||
<el-form-item>
|
||||
<el-alert
|
||||
title="仅支持 POST 请求,以请求体方式接收参数"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求地址">
|
||||
<el-input v-model="configForm[`task${listener.type}ListenerPath`]" />
|
||||
</el-form-item>
|
||||
<el-form-item label="请求头">
|
||||
<div
|
||||
class="flex pt-2"
|
||||
v-for="(item, index) in configForm[`task${listener.type}ListenerHeader`]"
|
||||
:key="index"
|
||||
>
|
||||
<div class="mr-2">
|
||||
<el-input class="w-160px" v-model="item.key" />
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-select class="w-100px!" v-model="item.type">
|
||||
<el-option
|
||||
v-for="types in LISTENER_MAP_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-input
|
||||
v-if="item.type === ListenerMapTypeEnum.FIXED_VALUE"
|
||||
class="w-160px"
|
||||
v-model="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-input v-model="item.value" style="width: 160px" />
|
||||
</div>
|
||||
<div class="mr-1 flex items-center">
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="deleteTaskListenerMap(configForm.createTaskListenerHeader, index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click="addTaskListenerMap(configForm.createTaskListenerHeader)"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" />添加一行
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求体" prop="createTaskListenerBody">
|
||||
<div
|
||||
class="flex pt-2"
|
||||
v-for="(item, index) in configForm.createTaskListenerBody"
|
||||
:key="index"
|
||||
>
|
||||
<div class="mr-2">
|
||||
<el-input v-model="item.key" style="width: 160px" />
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-select v-model="item.type" style="width: 100px">
|
||||
<el-option
|
||||
v-for="types in LISTENER_MAP_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
<el-select
|
||||
v-if="item.type === ListenerMapTypeEnum.FROM_FORM"
|
||||
class="w-160px!"
|
||||
v-model="item.value"
|
||||
>
|
||||
<el-option
|
||||
v-for="(field, fIdx) in formFieldOptions"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="!field.required"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-1 flex items-center">
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="
|
||||
deleteTaskListenerMap(
|
||||
configForm[`task${listener.type}ListenerHeader`],
|
||||
index
|
||||
)
|
||||
"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-input v-model="item.value" style="width: 160px" />
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click="addTaskListenerMap(configForm[`task${listener.type}ListenerHeader`])"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" />添加一行
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求体">
|
||||
<div
|
||||
class="flex pt-2"
|
||||
v-for="(item, index) in configForm[`task${listener.type}ListenerBody`]"
|
||||
:key="index"
|
||||
>
|
||||
<div class="mr-2">
|
||||
<el-input class="w-160px" v-model="item.key" />
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-select class="w-100px!" v-model="item.type">
|
||||
<el-option
|
||||
v-for="types in LISTENER_MAP_TYPES"
|
||||
:key="types.value"
|
||||
:label="types.label"
|
||||
:value="types.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-input
|
||||
v-if="item.type === ListenerMapTypeEnum.FIXED_VALUE"
|
||||
class="w-160px"
|
||||
v-model="item.value"
|
||||
/>
|
||||
<el-select
|
||||
v-if="item.type === ListenerMapTypeEnum.FROM_FORM"
|
||||
class="w-160px!"
|
||||
v-model="item.value"
|
||||
>
|
||||
<el-option
|
||||
v-for="(field, fIdx) in formFieldOptions"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="!field.required"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-1 flex items-center">
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="
|
||||
deleteTaskListenerMap(
|
||||
configForm[`task${listener.type}ListenerBody`],
|
||||
index
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mr-1 flex items-center">
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="deleteTaskListenerMap(configForm.createTaskListenerBody, index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click="addTaskListenerMap(configForm.createTaskListenerBody)"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" />添加一行
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click="addTaskListenerMap(configForm[`task${listener.type}ListenerBody`])"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" />添加一行
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TODO lesan:待实现 -->
|
||||
<el-divider content-position="left">
|
||||
<el-text tag="b" size="large">指派任务执行人员</el-text>
|
||||
</el-divider>
|
||||
<el-form-item prop="assignTaskListenerEnable">
|
||||
<el-switch
|
||||
v-model="configForm.assignTaskListenerEnable"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- TODO lesan:待实现 -->
|
||||
<el-divider content-position="left">
|
||||
<el-text tag="b" size="large">完成任务</el-text>
|
||||
</el-divider>
|
||||
<el-form-item prop="completeTaskListenerEnable">
|
||||
<el-switch
|
||||
v-model="configForm.completeTaskListenerEnable"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
@ -602,7 +622,8 @@ import {
|
|||
AssignEmptyHandlerType,
|
||||
FieldPermissionType,
|
||||
ProcessVariableEnum,
|
||||
LISTENER_MAP_TYPES
|
||||
LISTENER_MAP_TYPES,
|
||||
ListenerMapTypeEnum
|
||||
} from '../consts'
|
||||
|
||||
import {
|
||||
|
@ -693,6 +714,21 @@ const formRules = reactive({
|
|||
assignEmptyHandlerUserIds: [{ required: true, message: '用户不能为空', trigger: 'change' }],
|
||||
assignStartUserHandlerType: [{ required: true }]
|
||||
})
|
||||
// 监听器数组
|
||||
const taskListener = ref([
|
||||
{
|
||||
name: '创建任务',
|
||||
type: 'Create'
|
||||
},
|
||||
{
|
||||
name: '指派任务执行人员',
|
||||
type: 'Assign'
|
||||
},
|
||||
{
|
||||
name: '完成任务',
|
||||
type: 'Complete'
|
||||
}
|
||||
])
|
||||
|
||||
const {
|
||||
configForm: tempConfigForm,
|
||||
|
@ -796,11 +832,25 @@ const saveConfig = async () => {
|
|||
// 设置按钮权限
|
||||
currentNode.value.buttonsSetting = buttonsSetting.value
|
||||
// 创建任务监听器
|
||||
currentNode.value.createTaskListener = {
|
||||
enable: configForm.value.createTaskListenerEnable,
|
||||
path: configForm.value.createTaskListenerPath,
|
||||
header: configForm.value.createTaskListenerHeader,
|
||||
body: configForm.value.createTaskListenerBody
|
||||
currentNode.value.taskCreateListener = {
|
||||
enable: configForm.value.taskCreateListenerEnable ?? false,
|
||||
path: configForm.value.taskCreateListenerPath,
|
||||
header: configForm.value.taskCreateListenerHeader,
|
||||
body: configForm.value.taskCreateListenerBody
|
||||
}
|
||||
// 指派任务监听器
|
||||
currentNode.value.taskAssignListener = {
|
||||
enable: configForm.value.taskAssignListenerEnable ?? false,
|
||||
path: configForm.value.taskAssignListenerPath,
|
||||
header: configForm.value.taskAssignListenerHeader,
|
||||
body: configForm.value.taskAssignListenerBody
|
||||
}
|
||||
// 完成任务监听器
|
||||
currentNode.value.taskCompleteListener = {
|
||||
enable: configForm.value.taskCompleteListenerEnable ?? false,
|
||||
path: configForm.value.taskCompleteListenerPath,
|
||||
header: configForm.value.taskCompleteListenerHeader,
|
||||
body: configForm.value.taskCompleteListenerBody
|
||||
}
|
||||
|
||||
currentNode.value.showText = showText
|
||||
|
@ -853,11 +903,22 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
|
||||
// 4. 表单字段权限配置
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
// 5. 创建任务监听器
|
||||
configForm.value.createTaskListenerEnable = node.createTaskListener.enable
|
||||
configForm.value.createTaskListenerPath = node.createTaskListener.path
|
||||
configForm.value.createTaskListenerHeader = node.createTaskListener.header ?? []
|
||||
configForm.value.createTaskListenerBody = node.createTaskListener.body ?? []
|
||||
// 5. 监听器
|
||||
// 5.1 创建任务
|
||||
configForm.value.taskCreateListenerEnable = node.taskCreateListener!.enable
|
||||
configForm.value.taskCreateListenerPath = node.taskCreateListener!.path
|
||||
configForm.value.taskCreateListenerHeader = node.taskCreateListener?.header ?? []
|
||||
configForm.value.taskCreateListenerBody = node.taskCreateListener?.body ?? []
|
||||
// 5.2 指派任务
|
||||
configForm.value.taskAssignListenerEnable = node.taskAssignListener!.enable
|
||||
configForm.value.taskAssignListenerPath = node.taskAssignListener!.path
|
||||
configForm.value.taskAssignListenerHeader = node.taskAssignListener?.header ?? []
|
||||
configForm.value.taskAssignListenerBody = node.taskAssignListener?.body ?? []
|
||||
// 5.3 完成任务
|
||||
configForm.value.taskCompleteListenerEnable = node.taskCompleteListener!.enable
|
||||
configForm.value.taskCompleteListenerPath = node.taskCompleteListener!.path
|
||||
configForm.value.taskCompleteListenerHeader = node.taskCompleteListener?.header ?? []
|
||||
configForm.value.taskCompleteListenerBody = node.taskCompleteListener?.body ?? []
|
||||
}
|
||||
|
||||
defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件
|
||||
|
|
Loading…
Reference in New Issue