【代码优化】工作流:1)完善相关注释;2)解决模型每次操作后,刷新列表后,重渲染会导致滚动条的位置不对的问题
							parent
							
								
									c3cf479f6f
								
							
						
					
					
						commit
						71de0c3ecf
					
				| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="flex items-center h-50px">
 | 
					  <div class="flex items-center h-50px">
 | 
				
			||||||
 | 
					    <!-- 头部:分类名 -->
 | 
				
			||||||
    <div class="flex items-center">
 | 
					    <div class="flex items-center">
 | 
				
			||||||
      <el-tooltip content="拖动排序" v-if="isCategorySorting">
 | 
					      <el-tooltip content="拖动排序" v-if="isCategorySorting">
 | 
				
			||||||
        <Icon
 | 
					        <Icon
 | 
				
			||||||
| 
						 | 
					@ -11,6 +12,7 @@
 | 
				
			||||||
      <h3 class="ml-20px mr-8px text-18px">{{ categoryInfo.name }}</h3>
 | 
					      <h3 class="ml-20px mr-8px text-18px">{{ categoryInfo.name }}</h3>
 | 
				
			||||||
      <div class="color-gray-600 text-16px"> ({{ categoryInfo.modelList?.length || 0 }}) </div>
 | 
					      <div class="color-gray-600 text-16px"> ({{ categoryInfo.modelList?.length || 0 }}) </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <!-- 头部:操作 -->
 | 
				
			||||||
    <div class="flex-1 flex" v-if="!isCategorySorting">
 | 
					    <div class="flex-1 flex" v-if="!isCategorySorting">
 | 
				
			||||||
      <div
 | 
					      <div
 | 
				
			||||||
        v-if="categoryInfo.modelList.length > 0"
 | 
					        v-if="categoryInfo.modelList.length > 0"
 | 
				
			||||||
| 
						 | 
					@ -62,6 +64,7 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					  <!-- 模型列表 -->
 | 
				
			||||||
  <el-collapse-transition>
 | 
					  <el-collapse-transition>
 | 
				
			||||||
    <div v-show="isExpand">
 | 
					    <div v-show="isExpand">
 | 
				
			||||||
      <el-table
 | 
					      <el-table
 | 
				
			||||||
| 
						 | 
					@ -70,7 +73,7 @@
 | 
				
			||||||
        :header-cell-style="{ backgroundColor: isDark ? '' : '#edeff0', paddingLeft: '10px' }"
 | 
					        :header-cell-style="{ backgroundColor: isDark ? '' : '#edeff0', paddingLeft: '10px' }"
 | 
				
			||||||
        :cell-style="{ paddingLeft: '10px' }"
 | 
					        :cell-style="{ paddingLeft: '10px' }"
 | 
				
			||||||
        :row-style="{ height: '68px' }"
 | 
					        :row-style="{ height: '68px' }"
 | 
				
			||||||
        :data="tableData"
 | 
					        :data="modelList"
 | 
				
			||||||
        row-key="id"
 | 
					        row-key="id"
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <el-table-column label="流程名" prop="name" min-width="150">
 | 
					        <el-table-column label="流程名" prop="name" min-width="150">
 | 
				
			||||||
| 
						 | 
					@ -110,7 +113,7 @@
 | 
				
			||||||
        <el-table-column label="表单信息" prop="formType" min-width="200">
 | 
					        <el-table-column label="表单信息" prop="formType" min-width="200">
 | 
				
			||||||
          <template #default="scope">
 | 
					          <template #default="scope">
 | 
				
			||||||
            <el-button
 | 
					            <el-button
 | 
				
			||||||
              v-if="scope.row.formType === 10"
 | 
					              v-if="scope.row.formType === BpmModelFormType.NORMAL"
 | 
				
			||||||
              type="primary"
 | 
					              type="primary"
 | 
				
			||||||
              link
 | 
					              link
 | 
				
			||||||
              @click="handleFormDetail(scope.row)"
 | 
					              @click="handleFormDetail(scope.row)"
 | 
				
			||||||
| 
						 | 
					@ -118,7 +121,7 @@
 | 
				
			||||||
              <span>{{ scope.row.formName }}</span>
 | 
					              <span>{{ scope.row.formName }}</span>
 | 
				
			||||||
            </el-button>
 | 
					            </el-button>
 | 
				
			||||||
            <el-button
 | 
					            <el-button
 | 
				
			||||||
              v-else-if="scope.row.formType === 20"
 | 
					              v-else-if="scope.row.formType === BpmModelFormType.CUSTOM"
 | 
				
			||||||
              type="primary"
 | 
					              type="primary"
 | 
				
			||||||
              link
 | 
					              link
 | 
				
			||||||
              @click="handleFormDetail(scope.row)"
 | 
					              @click="handleFormDetail(scope.row)"
 | 
				
			||||||
| 
						 | 
					@ -246,7 +249,7 @@ import { formatDate } from '@/utils/formatTime'
 | 
				
			||||||
import * as ModelApi from '@/api/bpm/model'
 | 
					import * as ModelApi from '@/api/bpm/model'
 | 
				
			||||||
import * as FormApi from '@/api/bpm/form'
 | 
					import * as FormApi from '@/api/bpm/form'
 | 
				
			||||||
import { setConfAndFields2 } from '@/utils/formCreate'
 | 
					import { setConfAndFields2 } from '@/utils/formCreate'
 | 
				
			||||||
import { BpmModelType } from '@/utils/constants'
 | 
					import { BpmModelFormType, BpmModelType } from '@/utils/constants'
 | 
				
			||||||
import { checkPermi } from '@/utils/permission'
 | 
					import { checkPermi } from '@/utils/permission'
 | 
				
			||||||
import { useUserStoreWithOut } from '@/store/modules/user'
 | 
					import { useUserStoreWithOut } from '@/store/modules/user'
 | 
				
			||||||
import { useAppStore } from '@/store/modules/app'
 | 
					import { useAppStore } from '@/store/modules/app'
 | 
				
			||||||
| 
						 | 
					@ -255,20 +258,19 @@ import { cloneDeep } from 'lodash-es'
 | 
				
			||||||
defineOptions({ name: 'BpmModel' })
 | 
					defineOptions({ name: 'BpmModel' })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
  // 分类后的数据
 | 
					  categoryInfo: propTypes.object.def([]), // 分类后的数据
 | 
				
			||||||
  categoryInfo: propTypes.object.def([]),
 | 
					  isCategorySorting: propTypes.bool.def(false) // 是否分类在排序
 | 
				
			||||||
  isCategorySorting: propTypes.bool.def(false)
 | 
					 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
const emit = defineEmits(['success'])
 | 
					const emit = defineEmits(['success'])
 | 
				
			||||||
const appStore = useAppStore()
 | 
					 | 
				
			||||||
const message = useMessage() // 消息弹窗
 | 
					const message = useMessage() // 消息弹窗
 | 
				
			||||||
const isDark = computed(() => appStore.getIsDark)
 | 
					 | 
				
			||||||
const { t } = useI18n() // 国际化
 | 
					const { t } = useI18n() // 国际化
 | 
				
			||||||
const { push } = useRouter() // 路由
 | 
					const { push } = useRouter() // 路由
 | 
				
			||||||
const userStore = useUserStoreWithOut() // 用户信息缓存
 | 
					const userStore = useUserStoreWithOut() // 用户信息缓存
 | 
				
			||||||
 | 
					const isDark = computed(() => useAppStore().getIsDark) // 是否黑暗模式
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const isModelSorting = ref(false) // 是否正处于排序状态
 | 
					const isModelSorting = ref(false) // 是否正处于排序状态
 | 
				
			||||||
const tableData: any = ref([]) // 模型列表
 | 
					 | 
				
			||||||
const originalData: any = ref([]) // 原始数据
 | 
					const originalData: any = ref([]) // 原始数据
 | 
				
			||||||
 | 
					const modelList: any = ref([]) // 模型列表
 | 
				
			||||||
const isExpand = ref(false) // 是否处于展开状态
 | 
					const isExpand = ref(false) // 是否处于展开状态
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** '更多'操作按钮 */
 | 
					/** '更多'操作按钮 */
 | 
				
			||||||
| 
						 | 
					@ -414,7 +416,7 @@ const handleModelSort = () => {
 | 
				
			||||||
/** 处理模型的排序提交 */
 | 
					/** 处理模型的排序提交 */
 | 
				
			||||||
const handleModelSortSubmit = async () => {
 | 
					const handleModelSortSubmit = async () => {
 | 
				
			||||||
  // 保存排序
 | 
					  // 保存排序
 | 
				
			||||||
  const ids = tableData.value.map((item: any) => item.id)
 | 
					  const ids = modelList.value.map((item: any) => item.id)
 | 
				
			||||||
  await ModelApi.updateModelSortBatch(ids)
 | 
					  await ModelApi.updateModelSortBatch(ids)
 | 
				
			||||||
  // 刷新列表
 | 
					  // 刷新列表
 | 
				
			||||||
  isModelSorting.value = false
 | 
					  isModelSorting.value = false
 | 
				
			||||||
| 
						 | 
					@ -425,12 +427,12 @@ const handleModelSortSubmit = async () => {
 | 
				
			||||||
/** 处理模型的排序取消 */
 | 
					/** 处理模型的排序取消 */
 | 
				
			||||||
const handleModelSortCancel = () => {
 | 
					const handleModelSortCancel = () => {
 | 
				
			||||||
  // 恢复初始数据
 | 
					  // 恢复初始数据
 | 
				
			||||||
  tableData.value = cloneDeep(originalData.value)
 | 
					  modelList.value = cloneDeep(originalData.value)
 | 
				
			||||||
  isModelSorting.value = false
 | 
					  isModelSorting.value = false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 创建拖拽实例 */
 | 
				
			||||||
const tableRef = ref()
 | 
					const tableRef = ref()
 | 
				
			||||||
// 创建拖拽实例
 | 
					 | 
				
			||||||
const initSort = () => {
 | 
					const initSort = () => {
 | 
				
			||||||
  const table = document.querySelector(`.${props.categoryInfo.name} .el-table__body-wrapper tbody`)
 | 
					  const table = document.querySelector(`.${props.categoryInfo.name} .el-table__body-wrapper tbody`)
 | 
				
			||||||
  Sortable.create(table, {
 | 
					  Sortable.create(table, {
 | 
				
			||||||
| 
						 | 
					@ -441,19 +443,19 @@ const initSort = () => {
 | 
				
			||||||
    // 结束拖动事件
 | 
					    // 结束拖动事件
 | 
				
			||||||
    onEnd: ({ newDraggableIndex, oldDraggableIndex }) => {
 | 
					    onEnd: ({ newDraggableIndex, oldDraggableIndex }) => {
 | 
				
			||||||
      if (oldDraggableIndex !== newDraggableIndex) {
 | 
					      if (oldDraggableIndex !== newDraggableIndex) {
 | 
				
			||||||
        tableData.value.splice(
 | 
					        modelList.value.splice(
 | 
				
			||||||
          newDraggableIndex,
 | 
					          newDraggableIndex,
 | 
				
			||||||
          0,
 | 
					          0,
 | 
				
			||||||
          tableData.value.splice(oldDraggableIndex, 1)[0]
 | 
					          modelList.value.splice(oldDraggableIndex, 1)[0]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 更新表格数据
 | 
					/** 更新 modelList 模型列表 */
 | 
				
			||||||
const updateTableData = () => {
 | 
					const updateModeList = () => {
 | 
				
			||||||
  tableData.value = cloneDeep(props.categoryInfo.modelList)
 | 
					  modelList.value = cloneDeep(props.categoryInfo.modelList)
 | 
				
			||||||
  if (props.categoryInfo.modelList.length > 0) {
 | 
					  if (props.categoryInfo.modelList.length > 0) {
 | 
				
			||||||
    isExpand.value = true
 | 
					    isExpand.value = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -497,7 +499,7 @@ const openModelForm = (type: string, id?: number) => {
 | 
				
			||||||
  modelFormRef.value.open(type, id)
 | 
					  modelFormRef.value.open(type, id)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(() => props.categoryInfo.modelList, updateTableData, { immediate: true })
 | 
					watch(() => props.categoryInfo.modelList, updateModeList, { immediate: true })
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => props.isCategorySorting,
 | 
					  () => props.isCategorySorting,
 | 
				
			||||||
  (val) => {
 | 
					  (val) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,11 +38,11 @@
 | 
				
			||||||
            </el-button>
 | 
					            </el-button>
 | 
				
			||||||
            <template #dropdown>
 | 
					            <template #dropdown>
 | 
				
			||||||
              <el-dropdown-menu>
 | 
					              <el-dropdown-menu>
 | 
				
			||||||
                <el-dropdown-item command="handleAddCategory">
 | 
					                <el-dropdown-item command="handleCategoryAdd">
 | 
				
			||||||
                  <Icon icon="ep:circle-plus" :size="13" class="mr-5px" />
 | 
					                  <Icon icon="ep:circle-plus" :size="13" class="mr-5px" />
 | 
				
			||||||
                  新建分类
 | 
					                  新建分类
 | 
				
			||||||
                </el-dropdown-item>
 | 
					                </el-dropdown-item>
 | 
				
			||||||
                <el-dropdown-item command="handleSort">
 | 
					                <el-dropdown-item command="handleCategorySort">
 | 
				
			||||||
                  <Icon icon="fa:sort-amount-desc" :size="13" class="mr-5px" />
 | 
					                  <Icon icon="fa:sort-amount-desc" :size="13" class="mr-5px" />
 | 
				
			||||||
                  分类排序
 | 
					                  分类排序
 | 
				
			||||||
                </el-dropdown-item>
 | 
					                </el-dropdown-item>
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ import { CategoryApi } from '@/api/bpm/category'
 | 
				
			||||||
import * as ModelApi from '@/api/bpm/model'
 | 
					import * as ModelApi from '@/api/bpm/model'
 | 
				
			||||||
import ModelForm from './ModelForm.vue'
 | 
					import ModelForm from './ModelForm.vue'
 | 
				
			||||||
import CategoryForm from '../category/CategoryForm.vue'
 | 
					import CategoryForm from '../category/CategoryForm.vue'
 | 
				
			||||||
import { groupBy, cloneDeep } from 'lodash-es'
 | 
					import { cloneDeep } from 'lodash-es'
 | 
				
			||||||
import CategoryDraggableModel from './CategoryDraggableModel.vue'
 | 
					import CategoryDraggableModel from './CategoryDraggableModel.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({ name: 'BpmModel' })
 | 
					defineOptions({ name: 'BpmModel' })
 | 
				
			||||||
| 
						 | 
					@ -116,26 +116,6 @@ const queryFormRef = ref() // 搜索的表单
 | 
				
			||||||
const categoryGroup: any = ref([]) // 按照 category 分组的数据
 | 
					const categoryGroup: any = ref([]) // 按照 category 分组的数据
 | 
				
			||||||
const originalData: any = ref([]) // 原始数据
 | 
					const originalData: any = ref([]) // 原始数据
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 查询所有分类 */
 | 
					 | 
				
			||||||
const getAllCategory = async () => {
 | 
					 | 
				
			||||||
  const list = await CategoryApi.getCategorySimpleList()
 | 
					 | 
				
			||||||
  categoryGroup.value = list.map((item: any) => ({ ...item, modelList: [] }))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 查询所有流程模型接口 */
 | 
					 | 
				
			||||||
const getAllModel = async () => {
 | 
					 | 
				
			||||||
  // 查询所有流程模型
 | 
					 | 
				
			||||||
  const list = await ModelApi.getModelList(queryParams.name)
 | 
					 | 
				
			||||||
  // 按照 categoryName 分组
 | 
					 | 
				
			||||||
  const groupedData = groupBy(list, 'categoryName')
 | 
					 | 
				
			||||||
  Object.keys(groupedData).forEach((key) => {
 | 
					 | 
				
			||||||
    const category = categoryGroup.value.find((item: any) => item.name === key)
 | 
					 | 
				
			||||||
    if (category) {
 | 
					 | 
				
			||||||
      category.modelList = groupedData[key]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 搜索按钮操作 */
 | 
					/** 搜索按钮操作 */
 | 
				
			||||||
const handleQuery = () => {
 | 
					const handleQuery = () => {
 | 
				
			||||||
  getList()
 | 
					  getList()
 | 
				
			||||||
| 
						 | 
					@ -157,10 +137,10 @@ const formDetailPreview = ref({
 | 
				
			||||||
/** 右上角设置按钮 */
 | 
					/** 右上角设置按钮 */
 | 
				
			||||||
const handleCommand = (command: string) => {
 | 
					const handleCommand = (command: string) => {
 | 
				
			||||||
  switch (command) {
 | 
					  switch (command) {
 | 
				
			||||||
    case 'handleAddCategory':
 | 
					    case 'handleCategoryAdd':
 | 
				
			||||||
      handleAddCategory()
 | 
					      handleCategoryAdd()
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
    case 'handleSort':
 | 
					    case 'handleCategorySort':
 | 
				
			||||||
      handleCategorySort()
 | 
					      handleCategorySort()
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
| 
						 | 
					@ -170,7 +150,7 @@ const handleCommand = (command: string) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 新建分类 */
 | 
					/** 新建分类 */
 | 
				
			||||||
const categoryFormRef = ref()
 | 
					const categoryFormRef = ref()
 | 
				
			||||||
const handleAddCategory = () => {
 | 
					const handleCategoryAdd = () => {
 | 
				
			||||||
  categoryFormRef.value.open('create')
 | 
					  categoryFormRef.value.open('create')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,8 +183,15 @@ const handleCategorySortSubmit = async () => {
 | 
				
			||||||
const getList = async () => {
 | 
					const getList = async () => {
 | 
				
			||||||
  loading.value = true
 | 
					  loading.value = true
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    await getAllCategory()
 | 
					    // 查询模型 + 分裂的列表
 | 
				
			||||||
    await getAllModel()
 | 
					    const modelList = await ModelApi.getModelList(queryParams.name)
 | 
				
			||||||
 | 
					    const categoryList = await CategoryApi.getCategorySimpleList()
 | 
				
			||||||
 | 
					    // 按照 category 聚合
 | 
				
			||||||
 | 
					    // 注意:必须一次性赋值给 categoryGroup,否则每次操作后,列表会重新渲染,滚动条的位置会偏离!!!
 | 
				
			||||||
 | 
					    categoryGroup.value = categoryList.map((category: any) => ({
 | 
				
			||||||
 | 
					      ...category,
 | 
				
			||||||
 | 
					      modelList: modelList.filter((model: any) => model.categoryName == category.name)
 | 
				
			||||||
 | 
					    }))
 | 
				
			||||||
  } finally {
 | 
					  } finally {
 | 
				
			||||||
    loading.value = false
 | 
					    loading.value = false
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue