Pre Merge pull request !702 from Lemon/feature/bpm-流程审批-办理-抄送
commit
20fdfd8081
|
|
@ -114,7 +114,8 @@ const include = [
|
|||
'element-plus/es/components/segmented/style/css',
|
||||
'@element-plus/icons-vue',
|
||||
'element-plus/es/components/footer/style/css',
|
||||
'element-plus/es/components/empty/style/css'
|
||||
'element-plus/es/components/empty/style/css',
|
||||
'element-plus/es/components/mention/style/css'
|
||||
]
|
||||
|
||||
const exclude = ['@iconify/json']
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<svg t="1739406626368" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1300" width="200" height="200"><path d="M803.221 925.573H224.356c-68.568 0-124.352-55.784-124.352-124.353V222.356c0-68.568 55.784-124.352 124.352-124.352h355.311v64H224.356c-33.278 0-60.352 27.074-60.352 60.352V801.22c0 33.278 27.074 60.353 60.352 60.353H803.22c33.278 0 60.353-27.074 60.353-60.353V448.208h64V801.22c0 68.569-55.784 124.353-124.352 124.353z" fill="#ffffff" p-id="1301"></path><path d="M300.357 756.916l35.024-195.867L770.117 84.404c10.05-11.02 25.015-18.052 41.058-19.293 16.017-1.247 31.987 3.379 43.841 12.667l83.662 65.549c21.643 16.956 24.254 45.964 5.942 66.038l-437.613 479.8-206.65 67.751z m104.994-170.751l-13.14 73.487 69.671-22.842 415.465-455.517-59.909-46.939-412.087 451.811z" fill="#ffffff" p-id="1302"></path><path d="M732.25 220.897l41.144-49.023 81.151 68.11-41.145 49.023z" fill="#ffffff" p-id="1303"></path></svg>
|
||||
|
After Width: | Height: | Size: 964 B |
|
|
@ -15,6 +15,12 @@
|
|||
</div>
|
||||
<div class="handler-item-text">审批人</div>
|
||||
</div>
|
||||
<div class="handler-item" @click="addNode(NodeType.TRANSACTOR_NODE)">
|
||||
<div class="transactor handler-item-icon">
|
||||
<span class="iconfont icon-transactor icon-size"></span>
|
||||
</div>
|
||||
<div class="handler-item-text">办理人</div>
|
||||
</div>
|
||||
<div class="handler-item" @click="addNode(NodeType.COPY_TASK_NODE)">
|
||||
<div class="handler-item-icon copy">
|
||||
<span class="iconfont icon-size icon-copy"></span>
|
||||
|
|
@ -57,7 +63,7 @@
|
|||
</div>
|
||||
<div class="handler-item-text">触发器</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div class="add-icon"><Icon icon="ep:plus" /></div>
|
||||
</template>
|
||||
|
|
@ -78,7 +84,7 @@ import {
|
|||
SimpleFlowNode,
|
||||
DEFAULT_CONDITION_GROUP_VALUE
|
||||
} from './consts'
|
||||
import {generateUUID} from '@/utils'
|
||||
import { generateUUID } from '@/utils'
|
||||
|
||||
defineOptions({
|
||||
name: 'NodeHandler'
|
||||
|
|
@ -114,13 +120,13 @@ const addNode = (type: number) => {
|
|||
}
|
||||
|
||||
popoverShow.value = false
|
||||
if (type === NodeType.USER_TASK_NODE) {
|
||||
if (type === NodeType.USER_TASK_NODE || type === NodeType.TRANSACTOR_NODE) {
|
||||
const id = 'Activity_' + generateUUID()
|
||||
const data: SimpleFlowNode = {
|
||||
id: id,
|
||||
name: NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string,
|
||||
name: NODE_DEFAULT_NAME.get(type) as string,
|
||||
showText: '',
|
||||
type: NodeType.USER_TASK_NODE,
|
||||
type: type,
|
||||
approveMethod: ApproveMethodType.SEQUENTIAL_APPROVE,
|
||||
// 超时处理
|
||||
rejectHandler: {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@
|
|||
/>
|
||||
<!-- 审批节点 -->
|
||||
<UserTaskNode
|
||||
v-if="currentNode && currentNode.type === NodeType.USER_TASK_NODE"
|
||||
v-if="
|
||||
currentNode &&
|
||||
(currentNode.type === NodeType.USER_TASK_NODE ||
|
||||
currentNode.type === NodeType.TRANSACTOR_NODE)
|
||||
"
|
||||
:flow-node="currentNode"
|
||||
@update:flow-node="handleModelValueUpdate"
|
||||
@find:parent-node="findFromParentNode"
|
||||
|
|
|
|||
|
|
@ -45,4 +45,3 @@ watch(
|
|||
provide('tasks', approveTasks)
|
||||
provide('processInstance', currentProcessInstance)
|
||||
</script>
|
||||
p
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ export enum NodeType {
|
|||
*/
|
||||
COPY_TASK_NODE = 12,
|
||||
|
||||
/**
|
||||
* 办理人节点
|
||||
*/
|
||||
TRANSACTOR_NODE = 13,
|
||||
|
||||
/**
|
||||
* 延迟器节点
|
||||
*/
|
||||
|
|
@ -506,6 +511,7 @@ NODE_DEFAULT_TEXT.set(NodeType.START_USER_NODE, '请设置发起人')
|
|||
NODE_DEFAULT_TEXT.set(NodeType.DELAY_TIMER_NODE, '请设置延迟器')
|
||||
NODE_DEFAULT_TEXT.set(NodeType.ROUTER_BRANCH_NODE, '请设置路由节点')
|
||||
NODE_DEFAULT_TEXT.set(NodeType.TRIGGER_NODE, '请设置触发器')
|
||||
NODE_DEFAULT_TEXT.set(NodeType.TRANSACTOR_NODE, '请设置办理人')
|
||||
|
||||
export const NODE_DEFAULT_NAME = new Map<number, string>()
|
||||
NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人')
|
||||
|
|
@ -515,15 +521,17 @@ NODE_DEFAULT_NAME.set(NodeType.START_USER_NODE, '发起人')
|
|||
NODE_DEFAULT_NAME.set(NodeType.DELAY_TIMER_NODE, '延迟器')
|
||||
NODE_DEFAULT_NAME.set(NodeType.ROUTER_BRANCH_NODE, '路由分支')
|
||||
NODE_DEFAULT_NAME.set(NodeType.TRIGGER_NODE, '触发器')
|
||||
NODE_DEFAULT_NAME.set(NodeType.TRANSACTOR_NODE, '办理人')
|
||||
|
||||
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
|
||||
export const CANDIDATE_STRATEGY: DictDataVO[] = [
|
||||
{ label: '指定成员', value: CandidateStrategy.USER },
|
||||
{ label: '指定角色', value: CandidateStrategy.ROLE },
|
||||
{ label: '指定岗位', value: CandidateStrategy.POST },
|
||||
{ label: '部门成员', value: CandidateStrategy.DEPT_MEMBER },
|
||||
{ label: '部门负责人', value: CandidateStrategy.DEPT_LEADER },
|
||||
{ label: '连续多级部门负责人', value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER },
|
||||
{ label: '发起人自选', value: CandidateStrategy.START_USER_SELECT },
|
||||
{ label: '指定岗位', value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER },
|
||||
{ label: '发起人本人', value: CandidateStrategy.START_USER },
|
||||
{ label: '发起人部门负责人', value: CandidateStrategy.START_USER_DEPT_LEADER },
|
||||
{ label: '发起人连续部门负责人', value: CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER },
|
||||
|
|
@ -627,6 +635,16 @@ export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [
|
|||
{ id: OperationButtonType.RETURN, displayName: '退回', enable: true }
|
||||
]
|
||||
|
||||
// 办理人默认的按钮权限设置
|
||||
export const TRANSACTOR_DEFAULT_BUTTON_SETTING: ButtonSetting[] = [
|
||||
{ id: OperationButtonType.APPROVE, displayName: '办理', enable: true },
|
||||
{ id: OperationButtonType.REJECT, displayName: '拒绝', enable: false },
|
||||
{ id: OperationButtonType.TRANSFER, displayName: '转办', enable: false },
|
||||
{ id: OperationButtonType.DELEGATE, displayName: '委派', enable: false },
|
||||
{ id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: false },
|
||||
{ id: OperationButtonType.RETURN, displayName: '退回', enable: false }
|
||||
]
|
||||
|
||||
// 发起人的按钮权限。暂时定死,不可以编辑
|
||||
export const START_USER_BUTTON_SETTING: ButtonSetting[] = [
|
||||
{ id: OperationButtonType.APPROVE, displayName: '提交', enable: true },
|
||||
|
|
@ -717,7 +735,7 @@ export type RouterSetting = {
|
|||
export type TriggerSetting = {
|
||||
type: TriggerTypeEnum
|
||||
httpRequestSetting?: HttpRequestTriggerSetting
|
||||
normalFormSetting?: NormalFormTriggerSetting
|
||||
formSettings?: FormTriggerSetting[]
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -751,7 +769,13 @@ export type HttpRequestTriggerSetting = {
|
|||
/**
|
||||
* 流程表单触发器配置结构定义
|
||||
*/
|
||||
export type NormalFormTriggerSetting = {
|
||||
export type FormTriggerSetting = {
|
||||
// 条件类型
|
||||
conditionType?: ConditionType
|
||||
// 条件表达式
|
||||
conditionExpression?: string
|
||||
// 条件组
|
||||
conditionGroups?: ConditionGroup
|
||||
// 更新表单字段
|
||||
updateFormFields?: Record<string, any>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ import {
|
|||
AssignEmptyHandlerType,
|
||||
FieldPermissionType,
|
||||
HttpRequestParam,
|
||||
ProcessVariableEnum
|
||||
ProcessVariableEnum,
|
||||
ConditionType,
|
||||
ConditionGroup,
|
||||
COMPARISON_OPERATORS
|
||||
} from './consts'
|
||||
import { parseFormFields } from '@/components/FormCreate/src/utils'
|
||||
|
||||
|
|
@ -201,7 +204,7 @@ export function useNodeForm(nodeType: NodeType) {
|
|||
const deptTreeOptions = inject('deptTree', ref()) // 部门树
|
||||
const formFields = inject<Ref<string[]>>('formFields', ref([])) // 流程表单字段
|
||||
const configForm = ref<UserTaskFormType | CopyTaskFormType>()
|
||||
if (nodeType === NodeType.USER_TASK_NODE) {
|
||||
if (nodeType === NodeType.USER_TASK_NODE || nodeType === NodeType.TRANSACTOR_NODE) {
|
||||
configForm.value = {
|
||||
candidateStrategy: CandidateStrategy.USER,
|
||||
approveMethod: ApproveMethodType.SEQUENTIAL_APPROVE,
|
||||
|
|
@ -543,6 +546,66 @@ export function useTaskStatusClass(taskStatus: TaskStatusEnum | undefined): stri
|
|||
if (taskStatus === TaskStatusEnum.CANCEL) {
|
||||
return 'status-cancel'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
/** 条件组件文字展示 */
|
||||
export function getConditionShowText(
|
||||
conditonType: ConditionType | undefined,
|
||||
conditionExpression: string | undefined,
|
||||
conditionGroups: ConditionGroup | undefined,
|
||||
fieldOptions: Array<Record<string, any>>
|
||||
) {
|
||||
let showText = ''
|
||||
if (conditonType === ConditionType.EXPRESSION) {
|
||||
if (conditionExpression) {
|
||||
showText = `表达式:${conditionExpression}`
|
||||
}
|
||||
}
|
||||
if (conditonType === ConditionType.RULE) {
|
||||
// 条件组是否为与关系
|
||||
const groupAnd = conditionGroups?.and
|
||||
let warningMesg: undefined | string = undefined
|
||||
const conditionGroup = conditionGroups?.conditions.map((item) => {
|
||||
return (
|
||||
'(' +
|
||||
item.rules
|
||||
.map((rule) => {
|
||||
if (rule.leftSide && rule.rightSide) {
|
||||
return (
|
||||
getFormFieldTitle(fieldOptions, rule.leftSide) +
|
||||
' ' +
|
||||
getOpName(rule.opCode) +
|
||||
' ' +
|
||||
rule.rightSide
|
||||
)
|
||||
} else {
|
||||
// 有一条规则不完善。提示错误
|
||||
warningMesg = '请完善条件规则'
|
||||
return ''
|
||||
}
|
||||
})
|
||||
.join(item.and ? ' 且 ' : ' 或 ') +
|
||||
' ) '
|
||||
)
|
||||
})
|
||||
if (warningMesg) {
|
||||
showText = ''
|
||||
} else {
|
||||
showText = conditionGroup!.join(groupAnd ? ' 且 ' : ' 或 ')
|
||||
}
|
||||
}
|
||||
return showText
|
||||
}
|
||||
|
||||
/** 获取表单字段名称*/
|
||||
const getFormFieldTitle = (fieldOptions: Array<Record<string, any>>, field: string) => {
|
||||
const item = fieldOptions.find((item) => item.field === field)
|
||||
return item?.title
|
||||
}
|
||||
|
||||
/** 获取操作符名称 */
|
||||
const getOpName = (opCode: string): string => {
|
||||
const opName = COMPARISON_OPERATORS.find((item: any) => item.value === opCode)
|
||||
return opName?.label
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,13 +43,9 @@
|
|||
</el-drawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
SimpleFlowNode,
|
||||
ConditionType,
|
||||
COMPARISON_OPERATORS,
|
||||
} from '../consts'
|
||||
import { SimpleFlowNode, ConditionType } from '../consts'
|
||||
import { getDefaultConditionNodeName } from '../utils'
|
||||
import { useFormFieldsAndStartUser } from '../node'
|
||||
import { useFormFieldsAndStartUser, getConditionShowText } from '../node'
|
||||
import Condition from './components/Condition.vue'
|
||||
const message = useMessage() // 消息弹窗
|
||||
defineOptions({
|
||||
|
|
@ -93,8 +89,6 @@ const blurEvent = () => {
|
|||
getDefaultConditionNodeName(props.nodeIndex, currentNode.value?.conditionSetting?.defaultFlow)
|
||||
}
|
||||
|
||||
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
// 关闭
|
||||
|
|
@ -110,6 +104,8 @@ const handleClose = async (done: (cancel?: boolean) => void) => {
|
|||
done()
|
||||
}
|
||||
}
|
||||
// 流程表单字段和发起人字段
|
||||
const fieldOptions = useFormFieldsAndStartUser()
|
||||
|
||||
const conditionRef = ref()
|
||||
// 保存配置
|
||||
|
|
@ -118,7 +114,12 @@ const saveConfig = async () => {
|
|||
// 校验表单
|
||||
const valid = await conditionRef.value.validate()
|
||||
if (!valid) return false
|
||||
const showText = getShowText()
|
||||
const showText = getConditionShowText(
|
||||
condition.value?.conditionType,
|
||||
condition.value?.conditionExpression,
|
||||
condition.value.conditionGroups,
|
||||
fieldOptions
|
||||
)
|
||||
if (!showText) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -136,59 +137,6 @@ const saveConfig = async () => {
|
|||
settingVisible.value = false
|
||||
return true
|
||||
}
|
||||
const getShowText = (): string => {
|
||||
let showText = ''
|
||||
if (condition.value?.conditionType === ConditionType.EXPRESSION) {
|
||||
if (condition.value.conditionExpression) {
|
||||
showText = `表达式:${condition.value.conditionExpression}`
|
||||
}
|
||||
}
|
||||
if (condition.value?.conditionType === ConditionType.RULE) {
|
||||
// 条件组是否为与关系
|
||||
const groupAnd = condition.value.conditionGroups?.and
|
||||
let warningMesg: undefined | string = undefined
|
||||
const conditionGroup = condition.value.conditionGroups?.conditions.map((item) => {
|
||||
return (
|
||||
'(' +
|
||||
item.rules
|
||||
.map((rule) => {
|
||||
if (rule.leftSide && rule.rightSide) {
|
||||
return (
|
||||
getFieldTitle(rule.leftSide) + ' ' + getOpName(rule.opCode) + ' ' + rule.rightSide
|
||||
)
|
||||
} else {
|
||||
// 有一条规则不完善。提示错误
|
||||
warningMesg = '请完善条件规则'
|
||||
return ''
|
||||
}
|
||||
})
|
||||
.join(item.and ? ' 且 ' : ' 或 ') +
|
||||
' ) '
|
||||
)
|
||||
})
|
||||
if (warningMesg) {
|
||||
message.warning(warningMesg)
|
||||
showText = ''
|
||||
} else {
|
||||
showText = conditionGroup!.join(groupAnd ? ' 且 ' : ' 或 ')
|
||||
}
|
||||
}
|
||||
return showText
|
||||
}
|
||||
// 流程表单字段和发起人字段
|
||||
const fieldOptions = useFormFieldsAndStartUser()
|
||||
|
||||
/** 获取字段名称 */
|
||||
const getFieldTitle = (field: string) => {
|
||||
const item = fieldOptions.find((item) => item.field === field)
|
||||
return item?.title
|
||||
}
|
||||
|
||||
/** 获取操作符名称 */
|
||||
const getOpName = (opCode: string): string => {
|
||||
const opName = COMPARISON_OPERATORS.find((item: any) => item.value === opCode)
|
||||
return opName?.label
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -195,9 +195,13 @@
|
|||
<div class="field-permit-title">
|
||||
<div class="setting-title-label first-title"> 字段名称 </div>
|
||||
<div class="other-titles">
|
||||
<span class="setting-title-label">只读</span>
|
||||
<span class="setting-title-label">只读
|
||||
<el-switch v-model="readSwitch" @change="updatePermission('READ')" />
|
||||
</span>
|
||||
<span class="setting-title-label">可编辑</span>
|
||||
<span class="setting-title-label">隐藏</span>
|
||||
<span class="setting-title-label">隐藏
|
||||
<el-switch v-model="noneSwitch" @change="updatePermission('NONE')" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -367,7 +371,23 @@ const showCopyTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
// 表单字段权限
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
}
|
||||
const readSwitch = ref(false);
|
||||
const noneSwitch = ref(false);
|
||||
const updatePermission = (type: string) => {
|
||||
if (type === 'READ') {
|
||||
readSwitch.value = true;
|
||||
|
||||
noneSwitch.value = false;
|
||||
} else if (type === 'NONE') {
|
||||
readSwitch.value = false;
|
||||
|
||||
noneSwitch.value = true;
|
||||
}
|
||||
|
||||
fieldsPermissionConfig.value.forEach(field => {
|
||||
field.permission = type === 'READ' ? FieldPermissionType.READ : FieldPermissionType.NONE;
|
||||
});
|
||||
};
|
||||
defineExpose({ openDrawer, showCopyTaskNodeConfig }) // 暴露方法给父组件
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,15 @@
|
|||
<div class="field-permit-title">
|
||||
<div class="setting-title-label first-title"> 字段名称 </div>
|
||||
<div class="other-titles">
|
||||
<span class="setting-title-label">只读</span>
|
||||
<span class="setting-title-label">可编辑</span>
|
||||
<span class="setting-title-label">隐藏</span>
|
||||
<span class="setting-title-label">只读
|
||||
<el-switch v-model="readSwitch" @change="updatePermission('READ')" />
|
||||
</span>
|
||||
<span class="setting-title-label">可编辑
|
||||
<el-switch v-model="writeSwitch" @change="updatePermission('WRITE')" />
|
||||
</span>
|
||||
<span class="setting-title-label">隐藏
|
||||
<el-switch v-model="noneSwitch" @change="updatePermission('NONE')" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -156,8 +162,32 @@ const showStartUserNodeConfig = (node: SimpleFlowNode) => {
|
|||
// 表单字段权限
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
}
|
||||
const readSwitch = ref(false)
|
||||
const writeSwitch = ref(false)
|
||||
const noneSwitch = ref(false)
|
||||
const updatePermission = (type) => {
|
||||
if (type === 'READ') {
|
||||
readSwitch.value = true;
|
||||
writeSwitch.value = false;
|
||||
noneSwitch.value = false;
|
||||
} else if (type === 'WRITE') {
|
||||
readSwitch.value = false;
|
||||
writeSwitch.value = true;
|
||||
noneSwitch.value = false;
|
||||
} else if (type === 'NONE') {
|
||||
readSwitch.value = false;
|
||||
writeSwitch.value = false;
|
||||
noneSwitch.value = true;
|
||||
}
|
||||
|
||||
fieldsPermissionConfig.value.forEach(item => {
|
||||
item.permission = type === 'READ' ? FieldPermissionType.READ :
|
||||
type === 'WRITE' ? FieldPermissionType.WRITE :
|
||||
FieldPermissionType.NONE;
|
||||
});
|
||||
}
|
||||
defineExpose({ openDrawer, showStartUserNodeConfig }) // 暴露方法给父组件
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
:append-to-body="true"
|
||||
v-model="settingVisible"
|
||||
:show-close="false"
|
||||
:size="550"
|
||||
:size="630"
|
||||
:before-close="saveConfig"
|
||||
>
|
||||
<template #header>
|
||||
|
|
@ -121,62 +121,114 @@
|
|||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
configForm.type === TriggerTypeEnum.UPDATE_NORMAL_FORM && configForm.normalFormSetting
|
||||
"
|
||||
>
|
||||
<el-divider content-position="left">修改表单设置</el-divider>
|
||||
<div
|
||||
class="flex items-center"
|
||||
v-for="key in Object.keys(configForm.normalFormSetting.updateFormFields!)"
|
||||
:key="key"
|
||||
>
|
||||
<div class="mr-2 flex items-center">
|
||||
<el-form-item>
|
||||
<el-select
|
||||
class="w-160px!"
|
||||
:model-value="key"
|
||||
@update:model-value="(newKey) => updateFormFieldKey(key, newKey)"
|
||||
placeholder="请选择表单字段"
|
||||
:disabled="key !== ''"
|
||||
<!-- 表单数据修改触发器 -->
|
||||
<div v-if="configForm.type === TriggerTypeEnum.UPDATE_NORMAL_FORM">
|
||||
<div v-for="(formSetting, index) in configForm.formSettings" :key="index">
|
||||
<el-card class="w-580px mt-4">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>修改表单设置 {{ index + 1 }}</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
circle
|
||||
v-if="configForm.formSettings!.length > 1"
|
||||
@click="deleteFormSetting(index)"
|
||||
>
|
||||
<Icon icon="ep:close" />
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 条件设置 -->
|
||||
<ConditionDialog
|
||||
:ref="`condition-${index}`"
|
||||
@update-condition="(val) => handleConditionUpdate(index, val)"
|
||||
/>
|
||||
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
||||
<el-tag
|
||||
type="success"
|
||||
effect="light"
|
||||
closable
|
||||
@close="deleteFormUpdateCondition(formSetting)"
|
||||
@click="openFormUpdateCondition(index, formSetting)"
|
||||
>
|
||||
<el-option
|
||||
v-for="(field, fIdx) in optionalUpdateFormFields"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="field.disabled"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mx-2"><el-form-item>的值设置为</el-form-item></div>
|
||||
<div class="mr-2">
|
||||
<el-form-item
|
||||
:prop="`normalFormSetting.updateFormFields.${key}`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '值不能为空',
|
||||
trigger: 'blur'
|
||||
}"
|
||||
{{ showConditionText(formSetting) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
text
|
||||
@click="addFormUpdateCondition(index, formSetting)"
|
||||
>
|
||||
<el-input
|
||||
class="w-160px"
|
||||
v-model="configForm.normalFormSetting.updateFormFields![key]"
|
||||
placeholder="请输入"
|
||||
:disabled="!key"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mr-1 pt-1 cursor-pointer">
|
||||
<el-form-item>
|
||||
<Icon icon="ep:delete" :size="18" @click="deleteFormFieldSetting(key)" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<Icon icon="ep:link" class="mr-5px" />添加条件
|
||||
</el-button>
|
||||
<el-divider content-position="left">修改表单字段设置</el-divider>
|
||||
<!-- 表单字段修改设置 -->
|
||||
<div
|
||||
class="flex items-center"
|
||||
v-for="key in Object.keys(formSetting.updateFormFields || {})"
|
||||
:key="key"
|
||||
>
|
||||
<div class="mr-2 flex items-center">
|
||||
<el-form-item>
|
||||
<el-select
|
||||
class="w-160px!"
|
||||
:model-value="key"
|
||||
@update:model-value="(newKey) => updateFormFieldKey(formSetting, key, newKey)"
|
||||
placeholder="请选择表单字段"
|
||||
:disabled="key !== ''"
|
||||
>
|
||||
<el-option
|
||||
v-for="(field, fIdx) in optionalUpdateFormFields"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="field.disabled"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mx-2"><el-form-item>的值设置为</el-form-item></div>
|
||||
<div class="mr-2">
|
||||
<el-form-item
|
||||
:prop="`formSettings.${index}.updateFormFields.${key}`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '值不能为空',
|
||||
trigger: 'blur'
|
||||
}"
|
||||
>
|
||||
<el-input
|
||||
class="w-160px"
|
||||
v-model="formSetting.updateFormFields![key]"
|
||||
placeholder="请输入"
|
||||
:disabled="!key"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mr-1 pt-1 cursor-pointer">
|
||||
<el-form-item>
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="deleteFormFieldSetting(formSetting, key)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加表单字段按钮 -->
|
||||
<el-button type="primary" text @click="addFormFieldSetting(formSetting)">
|
||||
<Icon icon="ep:memo" class="mr-5px" />添加修改字段
|
||||
</el-button>
|
||||
</el-card>
|
||||
</div>
|
||||
<el-button type="primary" text @click="addFormFieldSetting()">
|
||||
<Icon icon="ep:plus" class="mr-5px" />添加修改字段
|
||||
|
||||
<!-- 添加新的设置 -->
|
||||
<el-button class="mt-6" type="primary" text @click="addFormSetting">
|
||||
<Icon icon="ep:setting" class="mr-5px" />添加设置
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
|
|
@ -191,10 +243,26 @@
|
|||
</el-drawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { SimpleFlowNode, NodeType, TriggerSetting, TRIGGER_TYPES, TriggerTypeEnum } from '../consts'
|
||||
import { useWatchNode, useDrawer, useNodeName, useFormFields } from '../node'
|
||||
import {
|
||||
SimpleFlowNode,
|
||||
NodeType,
|
||||
TriggerSetting,
|
||||
TRIGGER_TYPES,
|
||||
TriggerTypeEnum,
|
||||
FormTriggerSetting,
|
||||
DEFAULT_CONDITION_GROUP_VALUE
|
||||
} from '../consts'
|
||||
import {
|
||||
useWatchNode,
|
||||
useDrawer,
|
||||
useNodeName,
|
||||
useFormFields,
|
||||
useFormFieldsAndStartUser,
|
||||
getConditionShowText
|
||||
} from '../node'
|
||||
import HttpRequestParamSetting from './components/HttpRequestParamSetting.vue'
|
||||
|
||||
import ConditionDialog from './components/ConditionDialog.vue'
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
defineOptions({
|
||||
name: 'TriggerNodeConfig'
|
||||
})
|
||||
|
|
@ -227,28 +295,25 @@ const configForm = ref<TriggerSetting>({
|
|||
body: [],
|
||||
response: []
|
||||
},
|
||||
normalFormSetting: { updateFormFields: {} }
|
||||
formSettings: [
|
||||
{
|
||||
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
|
||||
updateFormFields: {}
|
||||
}
|
||||
]
|
||||
})
|
||||
// 流程表单字段
|
||||
const formFields = useFormFields()
|
||||
|
||||
// 可选的修改的表单字段
|
||||
const optionalUpdateFormFields = computed(() => {
|
||||
const usedFields = Object.keys(configForm.value.normalFormSetting?.updateFormFields || {})
|
||||
return formFields.map((field) => ({
|
||||
title: field.title,
|
||||
field: field.field,
|
||||
disabled: usedFields.includes(field.field)
|
||||
disabled: false
|
||||
}))
|
||||
})
|
||||
|
||||
const updateFormFieldKey = (oldKey: string, newKey: string) => {
|
||||
if (!configForm.value.normalFormSetting?.updateFormFields) return
|
||||
const value = configForm.value.normalFormSetting.updateFormFields[oldKey]
|
||||
delete configForm.value.normalFormSetting.updateFormFields[oldKey]
|
||||
configForm.value.normalFormSetting.updateFormFields[newKey] = value
|
||||
}
|
||||
|
||||
/** 添加 HTTP 请求返回值设置项*/
|
||||
const addHttpResponseSetting = (responseSetting: Record<string, string>[]) => {
|
||||
responseSetting.push({
|
||||
|
|
@ -262,17 +327,69 @@ const deleteHttpResponseSetting = (responseSetting: Record<string, string>[], in
|
|||
responseSetting.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 添加修改表单设置项 */
|
||||
const addFormFieldSetting = () => {
|
||||
if (configForm.value.normalFormSetting!.updateFormFields === undefined) {
|
||||
configForm.value.normalFormSetting!.updateFormFields = {}
|
||||
}
|
||||
configForm.value.normalFormSetting!.updateFormFields[''] = undefined
|
||||
/** 添加新的修改表单设置 */
|
||||
const addFormSetting = () => {
|
||||
configForm.value.formSettings!.push({
|
||||
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
|
||||
updateFormFields: {}
|
||||
})
|
||||
}
|
||||
/** 删除修改表单设置项 */
|
||||
const deleteFormFieldSetting = (key: string) => {
|
||||
if (!configForm.value.normalFormSetting?.updateFormFields) return
|
||||
delete configForm.value.normalFormSetting.updateFormFields[key]
|
||||
|
||||
/** 删除修改表单设置 */
|
||||
const deleteFormSetting = (index: number) => {
|
||||
configForm.value.formSettings!.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 添加条件配置 */
|
||||
const addFormUpdateCondition = (index: number, formSetting: FormTriggerSetting) => {
|
||||
const conditionDialog = proxy.$refs[`condition-${index}`][0]
|
||||
conditionDialog.open(formSetting)
|
||||
}
|
||||
/** 删除条件配置 */
|
||||
const deleteFormUpdateCondition = (formSetting: FormTriggerSetting) => {
|
||||
formSetting.conditionType = undefined
|
||||
}
|
||||
/** 打开条件配置弹窗 */
|
||||
const openFormUpdateCondition = (index: number, formSetting: FormTriggerSetting) => {
|
||||
const conditionDialog = proxy.$refs[`condition-${index}`][0]
|
||||
conditionDialog.open(formSetting)
|
||||
}
|
||||
/** 处理条件配置保存 */
|
||||
const handleConditionUpdate = (index: number, condition: any) => {
|
||||
configForm.value.formSettings![index].conditionType = condition.conditionType
|
||||
configForm.value.formSettings![index].conditionExpression = condition.conditionExpression
|
||||
configForm.value.formSettings![index].conditionGroups = condition.conditionGroups
|
||||
}
|
||||
/** 条件配置展示 */
|
||||
const showConditionText = (formSetting: FormTriggerSetting) => {
|
||||
return getConditionShowText(
|
||||
formSetting.conditionType,
|
||||
formSetting.conditionExpression,
|
||||
formSetting.conditionGroups,
|
||||
formFields
|
||||
)
|
||||
}
|
||||
|
||||
/** 添加修改字段设置项 */
|
||||
const addFormFieldSetting = (formSetting: FormTriggerSetting) => {
|
||||
if (!formSetting) return
|
||||
if (!formSetting.updateFormFields) {
|
||||
formSetting.updateFormFields = {}
|
||||
}
|
||||
formSetting.updateFormFields[''] = undefined
|
||||
}
|
||||
/** 更新字段 KEY */
|
||||
const updateFormFieldKey = (formSetting: FormTriggerSetting, oldKey: string, newKey: string) => {
|
||||
if (!formSetting?.updateFormFields) return
|
||||
const value = formSetting.updateFormFields[oldKey]
|
||||
delete formSetting.updateFormFields[oldKey]
|
||||
formSetting.updateFormFields[newKey] = value
|
||||
}
|
||||
|
||||
/** 删除修改字段设置项 */
|
||||
const deleteFormFieldSetting = (formSetting: FormTriggerSetting, key: string) => {
|
||||
if (!formSetting?.updateFormFields) return
|
||||
delete formSetting.updateFormFields[key]
|
||||
}
|
||||
|
||||
/** 保存配置 */
|
||||
|
|
@ -285,7 +402,7 @@ const saveConfig = async () => {
|
|||
currentNode.value.name = nodeName.value!
|
||||
currentNode.value.showText = showText
|
||||
if (configForm.value.type === TriggerTypeEnum.HTTP_REQUEST) {
|
||||
configForm.value.normalFormSetting = undefined
|
||||
configForm.value.formSettings = undefined
|
||||
}
|
||||
if (configForm.value.type === TriggerTypeEnum.UPDATE_NORMAL_FORM) {
|
||||
configForm.value.httpRequestSetting = undefined
|
||||
|
|
@ -301,12 +418,13 @@ const getShowText = (): string => {
|
|||
if (configForm.value.type === TriggerTypeEnum.HTTP_REQUEST) {
|
||||
showText = `${configForm.value.httpRequestSetting?.url}`
|
||||
} else if (configForm.value.type === TriggerTypeEnum.UPDATE_NORMAL_FORM) {
|
||||
const updatefields = Object.keys(configForm.value.normalFormSetting?.updateFormFields || {})
|
||||
if (updatefields.length === 0) {
|
||||
message.warning('请设置修改表单字段')
|
||||
} else {
|
||||
showText = '修改表单数据'
|
||||
for (const [index, setting] of configForm.value.formSettings!.entries()) {
|
||||
if (!setting.updateFormFields || Object.keys(setting.updateFormFields).length === 0) {
|
||||
message.warning(`请添加表单设置${index + 1}的修改字段`)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
showText = '修改表单数据'
|
||||
}
|
||||
return showText
|
||||
}
|
||||
|
|
@ -323,7 +441,12 @@ const showTriggerNodeConfig = (node: SimpleFlowNode) => {
|
|||
body: [],
|
||||
response: []
|
||||
},
|
||||
normalFormSetting: node.triggerSetting.normalFormSetting || { updateFormFields: {} }
|
||||
formSettings: node.triggerSetting.formSettings || [
|
||||
{
|
||||
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
|
||||
updateFormFields: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<div class="divide-line"></div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex flex-items-center mb-3">
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE" class="flex flex-items-center mb-3">
|
||||
<span class="font-size-16px mr-3">审批类型 :</span>
|
||||
<el-radio-group v-model="approveType">
|
||||
<el-radio
|
||||
|
|
@ -39,10 +39,10 @@
|
|||
</el-radio-group>
|
||||
</div>
|
||||
<el-tabs type="border-card" v-model="activeTabName" v-if="approveType === ApproveType.USER">
|
||||
<el-tab-pane label="审批人" name="user">
|
||||
<el-tab-pane :label="`${nodeTypeName}人`" name="user">
|
||||
<div>
|
||||
<el-form ref="formRef" :model="configForm" label-position="top" :rules="formRules">
|
||||
<el-form-item label="审批人设置" prop="candidateStrategy">
|
||||
<el-form-item :label="`${nodeTypeName}人设置`" prop="candidateStrategy">
|
||||
<el-radio-group
|
||||
v-model="configForm.candidateStrategy"
|
||||
@change="changeCandidateStrategy"
|
||||
|
|
@ -61,7 +61,13 @@
|
|||
label="指定角色"
|
||||
prop="roleIds"
|
||||
>
|
||||
<el-select filterable v-model="configForm.roleIds" clearable multiple style="width: 100%">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="configForm.roleIds"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.id"
|
||||
|
|
@ -99,7 +105,13 @@
|
|||
prop="postIds"
|
||||
span="24"
|
||||
>
|
||||
<el-select filterable v-model="configForm.postIds" clearable multiple style="width: 100%">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="configForm.postIds"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in postOptions"
|
||||
:key="item.id"
|
||||
|
|
@ -114,7 +126,13 @@
|
|||
prop="userIds"
|
||||
span="24"
|
||||
>
|
||||
<el-select filterable v-model="configForm.userIds" clearable multiple style="width: 100%">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="configForm.userIds"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
|
|
@ -128,7 +146,13 @@
|
|||
label="指定用户组"
|
||||
prop="userGroups"
|
||||
>
|
||||
<el-select filterable v-model="configForm.userGroups" clearable multiple style="width: 100%">
|
||||
<el-select
|
||||
filterable
|
||||
v-model="configForm.userGroups"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userGroupOptions"
|
||||
:key="item.id"
|
||||
|
|
@ -201,7 +225,7 @@
|
|||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="多人审批方式" prop="approveMethod">
|
||||
<el-form-item :label="`多人${nodeTypeName}方式`" prop="approveMethod">
|
||||
<el-radio-group v-model="configForm.approveMethod" @change="approveMethodChanged">
|
||||
<div class="flex-col">
|
||||
<div
|
||||
|
|
@ -230,93 +254,102 @@
|
|||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">审批人拒绝时</el-divider>
|
||||
<el-form-item prop="rejectHandlerType">
|
||||
<el-radio-group v-model="configForm.rejectHandlerType">
|
||||
<div class="flex-col">
|
||||
<div v-for="(item, index) in REJECT_HANDLER_TYPES" :key="index">
|
||||
<el-radio :key="item.value" :value="item.value" :label="item.label" />
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
||||
<el-divider content-position="left">审批人拒绝时</el-divider>
|
||||
<el-form-item prop="rejectHandlerType">
|
||||
<el-radio-group v-model="configForm.rejectHandlerType">
|
||||
<div class="flex-col">
|
||||
<div v-for="(item, index) in REJECT_HANDLER_TYPES" :key="index">
|
||||
<el-radio :key="item.value" :value="item.value" :label="item.label" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="configForm.rejectHandlerType == RejectHandlerType.RETURN_USER_TASK"
|
||||
label="驳回节点"
|
||||
prop="returnNodeId"
|
||||
>
|
||||
<el-select filterable v-model="configForm.returnNodeId" clearable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in returnTaskList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">审批人超时未处理时</el-divider>
|
||||
<el-form-item label="启用开关" prop="timeoutHandlerEnable">
|
||||
<el-switch
|
||||
v-model="configForm.timeoutHandlerEnable"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
@change="timeoutHandlerChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="执行动作"
|
||||
prop="timeoutHandlerType"
|
||||
v-if="configForm.timeoutHandlerEnable"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="configForm.timeoutHandlerType"
|
||||
@change="timeoutHandlerTypeChanged"
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="configForm.rejectHandlerType == RejectHandlerType.RETURN_USER_TASK"
|
||||
label="驳回节点"
|
||||
prop="returnNodeId"
|
||||
>
|
||||
<el-radio-button
|
||||
v-for="item in TIMEOUT_HANDLER_TYPES"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="超时时间设置" v-if="configForm.timeoutHandlerEnable">
|
||||
<span class="mr-2">当超过</span>
|
||||
<el-form-item prop="timeDuration">
|
||||
<el-input-number
|
||||
class="mr-2"
|
||||
:style="{ width: '100px' }"
|
||||
v-model="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
<el-select
|
||||
filterable
|
||||
v-model="configForm.returnNodeId"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in returnTaskList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
||||
<el-divider content-position="left">审批人超时未处理时</el-divider>
|
||||
<el-form-item label="启用开关" prop="timeoutHandlerEnable">
|
||||
<el-switch
|
||||
v-model="configForm.timeoutHandlerEnable"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
@change="timeoutHandlerChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-select
|
||||
filterable
|
||||
v-model="timeUnit"
|
||||
class="mr-2"
|
||||
:style="{ width: '100px' }"
|
||||
@change="timeUnitChange"
|
||||
<el-form-item
|
||||
label="执行动作"
|
||||
prop="timeoutHandlerType"
|
||||
v-if="configForm.timeoutHandlerEnable"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in TIME_UNIT_TYPES"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
未处理
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="最大提醒次数"
|
||||
prop="maxRemindCount"
|
||||
v-if="configForm.timeoutHandlerEnable && configForm.timeoutHandlerType === 1"
|
||||
>
|
||||
<el-input-number v-model="configForm.maxRemindCount" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
<el-radio-group
|
||||
v-model="configForm.timeoutHandlerType"
|
||||
@change="timeoutHandlerTypeChanged"
|
||||
>
|
||||
<el-radio-button
|
||||
v-for="item in TIMEOUT_HANDLER_TYPES"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="超时时间设置" v-if="configForm.timeoutHandlerEnable">
|
||||
<span class="mr-2">当超过</span>
|
||||
<el-form-item prop="timeDuration">
|
||||
<el-input-number
|
||||
class="mr-2"
|
||||
:style="{ width: '100px' }"
|
||||
v-model="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-select
|
||||
filterable
|
||||
v-model="timeUnit"
|
||||
class="mr-2"
|
||||
:style="{ width: '100px' }"
|
||||
@change="timeUnitChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in TIME_UNIT_TYPES"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
未处理
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="最大提醒次数"
|
||||
prop="maxRemindCount"
|
||||
v-if="configForm.timeoutHandlerEnable && configForm.timeoutHandlerType === 1"
|
||||
>
|
||||
<el-input-number v-model="configForm.maxRemindCount" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-divider content-position="left">审批人为空时</el-divider>
|
||||
<el-divider content-position="left">{{ nodeTypeName }}人为空时</el-divider>
|
||||
<el-form-item prop="assignEmptyHandlerType">
|
||||
<el-radio-group v-model="configForm.assignEmptyHandlerType">
|
||||
<div class="flex-col">
|
||||
|
|
@ -348,30 +381,44 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">审批人与提交人为同一人时</el-divider>
|
||||
<el-form-item prop="assignStartUserHandlerType">
|
||||
<el-radio-group v-model="configForm.assignStartUserHandlerType">
|
||||
<div class="flex-col">
|
||||
<div v-for="(item, index) in ASSIGN_START_USER_HANDLER_TYPES" :key="index">
|
||||
<el-radio :key="item.value" :value="item.value" :label="item.label" />
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
||||
<el-divider content-position="left">审批人与提交人为同一人时</el-divider>
|
||||
<el-form-item prop="assignStartUserHandlerType">
|
||||
<el-radio-group v-model="configForm.assignStartUserHandlerType">
|
||||
<div class="flex-col">
|
||||
<div v-for="(item, index) in ASSIGN_START_USER_HANDLER_TYPES" :key="index">
|
||||
<el-radio :key="item.value" :value="item.value" :label="item.label" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-divider content-position="left">是否需要签名</el-divider>
|
||||
<el-form-item prop="signEnable">
|
||||
<el-switch v-model="configForm.signEnable" active-text="是" inactive-text="否" />
|
||||
</el-form-item>
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
||||
<el-divider content-position="left">是否需要签名</el-divider>
|
||||
<el-form-item prop="signEnable">
|
||||
<el-switch v-model="configForm.signEnable" active-text="是" inactive-text="否" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-divider content-position="left">审批意见</el-divider>
|
||||
<el-form-item prop="reasonRequire">
|
||||
<el-switch v-model="configForm.reasonRequire" active-text="必填" inactive-text="非必填" />
|
||||
</el-form-item>
|
||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
||||
<el-divider content-position="left">审批意见</el-divider>
|
||||
<el-form-item prop="reasonRequire">
|
||||
<el-switch
|
||||
v-model="configForm.reasonRequire"
|
||||
active-text="必填"
|
||||
inactive-text="非必填"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="操作按钮设置" name="buttons">
|
||||
<el-tab-pane
|
||||
label="操作按钮设置"
|
||||
v-if="currentNode.type === NodeType.USER_TASK_NODE"
|
||||
name="buttons"
|
||||
>
|
||||
<div class="button-setting-pane">
|
||||
<div class="button-setting-desc">操作按钮</div>
|
||||
<div class="button-setting-title">
|
||||
|
|
@ -407,9 +454,15 @@
|
|||
<div class="field-permit-title">
|
||||
<div class="setting-title-label first-title"> 字段名称 </div>
|
||||
<div class="other-titles">
|
||||
<span class="setting-title-label">只读</span>
|
||||
<span class="setting-title-label">可编辑</span>
|
||||
<span class="setting-title-label">隐藏</span>
|
||||
<span class="setting-title-label">只读
|
||||
<el-switch v-model="readSwitch" @change="updatePermission('READ')" />
|
||||
</span>
|
||||
<span class="setting-title-label">可编辑
|
||||
<el-switch v-model="writeSwitch" @change="updatePermission('WRITE')" />
|
||||
</span>
|
||||
<span class="setting-title-label">隐藏
|
||||
<el-switch v-model="noneSwitch" @change="updatePermission('NONE')" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -448,7 +501,11 @@
|
|||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="监听器" name="listener">
|
||||
<UserTaskListener ref="userTaskListenerRef" v-model="configForm" :form-field-options="formFieldOptions" />
|
||||
<UserTaskListener
|
||||
ref="userTaskListenerRef"
|
||||
v-model="configForm"
|
||||
:form-field-options="formFieldOptions"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #footer>
|
||||
|
|
@ -485,7 +542,8 @@ import {
|
|||
ASSIGN_EMPTY_HANDLER_TYPES,
|
||||
AssignEmptyHandlerType,
|
||||
FieldPermissionType,
|
||||
ProcessVariableEnum
|
||||
ProcessVariableEnum,
|
||||
TRANSACTOR_DEFAULT_BUTTON_SETTING
|
||||
} from '../consts'
|
||||
|
||||
import {
|
||||
|
|
@ -588,7 +646,7 @@ const {
|
|||
handleCandidateParam,
|
||||
parseCandidateParam,
|
||||
getShowText
|
||||
} = useNodeForm(NodeType.USER_TASK_NODE)
|
||||
} = useNodeForm(currentNode.value.type)
|
||||
const configForm = tempConfigForm as Ref<UserTaskFormType>
|
||||
|
||||
// 改变审批人设置策略
|
||||
|
|
@ -627,7 +685,12 @@ const {
|
|||
|
||||
const userTaskListenerRef = ref()
|
||||
|
||||
// 保存配置
|
||||
/** 节点类型名称 */
|
||||
const nodeTypeName = computed(() => {
|
||||
return currentNode.value.type === NodeType.TRANSACTOR_NODE ? '办理' : '审批'
|
||||
})
|
||||
|
||||
/** 保存配置 */
|
||||
const saveConfig = async () => {
|
||||
// activeTabName.value = 'user'
|
||||
// 设置审批节点名称
|
||||
|
|
@ -713,7 +776,7 @@ const saveConfig = async () => {
|
|||
return true
|
||||
}
|
||||
|
||||
// 显示审批节点配置, 由父组件传过来
|
||||
/** 显示审批节点配置, 由父组件传过来 */
|
||||
const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
||||
nodeName.value = node.name
|
||||
// 1 审批类型
|
||||
|
|
@ -733,13 +796,13 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
configForm.value.approveRatio = node.approveRatio!
|
||||
}
|
||||
// 2.3 设置审批拒绝处理
|
||||
configForm.value.rejectHandlerType = node.rejectHandler!.type
|
||||
configForm.value.rejectHandlerType = node.rejectHandler?.type
|
||||
configForm.value.returnNodeId = node.rejectHandler?.returnNodeId
|
||||
const matchNodeList = []
|
||||
emits('find:returnTaskNodes', matchNodeList)
|
||||
returnTaskList.value = matchNodeList
|
||||
// 2.4 设置审批超时处理
|
||||
configForm.value.timeoutHandlerEnable = node.timeoutHandler!.enable
|
||||
configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable
|
||||
if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) {
|
||||
const strTimeDuration = node.timeoutHandler.timeDuration
|
||||
let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
|
||||
|
|
@ -755,7 +818,11 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
// 2.6 设置用户任务的审批人与发起人相同时
|
||||
configForm.value.assignStartUserHandlerType = node.assignStartUserHandlerType
|
||||
// 3. 操作按钮设置
|
||||
buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
|
||||
buttonsSetting.value =
|
||||
cloneDeep(node.buttonsSetting) ||
|
||||
(node.type === NodeType.TRANSACTOR_NODE
|
||||
? TRANSACTOR_DEFAULT_BUTTON_SETTING
|
||||
: DEFAULT_BUTTON_SETTING)
|
||||
// 4. 表单字段权限配置
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
// 5. 监听器
|
||||
|
|
@ -773,7 +840,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
header: node.taskAssignListener?.header ?? [],
|
||||
body: node.taskAssignListener?.body ?? []
|
||||
}
|
||||
// 5.3 完成任务
|
||||
// 5.3 完成任务
|
||||
configForm.value.taskCompleteListenerEnable = node.taskCompleteListener?.enable
|
||||
configForm.value.taskCompleteListenerPath = node.taskCompleteListener?.path
|
||||
configForm.value.taskCompleteListener = {
|
||||
|
|
@ -788,9 +855,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
|||
|
||||
defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件
|
||||
|
||||
/**
|
||||
* @description 操作按钮设置
|
||||
*/
|
||||
/** 操作按钮设置 */
|
||||
function useButtonsSetting() {
|
||||
const buttonsSetting = ref<ButtonSetting[]>()
|
||||
// 操作按钮显示名称可编辑
|
||||
|
|
@ -811,9 +876,7 @@ function useButtonsSetting() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 审批人超时未处理配置
|
||||
*/
|
||||
/** 审批人超时未处理配置 */
|
||||
function useTimeoutHandler() {
|
||||
// 时间单位
|
||||
const timeUnit = ref(TimeUnitType.HOUR)
|
||||
|
|
@ -896,6 +959,31 @@ function useTimeoutHandler() {
|
|||
cTimeoutMaxRemindCount
|
||||
}
|
||||
}
|
||||
const readSwitch = ref(false);
|
||||
const writeSwitch = ref(false);
|
||||
const noneSwitch = ref(false);
|
||||
|
||||
const updatePermission = (type: string) => {
|
||||
if (type === 'READ') {
|
||||
readSwitch.value = true;
|
||||
writeSwitch.value = false;
|
||||
noneSwitch.value = false;
|
||||
} else if (type === 'WRITE') {
|
||||
readSwitch.value = false;
|
||||
writeSwitch.value = true;
|
||||
noneSwitch.value = false;
|
||||
} else if (type === 'NONE') {
|
||||
readSwitch.value = false;
|
||||
writeSwitch.value = false;
|
||||
noneSwitch.value = true;
|
||||
}
|
||||
|
||||
fieldsPermissionConfig.value.forEach(field => {
|
||||
field.permission = type === 'READ' ? FieldPermissionType.READ :
|
||||
type === 'WRITE' ? FieldPermissionType.WRITE :
|
||||
FieldPermissionType.NONE;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,303 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" title="条件配置" width="600px" :fullscreen="false">
|
||||
<div class="h-410px">
|
||||
<el-scrollbar wrap-class="h-full">
|
||||
<el-form ref="formRef" :model="condition" :rules="formRules" label-position="top">
|
||||
<el-form-item label="配置方式" prop="conditionType">
|
||||
<el-radio-group v-model="condition.conditionType" @change="changeConditionType">
|
||||
<el-radio
|
||||
v-for="(dict, indexConditionType) in conditionConfigTypes"
|
||||
:key="indexConditionType"
|
||||
:value="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="condition.conditionType === ConditionType.RULE && condition.conditionGroups"
|
||||
label="条件规则"
|
||||
>
|
||||
<div class="condition-group-tool">
|
||||
<div class="flex items-center">
|
||||
<div class="mr-4">条件组关系</div>
|
||||
<el-switch
|
||||
v-model="condition.conditionGroups.and"
|
||||
inline-prompt
|
||||
active-text="且"
|
||||
inactive-text="或"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-space direction="vertical" :spacer="condition.conditionGroups.and ? '且' : '或'">
|
||||
<el-card
|
||||
class="condition-group"
|
||||
style="width: 530px"
|
||||
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
||||
:key="cIdx"
|
||||
>
|
||||
<div
|
||||
class="condition-group-delete"
|
||||
v-if="condition.conditionGroups.conditions.length > 1"
|
||||
>
|
||||
<Icon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
:size="18"
|
||||
@click="deleteConditionGroup(condition.conditionGroups.conditions, cIdx)"
|
||||
/>
|
||||
</div>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>条件组</div>
|
||||
<div class="flex">
|
||||
<div class="mr-4">规则关系</div>
|
||||
<el-switch
|
||||
v-model="equation.and"
|
||||
inline-prompt
|
||||
active-text="且"
|
||||
inactive-text="或"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex pt-2" v-for="(rule, rIdx) in equation.rules" :key="rIdx">
|
||||
<div class="mr-2">
|
||||
<el-form-item
|
||||
:prop="`conditionGroups.conditions.${cIdx}.rules.${rIdx}.leftSide`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '左值不能为空',
|
||||
trigger: 'change'
|
||||
}"
|
||||
>
|
||||
<el-select style="width: 160px" v-model="rule.leftSide">
|
||||
<el-option
|
||||
v-for="(field, fIdx) in fieldOptions"
|
||||
:key="fIdx"
|
||||
:label="field.title"
|
||||
:value="field.field"
|
||||
:disabled="!field.required"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-select v-model="rule.opCode" style="width: 100px">
|
||||
<el-option
|
||||
v-for="operator in COMPARISON_OPERATORS"
|
||||
:key="operator.value"
|
||||
:label="operator.label"
|
||||
:value="operator.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<el-form-item
|
||||
:prop="`conditionGroups.conditions.${cIdx}.rules.${rIdx}.rightSide`"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '右值不能为空',
|
||||
trigger: 'blur'
|
||||
}"
|
||||
>
|
||||
<el-input v-model="rule.rightSide" style="width: 160px" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="cursor-pointer mr-1 flex items-center" v-if="equation.rules.length > 1">
|
||||
<Icon
|
||||
icon="ep:delete"
|
||||
:size="18"
|
||||
@click="deleteConditionRule(equation, rIdx)"
|
||||
/>
|
||||
</div>
|
||||
<div class="cursor-pointer flex items-center">
|
||||
<Icon icon="ep:plus" :size="18" @click="addConditionRule(equation, rIdx)" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
<div title="添加条件组" class="mt-4 cursor-pointer">
|
||||
<Icon
|
||||
color="#0089ff"
|
||||
icon="ep:plus"
|
||||
:size="24"
|
||||
@click="addConditionGroup(condition.conditionGroups?.conditions)"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="condition.conditionType === ConditionType.EXPRESSION"
|
||||
label="条件表达式"
|
||||
prop="conditionExpression"
|
||||
>
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="condition.conditionExpression"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
COMPARISON_OPERATORS,
|
||||
CONDITION_CONFIG_TYPES,
|
||||
ConditionType,
|
||||
ConditionGroup,
|
||||
DEFAULT_CONDITION_GROUP_VALUE
|
||||
} from '../../consts'
|
||||
import { BpmModelFormType } from '@/utils/constants'
|
||||
import { useFormFieldsAndStartUser } from '../../node'
|
||||
defineOptions({
|
||||
name: 'ConditionDialog'
|
||||
})
|
||||
|
||||
const condition = ref<{
|
||||
conditionType: ConditionType
|
||||
conditionExpression?: string
|
||||
conditionGroups?: ConditionGroup
|
||||
}>({
|
||||
conditionType: ConditionType.RULE,
|
||||
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
updateCondition: [condition: object]
|
||||
}>()
|
||||
const message = useMessage() // 消息弹窗
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
|
||||
const formType = inject<Ref<number>>('formType') // 表单类型
|
||||
const conditionConfigTypes = computed(() => {
|
||||
return CONDITION_CONFIG_TYPES.filter((item) => {
|
||||
// 业务表单暂时去掉条件规则选项
|
||||
if (formType?.value === BpmModelFormType.CUSTOM && item.value === ConditionType.RULE) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/** 条件规则可选择的表单字段 */
|
||||
const fieldOptions = useFormFieldsAndStartUser()
|
||||
|
||||
// 表单校验规则
|
||||
const formRules = reactive({
|
||||
conditionType: [{ required: true, message: '配置方式不能为空', trigger: 'blur' }],
|
||||
conditionExpression: [{ required: true, message: '条件表达式不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 切换条件配置方式 */
|
||||
const changeConditionType = () => {
|
||||
if (condition.value.conditionType === ConditionType.RULE) {
|
||||
if (!condition.value.conditionGroups) {
|
||||
condition.value.conditionGroups = DEFAULT_CONDITION_GROUP_VALUE
|
||||
}
|
||||
}
|
||||
}
|
||||
const deleteConditionGroup = (conditions, index) => {
|
||||
conditions.splice(index, 1)
|
||||
}
|
||||
|
||||
const deleteConditionRule = (condition, index) => {
|
||||
condition.rules.splice(index, 1)
|
||||
}
|
||||
|
||||
const addConditionRule = (condition, index) => {
|
||||
const rule = {
|
||||
opCode: '==',
|
||||
leftSide: '',
|
||||
rightSide: ''
|
||||
}
|
||||
condition.rules.splice(index + 1, 0, rule)
|
||||
}
|
||||
|
||||
const addConditionGroup = (conditions) => {
|
||||
const condition = {
|
||||
and: true,
|
||||
rules: [
|
||||
{
|
||||
opCode: '==',
|
||||
leftSide: '',
|
||||
rightSide: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
conditions.push(condition)
|
||||
}
|
||||
|
||||
/** 保存条件设置 */
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) {
|
||||
message.warning('请完善条件规则')
|
||||
return
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 设置完的条件传递给父组件
|
||||
emit('updateCondition', condition.value)
|
||||
}
|
||||
|
||||
const open = (conditionObj: any | undefined) => {
|
||||
if (conditionObj) {
|
||||
condition.value.conditionType = conditionObj.conditionType
|
||||
condition.value.conditionExpression = conditionObj.conditionExpression
|
||||
condition.value.conditionGroups = conditionObj.conditionGroups
|
||||
}
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.condition-group-tool {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 500px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.condition-group {
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
border-color: #0089ff;
|
||||
|
||||
.condition-group-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.condition-group-delete {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-card__header) {
|
||||
padding: 8px var(--el-card-padding);
|
||||
border-bottom: 1px solid var(--el-card-border-color);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -9,7 +9,14 @@
|
|||
]"
|
||||
>
|
||||
<div class="node-title-container">
|
||||
<div class="node-title-icon user-task"><span class="iconfont icon-approve"></span></div>
|
||||
<div
|
||||
:class="`node-title-icon ${currentNode.type === NodeType.TRANSACTOR_NODE ? 'transactor-task' : 'user-task'}`"
|
||||
>
|
||||
<span
|
||||
:class="`iconfont ${currentNode.type === NodeType.TRANSACTOR_NODE ? 'icon-transactor' : 'icon-approve'}`"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
v-if="!readonly && showInput"
|
||||
type="text"
|
||||
|
|
@ -28,7 +35,7 @@
|
|||
{{ currentNode.showText }}
|
||||
</div>
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(NodeType.USER_TASK_NODE) }}
|
||||
{{ NODE_DEFAULT_TEXT.get(currentNode.type) }}
|
||||
</div>
|
||||
<Icon icon="ep:arrow-right-bold" v-if="!readonly" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -177,6 +177,10 @@
|
|||
color: #ca3a31
|
||||
}
|
||||
|
||||
.transactor {
|
||||
color: #330099;
|
||||
}
|
||||
|
||||
.handler-item-text {
|
||||
margin-top: 4px;
|
||||
width: 80px;
|
||||
|
|
@ -290,10 +294,14 @@
|
|||
&.trigger-node {
|
||||
color: #3373d2;
|
||||
}
|
||||
|
||||
|
||||
&.router-node {
|
||||
color: #ca3a31
|
||||
}
|
||||
|
||||
&.transactor-task {
|
||||
color: #330099;
|
||||
}
|
||||
}
|
||||
|
||||
.node-title {
|
||||
|
|
@ -777,7 +785,7 @@
|
|||
content: "\e7eb";
|
||||
}
|
||||
|
||||
.icon-handle:before {
|
||||
.icon-transactor:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ import {
|
|||
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { useFormFieldsPermission } from '@/components/SimpleProcessDesignerV2/src/node'
|
||||
import { BpmModelFormType } from '@/utils/constants'
|
||||
|
||||
defineOptions({ name: 'ElementCustomConfig4UserTask' })
|
||||
const props = defineProps({
|
||||
|
|
@ -248,7 +249,6 @@ const resetCustomConfigList = () => {
|
|||
bpmnElement.value.id,
|
||||
bpmnInstances().modeler
|
||||
)
|
||||
|
||||
// 获取元素扩展属性 或者 创建扩展属性
|
||||
elExtensionElements.value =
|
||||
bpmnElement.value.businessObject?.extensionElements ??
|
||||
|
|
@ -311,14 +311,13 @@ const resetCustomConfigList = () => {
|
|||
}
|
||||
|
||||
// 字段权限
|
||||
if (formType.value === 10) {
|
||||
if (formType.value === BpmModelFormType.NORMAL) {
|
||||
const fieldsPermissionList = elExtensionElements.value.values?.filter(
|
||||
(ex) => ex.$type === `${prefix}:FieldsPermission`
|
||||
)
|
||||
fieldsPermissionEl.value = []
|
||||
getNodeConfigFormFields()
|
||||
// 由于默认添加了发起人元素,这里需要删掉
|
||||
fieldsPermissionConfig.value = fieldsPermissionConfig.value.slice(1)
|
||||
fieldsPermissionConfig.value = fieldsPermissionConfig.value
|
||||
fieldsPermissionConfig.value.forEach((element) => {
|
||||
element.permission =
|
||||
fieldsPermissionList?.find((obj) => obj.field === element.field)?.permission ?? '1'
|
||||
|
|
@ -497,9 +496,9 @@ onMounted(async () => {
|
|||
<style lang="scss" scoped>
|
||||
.button-setting-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 14px;
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
flex-direction: column;
|
||||
|
||||
.button-setting-desc {
|
||||
padding-right: 8px;
|
||||
|
|
|
|||
|
|
@ -453,14 +453,14 @@ export function jsonParse(str: string) {
|
|||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param name
|
||||
* @param start
|
||||
* @param end
|
||||
* @param str 字符串
|
||||
* @param start 开始位置
|
||||
* @param end 结束位置
|
||||
*/
|
||||
|
||||
export const sliceName = (name: string,start: number, end : number) => {
|
||||
if (name.length > end) {
|
||||
return name.slice(start, end)
|
||||
export const subString = (str: string, start: number, end: number) => {
|
||||
if (str.length > end) {
|
||||
return str.slice(start, end)
|
||||
}
|
||||
return name
|
||||
return str
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
</el-tooltip>
|
||||
<el-image v-if="row.icon" :src="row.icon" class="h-38px w-38px mr-10px rounded" />
|
||||
<div v-else class="flow-icon">
|
||||
<span style="font-size: 12px; color: #fff">{{ sliceName(row.name,0,2) }}</span>
|
||||
<span style="font-size: 12px; color: #fff">{{ subString(row.name, 0, 2) }}</span>
|
||||
</div>
|
||||
{{ row.name }}
|
||||
</div>
|
||||
|
|
@ -273,7 +273,7 @@ import { useAppStore } from '@/store/modules/app'
|
|||
import { cloneDeep, isEqual } from 'lodash-es'
|
||||
import { useTagsView } from '@/hooks/web/useTagsView'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { sliceName } from '@/utils/index'
|
||||
import { subString } from '@/utils/index'
|
||||
|
||||
defineOptions({ name: 'BpmModel' })
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ import CustomContentPadProvider from '@/components/bpmnProcessDesigner/package/d
|
|||
// 自定义左侧菜单(修改 默认任务 为 用户任务)
|
||||
import CustomPaletteProvider from '@/components/bpmnProcessDesigner/package/designer/plugins/palette'
|
||||
import * as ModelApi from '@/api/bpm/model'
|
||||
import { BpmModelFormType } from '@/utils/constants'
|
||||
import * as FormApi from '@/api/bpm/form'
|
||||
|
||||
defineOptions({ name: 'BpmModelEditor' })
|
||||
|
||||
|
|
@ -49,7 +51,8 @@ const message = useMessage() // 国际化
|
|||
|
||||
// 表单信息
|
||||
const formFields = ref<string[]>([])
|
||||
const formType = ref(20)
|
||||
// 表单类型,暂仅限流程表单
|
||||
const formType = ref(BpmModelFormType.NORMAL)
|
||||
provide('formFields', formFields)
|
||||
provide('formType', formType)
|
||||
|
||||
|
|
@ -88,6 +91,20 @@ const save = async (bpmnXml: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
/** 监听表单 ID 变化,加载表单数据 */
|
||||
watch(
|
||||
() => modelData.value.formId,
|
||||
async (newFormId) => {
|
||||
if (newFormId && modelData.value.formType === BpmModelFormType.NORMAL) {
|
||||
const data = await FormApi.getForm(newFormId)
|
||||
formFields.value = data.fields
|
||||
} else {
|
||||
formFields.value = []
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 在组件卸载时清理
|
||||
onBeforeUnmount(() => {
|
||||
modeler.value = null
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modelData.formType === 10" label="流程表单" prop="formId">
|
||||
<el-form-item v-if="modelData.formType === BpmModelFormType.NORMAL" label="流程表单" prop="formId">
|
||||
<el-select v-model="modelData.formId" clearable style="width: 100%">
|
||||
<el-option v-for="form in formList" :key="form.id" :label="form.name" :value="form.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modelData.formType === 20" label="表单提交路由" prop="formCustomCreatePath">
|
||||
<el-form-item v-if="modelData.formType === BpmModelFormType.CUSTOM" label="表单提交路由" prop="formCustomCreatePath">
|
||||
<el-input
|
||||
v-model="modelData.formCustomCreatePath"
|
||||
placeholder="请输入表单提交路由"
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<Icon icon="ep:question" class="ml-5px" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modelData.formType === 20" label="表单查看地址" prop="formCustomViewPath">
|
||||
<el-form-item v-if="modelData.formType === BpmModelFormType.CUSTOM" label="表单查看地址" prop="formCustomViewPath">
|
||||
<el-input
|
||||
v-model="modelData.formCustomViewPath"
|
||||
placeholder="请输入表单查看的组件地址"
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
</el-form-item>
|
||||
<!-- 表单预览 -->
|
||||
<div
|
||||
v-if="modelData.formType === 10 && modelData.formId && formPreview.rule.length > 0"
|
||||
v-if="modelData.formType === BpmModelFormType.NORMAL && modelData.formId && formPreview.rule.length > 0"
|
||||
class="mt-20px"
|
||||
>
|
||||
<div class="flex items-center mb-15px">
|
||||
|
|
@ -68,6 +68,7 @@
|
|||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as FormApi from '@/api/bpm/form'
|
||||
import { setConfAndFields2 } from '@/utils/formCreate'
|
||||
import { BpmModelFormType } from '@/utils/constants'
|
||||
|
||||
const props = defineProps({
|
||||
formList: {
|
||||
|
|
@ -96,7 +97,7 @@ const formPreview = ref({
|
|||
watch(
|
||||
() => modelData.value.formId,
|
||||
async (newFormId) => {
|
||||
if (newFormId && modelData.value.formType === 10) {
|
||||
if (newFormId && modelData.value.formType === BpmModelFormType.NORMAL) {
|
||||
const data = await FormApi.getForm(newFormId)
|
||||
setConfAndFields2(formPreview.value, data.conf, data.fields)
|
||||
// 设置只读
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@
|
|||
class="w-32px h-32px"
|
||||
/>
|
||||
<div v-else class="flow-icon">
|
||||
<span style="font-size: 12px; color: #fff">{{
|
||||
sliceName(definition.name,0,2)
|
||||
}}</span>
|
||||
<span style="font-size: 12px; color: #fff">
|
||||
{{ subString(definition.name, 0, 2) }}
|
||||
</span>
|
||||
</div>
|
||||
<el-text class="!ml-10px" size="large">{{ definition.name }}</el-text>
|
||||
</div>
|
||||
|
|
@ -97,7 +97,7 @@ import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
|||
import { CategoryApi, CategoryVO } from '@/api/bpm/category'
|
||||
import ProcessDefinitionDetail from './ProcessDefinitionDetail.vue'
|
||||
import { groupBy } from 'lodash-es'
|
||||
import { sliceName } from '@/utils/index'
|
||||
import { subString } from '@/utils/index'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceCreate' })
|
||||
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@
|
|||
:rule="approveForm.rule"
|
||||
/>
|
||||
</el-card>
|
||||
<el-form-item label="审批意见" prop="reason">
|
||||
<el-form-item :label="`${nodeTypeName}意见`" prop="reason">
|
||||
<el-input
|
||||
v-model="approveReasonForm.reason"
|
||||
placeholder="请输入审批意见"
|
||||
:placeholder="`请输入${nodeTypeName}意见`"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
/>
|
||||
|
|
@ -504,6 +504,7 @@ import * as TaskApi from '@/api/bpm/task'
|
|||
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import {
|
||||
NodeType,
|
||||
OPERATION_BUTTON_NAME,
|
||||
OperationButtonType
|
||||
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
||||
|
|
@ -546,6 +547,7 @@ const returnList = ref([] as any) // 退回节点
|
|||
const runningTask = ref<any>() // 运行中的任务
|
||||
const approveForm = ref<any>({}) // 审批通过时,额外的补充信息
|
||||
const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
|
||||
const nodeTypeName = ref('审批') // 节点类型名称
|
||||
|
||||
// 审批通过意见表单
|
||||
const reasonRequire = ref()
|
||||
|
|
@ -558,7 +560,9 @@ const approveReasonForm = reactive({
|
|||
})
|
||||
const approveReasonRule = computed(() => {
|
||||
return {
|
||||
reason: [{ required: reasonRequire.value, message: '审批意见不能为空', trigger: 'blur' }],
|
||||
reason: [
|
||||
{ required: reasonRequire.value, message: nodeTypeName + '意见不能为空', trigger: 'blur' }
|
||||
],
|
||||
signPicUrl: [{ required: true, message: '签名不能为空', trigger: 'change' }]
|
||||
}
|
||||
})
|
||||
|
|
@ -969,9 +973,10 @@ const getButtonDisplayName = (btnType: OperationButtonType) => {
|
|||
|
||||
const loadTodoTask = (task: any) => {
|
||||
approveForm.value = {}
|
||||
approveFormFApi.value = {}
|
||||
runningTask.value = task
|
||||
approveFormFApi.value = {}
|
||||
reasonRequire.value = task?.reasonRequire ?? false
|
||||
nodeTypeName.value = task?.nodeType === NodeType.TRANSACTOR_NODE ? '办理' : '审批'
|
||||
// 处理 approve 表单.
|
||||
if (task && task.formId && task.formConf) {
|
||||
const tempApproveForm = {}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ const setSimpleModelNodeTaskStatus = (
|
|||
// 审批节点
|
||||
if (
|
||||
simpleModel.type === NodeType.START_USER_NODE ||
|
||||
simpleModel.type === NodeType.USER_TASK_NODE
|
||||
simpleModel.type === NodeType.USER_TASK_NODE ||
|
||||
simpleModel.type === NodeType.TRANSACTOR_NODE
|
||||
) {
|
||||
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||
if (rejectedTaskActivityIds.includes(simpleModel.id)) {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@
|
|||
"
|
||||
class="text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
|
||||
>
|
||||
<!-- TODO lesan:这里如果是办理,需要是办理意见 -->
|
||||
审批意见:{{ task.reason }}
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -179,6 +180,7 @@ import copySvg from '@/assets/svgs/bpm/copy.svg'
|
|||
import conditionSvg from '@/assets/svgs/bpm/condition.svg'
|
||||
import parallelSvg from '@/assets/svgs/bpm/parallel.svg'
|
||||
import finishSvg from '@/assets/svgs/bpm/finish.svg'
|
||||
import transactorSvg from '@/assets/svgs/bpm/transactor.svg'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceTimeline' })
|
||||
withDefaults(
|
||||
|
|
@ -240,6 +242,8 @@ const nodeTypeSvgMap = {
|
|||
[NodeType.START_USER_NODE]: { color: '#909398', svg: starterSvg },
|
||||
// 审批人节点
|
||||
[NodeType.USER_TASK_NODE]: { color: '#ff943e', svg: auditorSvg },
|
||||
// 办理人节点
|
||||
[NodeType.TRANSACTOR_NODE]: { color: '#ff943e', svg: transactorSvg },
|
||||
// 抄送人节点
|
||||
[NodeType.COPY_TASK_NODE]: { color: '#3296fb', svg: copySvg },
|
||||
// 条件分支节点
|
||||
|
|
@ -264,6 +268,7 @@ const getApprovalNodeIcon = (taskStatus: number, nodeType: NodeType) => {
|
|||
if (
|
||||
nodeType === NodeType.START_USER_NODE ||
|
||||
nodeType === NodeType.USER_TASK_NODE ||
|
||||
nodeType === NodeType.TRANSACTOR_NODE ||
|
||||
nodeType === NodeType.END_EVENT_NODE
|
||||
) {
|
||||
return statusIconMap[taskStatus]?.icon
|
||||
|
|
|
|||
Loading…
Reference in New Issue