1
1
<template >
2
- <div class =" flex items-center h-50px" >
2
+ <div class =" flex items-center h-50px" v-memo = " [categoryInfo.name, isCategorySorting] " >
3
3
<!-- 头部:分类名 -->
4
4
<div class =" flex items-center" >
5
5
<el-tooltip content =" 拖动排序" v-if =" isCategorySorting" >
13
13
<div class =" color-gray-600 text-16px" > ({{ categoryInfo.modelList?.length || 0 }}) </div >
14
14
</div >
15
15
<!-- 头部:操作 -->
16
- <div class =" flex-1 flex" v-if =" !isCategorySorting" >
16
+ <div class =" flex-1 flex" v-show =" !isCategorySorting" >
17
17
<div
18
18
v-if =" categoryInfo.modelList.length > 0"
19
19
class =" ml-20px flex items-center"
69
69
<el-collapse-transition >
70
70
<div v-show =" isExpand" >
71
71
<el-table
72
+ v-if =" modelList && modelList.length > 0"
72
73
:class =" categoryInfo.name"
73
74
ref =" tableRef"
74
- :header-cell-style =" { backgroundColor: isDark ? '' : '#edeff0', paddingLeft: '10px' }"
75
- :cell-style =" { paddingLeft: '10px' }"
76
- :row-style =" { height: '68px' }"
77
75
:data =" modelList"
78
76
row-key =" id"
77
+ :header-cell-style =" tableHeaderStyle"
78
+ :cell-style =" tableCellStyle"
79
+ :row-style =" { height: '68px' }"
79
80
>
80
81
<el-table-column label =" 流程名" prop =" name" min-width =" 150" >
81
- <template #default =" scope " >
82
+ <template #default =" { row } " >
82
83
<div class =" flex items-center" >
83
84
<el-tooltip content =" 拖动排序" v-if =" isModelSorting" >
84
85
<Icon
85
86
icon =" ic:round-drag-indicator"
86
87
class =" drag-icon cursor-move text-#8a909c mr-10px"
87
88
/>
88
89
</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 }}
91
92
</div >
92
93
</template >
93
94
</el-table-column >
94
95
<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" >
97
98
全部可见
98
99
</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 }}
101
102
</el-text >
102
103
<el-text v-else >
103
104
<el-tooltip
104
105
class =" box-item"
105
106
effect =" dark"
106
107
placement =" top"
107
- :content =" scope. row.startUsers.map((user: any) => user.nickname).join('、')"
108
+ :content =" row.startUsers.map((user: any) => user.nickname).join('、')"
108
109
>
109
- {{ scope. row.startUsers[0].nickname }}等 {{ scope. row.startUsers.length }} 人可见
110
+ {{ row.startUsers[0].nickname }}等 {{ row.startUsers.length }} 人可见
110
111
</el-tooltip >
111
112
</el-text >
112
113
</template >
248
249
<script lang="ts" setup>
249
250
import { CategoryApi , CategoryVO } from ' @/api/bpm/category'
250
251
import Sortable from ' sortablejs'
251
- import { propTypes } from ' @/utils/propTypes'
252
252
import { formatDate } from ' @/utils/formatTime'
253
253
import * as ModelApi from ' @/api/bpm/model'
254
254
import * as FormApi from ' @/api/bpm/form'
@@ -257,15 +257,49 @@ import { BpmModelFormType } from '@/utils/constants'
257
257
import { checkPermi } from ' @/utils/permission'
258
258
import { useUserStoreWithOut } from ' @/store/modules/user'
259
259
import { useAppStore } from ' @/store/modules/app'
260
- import { cloneDeep } from ' lodash-es'
260
+ import { cloneDeep , isEqual } from ' lodash-es'
261
261
import { useTagsView } from ' @/hooks/web/useTagsView'
262
+ import { useDebounceFn } from ' @vueuse/core'
262
263
263
264
defineOptions ({ name: ' BpmModel' })
264
265
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
+
269
303
const emit = defineEmits ([' success' ])
270
304
const message = useMessage () // 消息弹窗
271
305
const { t } = useI18n () // 国际化
@@ -274,10 +308,26 @@ const userStore = useUserStoreWithOut() // 用户信息缓存
274
308
const isDark = computed (() => useAppStore ().getIsDark ) // 是否黑暗模式
275
309
276
310
const isModelSorting = ref (false ) // 是否正处于排序状态
277
- const originalData: any = ref ([]) // 原始数据
278
- const modelList: any = ref ([]) // 模型列表
311
+ const originalData = ref < ModelInfo []> ([]) // 原始数据
312
+ const modelList = ref < ModelInfo []> ([]) // 模型列表
279
313
const isExpand = ref (false ) // 是否处于展开状态
280
314
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
+
281
331
/** '更多'操作按钮 */
282
332
const handleModelCommand = (command : string , row : any ) => {
283
333
switch (command ) {
@@ -401,12 +451,6 @@ const handleFormDetail = async (row: any) => {
401
451
}
402
452
}
403
453
404
- /** 判断是否可以操作 */
405
- const isManagerUser = (row : any ) => {
406
- const userId = userStore .getUser .id
407
- return row .managerUserIds && row .managerUserIds .includes (userId )
408
- }
409
-
410
454
/** 处理模型的排序 **/
411
455
const handleModelSort = () => {
412
456
// 保存初始数据
@@ -435,14 +479,15 @@ const handleModelSortCancel = () => {
435
479
436
480
/** 创建拖拽实例 */
437
481
const tableRef = ref ()
438
- const initSort = () => {
482
+ const initSort = useDebounceFn ( () => {
439
483
const table = document .querySelector (` .${props .categoryInfo .name } .el-table__body-wrapper tbody ` )
484
+ if (! table ) return
485
+
440
486
Sortable .create (table , {
441
487
group: ' shared' ,
442
488
animation: 150 ,
443
489
draggable: ' .el-table__row' ,
444
490
handle: ' .drag-icon' ,
445
- // 结束拖动事件
446
491
onEnd : ({ newDraggableIndex , oldDraggableIndex }) => {
447
492
if (oldDraggableIndex !== newDraggableIndex ) {
448
493
modelList .value .splice (
@@ -453,15 +498,18 @@ const initSort = () => {
453
498
}
454
499
}
455
500
})
456
- }
501
+ }, 200 )
457
502
458
503
/** 更新 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
+ }
463
511
}
464
- }
512
+ }, 100 )
465
513
466
514
/** 重命名弹窗确定 */
467
515
const renameCategoryVisible = ref (false )
@@ -512,14 +560,15 @@ const openModelForm = async (type: string, id?: number) => {
512
560
}
513
561
}
514
562
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
+ })
523
572
</script >
524
573
525
574
<style lang="scss">
@@ -536,10 +585,16 @@ watch(
536
585
}
537
586
</style >
538
587
<style lang="scss" scoped>
539
- :deep() {
540
- .el-table__cell {
588
+ .category-draggable-model {
589
+ : deep ( .el-table__cell ) {
541
590
overflow : hidden ;
542
591
border-bottom : none !important ;
543
592
}
593
+
594
+ // 优化表格渲染性能
595
+ :deep(.el-table__body ) {
596
+ will-change : transform ;
597
+ transform : translateZ (0 );
598
+ }
544
599
}
545
600
</style >
0 commit comments