Browse Source

feat: [bpm] 减签任务

jason 3 months ago
parent
commit
dfa374fdc9

+ 6 - 0
src/api/bpm/task/index.ts

@@ -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)
+}

+ 60 - 3
src/pages-bpm/processInstance/detail/components/operation-button.vue

@@ -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>

+ 181 - 0
src/pages-bpm/processInstance/detail/delete-sign/index.vue

@@ -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>

+ 6 - 0
src/utils/constants/biz-bpm-enum.ts

@@ -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, '减签')
 
 /**
  * 流程实例的变量枚举