流程待处理、已处理、以及流程详情页操作回显
This commit is contained in:
17
src/api/bpm-boot/activity.ts
Normal file
17
src/api/bpm-boot/activity.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import createAxios from '@/utils/request'
|
||||
|
||||
import { BPM_BOOT } from '@/utils/constantRequest'
|
||||
|
||||
const MAPPING_PATH = BPM_BOOT + '/bpm/activity'
|
||||
|
||||
|
||||
/**
|
||||
* 生成指定流程实例的高亮流程图
|
||||
*/
|
||||
export const getTaskListByReturn = (processInstanceId: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/getActivityList?processInstanceId='+processInstanceId,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
27
src/api/bpm-boot/definition.ts
Normal file
27
src/api/bpm-boot/definition.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import createAxios from '@/utils/request'
|
||||
|
||||
import { BPM_BOOT } from '@/utils/constantRequest'
|
||||
|
||||
const MAPPING_PATH = BPM_BOOT + '/bpm/processDefinition'
|
||||
|
||||
/**
|
||||
* 通过任务
|
||||
*/
|
||||
export const approveTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/approve',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得流程定义
|
||||
*/
|
||||
export const getProcessDefinitionById = (id: string, key: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/get?id=' + id + '&key=' + key,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
28
src/api/bpm-boot/instance.ts
Normal file
28
src/api/bpm-boot/instance.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import createAxios from '@/utils/request'
|
||||
|
||||
import { BPM_BOOT } from '@/utils/constantRequest'
|
||||
|
||||
const MAPPING_PATH = BPM_BOOT + '/bpm/processInstance'
|
||||
|
||||
/**
|
||||
* 通过任务
|
||||
*/
|
||||
export const approveTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/approve',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获得指定流程实例
|
||||
*/
|
||||
export const getProcessInstanceById = (id: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/get?id='+id,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
127
src/api/bpm-boot/task.ts
Normal file
127
src/api/bpm-boot/task.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import createAxios from '@/utils/request'
|
||||
|
||||
import { BPM_BOOT } from '@/utils/constantRequest'
|
||||
|
||||
const MAPPING_PATH = BPM_BOOT + '/bpm/task'
|
||||
|
||||
/**
|
||||
* 通过任务
|
||||
*/
|
||||
export const approveTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/approve',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 不通过任务
|
||||
*/
|
||||
export const rejectTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/reject',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 委派任务
|
||||
*/
|
||||
export const delegateTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/delegate',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 回退任务
|
||||
*/
|
||||
export const returnTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/return',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
export const createSignTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/createSign',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 减签
|
||||
*/
|
||||
export const deleteSignTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/deleteSign',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 转派任务
|
||||
*/
|
||||
export const transferTask = (data: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/transfer',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
export const getTaskListByParentTaskId = (parentTaskId: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/listByParentTaskId?parentTaskId='+parentTaskId,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有可回退的节点
|
||||
*/
|
||||
export const getTaskListByReturn = (id: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/listByReturn?id='+id,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获得指定流程实例的任务列表
|
||||
*/
|
||||
export const listByProcessInstanceId = (parentTaskId: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/listByParentTaskId?parentTaskId='+parentTaskId,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得指定流程实例的任务列表
|
||||
*/
|
||||
export const getTaskListByProcessInstanceId = (processInstanceId: string) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/listByProcessInstanceId?processInstanceId='+processInstanceId,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import createAxios from '@/utils/request'
|
||||
|
||||
import { SUPERVISION_BOOT } from '@/utils/constantRequest'
|
||||
|
||||
const MAPPING_PATH = SUPERVISION_BOOT + '/workflow/wfForm'
|
||||
const MAPPING_PATH = SUPERVISION_BOOT + '/userReport'
|
||||
|
||||
/**
|
||||
* 查询流程表单数据
|
||||
@@ -14,3 +14,14 @@ export const getUserReport = (data: any) => {
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据id获取用户档案录入的详细数据
|
||||
*/
|
||||
export const getUserReportById = (id: any) => {
|
||||
return createAxios({
|
||||
url: MAPPING_PATH + '/getById?id='+id,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1872,7 +1872,7 @@ export const IconJson = {
|
||||
'umbrella-beach',
|
||||
'underline',
|
||||
'undo',
|
||||
'undo-alt',
|
||||
'todo-alt',
|
||||
'union',
|
||||
'universal-access',
|
||||
'university',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div ref="tableHeader" class="cn-table-header">
|
||||
<div class="table-header ba-scroll-style">
|
||||
<el-form
|
||||
style="flex: 1; height: 32px; overflow: hidden; margin-right: 20px"
|
||||
style="flex: 1; height: 34px; overflow: hidden; margin-right: 20px"
|
||||
ref="headerForm"
|
||||
@submit.prevent=""
|
||||
@keyup.enter="onComSearch"
|
||||
|
||||
@@ -111,6 +111,14 @@ export const adminBaseRoute = {
|
||||
title: pageTitle('router.modelEdit')
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'instanceDetail',
|
||||
component: () => import('@/views/system/bpm/processInstance/detail/index.vue'),
|
||||
name: 'BpmProcessInstanceDetail',
|
||||
meta: {
|
||||
title: pageTitle('router.instanceDetail')
|
||||
}
|
||||
},
|
||||
// {
|
||||
// path: 'manager/model/edit',
|
||||
// component: () => import('@/views/bpm/model/editor/index.vue'),
|
||||
@@ -135,18 +143,7 @@ export const adminBaseRoute = {
|
||||
// activeMenu: '/bpm/manager/model'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// path: 'process-instance/detail',
|
||||
// component: () => import('@/views/bpm/processInstance/detail/index.vue'),
|
||||
// name: 'BpmProcessInstanceDetail',
|
||||
// meta: {
|
||||
// noCache: true,
|
||||
// hidden: true,
|
||||
// canTo: true,
|
||||
// title: '流程详情',
|
||||
// activeMenu: '/bpm/task/my'
|
||||
// }
|
||||
// },
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
50
src/views/bpm/oa/leave/detail.vue
Normal file
50
src/views/bpm/oa/leave/detail.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="请假类型">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">
|
||||
{{ formatDate(detailData.startTime, 'YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="结束时间">
|
||||
{{ formatDate(detailData.endTime, 'YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="原因">
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref, nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
defineOptions({ name: 'BpmOALeaveDetail' })
|
||||
|
||||
const { query } = useRoute() // 查询参数
|
||||
|
||||
const props = defineProps({
|
||||
id: propTypes.number.def(undefined)
|
||||
})
|
||||
const detailLoading = ref(false) // 表单的加载中
|
||||
const detailData = ref<any>({}) // 详情数据
|
||||
const queryId = query.id as unknown as number // 从 URL 传递过来的 id 编号
|
||||
|
||||
/** 获得数据 */
|
||||
const getInfo = async () => {
|
||||
detailLoading.value = true
|
||||
try {
|
||||
// detailData.value = await LeaveApi.getLeave(props.id || queryId)
|
||||
} finally {
|
||||
detailLoading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open: getInfo }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getInfo()
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<div class='default-main'>
|
||||
<el-descriptions :column='2' border>
|
||||
<el-descriptions-item label='填报人'>
|
||||
{{ detailData.reporter }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='填报日期'>
|
||||
{{ formatDate(detailData.reportDate, 'YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='填报部门'>
|
||||
{{ detailData.orgName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='工程预期投产日期'>
|
||||
{{ formatDate(detailData.expectedProductionDate, 'YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='用户性质'>
|
||||
{{ detailData.userType }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='所属地址'>
|
||||
{{ detailData.city }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='归口管理部门'>
|
||||
{{ detailData.responsibleDepartment }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='用户状态'>
|
||||
{{ detailData.userStatus }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='变电站'>
|
||||
{{ detailData.substation }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='工程名'>
|
||||
{{ detailData.projectName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='用户协议容量'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='电压等级'>
|
||||
{{ detailData.voltageLevel }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='非线性设备类型'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='预测评估单位'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='预测评估结论'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='是否需要治理'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label='是否开展背景测试'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='可研报告'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='项目初步设计说明书'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='预测评估评审意见报告'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span='2' label='其他附件'>
|
||||
{{ detailData.reason }}
|
||||
</el-descriptions-item>
|
||||
|
||||
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref, nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { getUserReportById } from '@/api/supervision-boot/userReport/form'
|
||||
|
||||
defineOptions({ name: 'BpmOALeaveDetail' })
|
||||
|
||||
const { query } = useRoute() // 查询参数
|
||||
|
||||
const props = defineProps({
|
||||
id: propTypes.number.def(undefined)
|
||||
})
|
||||
const detailLoading = ref(false) // 表单的加载中
|
||||
const detailData = ref<any>({}) // 详情数据
|
||||
const queryId = query.id as unknown as number // 从 URL 传递过来的 id 编号
|
||||
|
||||
/** 获得数据 */
|
||||
const getInfo = async () => {
|
||||
detailLoading.value = true
|
||||
try {
|
||||
await getUserReportById(props.id || queryId).then(res => {
|
||||
detailData.value = res.data
|
||||
})
|
||||
} finally {
|
||||
detailLoading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open: getInfo }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getInfo()
|
||||
})
|
||||
</script>
|
||||
@@ -1,49 +1,49 @@
|
||||
<template>
|
||||
<div>
|
||||
<content-wrap>
|
||||
<!-- 表单设计器 -->
|
||||
<FcDesigner ref='designer' height='780px'>
|
||||
<template #handle>
|
||||
<el-button round size='small' type='primary' @click='handleSave' class='ml10' :icon='Plus'>保存
|
||||
</el-button>
|
||||
<el-button round size='small' type='primary' @click='go(-1)' class='ml10' :icon='Back'>取消
|
||||
</el-button>
|
||||
</template>
|
||||
</FcDesigner>
|
||||
</content-wrap>
|
||||
<div class='default-main'>
|
||||
<content-wrap>
|
||||
<!-- 表单设计器 -->
|
||||
<FcDesigner ref='designer' height='780px'>
|
||||
<template #handle>
|
||||
<el-button round size='small' type='primary' @click='handleSave' class='ml10' :icon='Plus'>保存
|
||||
</el-button>
|
||||
<el-button round size='small' @click='go(-1)' class='ml10' :icon='Back'>取消
|
||||
</el-button>
|
||||
</template>
|
||||
</FcDesigner>
|
||||
</content-wrap>
|
||||
|
||||
<!-- 表单保存的弹窗 -->
|
||||
<el-dialog v-model='dialogVisible' title='保存表单' class='cn-operate-dialog' style='width: 415px;height: 350px'
|
||||
top='30vh'>
|
||||
<el-scrollbar>
|
||||
<el-form ref='formRef' :model='formData' :rules='formRules' label-width='80px'>
|
||||
<el-form-item label='表单名' prop='name'>
|
||||
<el-input v-model='formData.name' placeholder='请输入表单名' />
|
||||
</el-form-item>
|
||||
<el-form-item label='状态' prop='status'>
|
||||
<el-radio-group v-model='formData.status'>
|
||||
<el-radio
|
||||
v-for='dict in options'
|
||||
:key='dict.value'
|
||||
:label='dict.value'
|
||||
>
|
||||
{{ dict.name }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label='备注' prop='remark'>
|
||||
<el-input v-model='formData.remark' placeholder='请输入备注' type='textarea' />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<!-- 表单保存的弹窗 -->
|
||||
<el-dialog v-model='dialogVisible' title='保存表单' class='cn-operate-dialog' style='width: 415px;height: 350px'
|
||||
top='30vh'>
|
||||
<el-scrollbar>
|
||||
<el-form ref='formRef' :model='formData' :rules='formRules' label-width='80px'>
|
||||
<el-form-item label='表单名' prop='name'>
|
||||
<el-input v-model='formData.name' placeholder='请输入表单名' />
|
||||
</el-form-item>
|
||||
<el-form-item label='状态' prop='status'>
|
||||
<el-radio-group v-model='formData.status'>
|
||||
<el-radio
|
||||
v-for='dict in options'
|
||||
:key='dict.value'
|
||||
:label='dict.value'
|
||||
>
|
||||
{{ dict.name }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label='备注' prop='remark'>
|
||||
<el-input v-model='formData.remark' placeholder='请输入备注' type='textarea' />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<span class='dialog-footer'>
|
||||
<el-button :disabled='formLoading' type='primary' @click='submitForm'>确 定</el-button>
|
||||
<el-button @click='dialogVisible = false'>取 消</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, ref, reactive } from 'vue'
|
||||
@@ -57,14 +57,14 @@ import { Plus, Back } from '@element-plus/icons-vue'
|
||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
|
||||
|
||||
const options = ref([
|
||||
{
|
||||
value: 1,
|
||||
name: '开启'
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: '关闭'
|
||||
}
|
||||
{
|
||||
value: 1,
|
||||
name: '开启'
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
name: '关闭'
|
||||
}
|
||||
])
|
||||
|
||||
defineOptions({ name: 'BpmFormEditor' })
|
||||
@@ -81,74 +81,74 @@ useFormCreateDesigner(designer) // 表单设计器增强
|
||||
const dialogVisible = ref(false) // 弹窗是否展示
|
||||
const formLoading = ref(false) // 表单的加载中:提交的按钮禁用
|
||||
const formData = ref({
|
||||
name: '',
|
||||
status: 1,
|
||||
remark: ''
|
||||
name: '',
|
||||
status: 1,
|
||||
remark: ''
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '表单名不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
|
||||
name: [{ required: true, message: '表单名不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 处理保存按钮 */
|
||||
const handleSave = () => {
|
||||
dialogVisible.value = true
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
type FormVO = {
|
||||
id: number
|
||||
name: string
|
||||
conf: string
|
||||
fields: string[]
|
||||
status: number
|
||||
remark: string
|
||||
createTime: string
|
||||
id: number
|
||||
name: string
|
||||
conf: string
|
||||
fields: string[]
|
||||
status: number
|
||||
remark: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as FormVO
|
||||
data.conf = encodeConf(designer) // 表单配置
|
||||
data.fields = encodeFields(designer) // 表单字段
|
||||
if (!data.id) {
|
||||
await addForm(data)
|
||||
ElMessage.success('保存成功')
|
||||
} else {
|
||||
await updateForm(data)
|
||||
ElMessage.success('更新成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
close()
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as FormVO
|
||||
data.conf = encodeConf(designer) // 表单配置
|
||||
data.fields = encodeFields(designer) // 表单字段
|
||||
if (!data.id) {
|
||||
await addForm(data)
|
||||
ElMessage.success('保存成功')
|
||||
} else {
|
||||
await updateForm(data)
|
||||
ElMessage.success('更新成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
close()
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
/** 关闭按钮 */
|
||||
const close = () => {
|
||||
delView(unref(currentRoute))
|
||||
go(-1)
|
||||
delView(unref(currentRoute))
|
||||
go(-1)
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
// 场景一:新增表单
|
||||
const id = query.id as unknown as string
|
||||
if (!id) {
|
||||
return
|
||||
}
|
||||
// 场景二:修改表单
|
||||
await getById(id).then(res => {
|
||||
formData.value = res.data
|
||||
setConfAndFields(designer, res.data.conf, res.data.fields)
|
||||
})
|
||||
// 场景一:新增表单
|
||||
const id = query.id as unknown as string
|
||||
if (!id) {
|
||||
return
|
||||
}
|
||||
// 场景二:修改表单
|
||||
await getById(id).then(res => {
|
||||
formData.value = res.data
|
||||
setConfAndFields(designer, res.data.conf, res.data.fields)
|
||||
})
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 流程设计器,负责绘制流程等 -->
|
||||
<MyProcessDesigner
|
||||
key='designer'
|
||||
v-if='xmlString !== undefined'
|
||||
v-model='xmlString'
|
||||
:value='xmlString'
|
||||
v-bind='controlForm'
|
||||
keyboard
|
||||
ref='processDesigner'
|
||||
@init-finished='initModeler'
|
||||
:additionalModel='controlForm.additionalModel'
|
||||
@save='save'
|
||||
/>
|
||||
<!-- 流程属性器,负责编辑每个流程节点的属性 -->
|
||||
<MyProcessPenal
|
||||
key='penal'
|
||||
:bpmnModeler='modeler as any'
|
||||
:prefix='controlForm.prefix'
|
||||
class='process-panel'
|
||||
:model='model'
|
||||
/>
|
||||
</ContentWrap>
|
||||
<div class='default-main'>
|
||||
<ContentWrap>
|
||||
<!-- 流程设计器,负责绘制流程等 -->
|
||||
<MyProcessDesigner
|
||||
key='designer'
|
||||
v-if='xmlString !== undefined'
|
||||
v-model='xmlString'
|
||||
:value='xmlString'
|
||||
v-bind='controlForm'
|
||||
keyboard
|
||||
ref='processDesigner'
|
||||
@init-finished='initModeler'
|
||||
:additionalModel='controlForm.additionalModel'
|
||||
@save='save'
|
||||
/>
|
||||
<!-- 流程属性器,负责编辑每个流程节点的属性 -->
|
||||
<MyProcessPenal
|
||||
key='penal'
|
||||
:bpmnModeler='modeler as any'
|
||||
:prefix='controlForm.prefix'
|
||||
class='process-panel'
|
||||
:model='model'
|
||||
/>
|
||||
</ContentWrap>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<el-card v-loading="loading" class="box-card">
|
||||
<template #header>
|
||||
<span class="el-icon-picture-outline">流程图</span>
|
||||
</template>
|
||||
<MyProcessViewer
|
||||
key="designer"
|
||||
:activityData="activityList"
|
||||
:prefix="bpmnControlForm.prefix"
|
||||
:processInstanceData="processInstance"
|
||||
:taskData="tasks"
|
||||
:value="bpmnXml"
|
||||
v-bind="bpmnControlForm"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { MyProcessViewer } from '@/components/bpmnProcessDesigner/package'
|
||||
import { getTaskListByReturn } from '@/api/bpm-boot/activity'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceBpmnViewer' })
|
||||
|
||||
const props = defineProps({
|
||||
loading: propTypes.bool, // 是否加载中
|
||||
id: propTypes.string, // 流程实例的编号
|
||||
processInstance: propTypes.any, // 流程实例的信息
|
||||
tasks: propTypes.array, // 流程任务的数组
|
||||
bpmnXml: propTypes.string // BPMN XML
|
||||
})
|
||||
|
||||
const bpmnControlForm = ref({
|
||||
prefix: 'flowable'
|
||||
})
|
||||
const activityList = ref([]) // 任务列表
|
||||
|
||||
/** 只有 loading 完成时,才去加载流程列表 */
|
||||
watch(
|
||||
() => props.loading,
|
||||
async (value) => {
|
||||
if (value && props.id) {
|
||||
await getTaskListByReturn(props.id).then(res =>{
|
||||
activityList.value = res.data
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style>
|
||||
.box-card {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<el-card v-loading="loading" class="box-card">
|
||||
<template #header>
|
||||
<span class="el-icon-picture-outline">审批记录</span>
|
||||
</template>
|
||||
<el-col :offset="3" :span="17">
|
||||
<div class="block">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-if="processInstance.endTime"
|
||||
:type="getProcessInstanceTimelineItemType(processInstance)"
|
||||
>
|
||||
<p style="font-weight: 700">
|
||||
结束流程:在 {{ formatDate(processInstance?.endTime) }} 结束
|
||||
<el-tag :type='getTaskTimelineItemType(processInstance.status)'>
|
||||
{{getTaskNameItemType(processInstance.status)}}
|
||||
</el-tag>
|
||||
</p>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item
|
||||
v-for="(item, index) in tasks"
|
||||
:key="index"
|
||||
:type="getTaskTimelineItemType(item)"
|
||||
>
|
||||
<p style="font-weight: 700;margin: 8px">
|
||||
审批任务:{{ item.name }}
|
||||
<el-tag :type='getTaskTimelineItemType(item.status)'>
|
||||
{{getTaskNameItemType(item.status)}}
|
||||
</el-tag>
|
||||
<el-button
|
||||
class="ml-10px"
|
||||
v-if="!isEmpty(item.children)"
|
||||
@click="openChildrenTask(item)"
|
||||
size="small"
|
||||
>
|
||||
<Icon icon="ep:memo" /> 子任务
|
||||
</el-button>
|
||||
<el-button
|
||||
class="ml-10px"
|
||||
size="small"
|
||||
v-if="item.formId > 0"
|
||||
@click="handleFormDetail(item)"
|
||||
>
|
||||
<Icon icon="ep:document" /> 查看表单
|
||||
</el-button>
|
||||
</p>
|
||||
<el-card :body-style="{ padding: '10px' }">
|
||||
<label v-if="item.assigneeUser" style="margin-right: 30px; font-weight: normal">
|
||||
审批人:{{ item.assigneeUser.name }}
|
||||
<el-tag size="small" type="info">{{ item.assigneeUser.deptName }}</el-tag>
|
||||
</label>
|
||||
<label v-if="item.createTime" style="font-weight: normal">创建时间:</label>
|
||||
<label style="font-weight: normal; color: #8a909c">
|
||||
{{ formatDate(item?.createTime) }}
|
||||
</label>
|
||||
<label v-if="item.endTime" style="margin-left: 30px; font-weight: normal">
|
||||
审批时间:
|
||||
</label>
|
||||
<label v-if="item.endTime" style="font-weight: normal; color: #8a909c">
|
||||
{{ formatDate(item?.endTime) }}
|
||||
</label>
|
||||
<label v-if="item.durationInMillis" style="margin-left: 30px; font-weight: normal">
|
||||
耗时:
|
||||
</label>
|
||||
<label v-if="item.durationInMillis" style="font-weight: normal; color: #8a909c">
|
||||
{{ formatPast2(item?.durationInMillis) }}
|
||||
</label>
|
||||
<p v-if="item.reason"> 审批建议:{{ item.reason }} </p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item type="success">
|
||||
<p style="font-weight: 700">
|
||||
发起流程:【{{ processInstance.startUser?.name }}】在
|
||||
{{ formatDate(processInstance?.startTime) }} 发起【 {{ processInstance.name }} 】流程
|
||||
</p>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-card>
|
||||
|
||||
<!-- 弹窗:子任务 -->
|
||||
<TaskSignList ref="taskSignListRef" @success="refresh" />
|
||||
<!-- 弹窗:表单 -->
|
||||
<el-dialog title="表单详情" v-model="taskFormVisible" width="600">
|
||||
<form-create
|
||||
ref="fApi"
|
||||
v-model="taskForm.value"
|
||||
:option="taskForm.option"
|
||||
:rule="taskForm.rule"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { formatDate, formatPast2 } from '@/utils/formatTime'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import TaskSignList from './dialog/TaskSignList.vue'
|
||||
import type { ApiAttrs } from '@form-create/element-ui/types/config'
|
||||
import { setConfAndFields2 } from '@/utils/formCreate'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceTaskList' })
|
||||
|
||||
defineProps({
|
||||
loading: propTypes.bool, // 是否加载中
|
||||
processInstance: propTypes.object, // 流程实例
|
||||
tasks: propTypes.arrayOf(propTypes.object) // 流程任务的数组
|
||||
})
|
||||
|
||||
/** 获得流程实例对应的颜色 */
|
||||
const getProcessInstanceTimelineItemType = (item: any) => {
|
||||
if (item.status === 2) {
|
||||
return 'success'
|
||||
}
|
||||
if (item.status === 3) {
|
||||
return 'danger'
|
||||
}
|
||||
if (item.status === 4) {
|
||||
return 'warning'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/** 获得任务对应的颜色 */
|
||||
const getTaskTimelineItemType = (itemStatus: any) => {
|
||||
if ([0, 1, 6, 7].includes(itemStatus)) {
|
||||
return 'primary'
|
||||
}
|
||||
if (itemStatus === 2) {
|
||||
return 'success'
|
||||
}
|
||||
if (itemStatus === 3) {
|
||||
return 'danger'
|
||||
}
|
||||
if (itemStatus === 4) {
|
||||
return 'info'
|
||||
}
|
||||
if (itemStatus === 5) {
|
||||
return 'warning'
|
||||
}
|
||||
return 'primary'
|
||||
}
|
||||
const getTaskNameItemType = (itemStatus: any) => {
|
||||
|
||||
if (itemStatus === 1) {
|
||||
return '审批中'
|
||||
}
|
||||
if (itemStatus === 2) {
|
||||
return '审批通过'
|
||||
}
|
||||
if (itemStatus === 3) {
|
||||
return '审批不通过'
|
||||
}
|
||||
if (itemStatus === 4) {
|
||||
return '已取消'
|
||||
}
|
||||
return '审批中'
|
||||
}
|
||||
|
||||
/** 子任务 */
|
||||
const taskSignListRef = ref()
|
||||
const openChildrenTask = (item: any) => {
|
||||
taskSignListRef.value.open(item)
|
||||
}
|
||||
|
||||
/** 查看表单 */
|
||||
const fApi = ref<ApiAttrs>() // form-create 的 API 操作类
|
||||
const taskForm = ref({
|
||||
rule: [],
|
||||
option: {},
|
||||
value: {}
|
||||
}) // 流程任务的表单详情
|
||||
const taskFormVisible = ref(false)
|
||||
const handleFormDetail = async (row) => {
|
||||
// 设置表单
|
||||
setConfAndFields2(taskForm, row.formConf, row.formFields, row.formVariables)
|
||||
// 弹窗打开
|
||||
taskFormVisible.value = true
|
||||
// 隐藏提交、重置按钮,设置禁用只读
|
||||
await nextTick()
|
||||
fApi.value.fapi.btn.show(false)
|
||||
fApi.value?.fapi?.resetBtn.show(false)
|
||||
fApi.value?.fapi?.disabled(true)
|
||||
}
|
||||
|
||||
/** 刷新数据 */
|
||||
const emit = defineEmits(['refresh']) // 定义 success 事件,用于操作成功后的回调
|
||||
const refresh = () => {
|
||||
emit('refresh')
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="委派任务" width="500">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item label="接收人" prop="delegateUserId">
|
||||
<el-select v-model="formData.delegateUserId" clearable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in userList"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="委派理由" prop="reason">
|
||||
<el-input v-model="formData.reason" clearable placeholder="请输入委派理由" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { getUserSimpleList } from '@/api/user-boot/user'
|
||||
import { delegateTask } from '@/api/bpm-boot/task'
|
||||
|
||||
defineOptions({ name: 'BpmTaskDelegateForm' })
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
id: '',
|
||||
delegateUserId: undefined,
|
||||
reason: ''
|
||||
})
|
||||
const formRules = ref({
|
||||
delegateUserId: [{ required: true, message: '接收人不能为空', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '委派理由不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userList = ref<any[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: string) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
formData.value.id = id
|
||||
|
||||
// 获得用户列表
|
||||
await getUserSimpleList().then(res => {
|
||||
userList.value = res.data
|
||||
})
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await delegateTask(formData.value)
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
delegateUserId: undefined,
|
||||
reason: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<el-dialog v-model='dialogVisible' title='回退任务' width='500'>
|
||||
<el-form
|
||||
ref='formRef'
|
||||
v-loading='formLoading'
|
||||
:model='formData'
|
||||
:rules='formRules'
|
||||
label-width='110px'
|
||||
>
|
||||
<el-form-item label='退回节点' prop='targetTaskDefinitionKey'>
|
||||
<el-select v-model='formData.targetTaskDefinitionKey' clearable style='width: 100%'>
|
||||
<el-option
|
||||
v-for='item in returnList'
|
||||
:key='item.taskDefinitionKey'
|
||||
:label='item.name'
|
||||
:value='item.taskDefinitionKey'
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label='回退理由' prop='reason'>
|
||||
<el-input v-model='formData.reason' clearable placeholder='请输入回退理由' />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled='formLoading' type='primary' @click='submitForm'>确 定</el-button>
|
||||
<el-button @click='dialogVisible = false'>取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang='ts' name='TaskRollbackDialogForm' setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getTaskListByReturn, returnTask } from '@/api/bpm-boot/task'
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
id: '',
|
||||
targetTaskDefinitionKey: undefined,
|
||||
reason: ''
|
||||
})
|
||||
const formRules = ref({
|
||||
targetTaskDefinitionKey: [{ required: true, message: '必须选择回退节点', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '回退理由不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
const returnList = ref([] as any)
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: string) => {
|
||||
await getTaskListByReturn(id).then(res => {
|
||||
returnList.value = res.data
|
||||
})
|
||||
if (returnList.value.length === 0) {
|
||||
ElMessage.warning('当前没有可回退的节点')
|
||||
return false
|
||||
}
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
formData.value.id = id
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await returnTask(formData.value)
|
||||
ElMessage.success('回退成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
targetTaskDefinitionKey: undefined,
|
||||
reason: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="加签" width="500">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item label="加签处理人" prop="userIds">
|
||||
<el-select v-model="formData.userIds" multiple clearable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in userList"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="加签理由" prop="reason">
|
||||
<el-input v-model="formData.reason" clearable placeholder="请输入加签理由" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm('before')">
|
||||
向前加签
|
||||
</el-button>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm('after')">
|
||||
向后加签
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getUserSimpleList } from '@/api/user-boot/user'
|
||||
import { createSignTask } from '@/api/bpm-boot/task'
|
||||
defineOptions({ name: 'TaskSignCreateForm' })
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
id: '',
|
||||
userIds: [],
|
||||
type: '',
|
||||
reason: ''
|
||||
})
|
||||
const formRules = ref({
|
||||
userIds: [{ required: true, message: '加签处理人不能为空', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '加签理由不能为空', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userList = ref<any[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: string) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
formData.value.id = id
|
||||
// 获得用户列表
|
||||
// 获得用户列表
|
||||
await getUserSimpleList().then(res => {
|
||||
userList.value = res.data
|
||||
})
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async (type: string) => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
formData.value.type = type
|
||||
try {
|
||||
await createSignTask(formData.value)
|
||||
ElMessage.success('加签成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
userIds: [],
|
||||
type: '',
|
||||
reason: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="减签" width="500">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item label="减签任务" prop="id">
|
||||
<el-radio-group v-model="formData.id">
|
||||
<!-- <el-radio-button v-for="item in childrenTaskList" :key="item.id" :label="item.id">-->
|
||||
<!-- {{ item.name }}-->
|
||||
<!-- ({{ item.assigneeUser?.deptName || item.ownerUser?.deptName }} - -->
|
||||
<!-- {{ item.assigneeUser?.nickname || item.ownerUser?.nickname }})-->
|
||||
<!-- </el-radio-button>-->
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="减签理由" prop="reason">
|
||||
<el-input v-model="formData.reason" clearable placeholder="请输入减签理由" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { deleteSignTask, getTaskListByParentTaskId } from '@/api/bpm-boot/task'
|
||||
|
||||
defineOptions({ name: 'TaskSignDeleteForm' })
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
id: '',
|
||||
reason: ''
|
||||
})
|
||||
const formRules = ref({
|
||||
id: [{ required: true, message: '必须选择减签任务', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '减签理由不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
const childrenTaskList = ref([])
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: string) => {
|
||||
await getTaskListByParentTaskId(id).then(res => {
|
||||
childrenTaskList.value = res.data
|
||||
})
|
||||
|
||||
if (isEmpty(childrenTaskList.value)) {
|
||||
ElMessage.warning('当前没有可减签的任务')
|
||||
return false
|
||||
}
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await deleteSignTask(formData.value)
|
||||
ElMessage.success('减签成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
reason: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<el-drawer v-model="drawerVisible" title="子任务" size="880px">
|
||||
<!-- 当前任务 -->
|
||||
<template #header>
|
||||
<h4>【{{ parentTask.name }} 】审批人:{{ parentTask?.assigneeUser?.nickname }}</h4>
|
||||
<el-button
|
||||
style="margin-left: 5px"
|
||||
v-if="isSignDeleteButtonVisible(parentTask)"
|
||||
type="danger"
|
||||
plain
|
||||
@click="handleSignDelete(parentTask)"
|
||||
>
|
||||
<Icon icon="ep:remove" /> 减签
|
||||
</el-button>
|
||||
</template>
|
||||
<!-- 子任务列表 -->
|
||||
<el-table :data="parentTask.children" style="width: 100%" row-key="id" border>
|
||||
<el-table-column prop="assigneeUser.nickname" label="审批人" min-width="100">
|
||||
<template #default="scope">
|
||||
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="assigneeUser.deptName" label="所在部门" min-width="100">
|
||||
<template #default="scope">
|
||||
{{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批状态" prop="status" width="120">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="提交时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
label="结束时间"
|
||||
align="center"
|
||||
prop="endTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column label="操作" prop="operation" width="90">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="isSignDeleteButtonVisible(scope.row)"
|
||||
type="danger"
|
||||
plain
|
||||
size="small"
|
||||
@click="handleSignDelete(scope.row)"
|
||||
>
|
||||
<Icon icon="ep:remove" /> 减签
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 减签 -->
|
||||
<TaskSignDeleteForm ref="taskSignDeleteFormRef" @success="handleSignDeleteSuccess" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import TaskSignDeleteForm from './TaskSignDeleteForm.vue'
|
||||
|
||||
defineOptions({ name: 'TaskSignList' })
|
||||
|
||||
const drawerVisible = ref(false) // 抽屉的是否展示
|
||||
const parentTask = ref({} as any)
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (task: any) => {
|
||||
if (isEmpty(task.children)) {
|
||||
ElMessage.warning('该任务没有子任务')
|
||||
return
|
||||
}
|
||||
parentTask.value = task
|
||||
// 展开抽屉
|
||||
drawerVisible.value = true
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 发起减签 */
|
||||
const taskSignDeleteFormRef = ref()
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const handleSignDelete = (item: any) => {
|
||||
taskSignDeleteFormRef.value.open(item.id)
|
||||
}
|
||||
const handleSignDeleteSuccess = () => {
|
||||
emit('success')
|
||||
// 关闭抽屉
|
||||
drawerVisible.value = false
|
||||
}
|
||||
|
||||
/** 是否显示减签按钮 */
|
||||
const isSignDeleteButtonVisible = (task: any) => {
|
||||
return task && task.children && !isEmpty(task.children)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="转派任务" width="500">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item label="新审批人" prop="assigneeUserId">
|
||||
<el-select v-model="formData.assigneeUserId" clearable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in userList"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="转派理由" prop="reason">
|
||||
<el-input v-model="formData.reason" clearable placeholder="请输入转派理由" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref,nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getUserSimpleList } from '@/api/user-boot/user'
|
||||
import { transferTask } from '@/api/bpm-boot/task'
|
||||
|
||||
defineOptions({ name: 'TaskTransferForm' })
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
id: '',
|
||||
assigneeUserId: undefined,
|
||||
reason: ''
|
||||
})
|
||||
const formRules = ref({
|
||||
assigneeUserId: [{ required: true, message: '新审批人不能为空', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '转派理由不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userList = ref<any[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: string) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
formData.value.id = id
|
||||
// 获得用户列表
|
||||
await getUserSimpleList().then(res => {
|
||||
userList.value = res.data
|
||||
})
|
||||
}
|
||||
defineExpose({ open }) // 提供 openModal 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await transferTask(formData.value)
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
assigneeUserId: undefined,
|
||||
reason: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
429
src/views/system/bpm/processInstance/detail/index.vue
Normal file
429
src/views/system/bpm/processInstance/detail/index.vue
Normal file
@@ -0,0 +1,429 @@
|
||||
<template>
|
||||
<div class='default-main'>
|
||||
<!--返回按钮-->
|
||||
<back-component style='margin: 8px;position: absolute;z-index: 10;top: -3px;right: 2px' />
|
||||
<el-tabs type='border-card' v-model='tab'>
|
||||
<el-tab-pane label='流程审核' name='流程审核' v-if='runningTasks.length>0'>
|
||||
<el-card
|
||||
v-for='(item, index) in runningTasks'
|
||||
:key='index'
|
||||
v-loading='processInstanceLoading'
|
||||
class='box-card'
|
||||
>
|
||||
<template #header>
|
||||
<span class='el-icon-picture-outline'>当前任务【{{ item.name }}】</span>
|
||||
</template>
|
||||
<el-col :offset='6' :span='16'>
|
||||
<el-form
|
||||
:ref="'form' + index"
|
||||
:model='auditForms[index]'
|
||||
:rules='auditRule'
|
||||
label-width='100px'
|
||||
>
|
||||
<el-form-item v-if='processInstance && processInstance.name' label='流程名'>
|
||||
{{ processInstance.name }}
|
||||
</el-form-item>
|
||||
<el-form-item v-if='processInstance && processInstance.startUser' label='发起人'>
|
||||
{{ processInstance?.startUser.name }}
|
||||
</el-form-item>
|
||||
<el-form-item v-if='processInstance && processInstance.startUser' label='发起部门'>
|
||||
{{ processInstance?.startUser.deptName }}
|
||||
</el-form-item>
|
||||
|
||||
<el-card v-if='runningTasks[index].formId > 0' class='mb-15px !-mt-10px'>
|
||||
<template #header>
|
||||
<span class='el-icon-picture-outline'>
|
||||
填写表单【{{ runningTasks[index]?.formName }}】
|
||||
</span>
|
||||
</template>
|
||||
<form-create
|
||||
v-model='approveForms[index].value'
|
||||
v-model:api='approveFormFApis[index]'
|
||||
:option='approveForms[index].option'
|
||||
:rule='approveForms[index].rule'
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-form-item label='审批建议' prop='reason'>
|
||||
<el-input
|
||||
v-model='auditForms[index].reason'
|
||||
placeholder='请输入审批建议'
|
||||
type='textarea'
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label='抄送人' prop='copyUserIds'>-->
|
||||
<!-- <el-select v-model='auditForms[index].copyUserIds' multiple placeholder='请选择抄送人'>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for='item in userOptions'-->
|
||||
<!-- :key='item.id'-->
|
||||
<!-- :label='item.nickname'-->
|
||||
<!-- :value='item.id'-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<div style='margin-bottom: 20px; margin-left: 10%; font-size: 14px'>
|
||||
|
||||
<el-button
|
||||
type='success'
|
||||
:icon='Select'
|
||||
@click='handleAudit(item, true)'
|
||||
>通过
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
type='danger'
|
||||
:icon='Close'
|
||||
@click='handleAudit(item, false)'
|
||||
>不通过
|
||||
</el-button>
|
||||
|
||||
<!-- <el-button type='primary' @click='openTaskUpdateAssigneeForm(item.id)'>-->
|
||||
<!-- <Icon icon='ep:edit' />-->
|
||||
<!-- 转办-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button type='primary' @click='handleDelegate(item)'>-->
|
||||
<!-- <Icon icon='ep:position' />-->
|
||||
<!-- 委派-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button type='primary' @click='handleSign(item)'>-->
|
||||
<!-- <Icon icon='ep:plus' />-->
|
||||
<!-- 加签-->
|
||||
<!-- </el-button>-->
|
||||
|
||||
<el-button
|
||||
type='warning'
|
||||
:icon='Back'
|
||||
@click='handleBack(item)'
|
||||
>回退
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='申请信息' name='申请信息'>
|
||||
<!-- 申请信息 -->
|
||||
<el-card v-loading='processInstanceLoading' class='box-card'>
|
||||
<template #header>
|
||||
<span class='el-icon-document'>申请信息【{{ processInstance.name }}】</span>
|
||||
</template>
|
||||
<!-- 情况一:流程表单 -->
|
||||
<el-col v-if='processInstance?.processDefinition?.formType === 10' :offset='6' :span='16'>
|
||||
<form-create
|
||||
v-model='detailForm.value'
|
||||
v-model:api='fApi'
|
||||
:option='detailForm.option'
|
||||
:rule='detailForm.rule'
|
||||
/>
|
||||
</el-col>
|
||||
<!-- 情况二:业务表单 -->
|
||||
<div v-if='processInstance?.processDefinition?.formType === 20'>
|
||||
<BusinessFormComponent :id='processInstance.businessKey' />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='审批记录'>
|
||||
<!-- 审批记录 -->
|
||||
<ProcessInstanceTaskList
|
||||
:loading='tasksLoad'
|
||||
:process-instance='processInstance'
|
||||
:tasks='tasks'
|
||||
@refresh='getTaskList'
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label='流程图'>
|
||||
<!-- 高亮流程图 -->
|
||||
<!-- <ProcessInstanceBpmnViewer-->
|
||||
<!-- :id="`${id}`"-->
|
||||
<!-- :bpmn-xml="bpmnXml"-->
|
||||
<!-- :loading="processInstanceLoading"-->
|
||||
<!-- :process-instance="processInstance"-->
|
||||
<!-- :tasks="tasks"-->
|
||||
<!-- />--></el-tab-pane>
|
||||
</el-tabs>
|
||||
<ContentWrap>
|
||||
<!-- 弹窗:转派审批人 -->
|
||||
<TaskTransferForm ref='taskTransferFormRef' @success='getDetail' />
|
||||
<!-- 弹窗:回退节点 -->
|
||||
<TaskReturnForm ref='taskReturnFormRef' @success='getDetail' />
|
||||
<!-- 弹窗:委派,将任务委派给别人处理,处理完成后,会重新回到原审批人手中-->
|
||||
<TaskDelegateForm ref='taskDelegateForm' @success='getDetail' />
|
||||
<!-- 弹窗:加签,当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
|
||||
<TaskSignCreateForm ref='taskSignCreateFormRef' @success='getDetail' />
|
||||
</ContentWrap>
|
||||
</div>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, provide, ref, getCurrentInstance, reactive, watch, unref, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
|
||||
import { setConfAndFields2 } from '@/utils/formCreate'
|
||||
import type { ApiAttrs } from '@form-create/element-ui/types/config'
|
||||
import ProcessInstanceBpmnViewer from './ProcessInstanceBpmnViewer.vue'
|
||||
import ProcessInstanceTaskList from './ProcessInstanceTaskList.vue'
|
||||
import TaskReturnForm from './dialog/TaskReturnForm.vue'
|
||||
import TaskDelegateForm from './dialog/TaskDelegateForm.vue'
|
||||
import TaskTransferForm from './dialog/TaskTransferForm.vue'
|
||||
import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue'
|
||||
import { registerComponent } from '@/utils/routerHelper'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { approveTask, getTaskListByProcessInstanceId, listByProcessInstanceId, rejectTask } from '@/api/bpm-boot/task'
|
||||
import { getProcessInstanceById } from '@/api/bpm-boot/instance'
|
||||
import { getProcessDefinitionById } from '@/api/bpm-boot/definition'
|
||||
import { getUserSimpleList } from '@/api/user-boot/user'
|
||||
import { Close, Back, Select } from '@element-plus/icons-vue'
|
||||
import BackComponent from '@/components/icon/back/index.vue'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceDetail' })
|
||||
|
||||
const { query } = useRoute() // 查询参数
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const userId = JSON.parse(window.localStorage.getItem('adminInfo')).id// 当前登录的编号
|
||||
|
||||
|
||||
const id = query.id as unknown as string // 流程实例的编号
|
||||
const todo = query.todo// 是否存在待办事项
|
||||
const processInstanceLoading = ref(false) // 流程实例的加载中
|
||||
const processInstance = ref<any>({}) // 流程实例
|
||||
const bpmnXml = ref('') // BPMN XML
|
||||
const tasksLoad = ref(true) // 任务的加载中
|
||||
const tasks = ref<any[]>([]) // 任务列表
|
||||
// ========== 审批信息 ==========
|
||||
const runningTasks = ref<any[]>([]) // 运行中的任务
|
||||
const auditForms = ref<any[]>([]) // 审批任务的表单
|
||||
const auditRule = reactive({
|
||||
reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const approveForms = ref<any[]>([]) // 审批通过时,额外的补充信息
|
||||
const approveFormFApis = ref<ApiAttrs[]>([]) // approveForms 的 fAPi
|
||||
|
||||
// ========== 申请信息 ==========
|
||||
const fApi = ref<ApiAttrs>() //
|
||||
const detailForm = ref({
|
||||
rule: [],
|
||||
option: {},
|
||||
value: {}
|
||||
}) // 流程实例的表单详情
|
||||
|
||||
/** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
|
||||
watch(
|
||||
() => approveFormFApis.value,
|
||||
(value) => {
|
||||
value?.forEach((api) => {
|
||||
api.btn.show(false)
|
||||
api.resetBtn.show(false)
|
||||
})
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
/** 处理审批通过和不通过的操作 */
|
||||
const handleAudit = async (task, pass) => {
|
||||
// 1.1 获得对应表单
|
||||
const index = runningTasks.value.indexOf(task)
|
||||
const auditFormRef = proxy.$refs['form' + index][0]
|
||||
// 1.2 校验表单
|
||||
const elForm = unref(auditFormRef)
|
||||
if (!elForm) return
|
||||
const valid = await elForm.validate()
|
||||
if (!valid) return
|
||||
|
||||
// 2.1 提交审批
|
||||
const data = {
|
||||
id: task.id,
|
||||
reason: auditForms.value[index].reason,
|
||||
copyUserIds: auditForms.value[index].copyUserIds
|
||||
}
|
||||
if (pass) {
|
||||
// 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
|
||||
const formCreateApi = approveFormFApis.value[index]
|
||||
if (formCreateApi) {
|
||||
await formCreateApi.validate()
|
||||
data.variables = approveForms.value[index].value
|
||||
}
|
||||
await approveTask(data)
|
||||
ElMessage.success('审批通过成功')
|
||||
} else {
|
||||
await rejectTask(data)
|
||||
ElMessage.success('审批不通过成功')
|
||||
}
|
||||
// 2.2 加载最新数据
|
||||
getDetail()
|
||||
}
|
||||
|
||||
/** 转派审批人 */
|
||||
const taskTransferFormRef = ref()
|
||||
const openTaskUpdateAssigneeForm = (id: string) => {
|
||||
taskTransferFormRef.value.open(id)
|
||||
}
|
||||
|
||||
/** 处理审批退回的操作 */
|
||||
const taskDelegateForm = ref()
|
||||
const handleDelegate = async (task) => {
|
||||
taskDelegateForm.value.open(task.id)
|
||||
}
|
||||
|
||||
/** 处理审批退回的操作 */
|
||||
const taskReturnFormRef = ref()
|
||||
const handleBack = async (task: any) => {
|
||||
taskReturnFormRef.value.open(task.id)
|
||||
}
|
||||
|
||||
/** 处理审批加签的操作 */
|
||||
const taskSignCreateFormRef = ref()
|
||||
const handleSign = async (task: any) => {
|
||||
taskSignCreateFormRef.value.open(task.id)
|
||||
}
|
||||
|
||||
/** 获得详情 */
|
||||
const getDetail = () => {
|
||||
// 1. 获得流程实例相关
|
||||
getProcessInstance()
|
||||
// 2. 获得流程任务列表(审批记录)
|
||||
getTaskList()
|
||||
}
|
||||
|
||||
/** 加载流程实例 */
|
||||
const BusinessFormComponent = ref(null) // 异步组件
|
||||
const getProcessInstance = async () => {
|
||||
try {
|
||||
processInstanceLoading.value = true
|
||||
let data
|
||||
await getProcessInstanceById(id).then(res => {
|
||||
data = res.data
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
ElMessage.error('查询不到流程信息!')
|
||||
return
|
||||
}
|
||||
processInstance.value = data
|
||||
// 设置表单信息
|
||||
const processDefinition = data.processDefinition
|
||||
if (processDefinition.formType === 10) {
|
||||
setConfAndFields2(
|
||||
detailForm,
|
||||
processDefinition.formConf,
|
||||
processDefinition.formFields,
|
||||
data.formVariables
|
||||
)
|
||||
nextTick().then(() => {
|
||||
fApi.value?.btn.show(false)
|
||||
fApi.value?.resetBtn.show(false)
|
||||
fApi.value?.disabled(true)
|
||||
})
|
||||
} else {
|
||||
// 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue
|
||||
// BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
|
||||
BusinessFormComponent.value = registerComponent('/pqs/supervise/interfere/components/undocumented/detail')
|
||||
}
|
||||
|
||||
// 加载流程图
|
||||
bpmnXml.value = (
|
||||
await getProcessDefinitionById(processDefinition.id)
|
||||
)?.bpmnXml
|
||||
} finally {
|
||||
processInstanceLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载任务列表 */
|
||||
const getTaskList = async () => {
|
||||
runningTasks.value = []
|
||||
auditForms.value = []
|
||||
approveForms.value = []
|
||||
approveFormFApis.value = []
|
||||
try {
|
||||
// 获得未取消的任务
|
||||
tasksLoad.value = true
|
||||
let data
|
||||
await getTaskListByProcessInstanceId(id).then(res => {
|
||||
data = res.data
|
||||
})
|
||||
tasks.value = []
|
||||
// 1.1 移除已取消的审批
|
||||
data.forEach((task) => {
|
||||
if (task.status !== 4) {
|
||||
tasks.value.push(task)
|
||||
}
|
||||
})
|
||||
// 1.2 排序,将未完成的排在前面,已完成的排在后面;
|
||||
tasks.value.sort((a, b) => {
|
||||
// 有已完成的情况,按照完成时间倒序
|
||||
if (a.endTime && b.endTime) {
|
||||
return b.endTime - a.endTime
|
||||
} else if (a.endTime) {
|
||||
return 1
|
||||
} else if (b.endTime) {
|
||||
return -1
|
||||
// 都是未完成,按照创建时间倒序
|
||||
} else {
|
||||
return b.createTime - a.createTime
|
||||
}
|
||||
})
|
||||
|
||||
// 获得需要自己审批的任务
|
||||
loadRunningTask(tasks.value)
|
||||
} finally {
|
||||
tasksLoad.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 runningTasks 中的任务
|
||||
*/
|
||||
const loadRunningTask = (tasks) => {
|
||||
tasks.forEach((task) => {
|
||||
if (!isEmpty(task.children)) {
|
||||
loadRunningTask(task.children)
|
||||
}
|
||||
// 2.1 只有待处理才需要
|
||||
if (task.status !== 1 && task.status !== 6) {
|
||||
return
|
||||
}
|
||||
// 2.2 自己不是处理人
|
||||
if (!task.assigneeUser || task.assigneeUser.id !== userId) {
|
||||
return
|
||||
}
|
||||
// 2.3 添加到处理任务
|
||||
runningTasks.value.push({ ...task })
|
||||
auditForms.value.push({
|
||||
reason: '',
|
||||
copyUserIds: []
|
||||
})
|
||||
|
||||
// 2.4 处理 approve 表单
|
||||
if (task.formId && task.formConf) {
|
||||
const approveForm = {}
|
||||
setConfAndFields2(approveForm, task.formConf, task.formFields, task.formVariable)
|
||||
approveForms.value.push(approveForm)
|
||||
} else {
|
||||
approveForms.value.push({}) // 占位,避免为空
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const tab = ref('')
|
||||
|
||||
/** 初始化 */
|
||||
const userOptions = ref([]) // 用户列表
|
||||
onMounted(async () => {
|
||||
getDetail()
|
||||
|
||||
// 获得用户列表
|
||||
await getUserSimpleList().then(res => {
|
||||
userOptions.value = res.data
|
||||
})
|
||||
if (todo) {
|
||||
tab.value = '流程审核'
|
||||
} else {
|
||||
tab.value = '申请信息'
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
119
src/views/system/bpm/task/done/index.vue
Normal file
119
src/views/system/bpm/task/done/index.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<!--待办事项列表-->
|
||||
<template>
|
||||
<div class='default-main'>
|
||||
<TableHeader date-picker>
|
||||
<template v-slot:select>
|
||||
<el-form-item label='任务名称'>
|
||||
<el-input
|
||||
v-model='tableStore.table.params.searchValue'
|
||||
clearable
|
||||
placeholder='请输入任务名称'
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
</TableHeader>
|
||||
<!--表格-->
|
||||
<Table ref='tableRef'></Table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { onMounted, provide, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||
|
||||
|
||||
defineOptions({
|
||||
name: 'businessUser'
|
||||
})
|
||||
|
||||
const { push } = useRouter()
|
||||
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/bpm-boot/bpm/task/doneList',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '序号', type: 'seq', width: 80 },
|
||||
{ title: '流程名称', field: 'processInstance.name', minWidth: 130 },
|
||||
{ title: '发起人', field: 'processInstance.startUser.name', minWidth: 130 },
|
||||
{ title: '发起部门', field: 'processInstance.startUser.deptName', minWidth: 130 },
|
||||
{ title: '当前任务', field: 'name', minWidth: 130 },
|
||||
{ title: '发起时间', field: 'createTime', minWidth: 170 },
|
||||
{ title: '结束时间', field: 'endTime', minWidth: 170 },
|
||||
{
|
||||
title: '审批状态', field: 'status', minWidth: 130,
|
||||
render: 'tag',
|
||||
custom: {
|
||||
1: 'primary',
|
||||
2: 'success',
|
||||
3: 'danger',
|
||||
4: 'warning'
|
||||
},
|
||||
replaceValue: {
|
||||
1: '审批中',
|
||||
2: '审批通过',
|
||||
3: '审批不通过',
|
||||
4: '已取消'
|
||||
}
|
||||
},
|
||||
{ title: '审批建议', field: 'reason', minWidth: 150 },
|
||||
{ title: '耗时(s)', field: 'durationInMillis', minWidth: 150,
|
||||
formatter: (obj: any) => {
|
||||
return formatPast2(obj.row.durationInMillis)
|
||||
} },
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
minWidth: '150',
|
||||
fixed: 'right',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'productSetting',
|
||||
title: '流程历史',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-EditPen',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
handleAudit(row.processInstance.id)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
if (tableStore.table.params.addr) {
|
||||
tableStore.table.params.addrStrOption = tableStore.table.params.addr.map(tempArray => tempArray.join('/'))
|
||||
}
|
||||
for (let key in tableStore.table.params) {
|
||||
if (tableStore.table.params[key] === '') {
|
||||
delete tableStore.table.params[key]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 加载数据
|
||||
tableStore.index()
|
||||
})
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
/** 处理审批按钮 */
|
||||
const handleAudit = (instanceId: any) => {
|
||||
push({
|
||||
name: 'BpmProcessInstanceDetail',
|
||||
query: {
|
||||
id: instanceId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
96
src/views/system/bpm/task/todo/index.vue
Normal file
96
src/views/system/bpm/task/todo/index.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<!--待办事项列表-->
|
||||
<template>
|
||||
<div class='default-main'>
|
||||
<TableHeader date-picker>
|
||||
<template v-slot:select>
|
||||
<el-form-item label='任务名称'>
|
||||
<el-input
|
||||
v-model='tableStore.table.params.searchValue'
|
||||
clearable
|
||||
placeholder='请输入任务名称'
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
</TableHeader>
|
||||
<!--表格-->
|
||||
<Table ref='tableRef'></Table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { onMounted, provide, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
|
||||
defineOptions({
|
||||
name: 'businessUser'
|
||||
})
|
||||
|
||||
const { push } = useRouter()
|
||||
|
||||
|
||||
const tableStore = new TableStore({
|
||||
url: '/bpm-boot/bpm/task/todoList',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '序号', type: 'seq', width: 80 },
|
||||
{ title: '流程名称', field: 'processInstance.name', minWidth: 130 },
|
||||
{ title: '发起人', field: 'processInstance.startUser.name', minWidth: 130 },
|
||||
{ title: '发起部门', field: 'processInstance.startUser.deptName', minWidth: 130 },
|
||||
{ title: '发起时间', field: 'createTime', minWidth: 170 },
|
||||
{ title: '当前任务', field: 'name', minWidth: 130 },
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: '230',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'productSetting',
|
||||
title: '办理',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-EditPen',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
handleAudit(row.processInstance.id)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
if (tableStore.table.params.addr) {
|
||||
tableStore.table.params.addrStrOption = tableStore.table.params.addr.map(tempArray => tempArray.join('/'))
|
||||
}
|
||||
for (let key in tableStore.table.params) {
|
||||
if (tableStore.table.params[key] === '') {
|
||||
delete tableStore.table.params[key]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 加载数据
|
||||
tableStore.index()
|
||||
})
|
||||
tableStore.table.params.searchValue = ''
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
/** 处理审批按钮 */
|
||||
const handleAudit = (instanceId: any) => {
|
||||
push({
|
||||
name: 'BpmProcessInstanceDetail',
|
||||
query: {
|
||||
id: instanceId,
|
||||
todo: 'todo'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user