feat: [bpm] 减签任务

This commit is contained in:
jason
2026-01-13 11:00:54 +08:00
parent dc1d19fba6
commit dfa374fdc9
4 changed files with 253 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ export interface Task {
processInstance: ProcessInstance
reasonRequire?: boolean // 是否填写审批意见
buttonsSetting?: Record<number, OperationButtonSetting> // 按钮设置
children?: Task[] // 由加签生成,包含多层子任务
}
/** 查询待办任务分页列表 */
@@ -86,3 +87,8 @@ export function getTaskListByReturn(taskId: string) {
export function signCreateTask(data: { id: string, type: string, userIds: number[], reason: string }) {
return http.put<boolean>('/bpm/task/create-sign', data)
}
/** 减签任务 */
export function signDeleteTask(data: { id: string, reason: string }) {
return http.delete<boolean>('/bpm/task/delete-sign', data)
}

View File

@@ -41,7 +41,9 @@ import type { Action } from 'wot-design-uni/components/wd-action-sheet/types'
import type { ButtonType } from 'wot-design-uni/components/wd-button/types'
import type { Task } from '@/api/bpm/task'
import { useToast } from 'wot-design-uni'
import { useUserStore } from '@/store'
import {
BpmProcessInstanceStatus,
BpmTaskOperationButtonTypeEnum,
BpmTaskStatusEnum,
OPERATION_BUTTON_NAME,
@@ -71,7 +73,10 @@ const operationIconsMap: Record<number, string> = {
[BpmTaskOperationButtonTypeEnum.DELEGATE]: 'share',
[BpmTaskOperationButtonTypeEnum.RETURN]: 'arrow-left',
[BpmTaskOperationButtonTypeEnum.COPY]: 'copy',
[BpmTaskOperationButtonTypeEnum.DELETE_SIGN]: 'remove',
}
const userStore = useUserStore()
/** 左侧操作按钮 【最多两个】{转办, 委派, 退回, 加签, 抄送等} */
const leftOperations = ref<LeftOperationType[]>([])
@@ -90,7 +95,7 @@ function loadTodoTask(task: Task) {
if (task) {
reasonRequire.value = task.reasonRequire ?? false
// 右侧按钮
if (isHandleTaskStatus() && task.buttonsSetting && task.buttonsSetting[BpmTaskOperationButtonTypeEnum.REJECT]?.enable) {
if (isHandleTaskStatus() && isShowButton(BpmTaskOperationButtonTypeEnum.REJECT)) {
rightOperationTypes.push(BpmTaskOperationButtonTypeEnum.REJECT)
rightOperations.value.push({
operationType: BpmTaskOperationButtonTypeEnum.REJECT,
@@ -99,7 +104,7 @@ function loadTodoTask(task: Task) {
plain: true,
})
}
if (isHandleTaskStatus() && task.buttonsSetting && task.buttonsSetting[BpmTaskOperationButtonTypeEnum.APPROVE]?.enable) {
if (isHandleTaskStatus() && isShowButton(BpmTaskOperationButtonTypeEnum.APPROVE)) {
rightOperationTypes.push(BpmTaskOperationButtonTypeEnum.APPROVE)
rightOperations.value.push({
operationType: BpmTaskOperationButtonTypeEnum.APPROVE,
@@ -108,7 +113,7 @@ function loadTodoTask(task: Task) {
plain: false,
})
}
// TODO 减签
// 左侧操作,和更多操作
Object.keys(task.buttonsSetting || {}).forEach((key) => {
const operationType = Number(key)
@@ -128,6 +133,21 @@ function loadTodoTask(task: Task) {
}
}
})
/** 减签操作的显示 */
if (isShowDeleteSign()) {
if (leftOperations.value.length >= 2) {
moreOperations.value.push({
name: getButtonDisplayName(BpmTaskOperationButtonTypeEnum.DELETE_SIGN),
operationType: BpmTaskOperationButtonTypeEnum.DELETE_SIGN,
})
} else {
leftOperations.value.push({
operationType: BpmTaskOperationButtonTypeEnum.DELETE_SIGN,
iconName: operationIconsMap[BpmTaskOperationButtonTypeEnum.DELETE_SIGN],
displayName: getButtonDisplayName(BpmTaskOperationButtonTypeEnum.DELETE_SIGN),
})
}
}
}
}
/** 跳转到相应的操作页面 */
@@ -162,6 +182,11 @@ function handleOperation(operationType: number) {
url: `/pages-bpm/processInstance/detail/return/index?processInstanceId=${runningTask.value.processInstanceId}&taskId=${runningTask.value.id}`,
})
break
case BpmTaskOperationButtonTypeEnum.DELETE_SIGN:
uni.navigateTo({
url: `/pages-bpm/processInstance/detail/delete-sign/index?processInstanceId=${runningTask.value.processInstanceId}&taskId=${runningTask.value.id}&children=${encodeURIComponent(JSON.stringify(runningTask.value.children || []))}`,
})
break
}
}
@@ -209,6 +234,38 @@ function isHandleTaskStatus() {
return canHandle
}
/** 流程状态是否为结束状态 */
function isEndProcessStatus(status: number) {
let isEndStatus = false
if (
BpmProcessInstanceStatus.APPROVE === status
|| BpmProcessInstanceStatus.REJECT === status
|| BpmProcessInstanceStatus.CANCEL === status
) {
isEndStatus = true
}
return isEndStatus
}
/** 流程发起人是否为当前用户 */
function isProcessStartUser() {
let isStartUser = false
if (userStore.userInfo?.userId === runningTask.value?.processInstance?.startUser?.id) {
isStartUser = true
}
return isStartUser
}
/** 是否显示减签 */
function isShowDeleteSign() {
return runningTask.value?.children?.length > 0
}
/** 是否显示流程发起人取消 */
function isShowProcessStartCancel() {
return isProcessStartUser
}
/** 暴露方法 */
defineExpose({ loadTodoTask })
</script>

View File

@@ -0,0 +1,181 @@
<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="减签任务"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 操作表单 -->
<view class="p-24rpx">
<wd-form ref="formRef" :model="formData" :rules="formRules">
<wd-cell-group border>
<!-- 减签人员选择 -->
<wd-picker
v-model="formData.deleteSignTaskId"
:columns="taskOptions"
value-key="id"
label-key="label"
label="减签人员:"
label-width="180rpx"
placeholder="请选择减签人员"
prop="deleteSignTaskId"
/>
<!-- 审批意见 -->
<wd-textarea
v-model="formData.reason"
prop="reason"
label="审批意见:"
label-width="180rpx"
placeholder="请输入审批意见"
:maxlength="500"
show-word-limit
clearable
/>
</wd-cell-group>
<!-- 提交按钮 -->
<view class="mt-48rpx">
<wd-button
type="primary"
block
:loading="submitting"
:disabled="submitting"
@click="handleSubmit"
>
减签
</wd-button>
</view>
</wd-form>
</view>
</view>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'wot-design-uni/components/wd-form/types'
import { computed, onMounted, reactive, ref } from 'vue'
import { useToast } from 'wot-design-uni'
import { signDeleteTask } from '@/api/bpm/task'
import { navigateBackPlus } from '@/utils'
const props = defineProps<{
processInstanceId: string
taskId: string
children?: string // JSON 字符串格式的子任务数据
}>()
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const taskId = computed(() => props.taskId)
const processInstanceId = computed(() => props.processInstanceId)
const toast = useToast()
const submitting = ref(false)
const formRef = ref<FormInstance>()
const taskOptions = ref<any[]>([])
const formData = reactive({
deleteSignTaskId: '',
reason: '',
})
const formRules = {
deleteSignTaskId: [
{ required: true, message: '减签人员不能为空' },
],
reason: [
{ required: true, message: '审批意见不能为空' },
],
}
/** 返回上一页 */
function handleBack() {
navigateBackPlus(`/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`)
}
/** 初始化校验 */
if (!props.taskId || !props.processInstanceId) {
toast.show('参数错误')
}
/** 获取减签人员标签 */
function getDeleteSignUserLabel(task: any): string {
const deptName = task?.assigneeUser?.deptName || task?.ownerUser?.deptName
const nickname = task?.assigneeUser?.nickname || task?.ownerUser?.nickname
return `${nickname} ( 所属部门:${deptName} )`
}
/** 获取可减签的任务列表 */
async function loadDeleteSignTaskList() {
try {
let childTasks = []
// 从 URL 参数中获取子任务数据
if (props.children) {
try {
childTasks = JSON.parse(decodeURIComponent(props.children))
} catch (parseError) {
console.error('[delete-sign] 解析子任务数据失败:', parseError)
}
}
// 提示没有子任务数据
if (childTasks.length === 0) {
toast.show('没有可减签的任务')
return
}
taskOptions.value = childTasks.map(task => ({
id: task.id,
label: getDeleteSignUserLabel(task),
}))
} catch (error) {
console.error('[delete-sign] 获取可减签任务失败:', error)
toast.error('获取可减签任务失败')
}
}
/** 提交操作 */
async function handleSubmit() {
if (submitting.value)
return
// 使用 wd-form 的校验方法
const { valid } = await formRef.value!.validate()
if (!valid) {
return
}
submitting.value = true
try {
const result = await signDeleteTask({
id: formData.deleteSignTaskId,
reason: formData.reason,
})
if (result) {
toast.success('减签成功')
setTimeout(() => {
uni.redirectTo({
url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`,
})
}, 1500)
}
} catch (error) {
console.error('[delete-sign] 减签失败:', error)
toast.error('减签失败')
} finally {
submitting.value = false
}
}
/** 页面加载时获取可减签任务列表 */
onMounted(() => {
loadDeleteSignTaskList()
})
</script>

View File

@@ -147,6 +147,10 @@ export enum BpmTaskOperationButtonTypeEnum {
* 委派
*/
DELEGATE = 4,
/**
* 减签
*/
DELETE_SIGN = 8,
/**
* 拒绝
*/
@@ -159,6 +163,7 @@ export enum BpmTaskOperationButtonTypeEnum {
* 转办
*/
TRANSFER = 3,
}
/**
@@ -286,6 +291,7 @@ OPERATION_BUTTON_NAME.set(BpmTaskOperationButtonTypeEnum.DELEGATE, '委派')
OPERATION_BUTTON_NAME.set(BpmTaskOperationButtonTypeEnum.ADD_SIGN, '加签')
OPERATION_BUTTON_NAME.set(BpmTaskOperationButtonTypeEnum.RETURN, '退回')
OPERATION_BUTTON_NAME.set(BpmTaskOperationButtonTypeEnum.COPY, '抄送')
OPERATION_BUTTON_NAME.set(BpmTaskOperationButtonTypeEnum.DELETE_SIGN, '减签')
/**
* 流程实例的变量枚举