Merge branch 'feature/bpm' of https://github.com/yudaocode/yudao-ui-admin-vue3 into feature/bpm

pull/594/head
YunaiV 2024-11-21 19:35:13 +08:00
commit 397c09a195
6 changed files with 101 additions and 24 deletions

View File

@ -162,8 +162,10 @@ const getApprovalDetail = async (row: any) => {
startUserSelectTasks.value = data.activityNodes?.filter(
(node: ApprovalNodeInfo) => CandidateStrategy.START_USER_SELECT === node.candidateStrategy
)
for (const node of startUserSelectTasks.value) {
startUserSelectAssignees.value[node.id] = []
if (startUserSelectTasks.value?.length > 0) {
for (const node of startUserSelectTasks.value) {
startUserSelectAssignees.value[node.id] = []
}
}
// Timeline

View File

@ -22,7 +22,7 @@
<el-col :span="5">
<div class="flex flex-col">
<div
v-for="category in categoryList"
v-for="category in availableCategories"
:key="category.code"
class="flex items-center p-10px cursor-pointer text-14px rounded-md"
:class="categoryActive.code === category.code ? 'text-#3e7bff bg-#e8eeff' : ''"
@ -33,7 +33,7 @@
</div>
</el-col>
<el-col :span="19">
<el-scrollbar ref="scrollWrapper" height="700">
<el-scrollbar ref="scrollWrapper" height="700" @scroll="handleScroll">
<div
class="mb-20px pl-10px"
v-for="(definitions, categoryCode) in processDefinitionGroup"
@ -137,10 +137,6 @@ const getCategoryList = async () => {
try {
//
categoryList.value = await CategoryApi.getCategorySimpleList()
//
if (categoryList.value.length > 0) {
categoryActive.value = categoryList.value[0]
}
} finally {
}
}
@ -154,6 +150,11 @@ const getProcessDefinitionList = async () => {
})
//
filteredProcessDefinitionList.value = processDefinitionList.value
//
if (availableCategories.value.length > 0 && !categoryActive.value?.code) {
categoryActive.value = availableCategories.value[0]
}
} finally {
}
}
@ -220,10 +221,62 @@ const handleSelect = async (row, formVariables?) => {
processDefinitionDetailRef.value?.initProcessInfo(row, formVariables)
}
/** 处理滚动事件 */
const handleScroll = (e) => {
// 使
const scrollTop = e.scrollTop
//
const categoryPositions = categoryList.value
.map((category) => {
const categoryRef = proxy.$refs[`category-${category.code}`]
if (categoryRef?.[0]) {
return {
code: category.code,
offsetTop: categoryRef[0].offsetTop,
height: categoryRef[0].offsetHeight
}
}
return null
})
.filter(Boolean)
//
let currentCategory = categoryPositions[0]
for (const position of categoryPositions) {
// 50px
if (scrollTop >= position.offsetTop - 50) {
currentCategory = position
} else {
break
}
}
// active
if (currentCategory && categoryActive.value.code !== currentCategory.code) {
categoryActive.value = categoryList.value.find((c) => c.code === currentCategory.code)
}
}
/** 初始化 */
onMounted(() => {
getList()
})
/** 过滤出有流程的分类列表 */
const availableCategories = computed(() => {
if (!categoryList.value?.length || !processDefinitionGroup.value) {
return []
}
//
const availableCategoryCodes = Object.keys(processDefinitionGroup.value)
//
return categoryList.value.filter(category =>
availableCategoryCodes.includes(category.code)
)
})
</script>
<style lang="scss" scoped>

View File

@ -40,14 +40,22 @@ watch(
}
)
</script>
<style>
<style lang="scss" scoped>
.box-card {
height: 100%;
width: 100%;
margin-bottom: 20px;
}
margin-bottom: 0;
:deep(.process-viewer) {
height: 100% !important;
min-height: 500px;
:deep(.el-card__body) {
height: 100%;
padding: 0;
}
:deep(.process-viewer) {
height: 100% !important;
min-height: 100%;
width: 100%;
overflow: auto;
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div v-loading="loading" class="mb-20px">
<div v-loading="loading" class="process-viewer-container">
<SimpleProcessViewer
:flow-node="simpleModel"
:tasks="tasks"
@ -154,8 +154,15 @@ const setSimpleModelNodeTaskStatus = (
</script>
<style lang="scss" scoped>
:deep(.process-viewer) {
height: 100% !important;
min-height: 500px;
.process-viewer-container {
height: 100%;
width: 100%;
:deep(.process-viewer) {
height: 100% !important;
min-height: 100%;
width: 100%;
overflow: auto;
}
}
</style>

View File

@ -16,10 +16,10 @@
<img class="w-full h-full" :src="getApprovalNodeImg(activity.nodeType)" alt="" />
<div
v-if="showStatusIcon"
class="position-absolute top-17px left-17px rounded-full flex items-center p-2px"
class="position-absolute top-17px left-17px rounded-full flex items-center p-1px border-2 border-white border-solid"
:style="{ backgroundColor: getApprovalNodeColor(activity.status) }"
>
<el-icon :size="12" color="#fff">
<el-icon :size="11" color="#fff">
<component :is="getApprovalNodeIcon(activity.status, activity.nodeType)" />
</el-icon>
</div>
@ -106,10 +106,10 @@
<!-- 信息任务 ICON -->
<div
v-if="showStatusIcon && onlyStatusIconShow.includes(task.status)"
class="position-absolute top-19px left-23px rounded-full flex items-center p-2px"
class="position-absolute top-19px left-23px rounded-full flex items-center p-1px border-2 border-white border-solid"
:style="{ backgroundColor: statusIconMap2[task.status]?.color }"
>
<Icon :size="12" :icon="statusIconMap2[task.status]?.icon" color="#FFFFFF" />
<Icon :size="11" :icon="statusIconMap2[task.status]?.icon" color="#FFFFFF" />
</div>
</div>
</div>
@ -140,10 +140,10 @@
<!-- 信息任务 ICON -->
<div
v-if="showStatusIcon"
class="position-absolute top-19px left-23px rounded-full flex items-center p-2px"
class="position-absolute top-20px left-24px rounded-full flex items-center p-1px border-2 border-white border-solid"
:style="{ backgroundColor: statusIconMap2['-1']?.color }"
>
<Icon :size="12" :icon="statusIconMap2['-1']?.icon" color="#FFFFFF" />
<Icon :size="11" :icon="statusIconMap2['-1']?.icon" color="#FFFFFF" />
</div>
</div>
</div>

View File

@ -128,6 +128,7 @@ import { formatDate } from '@/utils/formatTime'
import { DICT_TYPE } from '@/utils/dict'
import { BpmModelType } from '@/utils/constants'
import { setConfAndFields2 } from '@/utils/formCreate'
import { registerComponent } from '@/utils/routerHelper'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import * as UserApi from '@/api/system/user'
@ -228,6 +229,9 @@ const getApprovalDetail = async () => {
})
}
})
} else {
// data.processDefinition.formCustomViewPath /crm/contract/detail/index.vue
BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
}
// Timeline
@ -319,9 +323,12 @@ $process-header-height: 194px;
$process-header-height - 40px
);
overflow: auto;
display: flex;
flex-direction: column;
:deep(.box-card) {
height: 100%;
flex: 1;
.el-card__body {
height: 100%;