review:【bpm】审批详情的操作们
This commit is contained in:
@@ -11,10 +11,12 @@ export interface TaskUser {
|
||||
deptName?: string
|
||||
}
|
||||
|
||||
/** 操作按钮设置 */
|
||||
export interface OperationButtonSetting {
|
||||
displayName: string // 按钮名称
|
||||
enable: boolean // 是否启用
|
||||
}
|
||||
|
||||
/** 流程任务 */
|
||||
export interface Task {
|
||||
id: string
|
||||
|
||||
@@ -85,13 +85,10 @@ 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 },
|
||||
@@ -100,12 +97,14 @@ const formRules = {
|
||||
{ required: true, message: '审批意见不能为空' },
|
||||
],
|
||||
}
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/** 返回上一页 */
|
||||
function handleBack() {
|
||||
navigateBackPlus(`/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`)
|
||||
}
|
||||
|
||||
// TODO @jason:最好放在 onMounted 里?或者其他地方,有个入口方法。
|
||||
/** 初始化校验 */
|
||||
if (!props.taskId || !props.processInstanceId) {
|
||||
toast.show('参数错误')
|
||||
@@ -113,23 +112,24 @@ if (!props.taskId || !props.processInstanceId) {
|
||||
|
||||
/** 提交操作 */
|
||||
async function handleSubmit(type: 'before' | 'after') {
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
|
||||
// 使用 wd-form 的校验方法
|
||||
}
|
||||
const { valid } = await formRef.value!.validate()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:submitting 改成 formLoading 哇?统一代码风格哈;
|
||||
submitting.value = true
|
||||
try {
|
||||
// TODO @jason:这里是不是不用判断 result 哈?
|
||||
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}成功`)
|
||||
@@ -137,9 +137,10 @@ async function handleSubmit(type: 'before' | 'after') {
|
||||
uni.redirectTo({
|
||||
url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`,
|
||||
})
|
||||
}, 1500)
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:可以不用这里的 catch 哈?
|
||||
const actionText = type === 'before' ? '向前加签' : '向后加签'
|
||||
console.error(`[add-sign] ${actionText}失败:`, error)
|
||||
toast.error(`${actionText}失败`)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="yd-page-container">
|
||||
<!-- TODO @芋艿:还有一些细节,在审批通过没搞完! -->
|
||||
<!-- TODO @jason:还有一些细节,在审批通过没搞完!1)签名;2)选择审批人;3)其它等等 -->
|
||||
<!-- 顶部导航栏 -->
|
||||
<wd-navbar
|
||||
:title="isApprove ? '审批同意' : '审批拒绝'"
|
||||
@@ -93,14 +93,18 @@ function validateForm() {
|
||||
/** 提交审批 */
|
||||
async function handleSubmit() {
|
||||
// TODO @jason:看看是不是要用原生的校验
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
if (!validateForm())
|
||||
}
|
||||
if (!validateForm()) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:要不换成 formLoading?保持项目统一;
|
||||
submitting.value = true
|
||||
try {
|
||||
const api = isApprove.value ? approveTask : rejectTask
|
||||
// TODO @jason:这里看看不用 result
|
||||
const result = await api({
|
||||
id: taskId.value as string,
|
||||
reason: formData.reason,
|
||||
@@ -111,8 +115,6 @@ async function handleSubmit() {
|
||||
handleBack()
|
||||
}, 1500)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[audit] 审批失败:', error)
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<!-- 更多操作 ActionSheet -->
|
||||
<wd-action-sheet v-if="moreOperations.length > 0" v-model="showMoreActions" :actions="moreOperations" title="请选择操作" @select="handleMoreAction" />
|
||||
|
||||
<!-- 右侧按钮,TODO 是否一定要保留两个按钮 -->
|
||||
<!-- 右侧按钮,TODO @jason:是否一定要保留两个按钮(需要的哈) -->
|
||||
<view class="flex flex-1 gap-16rpx">
|
||||
<wd-button
|
||||
v-for="(action, idx) in rightOperations"
|
||||
@@ -33,7 +33,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 无待审批的任务 仅显示取消按钮。TODO 看看还需要显示 -->
|
||||
<!-- 无待审批的任务 仅显示取消按钮。TODO @jason:看看还需要显示(这个微信交流下) -->
|
||||
<view v-if="!runningTask && isShowProcessStartCancel()" class="yd-detail-footer">
|
||||
<wd-button
|
||||
plain
|
||||
@@ -90,6 +90,7 @@ const operationIconsMap: Record<number, string> = {
|
||||
}
|
||||
|
||||
const userStore = useUserStore()
|
||||
// TODO @jason:字段注释,使用尾注释哈;
|
||||
/** 左侧操作按钮 【最多两个】{转办, 委派, 退回, 加签, 抄送等} */
|
||||
const leftOperations = ref<LeftOperationType[]>([])
|
||||
|
||||
@@ -98,7 +99,6 @@ const rightOperationTypes = []
|
||||
const rightOperations = ref<RightOperationType[]>([])
|
||||
/** 更多操作 */
|
||||
const moreOperations = ref<MoreOperationType[]>([])
|
||||
const toast = useToast()
|
||||
const runningTask = ref<Task>()
|
||||
const processInstance = ref<ProcessInstance>()
|
||||
const reasonRequire = ref<boolean>(false)
|
||||
@@ -109,6 +109,7 @@ function init(theProcessInstance: ProcessInstance, task: Task) {
|
||||
runningTask.value = task
|
||||
if (task) {
|
||||
reasonRequire.value = task.reasonRequire ?? false
|
||||
// TODO @jason:这里的判断,是否可以简化哈?就是默认计算出按钮,然后根据数量,去渲染具体的按钮。
|
||||
// 右侧按钮
|
||||
if (isHandleTaskStatus() && isShowButton(BpmTaskOperationButtonTypeEnum.REJECT)) {
|
||||
rightOperationTypes.push(BpmTaskOperationButtonTypeEnum.REJECT)
|
||||
@@ -148,7 +149,8 @@ function init(theProcessInstance: ProcessInstance, task: Task) {
|
||||
}
|
||||
}
|
||||
})
|
||||
/** 减签操作的显示 */
|
||||
|
||||
// 减签操作的显示
|
||||
if (isShowDeleteSign()) {
|
||||
if (leftOperations.value.length >= 2) {
|
||||
moreOperations.value.push({
|
||||
@@ -191,6 +193,7 @@ function init(theProcessInstance: ProcessInstance, task: Task) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 跳转到相应的操作页面 */
|
||||
function handleOperation(operationType: number) {
|
||||
switch (operationType) {
|
||||
|
||||
@@ -76,14 +76,11 @@ 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: '减签人员不能为空' },
|
||||
@@ -92,6 +89,7 @@ const formRules = {
|
||||
{ required: true, message: '审批意见不能为空' },
|
||||
],
|
||||
}
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/** 返回上一页 */
|
||||
function handleBack() {
|
||||
@@ -99,6 +97,7 @@ function handleBack() {
|
||||
}
|
||||
|
||||
/** 初始化校验 */
|
||||
// TODO @jason:最好放在 onMounted 里?或者其他地方,有个入口方法。
|
||||
if (!props.taskId || !props.processInstanceId) {
|
||||
toast.show('参数错误')
|
||||
}
|
||||
@@ -114,7 +113,7 @@ function getDeleteSignUserLabel(task: any): string {
|
||||
async function loadDeleteSignTaskList() {
|
||||
try {
|
||||
let childTasks = []
|
||||
|
||||
// TODO @jason:这里应该是从 props 里获取?
|
||||
// 从 URL 参数中获取子任务数据
|
||||
if (props.children) {
|
||||
try {
|
||||
@@ -123,7 +122,6 @@ async function loadDeleteSignTaskList() {
|
||||
console.error('[delete-sign] 解析子任务数据失败:', parseError)
|
||||
}
|
||||
}
|
||||
|
||||
// 提示没有子任务数据
|
||||
if (childTasks.length === 0) {
|
||||
toast.show('没有可减签的任务')
|
||||
@@ -135,6 +133,7 @@ async function loadDeleteSignTaskList() {
|
||||
label: getDeleteSignUserLabel(task),
|
||||
}))
|
||||
} catch (error) {
|
||||
// TODO @jason:这里不用 try catch 哈
|
||||
console.error('[delete-sign] 获取可减签任务失败:', error)
|
||||
toast.error('获取可减签任务失败')
|
||||
}
|
||||
@@ -142,31 +141,32 @@ async function loadDeleteSignTaskList() {
|
||||
|
||||
/** 提交操作 */
|
||||
async function handleSubmit() {
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
|
||||
// 使用 wd-form 的校验方法
|
||||
}
|
||||
const { valid } = await formRef.value!.validate()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:submitting 改成 formLoading 哇?统一代码风格哈;
|
||||
submitting.value = true
|
||||
try {
|
||||
// TODO @jason:这里是不是不用判断 result 哈?
|
||||
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)
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:可以不用这里的 catch 哈?
|
||||
console.error('[delete-sign] 减签失败:', error)
|
||||
toast.error('减签失败')
|
||||
} finally {
|
||||
@@ -174,7 +174,7 @@ async function handleSubmit() {
|
||||
}
|
||||
}
|
||||
|
||||
/** 页面加载时获取可减签任务列表 */
|
||||
/** 页面加载时,获取可减签任务列表 */
|
||||
onMounted(() => {
|
||||
loadDeleteSignTaskList()
|
||||
})
|
||||
|
||||
@@ -117,19 +117,18 @@ definePage({
|
||||
},
|
||||
})
|
||||
|
||||
const userStore = useUserStore()
|
||||
const toast = useToast()
|
||||
const processInstance = ref<ProcessInstance>()
|
||||
const processDefinition = ref<ProcessDefinition>()
|
||||
const tasks = ref<Task[]>([])
|
||||
const orderAsc = ref(true)
|
||||
|
||||
// 操作按钮组件 ref
|
||||
const operationButtonRef = ref()
|
||||
const operationButtonRef = ref() // 操作按钮组件 ref
|
||||
|
||||
/** 排序后的任务列表 */
|
||||
const sortedTasks = computed(() => {
|
||||
const list = [...tasks.value].filter(t => t.status !== 4) // 过滤已取消
|
||||
// TODO @jason:这里有红色报错,看看 fix 下哇?或者这块排序逻辑去掉,貌似没啥用。
|
||||
list.sort((a, b) => {
|
||||
if (a.endTime && b.endTime) {
|
||||
return orderAsc.value ? a.endTime - b.endTime : b.endTime - a.endTime
|
||||
@@ -227,11 +226,10 @@ function getStatusTextClass(status: number) {
|
||||
|
||||
/** 加载流程实例 */
|
||||
async function loadProcessInstance() {
|
||||
const param = {
|
||||
const data = await getApprovalDetail({
|
||||
processInstanceId: props.id,
|
||||
taskId: props.taskId,
|
||||
}
|
||||
const data = await getApprovalDetail(param)
|
||||
})
|
||||
if (!data || !data.processInstance) {
|
||||
toast.show('查询不到审批详情信息')
|
||||
return
|
||||
|
||||
@@ -72,17 +72,15 @@ const processInstanceId = computed(() => props.processInstanceId)
|
||||
const taskId = computed(() => props.taskId)
|
||||
const toast = useToast()
|
||||
const submitting = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const formData = reactive({
|
||||
cancelReason: '',
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
cancelReason: [
|
||||
{ required: true, message: '取消理由不能为空' },
|
||||
],
|
||||
}
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/** 返回上一页 */
|
||||
function handleBack() {
|
||||
@@ -99,31 +97,32 @@ if (!props.processInstanceId) {
|
||||
|
||||
/** 提交操作 */
|
||||
async function handleSubmit() {
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
|
||||
// 使用 wd-form 的校验方法
|
||||
}
|
||||
const { valid } = await formRef.value!.validate()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:最好放在 onMounted 里?或者其他地方,有个入口方法。
|
||||
submitting.value = true
|
||||
try {
|
||||
// TODO @jason:不判断 result 可以哇?
|
||||
const result = await cancelProcessInstanceByStartUser(
|
||||
processInstanceId.value,
|
||||
formData.cancelReason,
|
||||
)
|
||||
|
||||
if (result) {
|
||||
toast.success('流程取消成功')
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}`,
|
||||
})
|
||||
}, 1500)
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:错误处理,这里可以去掉哈。
|
||||
console.error('[process-cancel] 取消流程失败:', error)
|
||||
toast.error('取消流程失败')
|
||||
} finally {
|
||||
|
||||
@@ -76,13 +76,10 @@ const operationType = computed(() => props.type || 'transfer') // 默认转办
|
||||
const isDelegate = computed(() => operationType.value === 'delegate')
|
||||
const toast = useToast()
|
||||
const submitting = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const formData = reactive({
|
||||
userId: undefined as number | undefined,
|
||||
reason: '',
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
userId: [
|
||||
{ required: true, message: `请选择${isDelegate.value ? '接收人' : '新审批人'}` },
|
||||
@@ -91,6 +88,7 @@ const formRules = {
|
||||
{ required: true, message: '审批意见不能为空' },
|
||||
],
|
||||
}
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/** 返回上一页 */
|
||||
function handleBack() {
|
||||
@@ -98,52 +96,51 @@ function handleBack() {
|
||||
}
|
||||
|
||||
/** 初始化校验 */
|
||||
// TODO @jason:最好放在 onMounted 里?或者其他地方,有个入口方法。
|
||||
if (!props.taskId || !props.processInstanceId) {
|
||||
toast.show('参数错误')
|
||||
}
|
||||
|
||||
/** 提交操作 */
|
||||
async function handleSubmit() {
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
|
||||
// 使用 wd-form 的校验方法
|
||||
}
|
||||
const { valid } = await formRef.value!.validate()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:submitting 改成 formLoading 哇?统一代码风格哈;
|
||||
submitting.value = true
|
||||
try {
|
||||
const data = {
|
||||
id: taskId.value as string,
|
||||
reason: formData.reason,
|
||||
}
|
||||
|
||||
let result
|
||||
// todo @jason:这里是不是不用判断 result 哈?
|
||||
let result: boolean
|
||||
if (isDelegate.value) {
|
||||
// 委派
|
||||
result = await delegateTask({
|
||||
...data,
|
||||
delegateUserId: String(formData.userId),
|
||||
})
|
||||
} else {
|
||||
// 转办
|
||||
result = await transferTask({
|
||||
...data,
|
||||
assigneeUserId: String(formData.userId),
|
||||
})
|
||||
}
|
||||
|
||||
if (result) {
|
||||
toast.success(`${isDelegate.value ? '委派' : '转办'}成功`)
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`,
|
||||
})
|
||||
}, 1500)
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:可以不用这里的 catch 哈?
|
||||
console.error(`[reassign] ${isDelegate.value ? '委派' : '转办'}失败:`, error)
|
||||
toast.error(`${isDelegate.value ? '委派' : '转办'}失败`)
|
||||
} finally {
|
||||
|
||||
@@ -74,14 +74,11 @@ const taskId = computed(() => props.taskId)
|
||||
const processInstanceId = computed(() => props.processInstanceId)
|
||||
const toast = useToast()
|
||||
const submitting = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const activityOptions = ref<any[]>([])
|
||||
|
||||
const formData = reactive({
|
||||
targetActivityId: '',
|
||||
reason: '',
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
targetActivityId: [
|
||||
{ required: true, message: '退回节点不能为空' },
|
||||
@@ -90,6 +87,7 @@ const formRules = {
|
||||
{ required: true, message: '退回原因不能为空' },
|
||||
],
|
||||
}
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/** 返回上一页 */
|
||||
function handleBack() {
|
||||
@@ -97,6 +95,7 @@ function handleBack() {
|
||||
}
|
||||
|
||||
/** 初始化校验 */
|
||||
// TODO @jason:最好放在 onMounted 里?或者其他地方,有个入口方法。
|
||||
if (!props.taskId || !props.processInstanceId) {
|
||||
toast.show('参数错误')
|
||||
}
|
||||
@@ -105,10 +104,12 @@ if (!props.taskId || !props.processInstanceId) {
|
||||
async function loadReturnTaskList() {
|
||||
try {
|
||||
const result = await getTaskListByReturn(taskId.value)
|
||||
// TODO @jason:这个判断可以考虑去掉哈。
|
||||
if (result && Array.isArray(result)) {
|
||||
activityOptions.value = result
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:错误处理,这里可以去掉哈。
|
||||
console.error('[return] 获取可退回节点失败:', error)
|
||||
toast.error('获取可退回节点失败')
|
||||
}
|
||||
@@ -116,32 +117,33 @@ async function loadReturnTaskList() {
|
||||
|
||||
/** 提交操作 */
|
||||
async function handleSubmit() {
|
||||
if (submitting.value)
|
||||
if (submitting.value) {
|
||||
return
|
||||
|
||||
// 使用 wd-form 的校验方法
|
||||
}
|
||||
const { valid } = await formRef.value!.validate()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @jason:submitting 改成 formLoading 哇?统一代码风格哈;
|
||||
submitting.value = true
|
||||
try {
|
||||
// TODO @jason:这里是不是不用判断 result 哈?
|
||||
const result = await returnTask({
|
||||
id: taskId.value as string,
|
||||
targetTaskDefinitionKey: formData.targetActivityId,
|
||||
reason: formData.reason,
|
||||
})
|
||||
|
||||
if (result) {
|
||||
toast.success('退回成功')
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: `/pages-bpm/processInstance/detail/index?id=${processInstanceId.value}&taskId=${taskId.value}`,
|
||||
})
|
||||
}, 1500)
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO @jason:可以不用这里的 catch 哈?
|
||||
console.error('[return] 退回失败:', error)
|
||||
toast.error('退回失败')
|
||||
} finally {
|
||||
|
||||
@@ -63,7 +63,7 @@ export const useUserStore = defineStore(
|
||||
/** 获取用户信息 */
|
||||
const fetchUserInfo = async () => {
|
||||
const res = await getAuthPermissionInfo()
|
||||
// 后端返回的用户 Id 字段为 id.
|
||||
// 兼容:后端返回的用户 id 字段为 id
|
||||
res.user.userId = res.user.id
|
||||
setUserInfo(res)
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user