路由及相应重构回退vxe

This commit is contained in:
gexinzhineng/gxzn27 2023-04-06 14:33:01 +08:00
parent 561b617ca4
commit af26859ba8
5 changed files with 7 additions and 622 deletions

View File

@ -225,26 +225,26 @@ const remainingRouter: AppRouteRecordRaw[] = [
children: [
{
path: '/manager/form/edit',
component: () => import('@/views/bpm/form/editor/index.vue'),
component: () => import('@/views/bpm/form/formEditor.vue'),
name: 'bpmFormEditor',
meta: {
noCache: true,
hidden: true,
canTo: true,
title: '设计流程表单',
activeMenu: '/bpm/manager/form'
activeMenu: '/bpm/manager/formEditor'
}
},
{
path: '/manager/model/edit',
component: () => import('@/views/bpm/model/editor/index.vue'),
component: () => import('@/views/bpm/model/modelEditor.vue'),
name: 'modelEditor',
meta: {
noCache: true,
hidden: true,
canTo: true,
title: '设计流程',
activeMenu: '/bpm/manager/model'
activeMenu: '/bpm/manager/design'
}
},
{
@ -256,7 +256,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
hidden: true,
canTo: true,
title: '流程定义',
activeMenu: '/bpm/manager/model'
activeMenu: '/bpm/definition/index'
}
},
{
@ -272,7 +272,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
},
{
path: '/process-instance/create',
component: () => import('@/views/bpm/processInstance/create/index.vue'),
component: () => import('@/views/bpm/processInstance/create.vue'),
name: 'BpmProcessInstanceCreate',
meta: {
noCache: true,
@ -284,7 +284,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
},
{
path: '/process-instance/detail',
component: () => import('@/views/bpm/processInstance/detail/index.vue'),
component: () => import('@/views/bpm/processInstance/detail.vue'),
name: 'BpmProcessInstanceDetail',
meta: {
noCache: true,

View File

@ -1,106 +0,0 @@
<template>
<ContentWrap>
<!-- 表单设计器 -->
<fc-designer ref="designer" height="780px">
<template #handle>
<el-button round size="small" type="primary" @click="handleSave">
<Icon icon="ep:plus" class="mr-5px" /> 保存
</el-button>
</template>
</fc-designer>
</ContentWrap>
<!-- 表单保存的弹窗 -->
<Dialog title="保存表单" v-model="modelVisible" width="600">
<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 getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import * as FormApi from '@/api/bpm/form'
import { encodeConf, encodeFields, setConfAndFields } from '@/utils/formCreate'
const { t } = useI18n() //
const message = useMessage() //
const { query } = useRoute() //
const designer = ref() //
const modelVisible = ref(false) //
const formLoading = ref(false) //
const formData = ref({
name: '',
status: CommonStatusEnum.ENABLE,
remark: ''
})
const formRules = reactive({
name: [{ required: true, message: '表单名不能为空', trigger: 'blur' }],
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 处理保存按钮 */
const handleSave = () => {
modelVisible.value = true
}
/** 提交表单 */
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as FormApi.FormVO
data.conf = encodeConf(designer) //
data.fields = encodeFields(designer) //
if (!data.id) {
await FormApi.createFormApi(data)
message.success(t('common.createSuccess'))
} else {
await FormApi.updateFormApi(data)
message.success(t('common.updateSuccess'))
}
modelVisible.value = false
} finally {
formLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
//
const id = query.id as unknown as number
if (!id) {
return
}
//
const data = await FormApi.getFormApi(id)
formData.value = data
setConfAndFields(designer, data.conf, data.fields)
})
</script>

View File

@ -1,102 +0,0 @@
<template>
<ContentWrap>
<!-- 流程设计器负责绘制流程等 -->
<my-process-designer
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"
/>
<!-- 流程属性器负责编辑每个流程节点的属性 -->
<my-properties-panel
key="penal"
:bpmnModeler="modeler"
:prefix="controlForm.prefix"
class="process-panel"
:model="model"
/>
</ContentWrap>
</template>
<script setup lang="ts">
//
import CustomContentPadProvider from '@/components/bpmnProcessDesigner/package/designer/plugins/content-pad'
//
import CustomPaletteProvider from '@/components/bpmnProcessDesigner/package/designer/plugins/palette'
import * as ModelApi from '@/api/bpm/model'
const router = useRouter() //
const { query } = useRoute() //
const message = useMessage() //
const xmlString = ref(undefined) // BPMN XML
const modeler = ref(null) // BPMN Modeler
const controlForm = ref({
simulation: true,
labelEditing: false,
labelVisible: false,
prefix: 'flowable',
headerButtonSize: 'mini',
additionalModel: [CustomContentPadProvider, CustomPaletteProvider]
})
const model = ref<ModelApi.ModelVO>() //
/** 初始化 modeler */
const initModeler = (item) => {
setTimeout(() => {
modeler.value = item
}, 10)
}
/** 添加/修改模型 */
const save = async (bpmnXml) => {
const data = {
...model.value,
bpmnXml: bpmnXml // bpmnXml
} as unknown as ModelApi.ModelVO
//
if (data.id) {
await ModelApi.updateModelApi(data)
message.success('修改成功')
} else {
await ModelApi.createModelApi(data)
message.success('新增成功')
}
//
close()
}
/** 关闭按钮 */
const close = () => {
router.push({ path: '/bpm/manager/model' })
}
/** 初始化 */
onMounted(async () => {
const modelId = query.modelId as unknown as number
if (!modelId) {
message.error('缺少模型 modelId 编号')
return
}
//
const data = await ModelApi.getModelApi(modelId)
xmlString.value = data.bpmnXml
model.value = {
...data,
bpmnXml: undefined // bpmnXml
}
})
</script>
<style lang="scss">
.process-panel__container {
position: absolute;
right: 60px;
top: 90px;
}
</style>

View File

@ -1,130 +0,0 @@
<template>
<!-- 第一步通过流程定义的列表选择对应的流程 -->
<ContentWrap v-if="!selectProcessInstance">
<el-table v-loading="loading" :data="list">
<el-table-column label="流程名称" align="center" prop="name" />
<el-table-column label="流程分类" align="center" prop="category">
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
</template>
</el-table-column>
<el-table-column label="流程版本" align="center" prop="version">
<template #default="scope">
<el-tag>v{{ scope.row.version }}</el-tag>
</template>
</el-table-column>
<el-table-column label="流程描述" align="center" prop="description" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="handleSelect(scope.row)">
<Icon icon="ep:plus" /> 选择
</el-button>
</template>
</el-table-column>
</el-table>
</ContentWrap>
<!-- 第二步填写表单进行流程的提交 -->
<ContentWrap v-else>
<el-card class="box-card">
<div class="clearfix">
<span class="el-icon-document">申请信息{{ selectProcessInstance.name }}</span>
<el-button style="float: right" type="primary" @click="selectProcessInstance = 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"
:option="detailForm.option"
@submit="submitForm"
/>
</el-col>
</el-card>
<!-- 流程图预览 -->
<ProcessInstanceBpmnViewer :bpmn-xml="bpmnXML" />
</ContentWrap>
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
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'
const router = useRouter() //
const message = useMessage() //
// ========== ==========
const loading = ref(true) //
const list = ref([]) //
const queryParams = reactive({
suspensionState: 1
})
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
list.value = await DefinitionApi.getProcessDefinitionList(queryParams)
} finally {
loading.value = false
}
}
// ========== ==========
const bpmnXML = ref(null) // BPMN
const fApi = ref<ApiAttrs>()
const detailForm = ref({
//
rule: [],
option: {}
})
const selectProcessInstance = ref() //
/** 处理选择流程的按钮操作 **/
const handleSelect = async (row) => {
//
selectProcessInstance.value = row
//
if (row.formType == 10) {
//
setConfAndFields2(detailForm, row.formConf, row.formFields)
//
bpmnXML.value = await DefinitionApi.getProcessDefinitionBpmnXML(row.id)
//
} else if (row.formCustomCreatePath) {
await router.push({
path: row.formCustomCreatePath
})
// Tab
}
}
/** 提交按钮 */
const submitForm = async (formData) => {
if (!fApi.value || !selectProcessInstance.value) {
return
}
//
fApi.value.btn.loading(true)
try {
await ProcessInstanceApi.createProcessInstanceApi({
processDefinitionId: selectProcessInstance.value.id,
variables: formData
})
//
message.success('发起流程成功')
router.go(-1)
} finally {
fApi.value.btn.loading(false)
}
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>

View File

@ -1,277 +0,0 @@
<template>
<ContentWrap>
<!-- 审批信息 -->
<el-card
class="box-card"
v-loading="processInstanceLoading"
v-for="(item, index) in runningTasks"
:key="index"
>
<template #header>
<span class="el-icon-picture-outline">审批任务{{ item.name }}</span>
</template>
<el-col :span="16" :offset="6">
<el-form
:ref="'form' + index"
:model="auditForms[index]"
:rules="auditRule"
label-width="100px"
>
<el-form-item label="流程名" v-if="processInstance && processInstance.name">
{{ processInstance.name }}
</el-form-item>
<el-form-item label="流程发起人" v-if="processInstance && processInstance.startUser">
{{ processInstance.startUser.nickname }}
<el-tag type="info" size="small">{{ processInstance.startUser.deptName }}</el-tag>
</el-form-item>
<el-form-item label="审批建议" prop="reason">
<el-input
type="textarea"
v-model="auditForms[index].reason"
placeholder="请输入审批建议"
/>
</el-form-item>
</el-form>
<div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
<el-button type="success" @click="handleAudit(item, true)">
<Icon icon="ep:select" /> 通过
</el-button>
<el-button type="danger" @click="handleAudit(item, false)">
<Icon icon="ep:close" /> 不通过
</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="warning" @click="handleBack(item)">
<Icon icon="ep:back" /> 退回
</el-button>
</div>
</el-col>
</el-card>
<!-- 申请信息 -->
<el-card class="box-card" v-loading="processInstanceLoading">
<template #header>
<span class="el-icon-document">申请信息{{ processInstance.name }}</span>
</template>
<!-- 情况一流程表单 -->
<el-col v-if="processInstance?.processDefinition?.formType === 10" :span="16" :offset="6">
<form-create
ref="fApi"
:rule="detailForm.rule"
:option="detailForm.option"
v-model="detailForm.value"
/>
</el-col>
<!-- 情况二流程表单 -->
<div v-if="processInstance?.processDefinition?.formType === 20">
<router-link
:to="
processInstance.processDefinition.formCustomViewPath +
'?id=' +
processInstance.businessKey
"
>
<el-button type="primary"><Icon icon="ep:view" /> 点击查看</el-button>
</router-link>
</div>
</el-card>
<!-- 审批记录 -->
<ProcessInstanceTaskList :loading="tasksLoad" :tasks="tasks" />
<!-- 高亮流程图 -->
<ProcessInstanceBpmnViewer
:id="id"
:process-instance="processInstance"
:loading="processInstanceLoading"
:tasks="tasks"
:bpmn-xml="bpmnXML"
/>
<!-- 弹窗转派审批人 -->
<TaskUpdateAssigneeForm ref="taskUpdateAssigneeFormRef" @success="getDetail" />
</ContentWrap>
</template>
<script setup lang="ts">
import { useUserStore } from '@/store/modules/user'
import { setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import * as DefinitionApi from '@/api/bpm/definition'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import * as TaskApi from '@/api/bpm/task'
import TaskUpdateAssigneeForm from './TaskUpdateAssigneeForm.vue'
import ProcessInstanceBpmnViewer from './ProcessInstanceBpmnViewer.vue'
import ProcessInstanceTaskList from './ProcessInstanceTaskList.vue'
const { query } = useRoute() //
const message = useMessage() //
const { proxy } = getCurrentInstance() as any
const userId = useUserStore().getUser.id //
const id = query.id as unknown as number //
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 fApi = ref<ApiAttrs>() //
const detailForm = ref({
//
rule: [],
option: {},
value: {}
})
/** 处理审批通过和不通过的操作 */
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
}
if (pass) {
await TaskApi.approveTask(data)
message.success('审批通过成功')
} else {
await TaskApi.rejectTask(data)
message.success('审批不通过成功')
}
// 2.2
getDetail()
}
/** 转派审批人 */
const taskUpdateAssigneeFormRef = ref()
const openTaskUpdateAssigneeForm = (id: string) => {
taskUpdateAssigneeFormRef.value.open(id)
}
/** 处理审批退回的操作 */
const handleDelegate = async (task) => {
message.error('暂不支持【委派】功能,可以使用【转派】替代!')
console.log(task)
}
/** 处理审批退回的操作 */
const handleBack = async (task) => {
message.error('暂不支持【退回】功能!')
console.log(task)
}
/** 获得详情 */
const getDetail = () => {
// 1.
getProcessInstance()
// 2.
getTaskList()
}
/** 加载流程实例 */
const getProcessInstance = async () => {
try {
processInstanceLoading.value = true
const data = await ProcessInstanceApi.getProcessInstanceApi(id)
if (!data) {
message.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?.fapi?.btn.show(false)
fApi.value?.fapi?.resetBtn.show(false)
fApi.value?.fapi?.disabled(true)
})
}
//
bpmnXML.value = await DefinitionApi.getProcessDefinitionBpmnXML(processDefinition.id)
} finally {
processInstanceLoading.value = false
}
}
/** 加载任务列表 */
const getTaskList = async () => {
try {
//
tasksLoad.value = true
const data = await TaskApi.getTaskListByProcessInstanceId(id)
tasks.value = []
// 1.1
data.forEach((task) => {
if (task.result !== 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
}
})
//
runningTasks.value = []
auditForms.value = []
tasks.value.forEach((task) => {
// 2.1
if (task.result !== 1) {
return
}
// 2.2
if (!task.assigneeUser || task.assigneeUser.id !== userId) {
return
}
// 2.3
runningTasks.value.push({ ...task })
auditForms.value.push({
reason: ''
})
})
} finally {
tasksLoad.value = false
}
}
/** 初始化 */
onMounted(() => {
getDetail()
})
</script>