Commit 6b06f320 by YunaiV

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

# Conflicts:
#	src/views/bpm/processInstance/detail/index_new.vue
parents 33f3bc05 4342c3ee
...@@ -46,7 +46,7 @@ export type ApprovalNodeInfo = { ...@@ -46,7 +46,7 @@ export type ApprovalNodeInfo = {
status: number status: number
startTime?: Date startTime?: Date
endTime?: Date endTime?: Date
candidateUserList?: User[] candidateUsers?: User[]
tasks: ApprovalTaskInfo[] tasks: ApprovalTaskInfo[]
} }
......
...@@ -106,6 +106,11 @@ export const signDeleteTask = async (data: any) => { ...@@ -106,6 +106,11 @@ export const signDeleteTask = async (data: any) => {
return await request.delete({ url: '/bpm/task/delete-sign', data }) return await request.delete({ url: '/bpm/task/delete-sign', data })
} }
// 抄送
export const copyTask = async (data: any) => {
return await request.put({ url: '/bpm/task/copy', data })
}
// 获取减签任务列表 // 获取减签任务列表
export const getChildrenTaskList = async (id: string) => { export const getChildrenTaskList = async (id: string) => {
return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id }) return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
......
...@@ -362,7 +362,11 @@ export enum OperationButtonType { ...@@ -362,7 +362,11 @@ export enum OperationButtonType {
/** /**
* 回退 * 回退
*/ */
RETURN = 6 RETURN = 6,
/**
* 抄送
*/
COPY = 7
} }
/** /**
...@@ -504,6 +508,7 @@ OPERATION_BUTTON_NAME.set(OperationButtonType.TRANSFER, '转办') ...@@ -504,6 +508,7 @@ OPERATION_BUTTON_NAME.set(OperationButtonType.TRANSFER, '转办')
OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派') OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派')
OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签') OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签')
OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '回退') OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '回退')
OPERATION_BUTTON_NAME.set(OperationButtonType.COPY, '抄送')
// 默认的按钮权限设置 // 默认的按钮权限设置
export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [ export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [
......
...@@ -139,7 +139,6 @@ ...@@ -139,7 +139,6 @@
clearable clearable
multiple multiple
style="width: 100%" style="width: 100%"
@change="changedCandidateUsers"
> >
<el-option <el-option
v-for="item in userOptions" v-for="item in userOptions"
...@@ -187,10 +186,6 @@ ...@@ -187,10 +186,6 @@
<el-radio <el-radio
:value="item.value" :value="item.value"
:label="item.value" :label="item.value"
:disabled="
item.value !== ApproveMethodType.RANDOM_SELECT_ONE_APPROVE &&
notAllowedMultiApprovers
"
> >
{{ item.label }} {{ item.label }}
</el-radio> </el-radio>
...@@ -537,8 +532,7 @@ const { ...@@ -537,8 +532,7 @@ const {
getShowText getShowText
} = useNodeForm(NodeType.USER_TASK_NODE) } = useNodeForm(NodeType.USER_TASK_NODE)
const configForm = tempConfigForm as Ref<UserTaskFormType> const configForm = tempConfigForm as Ref<UserTaskFormType>
// 不允许多人审批
const notAllowedMultiApprovers = ref(false)
// 改变审批人设置策略 // 改变审批人设置策略
const changeCandidateStrategy = () => { const changeCandidateStrategy = () => {
configForm.value.userIds = [] configForm.value.userIds = []
...@@ -548,29 +542,8 @@ const changeCandidateStrategy = () => { ...@@ -548,29 +542,8 @@ const changeCandidateStrategy = () => {
configForm.value.userGroups = [] configForm.value.userGroups = []
configForm.value.deptLevel = 1 configForm.value.deptLevel = 1
configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE
if (
configForm.value.candidateStrategy === CandidateStrategy.START_USER ||
configForm.value.candidateStrategy === CandidateStrategy.USER
) {
notAllowedMultiApprovers.value = true
} else {
notAllowedMultiApprovers.value = false
}
}
// 改变审批候选人
const changedCandidateUsers = () => {
if (
configForm.value.userIds &&
configForm.value.userIds?.length <= 1 &&
configForm.value.candidateStrategy === CandidateStrategy.USER
) {
configForm.value.approveMethod = ApproveMethodType.RANDOM_SELECT_ONE_APPROVE
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
notAllowedMultiApprovers.value = true
} else {
notAllowedMultiApprovers.value = false
}
} }
// 审批方式改变 // 审批方式改变
const approveMethodChanged = () => { const approveMethodChanged = () => {
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
...@@ -666,11 +639,6 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { ...@@ -666,11 +639,6 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
configForm.value.candidateStrategy = node.candidateStrategy! configForm.value.candidateStrategy = node.candidateStrategy!
// 解析候选人参数 // 解析候选人参数
parseCandidateParam(node.candidateStrategy!, node?.candidateParam) parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
if (configForm.value.userIds && configForm.value.userIds.length > 1) {
notAllowedMultiApprovers.value = true
} else {
notAllowedMultiApprovers.value = false
}
// 2.2 设置审批方式 // 2.2 设置审批方式
configForm.value.approveMethod = node.approveMethod! configForm.value.approveMethod = node.approveMethod!
if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) { if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<div class="flex items-center mt-1"> <div class="flex items-center mt-1">
<!-- 情况一:遍历每个审批节点下的【进行中】task 任务 --> <!-- 情况一:遍历每个审批节点下的【进行中】task 任务 -->
<div v-for="(task, idx) in activity.tasks" :key="idx" class="flex items-center"> <div v-for="(task, idx) in activity.tasks" :key="idx" class="flex items-center">
<div class="flex items-center flex-col pr-2"> <div class="flex flex-col pr-2">
<div class="position-relative" v-if="task.assigneeUser || task.ownerUser"> <div class="position-relative" v-if="task.assigneeUser || task.ownerUser">
<!-- 信息:头像 --> <!-- 信息:头像 -->
<el-avatar <el-avatar
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
<!-- 信息:昵称 --> <!-- 信息:昵称 -->
<div <div
v-if="task.assigneeUser && task.assigneeUser.nickname" v-if="task.assigneeUser && task.assigneeUser.nickname"
class="text-10px text-align-center" class="text-12px text-align-center"
> >
{{ task.assigneeUser.nickname }} {{ task.assigneeUser.nickname }}
</div> </div>
...@@ -57,14 +57,20 @@ ...@@ -57,14 +57,20 @@
> >
{{ task.ownerUser.nickname }} {{ task.ownerUser.nickname }}
</div> </div>
<!-- TODO @jason:审批意见,要展示哈。 --> <div v-if="task.reason" class="text-#a5a5a5 my-4px text-12px flex items-center w-100%">
<!-- <div v-if="task.reason" :title="task.reason" class="text-13px text-truncate w-150px mt-1"> 审批意见: {{ task.reason }}</div> --> <div
:title="task.reason"
class="text-truncate w-200px border-1px border-#a5a5a5 border-dashed rounded py-5px px-15px text-#2d2d2d"
>
{{ task.reason }}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 --> <!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
<div <div
v-for="(user, idx1) in activity.candidateUserList" v-for="(user, idx1) in activity.candidateUsers"
:key="idx1" :key="idx1"
class="flex items-center" class="flex items-center"
> >
...@@ -91,7 +97,6 @@ ...@@ -91,7 +97,6 @@
<div v-if="user.nickname" class="text-10px text-align-center"> <div v-if="user.nickname" class="text-10px text-align-center">
{{ user.nickname }} {{ user.nickname }}
</div> </div>
<!-- <div v-if="task.reason" :title="task.reason" class="text-13px text-truncate w-150px mt-1"> 审批意见: {{ task.reason }}</div> -->
</div> </div>
</div> </div>
</div> </div>
......
...@@ -12,25 +12,37 @@ ...@@ -12,25 +12,37 @@
<el-divider class="!my-8px" /> <el-divider class="!my-8px" />
<div class="flex items-center gap-5 mb-10px h-40px"> <div class="flex items-center gap-5 mb-10px h-40px">
<div class="text-26px font-bold mb-5px">{{ processInstance.name }}</div> <div class="text-26px font-bold mb-5px">{{ processInstance.name }}</div>
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="processInstance.status" /> <dict-tag
v-if="processInstance.status"
:type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value="processInstance.status"
/>
</div> </div>
<div class="flex items-center gap-5 mb-10px text-13px h-35px"> <div class="flex items-center gap-5 mb-10px text-13px h-35px">
<div <div
class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600" class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
> >
<img class="rounded-full h-28px" src="@/assets/imgs/avatar.jpg" alt="" /> <!-- <img class="rounded-full h-28px" src="@/assets/imgs/avatar.jpg" alt="" /> -->
<el-avatar
:size="28"
v-if="processInstance?.startUser?.avatar"
:src="processInstance?.startUser?.avatar"
/>
<el-avatar :size="28" v-else-if="processInstance?.startUser?.nickname">
{{ processInstance?.startUser?.nickname.substring(0, 1) }}
</el-avatar>
{{ processInstance?.startUser?.nickname }} {{ processInstance?.startUser?.nickname }}
</div> </div>
<div class="text-#878c93"> {{ formatDate(processInstance.startTime) }} 提交 </div> <div class="text-#878c93"> {{ formatDate(processInstance.startTime) }} 提交 </div>
</div> </div>
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab" @tab-change="onTabChange">
<!-- 表单信息 --> <!-- 表单信息 -->
<el-tab-pane label="审批详情" name="form"> <el-tab-pane label="审批详情" name="form">
<div class="form-scroll-area"> <div class="form-scroll-area">
<el-scrollbar> <el-scrollbar>
<el-row :gutter="10"> <el-row>
<el-col :span="18" class="!flex !flex-col formCol"> <el-col :span="18" class="!flex !flex-col formCol">
<!-- 表单信息 --> <!-- 表单信息 -->
<div <div
...@@ -38,11 +50,7 @@ ...@@ -38,11 +50,7 @@
class="form-box flex flex-col mb-30px flex-1" class="form-box flex flex-col mb-30px flex-1"
> >
<!-- 情况一:流程表单 --> <!-- 情况一:流程表单 -->
<el-col <el-col v-if="processInstance?.processDefinition?.formType === 10">
v-if="processInstance?.processDefinition?.formType === 10"
:offset="6"
:span="16"
>
<form-create <form-create
v-model="detailForm.value" v-model="detailForm.value"
v-model:api="fApi" v-model:api="fApi"
...@@ -64,27 +72,36 @@ ...@@ -64,27 +72,36 @@
</el-scrollbar> </el-scrollbar>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- 流程图 --> <!-- 流程图 -->
<el-tab-pane label="流程图" name="diagram"> <el-tab-pane label="流程图" name="diagram">
<div class="form-scroll-area">
<ProcessInstanceBpmnViewer :id="`${id}`" :loading="processInstanceLoading" /> <ProcessInstanceBpmnViewer :id="`${id}`" :loading="processInstanceLoading" />
</div>
</el-tab-pane> </el-tab-pane>
<!-- 流转记录 --> <!-- 流转记录 -->
<el-tab-pane label="流转记录" name="record"> <el-tab-pane label="流转记录" name="record">
<div class="form-scroll-area">
<el-scrollbar>
<ProcessInstanceTaskList <ProcessInstanceTaskList
:loading="tasksLoad" :loading="tasksLoad"
:process-instance="processInstance" :process-instance="processInstance"
:tasks="tasks" :tasks="tasks"
@refresh="getTaskList"
/> />
</el-scrollbar>
</div>
</el-tab-pane> </el-tab-pane>
<!-- 流转评论 TODO 待开发 --> <!-- 流转评论 TODO 待开发 -->
<el-tab-pane label="流转评论" name="comment"> 流转评论 </el-tab-pane> <el-tab-pane label="流转评论" name="comment">
<div class="form-scroll-area">
<el-scrollbar> 流转评论 </el-scrollbar>
</div>
</el-tab-pane>
</el-tabs> </el-tabs>
<div <div class="b-t-solid border-t-1px border-[var(--el-border-color)]">
class="b-t-solid border-t-1px border-[var(--el-border-color)]"
v-if="activeTab === 'form'"
>
<!-- 操作栏按钮 --> <!-- 操作栏按钮 -->
<ProcessInstanceOperationButton <ProcessInstanceOperationButton
ref="operationButtonRef" ref="operationButtonRef"
...@@ -125,6 +142,7 @@ const props = defineProps<{ ...@@ -125,6 +142,7 @@ const props = defineProps<{
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
const processInstanceLoading = ref(false) // 流程实例的加载中 const processInstanceLoading = ref(false) // 流程实例的加载中
const processInstance = ref<any>({}) // 流程实例 const processInstance = ref<any>({}) // 流程实例
let processDefinitionId = undefined // 流程定义 Id
const operationButtonRef = ref() const operationButtonRef = ref()
const timelineRef = ref() const timelineRef = ref()
const bpmnXml = ref('') // BPMN XML const bpmnXml = ref('') // BPMN XML
...@@ -145,10 +163,10 @@ const detailForm = ref({ ...@@ -145,10 +163,10 @@ const detailForm = ref({
}) // 流程实例的表单详情 }) // 流程实例的表单详情
/** 获得详情 */ /** 获得详情 */
const getDetail = () => { const getDetail = async () => {
// 1. 获得流程实例相关 // 1. 获得流程实例相关
getProcessInstance() getProcessInstance()
// 2. 获得流程任务列表(审批记录) // 2. 获得流程任务列表
getTaskList() getTaskList()
} }
...@@ -176,12 +194,18 @@ const getProcessInstance = async () => { ...@@ -176,12 +194,18 @@ const getProcessInstance = async () => {
activityId: props.activityId activityId: props.activityId
}) })
} }
if (detailForm.value.rule.length > 0) { // 避免刷新 form-create 表单不显示
detailForm.value.value = data.formVariables
} else {
setConfAndFields2( setConfAndFields2(
detailForm, detailForm,
processDefinition.formConf, processDefinition.formConf,
processDefinition.formFields, processDefinition.formFields,
data.formVariables data.formVariables
) )
}
nextTick().then(() => { nextTick().then(() => {
fApi.value?.btn.show(false) fApi.value?.btn.show(false)
fApi.value?.resetBtn.show(false) fApi.value?.resetBtn.show(false)
...@@ -196,9 +220,9 @@ const getProcessInstance = async () => { ...@@ -196,9 +220,9 @@ const getProcessInstance = async () => {
// 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue // 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue
BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath) BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
} }
processDefinitionId = processDefinition.id
// 加载流程图 // 加载流程图
bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinition.id))?.bpmnXml // bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinition.id))?.bpmnXml
} finally { } finally {
processInstanceLoading.value = false processInstanceLoading.value = false
} }
...@@ -267,6 +291,13 @@ const refresh = () => { ...@@ -267,6 +291,13 @@ const refresh = () => {
/** 当前的Tab */ /** 当前的Tab */
const activeTab = ref('form') const activeTab = ref('form')
/** Tab 切换 加载流程图,直接加载显示不出来,不知道啥原因,所以切换以后在加载 */
const onTabChange = async (tabName: string) => {
if (tabName === 'diagram' && processDefinitionId && !bpmnXml.value) {
//加载流程图
bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinitionId))?.bpmnXml
}
}
/** 初始化 */ /** 初始化 */
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表 const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
onMounted(async () => { onMounted(async () => {
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
/> />
<el-table-column align="center" label="抄送任务" prop="taskName" min-width="180" /> <el-table-column align="center" label="抄送任务" prop="taskName" min-width="180" />
<el-table-column align="center" label="抄送人" prop="creatorName" min-width="100" /> <el-table-column align="center" label="抄送人" prop="creatorName" min-width="100" />
<el-table-column align="center" label="抄送意见" prop="reason" width="150" />
<el-table-column <el-table-column
align="center" align="center"
label="抄送时间" label="抄送时间"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment