Jelajahi Sumber

feat: [bpm] 加签任务

jason 3 bulan lalu
induk
melakukan
dc1d19fba6

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

@@ -81,3 +81,8 @@ export function returnTask(data: { id: string, targetTaskDefinitionKey: string,
 export function getTaskListByReturn(taskId: string) {
   return http.get<any[]>(`/bpm/task/list-by-return?id=${taskId}`)
 }
+
+/** 加签任务 */
+export function signCreateTask(data: { id: string, type: string, userIds: number[], reason: string }) {
+  return http.put<boolean>('/bpm/task/create-sign', data)
+}

+ 3 - 0
src/components/system-select/user-picker.vue

@@ -7,6 +7,7 @@
     value-key="id"
     label-key="nickname"
     :type="type"
+    :prop="prop"
     filterable
     :placeholder="placeholder"
     @confirm="handleConfirm"
@@ -23,10 +24,12 @@ const props = withDefaults(defineProps<{
   type?: 'radio' | 'checkbox'
   label?: string
   placeholder?: string
+  prop?: string
 }>(), {
   type: 'checkbox',
   label: '',
   placeholder: '请选择',
+  prop: '',
 })
 
 const emit = defineEmits<{

+ 150 - 0
src/pages-bpm/processInstance/detail/add-sign/index.vue

@@ -0,0 +1,150 @@
+<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>
+          <!-- 加签处理人 -->
+          <UserPicker
+            v-model="formData.userIds"
+            prop="userIds"
+            type="checkbox"
+            label="加签处理人:"
+            label-width="200rpx"
+            placeholder="请选择加签处理人"
+            :rules="formRules.userIds"
+          />
+
+          <!-- 审批意见 -->
+          <wd-textarea
+            v-model="formData.reason"
+            prop="reason"
+            label="审批意见:"
+            label-width="200rpx"
+            placeholder="请输入审批意见"
+            :maxlength="500"
+            show-word-limit
+            clearable
+          />
+        </wd-cell-group>
+        <!-- 提交按钮 -->
+        <view class="mt-48rpx flex gap-16rpx">
+          <wd-button
+            type="primary"
+            class="flex-1"
+            plain
+            :loading="submitting"
+            :disabled="submitting"
+            @click="handleSubmit('before')"
+          >
+            向前加签
+          </wd-button>
+          <wd-button
+            type="primary"
+            class="flex-1"
+            :loading="submitting"
+            :disabled="submitting"
+            @click="handleSubmit('after')"
+          >
+            向后加签
+          </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, reactive, ref } from 'vue'
+import { useToast } from 'wot-design-uni'
+import { signCreateTask } from '@/api/bpm/task'
+import UserPicker from '@/components/system-select/user-picker.vue'
+import { navigateBackPlus } from '@/utils'
+
+const props = defineProps<{
+  processInstanceId: string
+  taskId: string
+}>()
+
+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 formData = reactive({
+  userIds: [] as number[],
+  reason: '',
+})
+
+const formRules = {
+  userIds: [
+    { required: true, message: '加签处理人不能为空', validator: (value: number[]) => value.length > 0 },
+  ],
+  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('参数错误')
+}
+
+/** 提交操作 */
+async function handleSubmit(type: 'before' | 'after') {
+  if (submitting.value)
+    return
+
+  // 使用 wd-form 的校验方法
+  const { valid } = await formRef.value!.validate()
+  if (!valid) {
+    return
+  }
+  submitting.value = true
+  try {
+    const result = await signCreateTask({
+      id: taskId.value as string,
+      type,
+      userIds: formData.userIds,
+      reason: formData.reason,
+    })
+
+    if (result) {
+      const actionText = type === 'before' ? '向前加签' : '向后加签'
+      toast.success(`${actionText}成功`)
+      setTimeout(() => {
+        uni.redirectTo({
+          url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`,
+        })
+      }, 1500)
+    }
+  } catch (error) {
+    const actionText = type === 'before' ? '向前加签' : '向后加签'
+    console.error(`[add-sign] ${actionText}失败:`, error)
+    toast.error(`${actionText}失败`)
+  } finally {
+    submitting.value = false
+  }
+}
+</script>

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

@@ -108,7 +108,6 @@ function loadTodoTask(task: Task) {
         plain: false,
       })
     }
-    console.log('rightOperationTypes====>', rightOperationTypes)
     // TODO 减签
     // 左侧操作,和更多操作
     Object.keys(task.buttonsSetting || {}).forEach((key) => {
@@ -154,7 +153,9 @@ function handleOperation(operationType: number) {
       })
       break
     case BpmTaskOperationButtonTypeEnum.ADD_SIGN:
-      toast.show('加签功能待实现')
+      uni.navigateTo({
+        url: `/pages-bpm/processInstance/detail/add-sign/index?processInstanceId=${runningTask.value.processInstanceId}&taskId=${runningTask.value.id}`,
+      })
       break
     case BpmTaskOperationButtonTypeEnum.RETURN:
       uni.navigateTo({

+ 0 - 1
src/pages-bpm/processInstance/detail/return/index.vue

@@ -105,7 +105,6 @@ if (!props.taskId || !props.processInstanceId) {
 async function loadReturnTaskList() {
   try {
     const result = await getTaskListByReturn(taskId.value)
-    console.log('[return] 获取可退回节点:', result)
     if (result && Array.isArray(result)) {
       activityOptions.value = result
     }