Skip to content

Commit 7f50584

Browse files
committed
perf: 优化流程模型分类组件性能和类型定义
1 parent 3d59191 commit 7f50584

File tree

1 file changed

+101
-46
lines changed

1 file changed

+101
-46
lines changed

src/views/bpm/model/CategoryDraggableModel.vue

Lines changed: 101 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="flex items-center h-50px">
2+
<div class="flex items-center h-50px" v-memo="[categoryInfo.name, isCategorySorting]">
33
<!-- 头部:分类名 -->
44
<div class="flex items-center">
55
<el-tooltip content="拖动排序" v-if="isCategorySorting">
@@ -13,7 +13,7 @@
1313
<div class="color-gray-600 text-16px"> ({{ categoryInfo.modelList?.length || 0 }}) </div>
1414
</div>
1515
<!-- 头部:操作 -->
16-
<div class="flex-1 flex" v-if="!isCategorySorting">
16+
<div class="flex-1 flex" v-show="!isCategorySorting">
1717
<div
1818
v-if="categoryInfo.modelList.length > 0"
1919
class="ml-20px flex items-center"
@@ -69,44 +69,45 @@
6969
<el-collapse-transition>
7070
<div v-show="isExpand">
7171
<el-table
72+
v-if="modelList && modelList.length > 0"
7273
:class="categoryInfo.name"
7374
ref="tableRef"
74-
:header-cell-style="{ backgroundColor: isDark ? '' : '#edeff0', paddingLeft: '10px' }"
75-
:cell-style="{ paddingLeft: '10px' }"
76-
:row-style="{ height: '68px' }"
7775
:data="modelList"
7876
row-key="id"
77+
:header-cell-style="tableHeaderStyle"
78+
:cell-style="tableCellStyle"
79+
:row-style="{ height: '68px' }"
7980
>
8081
<el-table-column label="流程名" prop="name" min-width="150">
81-
<template #default="scope">
82+
<template #default="{ row }">
8283
<div class="flex items-center">
8384
<el-tooltip content="拖动排序" v-if="isModelSorting">
8485
<Icon
8586
icon="ic:round-drag-indicator"
8687
class="drag-icon cursor-move text-#8a909c mr-10px"
8788
/>
8889
</el-tooltip>
89-
<el-image :src="scope.row.icon" class="h-38px w-38px mr-10px rounded" />
90-
{{ scope.row.name }}
90+
<el-image v-if="row.icon" :src="row.icon" class="h-38px w-38px mr-10px rounded" />
91+
{{ row.name }}
9192
</div>
9293
</template>
9394
</el-table-column>
9495
<el-table-column label="可见范围" prop="startUserIds" min-width="150">
95-
<template #default="scope">
96-
<el-text v-if="!scope.row.startUsers || scope.row.startUsers.length === 0">
96+
<template #default="{ row }">
97+
<el-text v-if="!row.startUsers?.length">
9798
全部可见
9899
</el-text>
99-
<el-text v-else-if="scope.row.startUsers.length == 1">
100-
{{ scope.row.startUsers[0].nickname }}
100+
<el-text v-else-if="row.startUsers.length === 1">
101+
{{ row.startUsers[0].nickname }}
101102
</el-text>
102103
<el-text v-else>
103104
<el-tooltip
104105
class="box-item"
105106
effect="dark"
106107
placement="top"
107-
:content="scope.row.startUsers.map((user: any) => user.nickname).join('、')"
108+
:content="row.startUsers.map((user: any) => user.nickname).join('、')"
108109
>
109-
{{ scope.row.startUsers[0].nickname }}等 {{ scope.row.startUsers.length }} 人可见
110+
{{ row.startUsers[0].nickname }}等 {{ row.startUsers.length }} 人可见
110111
</el-tooltip>
111112
</el-text>
112113
</template>
@@ -248,7 +249,6 @@
248249
<script lang="ts" setup>
249250
import { CategoryApi, CategoryVO } from '@/api/bpm/category'
250251
import Sortable from 'sortablejs'
251-
import { propTypes } from '@/utils/propTypes'
252252
import { formatDate } from '@/utils/formatTime'
253253
import * as ModelApi from '@/api/bpm/model'
254254
import * as FormApi from '@/api/bpm/form'
@@ -257,15 +257,49 @@ import { BpmModelFormType } from '@/utils/constants'
257257
import { checkPermi } from '@/utils/permission'
258258
import { useUserStoreWithOut } from '@/store/modules/user'
259259
import { useAppStore } from '@/store/modules/app'
260-
import { cloneDeep } from 'lodash-es'
260+
import { cloneDeep, isEqual } from 'lodash-es'
261261
import { useTagsView } from '@/hooks/web/useTagsView'
262+
import { useDebounceFn } from '@vueuse/core'
262263
263264
defineOptions({ name: 'BpmModel' })
264265
265-
const props = defineProps({
266-
categoryInfo: propTypes.object.def([]), // 分类后的数据
267-
isCategorySorting: propTypes.bool.def(false) // 是否分类在排序
268-
})
266+
// 优化 Props 类型定义
267+
interface UserInfo {
268+
nickname: string
269+
[key: string]: any
270+
}
271+
272+
interface ProcessDefinition {
273+
deploymentTime: string
274+
version: number
275+
suspensionState: number
276+
}
277+
278+
interface ModelInfo {
279+
id: number
280+
name: string
281+
icon?: string
282+
startUsers?: UserInfo[]
283+
processDefinition?: ProcessDefinition
284+
formType?: number
285+
formId?: number
286+
formName?: string
287+
formCustomCreatePath?: string
288+
managerUserIds?: number[]
289+
[key: string]: any
290+
}
291+
292+
interface CategoryInfoProps {
293+
id: number
294+
name: string
295+
modelList: ModelInfo[]
296+
}
297+
298+
const props = defineProps<{
299+
categoryInfo: CategoryInfoProps
300+
isCategorySorting: boolean
301+
}>()
302+
269303
const emit = defineEmits(['success'])
270304
const message = useMessage() // 消息弹窗
271305
const { t } = useI18n() // 国际化
@@ -274,10 +308,26 @@ const userStore = useUserStoreWithOut() // 用户信息缓存
274308
const isDark = computed(() => useAppStore().getIsDark) // 是否黑暗模式
275309
276310
const isModelSorting = ref(false) // 是否正处于排序状态
277-
const originalData: any = ref([]) // 原始数据
278-
const modelList: any = ref([]) // 模型列表
311+
const originalData = ref<ModelInfo[]>([]) // 原始数据
312+
const modelList = ref<ModelInfo[]>([]) // 模型列表
279313
const isExpand = ref(false) // 是否处于展开状态
280314
315+
// 使用 computed 优化表格样式计算
316+
const tableHeaderStyle = computed(() => ({
317+
backgroundColor: isDark.value ? '' : '#edeff0',
318+
paddingLeft: '10px'
319+
}))
320+
321+
const tableCellStyle = computed(() => ({
322+
paddingLeft: '10px'
323+
}))
324+
325+
// 使用 computed 优化可见性判断
326+
const isManagerUser = computed(() => {
327+
const userId = userStore.getUser?.id
328+
return (row: ModelInfo) => row.managerUserIds?.includes(userId)
329+
})
330+
281331
/** '更多'操作按钮 */
282332
const handleModelCommand = (command: string, row: any) => {
283333
switch (command) {
@@ -401,12 +451,6 @@ const handleFormDetail = async (row: any) => {
401451
}
402452
}
403453
404-
/** 判断是否可以操作 */
405-
const isManagerUser = (row: any) => {
406-
const userId = userStore.getUser.id
407-
return row.managerUserIds && row.managerUserIds.includes(userId)
408-
}
409-
410454
/** 处理模型的排序 **/
411455
const handleModelSort = () => {
412456
// 保存初始数据
@@ -435,14 +479,15 @@ const handleModelSortCancel = () => {
435479
436480
/** 创建拖拽实例 */
437481
const tableRef = ref()
438-
const initSort = () => {
482+
const initSort = useDebounceFn(() => {
439483
const table = document.querySelector(`.${props.categoryInfo.name} .el-table__body-wrapper tbody`)
484+
if (!table) return
485+
440486
Sortable.create(table, {
441487
group: 'shared',
442488
animation: 150,
443489
draggable: '.el-table__row',
444490
handle: '.drag-icon',
445-
// 结束拖动事件
446491
onEnd: ({ newDraggableIndex, oldDraggableIndex }) => {
447492
if (oldDraggableIndex !== newDraggableIndex) {
448493
modelList.value.splice(
@@ -453,15 +498,18 @@ const initSort = () => {
453498
}
454499
}
455500
})
456-
}
501+
}, 200)
457502
458503
/** 更新 modelList 模型列表 */
459-
const updateModeList = () => {
460-
modelList.value = cloneDeep(props.categoryInfo.modelList)
461-
if (props.categoryInfo.modelList.length > 0) {
462-
isExpand.value = true
504+
const updateModeList = useDebounceFn(() => {
505+
const newModelList = props.categoryInfo.modelList
506+
if (!isEqual(modelList.value, newModelList)) {
507+
modelList.value = cloneDeep(newModelList)
508+
if (newModelList?.length > 0) {
509+
isExpand.value = true
510+
}
463511
}
464-
}
512+
}, 100)
465513
466514
/** 重命名弹窗确定 */
467515
const renameCategoryVisible = ref(false)
@@ -512,14 +560,15 @@ const openModelForm = async (type: string, id?: number) => {
512560
}
513561
}
514562
515-
watch(() => props.categoryInfo.modelList, updateModeList, { immediate: true })
516-
watch(
517-
() => props.isCategorySorting,
518-
(val) => {
519-
if (val) isExpand.value = false
520-
},
521-
{ immediate: true }
522-
)
563+
watchEffect(() => {
564+
if (props.categoryInfo?.modelList) {
565+
updateModeList()
566+
}
567+
568+
if (props.isCategorySorting) {
569+
isExpand.value = false
570+
}
571+
})
523572
</script>
524573

525574
<style lang="scss">
@@ -536,10 +585,16 @@ watch(
536585
}
537586
</style>
538587
<style lang="scss" scoped>
539-
:deep() {
540-
.el-table__cell {
588+
.category-draggable-model {
589+
:deep(.el-table__cell) {
541590
overflow: hidden;
542591
border-bottom: none !important;
543592
}
593+
594+
// 优化表格渲染性能
595+
:deep(.el-table__body) {
596+
will-change: transform;
597+
transform: translateZ(0);
598+
}
544599
}
545600
</style>

0 commit comments

Comments
 (0)