|
@@ -16,13 +16,13 @@
|
|
|
<el-form-item>
|
|
|
<div class="stats-item">
|
|
|
<el-tooltip content="聚焦节点说明" placement="top">
|
|
|
- <span>聚焦节点数: {{ nodeData.num }}</span>
|
|
|
+ <span>聚焦节点数: {{ nodeData.amount }}</span>
|
|
|
</el-tooltip>
|
|
|
<el-tooltip content="孤立节点说明" placement="top">
|
|
|
- <span>孤立节点数: {{ nodeData.num }}</span>
|
|
|
+ <span>孤立节点数: {{ nodeData.amount }}</span>
|
|
|
</el-tooltip>
|
|
|
<el-tooltip content="总节点说明" placement="top">
|
|
|
- <span>总节点数: {{ nodeData.num }}</span>
|
|
|
+ <span>总节点数: {{ nodeData.amount }}</span>
|
|
|
</el-tooltip>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
@@ -32,7 +32,7 @@
|
|
|
<el-tooltip content="边集中度说明" placement="top">
|
|
|
<span>边集中度: {{ edgeData.concentration }}</span>
|
|
|
</el-tooltip>
|
|
|
- <span>总边数: {{ edgeData.num }}</span>
|
|
|
+ <span>总边数: {{ edgeData.amount }}</span>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
@@ -111,9 +111,9 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, reactive, onMounted, nextTick, inject, provide } from 'vue'
|
|
|
+import { ref, reactive, onMounted, nextTick, inject, provide, watch } from 'vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
-import { useRouter } from 'vue-router'
|
|
|
+import { useRouter, useRoute } from 'vue-router'
|
|
|
import { Delete, ArrowDown, ArrowRight, VideoPlay, VideoPause, SwitchButton } from '@element-plus/icons-vue'
|
|
|
import { getData, postData, deleteData } from '@/api/axios.js'
|
|
|
import { pl } from 'element-plus/es/locales.mjs'
|
|
@@ -122,9 +122,9 @@ import { pl } from 'element-plus/es/locales.mjs'
|
|
|
const useAnalyzeInfo = inject('analyzeInfo')
|
|
|
const router = useRouter()
|
|
|
|
|
|
-const nodeData = useAnalyzeInfo.analyzeInfo.value.nodeFile
|
|
|
-const edgeData = useAnalyzeInfo.analyzeInfo.value.edgeFile
|
|
|
-const mission = useAnalyzeInfo.analyzeInfo.value.mission
|
|
|
+const nodeData = ref(useAnalyzeInfo.analyzeInfo.value.nodeFile)
|
|
|
+const edgeData = ref(useAnalyzeInfo.analyzeInfo.value.edgeFile)
|
|
|
+const mission = ref(useAnalyzeInfo.analyzeInfo.value.mission)
|
|
|
// 算法列表
|
|
|
const algorithms = ref([
|
|
|
{ label: '算法A', value: 'algA', level: 0 },
|
|
@@ -178,38 +178,46 @@ const MAX_COLUMNS = 3
|
|
|
const MAX_ROWS = 5
|
|
|
|
|
|
|
|
|
-// 获取初始数据
|
|
|
-onMounted(async () => {
|
|
|
- try {
|
|
|
- // 这里替换实际API调用
|
|
|
- await fetchData()
|
|
|
- } finally {
|
|
|
- loading.value = false
|
|
|
- }
|
|
|
-})
|
|
|
+
|
|
|
|
|
|
const fetchData = async () => {
|
|
|
+ // 如果当前没有保存的节点和边的数据,则尝试获取任务数据
|
|
|
// 如果已经保存了节点和边的数据,则省略获取数据
|
|
|
- if (nodeData.id && edgeData.id) {
|
|
|
- console.log("跳过获取数据")
|
|
|
+ // 更新节点、边、任务数据
|
|
|
+ console.log(useAnalyzeInfo.analyzeInfo.value)
|
|
|
+ if (nodeData.value.amound == 0 || edgeData.value.amound == 0 || mission.value.id == null) {
|
|
|
+ const recoveryData = JSON.parse(sessionStorage.getItem('analyze-info'))
|
|
|
+ if (recoveryData == null) {
|
|
|
+ ElMessage.error("未获取到当前任务信息")
|
|
|
+ router.push("/dashboard")
|
|
|
+ } else {
|
|
|
+ useAnalyzeInfo.analyzeInfo.value = recoveryData
|
|
|
+ }
|
|
|
+ }
|
|
|
+ nodeData.value = useAnalyzeInfo.analyzeInfo.value.nodeFile
|
|
|
+ edgeData.value = useAnalyzeInfo.analyzeInfo.value.edgeFile
|
|
|
+ mission.value = useAnalyzeInfo.analyzeInfo.value.mission
|
|
|
+ console.log(nodeData)
|
|
|
+ if (nodeData.value.amound == 0 || edgeData.value.amound == 0 || mission.value.id == null) {
|
|
|
+ console.log("从缓存中获取节点、边、任务数据失败")
|
|
|
+ ElMessage.error("从缓存中获取节点、边、任务数据失败")
|
|
|
return
|
|
|
}
|
|
|
- // 如果是从历史文件进入的规划,则应当获取节点和边的数据
|
|
|
- loading.value = true
|
|
|
- // 模拟API请求
|
|
|
- await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
- Object.assign(nodeData, {
|
|
|
- sNodes: 10,
|
|
|
- dNodes: 5,
|
|
|
- i: 8,
|
|
|
- focus: 15,
|
|
|
- isolate: 3,
|
|
|
- total: 23
|
|
|
- })
|
|
|
- Object.assign(edgeData, {
|
|
|
- concentration: 0.75,
|
|
|
- total: 45
|
|
|
- })
|
|
|
+ // 当前进入plan必须先选择mission,所以不必再获取信息
|
|
|
+ // loading.value = true
|
|
|
+ // await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
+ // Object.assign(nodeData, {
|
|
|
+ // sNodes: 10,
|
|
|
+ // dNodes: 5,
|
|
|
+ // i: 8,
|
|
|
+ // focus: 15,
|
|
|
+ // isolate: 3,
|
|
|
+ // total: 23
|
|
|
+ // })
|
|
|
+ // Object.assign(edgeData, {
|
|
|
+ // concentration: 0.75,
|
|
|
+ // total: 45
|
|
|
+ // })
|
|
|
|
|
|
loading.value = false
|
|
|
}
|
|
@@ -254,13 +262,10 @@ const calculateLayout = () => {
|
|
|
}
|
|
|
|
|
|
// 计算绝对位置(无响应式更新)
|
|
|
- console.log(btn)
|
|
|
- console.log(containerWidth, COLUMN_GAP, MAX_COLUMNS)
|
|
|
const pos = {
|
|
|
x: 20 + btn.col * COLUMN_GAP,
|
|
|
y: btn.row * ROW_GAP
|
|
|
}
|
|
|
- console.log(pos)
|
|
|
|
|
|
// 直接赋值避免触发响应式更新
|
|
|
if (btn.position.x !== pos.x || btn.position.y !== pos.y) {
|
|
@@ -270,7 +275,7 @@ const calculateLayout = () => {
|
|
|
})
|
|
|
setTimeout(() => {
|
|
|
updateConnections()
|
|
|
- }, 200)
|
|
|
+ }, 500)
|
|
|
|
|
|
})
|
|
|
}
|
|
@@ -282,13 +287,13 @@ const hideExtraBtns = (index) => {
|
|
|
|
|
|
// 获取按钮中心坐标
|
|
|
const getButtonCenter = (btn) => {
|
|
|
- const index = buttons.value.findIndex(b => b.id === btn.id)
|
|
|
- if (index === -1 || !buttonRefs.value[index]) return { x: 0, y: 0 }
|
|
|
|
|
|
- const el = buttonRefs.value[index]
|
|
|
+ const el = buttonRefs.value.find(b => b.__vnode.key === "btn-" + btn.id)
|
|
|
+ if (!el) return { x: 0, y: 0 }
|
|
|
+
|
|
|
const containerRect = flowContainer.value.getBoundingClientRect()
|
|
|
const btnRect = el.getBoundingClientRect()
|
|
|
-
|
|
|
+ console.log(btn.id, containerRect, btnRect)
|
|
|
return {
|
|
|
x: btnRect.left - containerRect.left + el.offsetWidth / 2,
|
|
|
y: btnRect.top - containerRect.top + el.offsetHeight / 2,
|
|
@@ -303,9 +308,10 @@ const getButtonCenter = (btn) => {
|
|
|
|
|
|
// 更新连接线
|
|
|
const updateConnections = () => {
|
|
|
- connections.value = []
|
|
|
|
|
|
+ connections.value = []
|
|
|
// 遍历所有按钮建立连接关系
|
|
|
+ console.log(buttons)
|
|
|
buttons.value.forEach(btn => {
|
|
|
if (btn.parentId) {
|
|
|
const parent = buttons.value.find(b => b.id === btn.parentId)
|
|
@@ -313,8 +319,13 @@ const updateConnections = () => {
|
|
|
|
|
|
// 获取实际渲染位置
|
|
|
console.log("redraw line", btn.id, parent.id)
|
|
|
- const start = getButtonCenter(parent)
|
|
|
- const end = getButtonCenter(btn)
|
|
|
+ let start = getButtonCenter(parent)
|
|
|
+ let end = getButtonCenter(btn)
|
|
|
+ // 解决颠倒问题
|
|
|
+ // if(start.top > end.top){
|
|
|
+ // start = getButtonCenter(btn)
|
|
|
+ // end = getButtonCenter(parent)
|
|
|
+ // }
|
|
|
// 除初始节点的并行外,均为父下到子上
|
|
|
if (btn.row !== 0) {
|
|
|
if (start.x > 0 && start.y > 0 && end.x > 0 && end.y > 0) {
|
|
@@ -411,13 +422,20 @@ const canExpandBottom = (btn) => {
|
|
|
|
|
|
|
|
|
// 添加新按钮
|
|
|
-const addButton = (parentIndex, direction) => {
|
|
|
- let parent = buttons.value[parentIndex]
|
|
|
+// 可以同时传入数据,直接完成构建
|
|
|
+const addButton = (parentIndex, direction, button = null) => {
|
|
|
+ let parent = null
|
|
|
+ if (button) {
|
|
|
+ parent = buttons.value.find(p => p.id === button.parent)
|
|
|
+ } else {
|
|
|
+ parent = buttons.value[parentIndex]
|
|
|
+ }
|
|
|
if (!parent.algorithm) {
|
|
|
ElMessage.error("必须先选择当前流程算法")
|
|
|
return
|
|
|
}
|
|
|
- const newId = Date.now()
|
|
|
+ // 如果传入数据,则使用数据中的值
|
|
|
+ const newId = button ? button.id : Date.now()
|
|
|
let selfCol = parent.col
|
|
|
let selfRow = parent.row
|
|
|
let allowCreate = true
|
|
@@ -425,7 +443,7 @@ const addButton = (parentIndex, direction) => {
|
|
|
let allowedAlgorithms = []
|
|
|
if (direction == 'right') {
|
|
|
// 创建并行节点时,从父节点的父节点开始
|
|
|
- // 初始节点没有更上一级
|
|
|
+ // 初始节点有更上一级
|
|
|
if (parent.parentId) {
|
|
|
parent = buttons.value.find(b => b.id === parent.parentId)
|
|
|
}
|
|
@@ -475,14 +493,14 @@ const addButton = (parentIndex, direction) => {
|
|
|
|
|
|
const newBtn = {
|
|
|
id: newId,
|
|
|
- label: '请选择处理算法',
|
|
|
- parentId: parent.id,
|
|
|
+ label: button ? algorithms.value.find(p => p.value === button.algorithm).label : '请选择处理算法',
|
|
|
+ parentId: button ? button.parent : parent.id,
|
|
|
direction,
|
|
|
col: selfCol,
|
|
|
row: selfRow,
|
|
|
position: { ...parent.position },
|
|
|
children: [],
|
|
|
- algorithm: null,
|
|
|
+ algorithm: button ? algorithms.value.find(p => p.value === button.algorithm) : null,
|
|
|
algorithms: allowedAlgorithms,
|
|
|
}
|
|
|
|
|
@@ -554,15 +572,15 @@ const submitPlan = async () => {
|
|
|
}
|
|
|
}
|
|
|
try {
|
|
|
- const response = await postData('/plan/', { mission: mission.id, plans: plans })
|
|
|
+ const response = await postData('/plan/', { mission: mission.value.id, plans: plans })
|
|
|
planning.value = false
|
|
|
calculating.value = true
|
|
|
- if(response.message === "规划提交成功"){
|
|
|
+ if (response.message === "规划提交成功") {
|
|
|
ElMessage.success('规划已提交')
|
|
|
- }else if(response.message === "规划已覆盖"){
|
|
|
+ } else if (response.message === "规划已覆盖") {
|
|
|
ElMessage.warning('该计算任务规划已被覆盖')
|
|
|
}
|
|
|
- response.data.forEach( p => {
|
|
|
+ response.data.forEach(p => {
|
|
|
const btn = buttons.value.find(btn => btn.col === p.col && btn.row === p.row)
|
|
|
btn.id = p.id
|
|
|
btn.parentId = p.parentId
|
|
@@ -571,12 +589,19 @@ const submitPlan = async () => {
|
|
|
const newPath = currentPath.endsWith('/') ? currentPath + 'calculate' : currentPath + '/calculate';
|
|
|
router.push(newPath)
|
|
|
} catch (e) {
|
|
|
- ElMessage.error(e.response.data.message)
|
|
|
+ ElMessage.error(e.response.data.message)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
// 初始化
|
|
|
-onMounted(() => {
|
|
|
+onMounted(async () => {
|
|
|
+ console.log("Mounted")
|
|
|
+ try {
|
|
|
+ await fetchData()
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
const resizeObserver = new ResizeObserver(() => {
|
|
|
calculateLayout()
|
|
|
})
|
|
@@ -585,6 +610,110 @@ onMounted(() => {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+const route = useRoute();
|
|
|
+// 监听路由变化
|
|
|
+watch(
|
|
|
+ () => route.path,
|
|
|
+ async (newPath) => {
|
|
|
+ // 路由变化时,修改显示内容
|
|
|
+ if (newPath === '/dashboard/analyze/plan/calculate' || newPath === '/dashboard/analyze/plan') {
|
|
|
+ // 进入计算页面,尝试获取plan数据,该数据需存入buttons响应数据中
|
|
|
+ // 检查buttons中是否有数据
|
|
|
+ if (buttons.value.length === 1 && buttons.value[0].label === "请选择处理算法") {
|
|
|
+ console.log("缓存中没有数据")
|
|
|
+ // 缓存中没有数据,需要重新获取
|
|
|
+ try {
|
|
|
+ if (mission.value.id === null) {
|
|
|
+ fetchData()
|
|
|
+ }
|
|
|
+ const response = await getData('/plan/', { mission: mission.value.id })
|
|
|
+ const rootBtn = response.data.find(p => p.parent === null)
|
|
|
+ let findStack = [rootBtn]
|
|
|
+ let row = 0
|
|
|
+ while (findStack) {
|
|
|
+ // 初始化列数
|
|
|
+ let col = 0
|
|
|
+ // 记录前一个节点
|
|
|
+ let pre = null
|
|
|
+ let parent = findStack.pop()
|
|
|
+ if (parent === null || parent === undefined) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ response.data.filter(p => p.parent === parent.id).forEach(p => {
|
|
|
+ findStack.push(p)
|
|
|
+ let algorithm = algorithms.value.find(algo => algo.value === p.algorithm)
|
|
|
+ // 第一行第一列节点,直接修改初始节点
|
|
|
+ if (row === 0 && col === 0) {
|
|
|
+ buttons.value[0].id = p.id
|
|
|
+ buttons.value[0].algorithm = algorithm
|
|
|
+ buttons.value[0].label = algorithm.label
|
|
|
+ // 同时修改列计数第一列被当前节点占据
|
|
|
+ colRecord.value[0] = p.id
|
|
|
+ } else {
|
|
|
+ // 后续节点,同一个parent,在panrent的下方水平扩展
|
|
|
+ if (col == 0) {
|
|
|
+ // 子节点中第一个,在parent的下方扩展
|
|
|
+ addButton(p.parent, 'bottom', p)
|
|
|
+ } else {
|
|
|
+ // 子节点的后续,在第一个子节点的水平扩展
|
|
|
+ addButton(pre.id, 'right',)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 保存上一个节点
|
|
|
+ pre = p
|
|
|
+ // 横向序号
|
|
|
+ col += 1
|
|
|
+ })
|
|
|
+ //过了第一个行,后续row全部不等于0,注意此时row已经失真
|
|
|
+ row += 1
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success("规划任务恢复成功")
|
|
|
+ // 切换route-view
|
|
|
+ if (newPath === '/dashboard/analyze/plan') {
|
|
|
+ planning.value = true
|
|
|
+ calculating.value = false
|
|
|
+ } else {
|
|
|
+ planning.value = false
|
|
|
+ calculating.value = true
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ ElMessage.error("获取规划任务数据出错,返回规划页面")
|
|
|
+ planning.value = true
|
|
|
+ calculating.value = false
|
|
|
+ router.push('/dashboard/analyze/plan')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 缓存中有数据,不做处理
|
|
|
+ // 切换route-view
|
|
|
+ if (newPath === '/dashboard/analyze/plan') {
|
|
|
+ calculateLayout()
|
|
|
+ planning.value = true
|
|
|
+ calculating.value = false
|
|
|
+ } else {
|
|
|
+ planning.value = false
|
|
|
+ calculating.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // if (newPath === '/dashboard/analyze/plan') {
|
|
|
+ // try {
|
|
|
+ // await fetchData()
|
|
|
+ // } finally {
|
|
|
+ // loading.value = false
|
|
|
+ // }
|
|
|
+ // const resizeObserver = new ResizeObserver(() => {
|
|
|
+ // calculateLayout()
|
|
|
+ // })
|
|
|
+ // if (flowContainer.value) {
|
|
|
+ // resizeObserver.observe(flowContainer.value)
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+);
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|