feat: 发起流程页面-增加搜索框、前端搜索功能完成;右侧展示所有流程,通过滚动或者点击,可以切换分类;鼠标hover时,展示描述

pull/582/head
GoldenZqqq 2024-11-05 17:22:12 +08:00
parent 5121d5694d
commit cd69659c93
1 changed files with 227 additions and 56 deletions

View File

@ -1,46 +1,74 @@
<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 }}
<template v-if="!selectProcessDefinition">
<el-input
v-model="currentSearchKey"
class="!w-50% mb-15px"
placeholder="请输入流程名称"
clearable
@keyup.enter="handleQuery"
@clear="handleClear"
>
<template #prefix>
<Icon icon="ep:search" />
</template>
</el-input>
<ContentWrap
:class="{ 'process-definition-container': filteredProcessDefinitionList?.length }"
class="position-relative pb-20px h-700px"
v-loading="loading"
>
<el-row v-if="filteredProcessDefinitionList?.length" :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>
</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>
</el-col>
<el-col :span="19">
<el-scrollbar ref="scrollWrapper" height="700">
<div
class="mb-20px pl-10px"
v-for="(definitions, title) in processDefinitionGroup"
:key="title"
:ref="`category-${title}`"
>
<h3 class="text-18px font-bold mb-10px mt-5px">{{ title }}</h3>
<div class="grid grid-cols-3 gap3">
<el-tooltip
v-for="definition in definitions"
:key="definition.id"
:content="definition.description"
placement="top"
>
<el-card
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>
</el-tooltip>
</div>
</template>
</el-card>
</div>
<el-empty v-else />
</el-col>
</el-row>
</ContentWrap>
</div>
</el-scrollbar>
</el-col>
</el-row>
<el-empty class="!py-200px" :image-size="200" description="没有找到搜索结果" v-else />
</ContentWrap>
</template>
<!-- 第二步填写表单进行流程的提交 -->
<ProcessDefinitionDetail
@ -56,12 +84,14 @@ import * as DefinitionApi from '@/api/bpm/definition'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import { CategoryApi } from '@/api/bpm/category'
import ProcessDefinitionDetail from './ProcessDefinitionDetail.vue'
import { groupBy } from 'lodash-es'
defineOptions({ name: 'BpmProcessInstanceCreate' })
const { proxy } = getCurrentInstance() as any
const route = useRoute() //
const message = useMessage() //
const currentSearchKey = ref('') //
const processInstanceId: any = route.query.processInstanceId
const loading = ref(true) //
const categoryList: any = ref([]) //
@ -71,15 +101,10 @@ const processDefinitionList = ref([]) // 流程定义的列表
const getList = async () => {
loading.value = true
try {
//
categoryList.value = await CategoryApi.getCategorySimpleList()
if (categoryList.value.length > 0) {
categoryActive.value = categoryList.value[0]
}
//
processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({
suspensionState: 1
})
//
await getCategoryList()
//
await getDefinitionList()
// processInstanceId
if (processInstanceId?.length > 0) {
@ -102,11 +127,149 @@ const getList = async () => {
}
}
/** 选中分类对应的流程定义列表 */
const categoryProcessDefinitionList: any = computed(() => {
return processDefinitionList.value.filter(
(item: any) => item.category == categoryActive.value.code
)
//
const getCategoryList = async () => {
try {
//
categoryList.value = await CategoryApi.getCategorySimpleList()
if (categoryList.value.length > 0) {
categoryActive.value = categoryList.value[0]
}
} finally {
}
}
//
const getDefinitionList = async () => {
try {
//
processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({
suspensionState: 1
})
/* 测试数据 */
// processDefinitionList.value = [
// {
// id: 'business:3:fab1dceb-95be-11ef-8c7d-00a6181404fd',
// version: 3,
// name: '',
// key: 'business',
// icon: 'https://picsum.photos/200?r=2',
// description: '',
// category: 'test0',
// categoryName: '0',
// formType: 10,
// formId: 27,
// formName: null,
// formConf:
// '{"form":{"inline":false,"hideRequiredAsterisk":false,"labelPosition":"right","size":"default","labelWidth":"100px"},"resetBtn":{"show":false,"innerText":""},"submitBtn":{"show":false,"innerText":""}}',
// formFields: [
// '{"type":"input","field":"F1yrm2sosxgeabc","title":"","info":"","$required":false,"props":{"type":"text","placeholder":"123"},"_fc_id":"id_Fhrbm2sosxgeacc","name":"ref_Festm2sosxgeadc","display":true,"hidden":false,"_fc_drag_tag":"input"}',
// '{"type":"radio","field":"F9r3m2sp1b34aec","title":"","info":"","$required":false,"props":{"_optionType":2},"_fc_id":"id_F4nwm2sp1b34afc","name":"ref_Fkodm2sp1b34agc","display":true,"hidden":false,"_fc_drag_tag":"radio","options":[{"label":"","value":"1"},{"label":"","value":"2"},{"label":"","value":"3"}]}',
// '{"type":"datePicker","field":"Finom2tsbwbpadc","title":"","info":"","$required":false,"props":{"type":"datetimerange"},"_fc_id":"id_F028m2tsbwbpaec","name":"ref_F0okm2tsbwbpafc","display":true,"hidden":false,"_fc_drag_tag":"dateRange"}'
// ],
// formCustomCreatePath: '',
// formCustomViewPath: '',
// suspensionState: 1,
// deploymentTime: null,
// bpmnXml: null,
// startUserSelectTasks: null
// },
// {
// id: 'oa_leave:1:6e5ac269-5f87-11ef-bdb6-00a6181404fd',
// version: 1,
// name: 'oa_leave',
// key: 'oa_leave',
// icon: null,
// description: 'oa_leave',
// category: 'etst',
// categoryName: '1',
// formType: 20,
// formId: null,
// formName: null,
// formConf: null,
// formFields: null,
// formCustomCreatePath: '/bpm/oa/leave/create',
// formCustomViewPath: '/bpm/oa/leave/detail',
// suspensionState: 1,
// deploymentTime: null,
// bpmnXml: null,
// startUserSelectTasks: null
// },
// {
// id: 'oa_leave:3:c9d06889-94fd-11ef-bf08-00a6181404fd',
// version: 3,
// name: '',
// key: 'oa_leave',
// icon: 'https://picsum.photos/200?r=1',
// description: '',
// category: 'test3',
// categoryName: '3',
// formType: 10,
// formId: 27,
// formName: null,
// formConf:
// '{"form":{"inline":false,"hideRequiredAsterisk":false,"labelPosition":"right","size":"default","labelWidth":"100px"},"resetBtn":{"show":false,"innerText":""},"submitBtn":{"show":true,"innerText":""}}',
// formFields: [
// '{"type":"input","field":"F1yrm2sosxgeabc","title":"","info":"","$required":false,"props":{"type":"text","placeholder":"123"},"_fc_id":"id_Fhrbm2sosxgeacc","name":"ref_Festm2sosxgeadc","display":true,"hidden":false,"_fc_drag_tag":"input"}',
// '{"type":"radio","field":"F9r3m2sp1b34aec","title":"","info":"","$required":false,"props":{"_optionType":2},"_fc_id":"id_F4nwm2sp1b34afc","name":"ref_Fkodm2sp1b34agc","display":true,"hidden":false,"_fc_drag_tag":"radio","options":[{"label":"","value":"1"},{"label":"","value":"2"},{"label":"","value":"3"}]}'
// ],
// formCustomCreatePath: 'bpm/oa/leave/create',
// formCustomViewPath: 'bpm/oa/leave/create',
// suspensionState: 1,
// deploymentTime: null,
// bpmnXml: null,
// startUserSelectTasks: null
// }
// ]
/* 测试数据 */
// processDefinitionList.value = [
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value,
// ...processDefinitionList.value
// ]
//
filteredProcessDefinitionList.value = processDefinitionList.value
} finally {
}
}
const filteredProcessDefinitionList = ref([]) //
//
const handleQuery = () => {
if (currentSearchKey.value.trim()) {
//
filteredProcessDefinitionList.value = processDefinitionList.value.filter(
(definition: any) =>
definition.name.toLowerCase().includes(currentSearchKey.value.toLowerCase()) //
)
} else {
//
filteredProcessDefinitionList.value = processDefinitionList.value
}
}
// input `clearable`
const handleClear = () => {
filteredProcessDefinitionList.value = processDefinitionList.value
}
//
const processDefinitionGroup: any = computed(() => {
if (!processDefinitionList.value?.length) return {}
return groupBy(filteredProcessDefinitionList.value, 'categoryName')
})
// ========== ==========
@ -122,8 +285,16 @@ const handleSelect = async (row, formVariables?) => {
processDefinitionDetailRef.value?.initProcessInfo(row, formVariables)
}
//
const handleCategoryClick = (val: number) => {
categoryActive.value = val
const handleCategoryClick = (category) => {
categoryActive.value = category
const categoryRef = proxy.$refs[`category-${category.name}`] // DOM
if (categoryRef?.length) {
const scrollWrapper = proxy.$refs.scrollWrapper //
const categoryOffsetTop = categoryRef[0].offsetTop
//
scrollWrapper.scrollTo({ top: categoryOffsetTop, behavior: 'smooth' })
}
}
/** 初始化 */