【功能完善】审批时,流程表单可编辑字段,可修改。
parent
ee46a31a81
commit
0b6af855ac
|
@ -15,7 +15,6 @@ import {
|
||||||
AssignStartUserHandlerType,
|
AssignStartUserHandlerType,
|
||||||
AssignEmptyHandlerType,
|
AssignEmptyHandlerType,
|
||||||
FieldPermissionType,
|
FieldPermissionType,
|
||||||
ProcessVariableEnum
|
|
||||||
} from './consts'
|
} from './consts'
|
||||||
import { parseFormFields } from '@/components/FormCreate/src/utils/index'
|
import { parseFormFields } from '@/components/FormCreate/src/utils/index'
|
||||||
export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
|
export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
|
||||||
|
@ -37,13 +36,6 @@ const parseFormCreateFields = (formFields?: string[]) => {
|
||||||
parseFormFields(JSON.parse(fieldStr), result)
|
parseFormFields(JSON.parse(fieldStr), result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 固定添加发起人 ID 字段
|
|
||||||
result.unshift({
|
|
||||||
field: ProcessVariableEnum.START_USER_ID,
|
|
||||||
title: '发起人',
|
|
||||||
type: 'UserSelect',
|
|
||||||
required: true
|
|
||||||
})
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
<div class="mr-2">
|
<div class="mr-2">
|
||||||
<el-select style="width: 160px" v-model="rule.leftSide">
|
<el-select style="width: 160px" v-model="rule.leftSide">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item, index) in fieldsInfo"
|
v-for="(item, index) in fieldOptions"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.title"
|
:label="item.title"
|
||||||
:value="item.field"
|
:value="item.field"
|
||||||
|
@ -160,7 +160,8 @@ import {
|
||||||
COMPARISON_OPERATORS,
|
COMPARISON_OPERATORS,
|
||||||
ConditionGroup,
|
ConditionGroup,
|
||||||
Condition,
|
Condition,
|
||||||
ConditionRule
|
ConditionRule,
|
||||||
|
ProcessVariableEnum
|
||||||
} from '../consts'
|
} from '../consts'
|
||||||
import { getDefaultConditionNodeName } from '../utils'
|
import { getDefaultConditionNodeName } from '../utils'
|
||||||
import { useFormFields } from '../node'
|
import { useFormFields } from '../node'
|
||||||
|
@ -364,9 +365,21 @@ const addConditionRule = (condition: Condition, idx: number) => {
|
||||||
const deleteConditionRule = (condition: Condition, idx: number) => {
|
const deleteConditionRule = (condition: Condition, idx: number) => {
|
||||||
condition.rules.splice(idx, 1)
|
condition.rules.splice(idx, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldsInfo = useFormFields()
|
const fieldsInfo = useFormFields()
|
||||||
|
|
||||||
|
/** 条件规则可选择的表单字段 */
|
||||||
|
const fieldOptions = computed(() => {
|
||||||
|
const fieldsCopy = fieldsInfo.slice();
|
||||||
|
// 固定添加发起人 ID 字段
|
||||||
|
fieldsCopy.unshift({
|
||||||
|
field: ProcessVariableEnum.START_USER_ID,
|
||||||
|
title: '发起人',
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
return fieldsCopy
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const getFieldTitle = (field: string) => {
|
const getFieldTitle = (field: string) => {
|
||||||
const item = fieldsInfo.find((item) => item.field === field)
|
const item = fieldsInfo.find((item) => item.field === field)
|
||||||
return item?.title
|
return item?.title
|
||||||
|
|
|
@ -469,7 +469,8 @@ import {
|
||||||
TimeoutHandlerType,
|
TimeoutHandlerType,
|
||||||
ASSIGN_EMPTY_HANDLER_TYPES,
|
ASSIGN_EMPTY_HANDLER_TYPES,
|
||||||
AssignEmptyHandlerType,
|
AssignEmptyHandlerType,
|
||||||
FieldPermissionType
|
FieldPermissionType,
|
||||||
|
ProcessVariableEnum
|
||||||
} from '../consts'
|
} from '../consts'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -519,6 +520,13 @@ const { formType, fieldsPermissionConfig, formFieldOptions, getNodeConfigFormFie
|
||||||
useFormFieldsPermission(FieldPermissionType.READ)
|
useFormFieldsPermission(FieldPermissionType.READ)
|
||||||
// 表单内用户字段选项, 必须是必填和用户选择器
|
// 表单内用户字段选项, 必须是必填和用户选择器
|
||||||
const userFieldOnFormOptions = computed(() => {
|
const userFieldOnFormOptions = computed(() => {
|
||||||
|
// 固定添加发起人 ID 字段
|
||||||
|
formFieldOptions.unshift({
|
||||||
|
field: ProcessVariableEnum.START_USER_ID,
|
||||||
|
title: '发起人',
|
||||||
|
type: 'UserSelect',
|
||||||
|
required: true
|
||||||
|
})
|
||||||
return formFieldOptions.filter((item) => item.type === 'UserSelect')
|
return formFieldOptions.filter((item) => item.type === 'UserSelect')
|
||||||
})
|
})
|
||||||
// 表单内部门字段选项, 必须是必填和部门选择器
|
// 表单内部门字段选项, 必须是必填和部门选择器
|
||||||
|
|
|
@ -477,13 +477,12 @@ import { useUserStoreWithOut } from '@/store/modules/user'
|
||||||
import { setConfAndFields2 } from '@/utils/formCreate'
|
import { setConfAndFields2 } from '@/utils/formCreate'
|
||||||
import * as TaskApi from '@/api/bpm/task'
|
import * as TaskApi from '@/api/bpm/task'
|
||||||
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import * as UserApi from '@/api/system/user'
|
||||||
import {
|
import {
|
||||||
OperationButtonType,
|
OperationButtonType,
|
||||||
OPERATION_BUTTON_NAME
|
OPERATION_BUTTON_NAME
|
||||||
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
} from '@/components/SimpleProcessDesignerV2/src/consts'
|
||||||
import { BpmProcessInstanceStatus } from '@/utils/constants'
|
import { BpmProcessInstanceStatus, BpmModelFormType } from '@/utils/constants'
|
||||||
|
|
||||||
defineOptions({ name: 'ProcessInstanceBtnContainer' })
|
defineOptions({ name: 'ProcessInstanceBtnContainer' })
|
||||||
|
|
||||||
const router = useRouter() // 路由
|
const router = useRouter() // 路由
|
||||||
|
@ -492,11 +491,15 @@ const { proxy } = getCurrentInstance() as any
|
||||||
|
|
||||||
const userId = useUserStoreWithOut().getUser.id // 当前登录的编号
|
const userId = useUserStoreWithOut().getUser.id // 当前登录的编号
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const props = defineProps({
|
|
||||||
processInstance: propTypes.object, // 流程实例信息
|
const props = defineProps< {
|
||||||
processDefinition: propTypes.object, // 流程定义信息
|
processInstance: any, // 流程实例信息
|
||||||
userOptions: propTypes.any
|
processDefinition: any, // 流程定义信息
|
||||||
})
|
userOptions: UserApi.UserVO[],
|
||||||
|
normalForm: any, // 流程表单 formCreate
|
||||||
|
normalFormApi: any, // 流程表单 formCreate Api
|
||||||
|
writableFields: string[] // 流程表单可以编辑的字段
|
||||||
|
}>()
|
||||||
|
|
||||||
const formLoading = ref(false) // 表单加载中
|
const formLoading = ref(false) // 表单加载中
|
||||||
const popOverVisible = ref({
|
const popOverVisible = ref({
|
||||||
|
@ -554,6 +557,14 @@ const openReturnPopover = async () => {
|
||||||
|
|
||||||
/** 弹出气泡卡 */
|
/** 弹出气泡卡 */
|
||||||
const openPopover = async (type: string) => {
|
const openPopover = async (type: string) => {
|
||||||
|
if (type === 'approve') {
|
||||||
|
// 校验流程表单
|
||||||
|
const valid = await validateNormalForm();
|
||||||
|
if (!valid) {
|
||||||
|
message.error('表单校验不通过,请先完善表单!!')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
Object.keys(popOverVisible.value).forEach((item) => {
|
Object.keys(popOverVisible.value).forEach((item) => {
|
||||||
popOverVisible.value[item] = item === type
|
popOverVisible.value[item] = item === type
|
||||||
})
|
})
|
||||||
|
@ -565,24 +576,29 @@ const openPopover = async (type: string) => {
|
||||||
const handleAudit = async (pass: boolean) => {
|
const handleAudit = async (pass: boolean) => {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
|
// 校验审批表单
|
||||||
const genericFormRef = proxy.$refs['formRef']
|
const genericFormRef = proxy.$refs['formRef']
|
||||||
// 1.2 校验表单
|
|
||||||
const elForm = unref(genericFormRef)
|
const elForm = unref(genericFormRef)
|
||||||
if (!elForm) return
|
if (!elForm) return
|
||||||
const valid = await elForm.validate()
|
const valid = await elForm.validate()
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
|
// 提交审批
|
||||||
// 2.1 提交审批
|
|
||||||
const data = {
|
const data = {
|
||||||
id: runningTask.value.id,
|
id: runningTask.value.id,
|
||||||
reason: genericForm.value.reason
|
reason: genericForm.value.reason,
|
||||||
}
|
}
|
||||||
if (pass) {
|
if (pass) {
|
||||||
|
// 获取修改的流程变量, 暂时只支持流程表单
|
||||||
|
const variables = getUpdatedProcessInstanceVaiables();
|
||||||
|
// 审批通过, 把修改的字段值赋于流程实例变量
|
||||||
|
// @ts-ignore
|
||||||
|
data.variables = variables
|
||||||
// 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
|
// 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
|
||||||
const formCreateApi = approveFormFApi.value
|
const formCreateApi = approveFormFApi.value
|
||||||
if (Object.keys(formCreateApi)?.length > 0) {
|
if (Object.keys(formCreateApi)?.length > 0) {
|
||||||
await formCreateApi.validate()
|
await formCreateApi.validate()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
// TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
|
||||||
data.variables = approveForm.value.value
|
data.variables = approveForm.value.value
|
||||||
}
|
}
|
||||||
await TaskApi.approveTask(data)
|
await TaskApi.approveTask(data)
|
||||||
|
@ -855,6 +871,30 @@ const loadTodoTask = (task: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 校验流程表单 */
|
||||||
|
const validateNormalForm = async () => {
|
||||||
|
if (props.processDefinition?.formType === BpmModelFormType.NORMAL) {
|
||||||
|
let valid = true
|
||||||
|
try {
|
||||||
|
await props.normalFormApi?.validate()
|
||||||
|
} catch {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 从可以编辑的流程表单字段,获取需要修改的流程实例的变量 */
|
||||||
|
const getUpdatedProcessInstanceVaiables = ()=> {
|
||||||
|
const variables = {}
|
||||||
|
props.writableFields.forEach( (field) => {
|
||||||
|
const fieldValue = props.normalFormApi.getValue(field)
|
||||||
|
variables[field] = fieldValue;
|
||||||
|
})
|
||||||
|
return variables
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({ loadTodoTask })
|
defineExpose({ loadTodoTask })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
class="form-box flex flex-col mb-30px flex-1"
|
class="form-box flex flex-col mb-30px flex-1"
|
||||||
>
|
>
|
||||||
<!-- 情况一:流程表单 -->
|
<!-- 情况一:流程表单 -->
|
||||||
<el-col v-if="processDefinition?.formType === 10">
|
<el-col v-if="processDefinition?.formType === BpmModelFormType.NORMAL">
|
||||||
<form-create
|
<form-create
|
||||||
v-model="detailForm.value"
|
v-model="detailForm.value"
|
||||||
v-model:api="fApi"
|
v-model:api="fApi"
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
/>
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- 情况二:业务表单 -->
|
<!-- 情况二:业务表单 -->
|
||||||
<div v-if="processDefinition?.formType === 20">
|
<div v-if="processDefinition?.formType === BpmModelFormType.CUSTOM">
|
||||||
<BusinessFormComponent :id="processInstance.businessKey" />
|
<BusinessFormComponent :id="processInstance.businessKey" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -116,6 +116,9 @@
|
||||||
:process-instance="processInstance"
|
:process-instance="processInstance"
|
||||||
:process-definition="processDefinition"
|
:process-definition="processDefinition"
|
||||||
:userOptions="userOptions"
|
:userOptions="userOptions"
|
||||||
|
:normal-form ="detailForm"
|
||||||
|
:normal-form-api="fApi"
|
||||||
|
:writable-fields="writableFields"
|
||||||
@success="refresh"
|
@success="refresh"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,7 +129,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
import { DICT_TYPE } from '@/utils/dict'
|
||||||
import { BpmModelType } from '@/utils/constants'
|
import { BpmModelType,BpmModelFormType } from '@/utils/constants'
|
||||||
import { setConfAndFields2 } from '@/utils/formCreate'
|
import { setConfAndFields2 } from '@/utils/formCreate'
|
||||||
import { registerComponent } from '@/utils/routerHelper'
|
import { registerComponent } from '@/utils/routerHelper'
|
||||||
import type { ApiAttrs } from '@form-create/element-ui/types/config'
|
import type { ApiAttrs } from '@form-create/element-ui/types/config'
|
||||||
|
@ -171,6 +174,9 @@ const detailForm = ref({
|
||||||
value: {}
|
value: {}
|
||||||
}) // 流程实例的表单详情
|
}) // 流程实例的表单详情
|
||||||
|
|
||||||
|
// 表单可以编辑的字段
|
||||||
|
const writableFields : Array<string> = [];
|
||||||
|
|
||||||
/** 获得详情 */
|
/** 获得详情 */
|
||||||
const getDetail = () => {
|
const getDetail = () => {
|
||||||
getApprovalDetail()
|
getApprovalDetail()
|
||||||
|
@ -202,11 +208,12 @@ const getApprovalDetail = async () => {
|
||||||
processDefinition.value = data.processDefinition
|
processDefinition.value = data.processDefinition
|
||||||
|
|
||||||
// 设置表单信息
|
// 设置表单信息
|
||||||
if (processDefinition.value.formType === 10) {
|
if (processDefinition.value.formType === BpmModelFormType.NORMAL) {
|
||||||
// 获取表单字段权限
|
// 获取表单字段权限
|
||||||
const formFieldsPermission = data.formFieldsPermission
|
const formFieldsPermission = data.formFieldsPermission
|
||||||
|
// 清空可编辑字段为空
|
||||||
if (detailForm.value.rule.length > 0) {
|
writableFields.splice(0)
|
||||||
|
if (detailForm.value.rule?.length > 0) {
|
||||||
// 避免刷新 form-create 显示不了
|
// 避免刷新 form-create 显示不了
|
||||||
detailForm.value.value = processInstance.value.formVariables
|
detailForm.value.value = processInstance.value.formVariables
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,6 +278,8 @@ const setFieldPermission = (field: string, permission: string) => {
|
||||||
if (permission === FieldPermissionType.WRITE) {
|
if (permission === FieldPermissionType.WRITE) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
fApi.value?.disabled(false, field)
|
fApi.value?.disabled(false, field)
|
||||||
|
// 加入可以编辑的字段
|
||||||
|
writableFields.push(field);
|
||||||
}
|
}
|
||||||
if (permission === FieldPermissionType.NONE) {
|
if (permission === FieldPermissionType.NONE) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
|
@ -314,6 +323,7 @@ $process-header-height: 194px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
.form-scroll-area {
|
.form-scroll-area {
|
||||||
|
display: flex;
|
||||||
height: calc(
|
height: calc(
|
||||||
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
|
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
|
||||||
$process-header-height - 40px
|
$process-header-height - 40px
|
||||||
|
@ -323,7 +333,6 @@ $process-header-height: 194px;
|
||||||
$process-header-height - 40px
|
$process-header-height - 40px
|
||||||
);
|
);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
:deep(.box-card) {
|
:deep(.box-card) {
|
||||||
|
|
Loading…
Reference in New Issue