页面优化

This commit is contained in:
Lxq
2026-01-08 14:10:55 +08:00
parent 2c25ef613b
commit 7c2678429c
11 changed files with 150 additions and 59 deletions

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="dept-page"> <div class="dept-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>部门管理</el-breadcrumb-item>
</el-breadcrumb>
<div class="dept-container"> <div class="dept-container">
<!-- 左侧树形控件 --> <!-- 左侧树形控件 -->
<el-card class="tree-card" shadow="never"> <el-card class="tree-card" shadow="never">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="devinfo-page"> <div class="devinfo-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>业务管理</el-breadcrumb-item>
<el-breadcrumb-item>设备管理</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索栏 --> <!-- 搜索栏 -->
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="plc-devinfo-page"> <div class="plc-devinfo-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>业务管理</el-breadcrumb-item>
<el-breadcrumb-item>PLC设备管理</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索栏 --> <!-- 搜索栏 -->
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="flowinfo-page"> <div class="flowinfo-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>流程管理</el-breadcrumb-item>
<el-breadcrumb-item>标准流程管理</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索栏 --> <!-- 搜索栏 -->
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="island-info-page"> <div class="island-info-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>业务管理</el-breadcrumb-item>
<el-breadcrumb-item>功能岛管理</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索栏 --> <!-- 搜索栏 -->
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="manage-log-page"> <div class="manage-log-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>操作日志管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="90px"> <el-form :inline="true" :model="queryForm" label-width="90px">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="position-page"> <div class="position-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>职位管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="80px"> <el-form :inline="true" :model="queryForm" label-width="80px">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="role-page"> <div class="role-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>角色管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="80px"> <el-form :inline="true" :model="queryForm" label-width="80px">

View File

@@ -1,30 +1,35 @@
<template> <template>
<div class="flow-info-container"> <div class="step-info-wrapper">
<!-- 左侧功能岛组件面板 --> <el-breadcrumb separator="/" style="margin-bottom: 16px">
<div class="component-panel"> <el-breadcrumb-item>流程管理</el-breadcrumb-item>
<el-breadcrumb-item>流程创建</el-breadcrumb-item>
</el-breadcrumb>
<div class="flow-info-container">
<!-- 左侧功能岛组件面板 -->
<div class="component-panel">
<div class="panel-header"> <div class="panel-header">
<h3>功能岛</h3> <h3>功能岛</h3>
</div> </div>
<div class="component-list"> <div class="component-list">
<div class="component-items"> <div class="component-items">
<div <div
v-for="(item, index) in islandList" v-for="(item, index) in processedIslandList"
:key="item.id" :key="item.id"
class="component-item" class="component-item"
:style="{ animationDelay: `${index * 50}ms` }" :style="{ animationDelay: item.animationDelay }"
draggable="true" draggable="true"
@dragstart="handleDragStart($event, item)" @dragstart="handleDragStart($event, item)"
> >
<el-icon class="component-icon"> <el-icon class="component-icon">
<component :is="getIslandIcon(item.islandName || item.name)" /> <component :is="item.icon" />
</el-icon> </el-icon>
<div class="component-name">{{ index + 1 }}. {{ item.islandName || item.name }}</div> <div class="component-name">{{ index + 1 }}. {{ item.islandName || item.name }}</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- 中间流程设计画布 --> <!-- 中间流程设计画布 -->
<div <div
class="workflow-canvas" class="workflow-canvas"
v-loading="workflowLoading" v-loading="workflowLoading"
@@ -40,7 +45,7 @@
{{ flowName }} {{ flowName }}
</template> </template>
<template v-else> <template v-else>
未选择标准流程 <el-link type="primary" @click="goFlowList">请先选择标准流程</el-link>
</template> </template>
</div> </div>
<div class="canvas-status"> <div class="canvas-status">
@@ -58,7 +63,6 @@
:key="index" :key="index"
class="workflow-item" class="workflow-item"
:class="{ 'is-selected': selectedItemIndex === index }" :class="{ 'is-selected': selectedItemIndex === index }"
:style="{ animationDelay: `${index * 100}ms` }"
draggable="true" draggable="true"
@dragstart="handleWorkflowItemDragStart($event, index)" @dragstart="handleWorkflowItemDragStart($event, index)"
@dragover.stop="handleWorkflowItemDragOver($event, index)" @dragover.stop="handleWorkflowItemDragOver($event, index)"
@@ -71,7 +75,7 @@
</div> </div>
<div class="item-header"> <div class="item-header">
<el-icon class="item-icon"> <el-icon class="item-icon">
<component :is="getIslandIcon(item.islandName || item.name)" /> <component :is="getIslandIconCached(item.islandName || item.name)" />
</el-icon> </el-icon>
<div class="item-name">{{ item.islandName || item.name }}</div> <div class="item-name">{{ item.islandName || item.name }}</div>
<el-dropdown trigger="hover" @command="handleCommand($event, index, item)"> <el-dropdown trigger="hover" @command="handleCommand($event, index, item)">
@@ -108,12 +112,14 @@
</div> </div>
<div class="action-buttons"> <div class="action-buttons">
<el-button plain @click="goFlowList">退出</el-button>
<el-button type="primary" plain @click="clearWorkflow">清空</el-button> <el-button type="primary" plain @click="clearWorkflow">清空</el-button>
<el-button type="primary" @click="saveWorkflow" :loading="savingWorkflow">保存</el-button> <el-button type="primary" @click="saveWorkflow" :loading="savingWorkflow">保存</el-button>
</div> </div>
</div> </div>
</div>
<!-- 编辑抽屉 --> <!-- 编辑抽屉 -->
<el-drawer <el-drawer
v-model="drawerVisible" v-model="drawerVisible"
:title="drawerTitle" :title="drawerTitle"
@@ -252,10 +258,31 @@ const islandList = ref<any[]>([])
const loading = ref(false) const loading = ref(false)
const workflowLoading = ref(false) const workflowLoading = ref(false)
// 缓存功能岛图标,避免模板中重复计算
const islandIconCache = new Map<string, any>()
// 缓存处理后的功能岛列表
const processedIslandList = computed(() => {
return islandList.value.map((item, index) => {
const key = item.islandName || item.name || ''
if (!islandIconCache.has(key)) {
islandIconCache.set(key, getIslandIcon(key))
}
return {
...item,
icon: islandIconCache.get(key),
animationDelay: `${index * 50}ms`,
}
})
})
// 当前流程中的组件 // 当前流程中的组件
const workflowItems = ref<any[]>([]) const workflowItems = ref<any[]>([])
const selectedItemIndex = ref(-1) const selectedItemIndex = ref(-1)
const workflowGridRef = ref<HTMLElement | null>(null) const workflowGridRef = ref<HTMLElement | null>(null)
const goFlowList = () => {
router.push('/flow-info')
}
const generateInstanceId = (base?: number | string) => const generateInstanceId = (base?: number | string) =>
`island-${base ?? 'unknown'}-${Date.now()}-${Math.random().toString(16).slice(2)}` `island-${base ?? 'unknown'}-${Date.now()}-${Math.random().toString(16).slice(2)}`
@@ -380,6 +407,15 @@ const isAddLimitExceeded = (item: any): boolean => {
return false return false
} }
// 获取功能岛图标(带缓存)
const getIslandIconCached = (name: string) => {
const key = name || ''
if (!islandIconCache.has(key)) {
islandIconCache.set(key, getIslandIcon(key))
}
return islandIconCache.get(key)!
}
// 获取功能岛图标 // 获取功能岛图标
const getIslandIcon = (name: string) => { const getIslandIcon = (name: string) => {
if (!name) return Box if (!name) return Box
@@ -596,11 +632,21 @@ const handleDrop = (event: DragEvent) => {
} }
} }
// 缓存 workflow-item 元素引用避免频繁查询DOM
let workflowItemElements: NodeListOf<HTMLElement> | null = null
const getWorkflowItems = () => {
if (!workflowItemElements || workflowItemElements.length !== workflowItems.value.length) {
workflowItemElements = document.querySelectorAll('.workflow-item') as NodeListOf<HTMLElement>
}
return workflowItemElements
}
// 容器拖拽经过 // 容器拖拽经过
const handleContainerDragOver = (event: DragEvent) => { const handleContainerDragOver = (event: DragEvent) => {
event.preventDefault() event.preventDefault()
event.dataTransfer!.dropEffect = isExternalDrag.value ? 'copy' : 'move' event.dataTransfer!.dropEffect = isExternalDrag.value ? 'copy' : 'move'
const items = document.querySelectorAll('.workflow-item') // 使用缓存的DOM查询但保持实时更新拖拽需要即时反馈
const items = getWorkflowItems()
items.forEach((item) => { items.forEach((item) => {
item.classList.remove('drag-over-top', 'drag-over-bottom') item.classList.remove('drag-over-top', 'drag-over-bottom')
}) })
@@ -630,11 +676,13 @@ const handleContainerDrop = (event: DragEvent) => {
instanceId: generateInstanceId(dragItemData.id), instanceId: generateInstanceId(dragItemData.id),
} }
const items = document.querySelectorAll('.workflow-item') // 使用 workflowItems 数组长度计算避免DOM查询
const items = getWorkflowItems()
let insertIndex = 0 let insertIndex = 0
let minDistance = Infinity let minDistance = Infinity
const mouseY = event.clientY const mouseY = event.clientY
// 使用 requestAnimationFrame 优化性能
items.forEach((item, index) => { items.forEach((item, index) => {
const rect = item.getBoundingClientRect() const rect = item.getBoundingClientRect()
const centerY = rect.top + rect.height / 2 const centerY = rect.top + rect.height / 2
@@ -649,28 +697,18 @@ const handleContainerDrop = (event: DragEvent) => {
workflowItems.value.splice(insertIndex, 0, dragItemData) workflowItems.value.splice(insertIndex, 0, dragItemData)
selectedItemIndex.value = insertIndex selectedItemIndex.value = insertIndex
// 更新所有相同功能岛的描述 // 优化:使用 Map 减少嵌套循环,从 O(n²) 降到 O(n)
workflowItems.value.forEach((item, i) => { updateIslandDescriptions()
const key = getIslandDescriptionKey(item.islandName || item.name)
const sameItems = workflowItems.value.filter((it) => {
const k = getIslandDescriptionKey(it.islandName || it.name)
return k === key
})
const index = sameItems.findIndex((it) => it === item)
if (index !== -1) {
item.description = `${chineseNumbers[index]}${key}`
item.sort = index
}
})
} }
dragItemData = null dragItemData = null
isExternalDrag.value = false isExternalDrag.value = false
const items = document.querySelectorAll('.workflow-item') const items = getWorkflowItems()
items.forEach((item) => { items.forEach((item) => {
item.classList.remove('is-dragging', 'drag-over-top', 'drag-over-bottom') item.classList.remove('is-dragging', 'drag-over-top', 'drag-over-bottom')
}) })
workflowItemElements = null // 清除缓存
} }
// 流程项拖拽开始 // 流程项拖拽开始
@@ -716,21 +754,10 @@ const handleWorkflowItemDrop = (event: DragEvent, targetIndex: number) => {
selectedItemIndex.value = newIndex selectedItemIndex.value = newIndex
} }
// 更新描述 // 更新描述 - 使用优化函数
workflowItems.value.forEach((item, i) => { updateIslandDescriptions()
const key = getIslandDescriptionKey(item.islandName || item.name)
const sameItems = workflowItems.value.filter((it) => {
const k = getIslandDescriptionKey(it.islandName || it.name)
return k === key
})
const index = sameItems.findIndex((it) => it === item)
if (index !== -1) {
item.description = `${chineseNumbers[index]}${key}`
item.sort = index
}
})
const items = document.querySelectorAll('.workflow-item') const items = getWorkflowItems()
items.forEach((item) => { items.forEach((item) => {
item.classList.remove('is-dragging', 'drag-over-top', 'drag-over-bottom') item.classList.remove('is-dragging', 'drag-over-top', 'drag-over-bottom')
}) })
@@ -742,13 +769,36 @@ const handleWorkflowItemDrop = (event: DragEvent, targetIndex: number) => {
// 流程项拖拽结束 // 流程项拖拽结束
const handleWorkflowItemDragEnd = () => { const handleWorkflowItemDragEnd = () => {
const items = document.querySelectorAll('.workflow-item') const items = getWorkflowItems()
items.forEach((item) => { items.forEach((item) => {
item.classList.remove('drag-over-top', 'drag-over-bottom') item.classList.remove('drag-over-top', 'drag-over-bottom')
}) })
dragSourceIndex = -1 dragSourceIndex = -1
dragItemData = null dragItemData = null
isExternalDrag.value = false isExternalDrag.value = false
workflowItemElements = null // 清除缓存,下次重新查询
}
// 优化:统一更新功能岛描述的函数,使用 Map 优化性能
const updateIslandDescriptions = () => {
// 使用 Map 按描述关键词分组,从 O(n²) 优化到 O(n)
const islandGroups = new Map<string, any[]>()
workflowItems.value.forEach((item) => {
const key = getIslandDescriptionKey(item.islandName || item.name)
if (!islandGroups.has(key)) {
islandGroups.set(key, [])
}
islandGroups.get(key)!.push(item)
})
// 更新每个分组的描述
islandGroups.forEach((items, key) => {
items.forEach((item, index) => {
item.description = `${chineseNumbers[index] || index + 1}${key}`
item.sort = index
})
})
} }
// 选择流程项 // 选择流程项
@@ -1144,6 +1194,13 @@ const saveWorkflow = async () => {
hasRemoteWorkflow.value = true hasRemoteWorkflow.value = true
clearParamCache() clearParamCache()
await loadWorkflowFromServer() await loadWorkflowFromServer()
// 如果是从标准流程管理页面跳转过来的有flowId保存成功后跳转回去
if (flowId.value) {
setTimeout(() => {
router.push('/flow-info')
}, 500) // 延迟500ms让用户看到成功提示
}
} else { } else {
ElMessage.error(res?.message || res?.msg || '保存失败') ElMessage.error(res?.message || res?.msg || '保存失败')
} }
@@ -1176,9 +1233,17 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.step-info-wrapper {
display: flex;
flex-direction: column;
height: calc(100vh - 140px);
min-height: 0;
}
.flow-info-container { .flow-info-container {
display: flex; display: flex;
height: calc(100vh - 100px); flex: 1;
min-height: 0;
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
background-color: #f0f2f5; background-color: #f0f2f5;
@@ -1371,8 +1436,6 @@ onMounted(() => {
box-sizing: border-box; box-sizing: border-box;
transition: all 0.3s; transition: all 0.3s;
cursor: pointer; cursor: pointer;
animation: fadeInUp 0.5s ease-out forwards;
opacity: 0;
&.is-selected { &.is-selected {
border-color: #409eff; border-color: #409eff;
@@ -1639,17 +1702,5 @@ onMounted(() => {
transform: translateY(0); transform: translateY(0);
} }
} }
// 流程卡片动画:淡入+向上移动
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(15px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style> </style>

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="user-role-page"> <div class="user-role-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>用户角色管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="80px"> <el-form :inline="true" :model="queryForm" label-width="80px">

View File

@@ -1,5 +1,9 @@
<template> <template>
<div class="user-page"> <div class="user-page">
<el-breadcrumb separator="/" style="margin-bottom: 16px">
<el-breadcrumb-item>系统管理</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
<el-card class="search-card" shadow="never"> <el-card class="search-card" shadow="never">
<div class="search-bar"> <div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="80px"> <el-form :inline="true" :model="queryForm" label-width="80px">