feat: 流程发起模块-第一步根据流程分类选择对应的流程页面样式与布局优化

pull/582/head
GoldenZqqq 2024-10-25 15:17:31 +08:00
parent a6f325b14d
commit bd4ac52a2d
2 changed files with 402 additions and 0 deletions

View File

@ -0,0 +1,294 @@
<template>
<!-- 第一步通过流程定义的列表选择对应的流程 -->
<ContentWrap
class="process-definition-container position-relative pb-20px"
v-if="!selectProcessDefinition"
v-loading="loading"
>
<el-row :gutter="20" class="!flex-nowrap">
<el-col :span="5">
<div class="flex flex-col">
<div
v-for="category in categoryList"
:key="category.code"
class="flex items-center p-10px cursor-pointer text-14px rounded-md"
:class="categoryActive.code === category.code ? 'text-#3e7bff bg-#e8eeff' : ''"
@click="handleCategoryClick(category)"
>
{{ category.name }}
</div>
</div>
</el-col>
<el-col :span="19">
<h3 class="text-16px font-bold mb-10px mt-5px">{{ categoryActive.name }}</h3>
<div class="grid grid-cols-3 gap3" v-if="categoryProcessDefinitionList.length">
<el-card
v-for="definition in categoryProcessDefinitionList"
:key="definition.id"
shadow="hover"
class="cursor-pointer definition-item-card"
@click="handleSelect(definition)"
>
<template #default>
<div class="flex">
<el-image :src="definition.icon" class="w-32px h-32px" />
<el-text class="!ml-10px" size="large">{{ definition.name }}</el-text>
</div>
</template>
</el-card>
</div>
<el-empty v-else />
</el-col>
</el-row>
</ContentWrap>
<!-- 第二步填写表单进行流程的提交 -->
<ContentWrap v-else>
<el-card class="box-card">
<div class="clearfix">
<span class="el-icon-document">申请信息{{ selectProcessDefinition.name }}</span>
<el-button style="float: right" type="primary" @click="selectProcessDefinition = undefined">
<Icon icon="ep:delete" /> 选择其它流程
</el-button>
</div>
<el-col :span="16" :offset="6" style="margin-top: 20px">
<form-create
:rule="detailForm.rule"
v-model:api="fApi"
v-model="detailForm.value"
:option="detailForm.option"
@submit="submitForm"
>
<template #type-startUserSelect>
<el-col :span="24">
<el-card class="mb-10px">
<template #header>指定审批人</template>
<el-form
:model="startUserSelectAssignees"
:rules="startUserSelectAssigneesFormRules"
ref="startUserSelectAssigneesFormRef"
>
<el-form-item
v-for="userTask in startUserSelectTasks"
:key="userTask.id"
:label="`任务【${userTask.name}】`"
:prop="userTask.id"
>
<el-select
v-model="startUserSelectAssignees[userTask.id]"
multiple
placeholder="请选择审批人"
>
<el-option
v-for="user in userList"
:key="user.id"
:label="user.nickname"
:value="user.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-card>
</el-col>
</template>
</form-create>
</el-col>
</el-card>
<!-- 流程图预览 -->
<ProcessInstanceBpmnViewer :bpmn-xml="bpmnXML" />
</ContentWrap>
</template>
<script lang="ts" setup>
import * as DefinitionApi from '@/api/bpm/definition'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import { setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue'
import { CategoryApi } from '@/api/bpm/category'
import { useTagsViewStore } from '@/store/modules/tagsView'
import * as UserApi from '@/api/system/user'
import { categoryList as cl, processDefinitionList as pl } from './mock'
defineOptions({ name: 'BpmProcessInstanceCreate' })
const route = useRoute() //
const { push, currentRoute } = useRouter() //
const message = useMessage() //
const { delView } = useTagsViewStore() //
const processInstanceId: any = route.query.processInstanceId
const loading = ref(true) //
const categoryList: any = ref([]) //
const categoryActive: any = ref({}) //
const processDefinitionList = ref([]) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
//
categoryList.value = await CategoryApi.getCategorySimpleList()
//
categoryList.value = cl
if (categoryList.value.length > 0) {
categoryActive.value = categoryList.value[0]
}
console.log('[ categoryActive.value ] >', categoryActive.value)
//
processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({
suspensionState: 1
})
//
processDefinitionList.value = pl as any
// processInstanceId
if (processInstanceId?.length > 0) {
const processInstance = await ProcessInstanceApi.getProcessInstance(processInstanceId)
if (!processInstance) {
message.error('重新发起流程失败,原因:流程实例不存在')
return
}
const processDefinition = processDefinitionList.value.find(
(item: any) => item.key == processInstance.processDefinition?.key
)
if (!processDefinition) {
message.error('重新发起流程失败,原因:流程定义不存在')
return
}
await handleSelect(processDefinition, processInstance.formVariables)
}
} finally {
loading.value = false
}
}
/** 选中分类对应的流程定义列表 */
const categoryProcessDefinitionList: any = computed(() => {
return processDefinitionList.value.filter(
(item: any) => item.category == categoryActive.value.code
)
})
// ========== ==========
const fApi = ref<ApiAttrs>()
const detailForm: any = ref({
rule: [],
option: {},
value: {}
}) //
const selectProcessDefinition = ref() //
//
const bpmnXML: any = ref(null) // BPMN
const startUserSelectTasks: any = ref([]) //
const startUserSelectAssignees = ref({}) //
const startUserSelectAssigneesFormRef = ref() // Ref
const startUserSelectAssigneesFormRules = ref({}) // Rules
const userList = ref<any[]>([]) //
/** 处理选择流程的按钮操作 **/
const handleSelect = async (row, formVariables?) => {
//
selectProcessDefinition.value = row
//
startUserSelectTasks.value = []
startUserSelectAssignees.value = {}
startUserSelectAssigneesFormRules.value = {}
//
if (row.formType == 10) {
//
setConfAndFields2(detailForm, row.formConf, row.formFields, formVariables)
//
const processDefinitionDetail = await DefinitionApi.getProcessDefinition(row.id)
if (processDefinitionDetail) {
bpmnXML.value = processDefinitionDetail.bpmnXml
startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks
//
if (startUserSelectTasks.value?.length > 0) {
detailForm.value.rule.push({
type: 'startUserSelect',
props: {
title: '指定审批人'
}
})
//
for (const userTask of startUserSelectTasks.value) {
startUserSelectAssignees.value[userTask.id] = []
startUserSelectAssigneesFormRules.value[userTask.id] = [
{ required: true, message: '请选择审批人', trigger: 'blur' }
]
}
//
userList.value = await UserApi.getSimpleUserList()
}
}
//
} else if (row.formCustomCreatePath) {
await push({
path: row.formCustomCreatePath
})
// Tab
}
}
/** 提交按钮 */
const submitForm = async (formData) => {
if (!fApi.value || !selectProcessDefinition.value) {
return
}
//
if (startUserSelectTasks.value?.length > 0) {
await startUserSelectAssigneesFormRef.value.validate()
}
//
fApi.value.btn.loading(true)
try {
await ProcessInstanceApi.createProcessInstance({
processDefinitionId: selectProcessDefinition.value.id,
variables: formData,
startUserSelectAssignees: startUserSelectAssignees.value
})
//
message.success('发起流程成功')
//
delView(unref(currentRoute))
await push({
name: 'BpmProcessInstanceMy'
})
} finally {
fApi.value.btn.loading(false)
}
}
//
const handleCategoryClick = (val) => {
categoryActive.value = val
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped>
.process-definition-container::before {
content: '';
border-left: 1px solid #e6e6e6;
position: absolute;
left: 20.8%;
height: 100%;
}
:deep() {
.definition-item-card {
.el-card__body {
padding: 14px;
}
}
}
</style>

View File

@ -0,0 +1,108 @@
// 模拟流程分类数据
export const categoryList = [
{ name: '审批流程', code: 'approval' },
{ name: '管理流程', code: 'management' }
]
// 模拟流程定义数据
export const processDefinitionList = [
{
id: '1',
key: 'process_1',
name: '请假申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=1',
formType: 10,
formConf: {}, // 根据需要定义表单配置
formFields: [], // 根据需要定义表单字段
startUserSelectTasks: [
{ id: 'task1', name: '部门经理' },
{ id: 'task2', name: '人力资源' }
]
},
{
id: '2',
key: 'process_2',
name: '报销申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=2',
formType: 10,
formConf: {},
formFields: [],
startUserSelectTasks: [{ id: 'task3', name: '财务' }]
},
{
id: '3',
key: 'process_1',
name: '请假申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=1',
formType: 10,
formConf: {}, // 根据需要定义表单配置
formFields: [], // 根据需要定义表单字段
startUserSelectTasks: [
{ id: 'task1', name: '部门经理' },
{ id: 'task2', name: '人力资源' }
]
},
{
id: '4',
key: 'process_2',
name: '报销申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=2',
formType: 10,
formConf: {},
formFields: [],
startUserSelectTasks: [{ id: 'task3', name: '财务' }]
},{
id: '5',
key: 'process_1',
name: '请假申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=1',
formType: 10,
formConf: {}, // 根据需要定义表单配置
formFields: [], // 根据需要定义表单字段
startUserSelectTasks: [
{ id: 'task1', name: '部门经理' },
{ id: 'task2', name: '人力资源' }
]
},
{
id: '6',
key: 'process_2',
name: '报销申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=2',
formType: 10,
formConf: {},
formFields: [],
startUserSelectTasks: [{ id: 'task3', name: '财务' }]
},
{
id: '7',
key: 'process_1',
name: '请假申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=1',
formType: 10,
formConf: {}, // 根据需要定义表单配置
formFields: [], // 根据需要定义表单字段
startUserSelectTasks: [
{ id: 'task1', name: '部门经理' },
{ id: 'task2', name: '人力资源' }
]
},
{
id: '8',
key: 'process_2',
name: '报销申请',
category: 'approval',
icon: 'https://picsum.photos/200?r=2',
formType: 10,
formConf: {},
formFields: [],
startUserSelectTasks: [{ id: 'task3', name: '财务' }]
}
]