From 6a24cd17cc6a07e0771c4dea231d9ed6d8eff5a5 Mon Sep 17 00:00:00 2001 From: zhanghao <774378400@qq.com> Date: Tue, 18 Aug 2026 13:32:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8C=89=E9=80=89=E4=B8=AD=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=B1=95=E7=A4=BA=E8=BF=90=E8=A1=8C=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/inspection/runTask/index.vue | 85 ++++++++++++------ .../intelligenceTest/runningTask/index.vue | 86 ++++++++++++------- 2 files changed, 115 insertions(+), 56 deletions(-) diff --git a/src/views/inspection/runTask/index.vue b/src/views/inspection/runTask/index.vue index 2c4d98b..099c61c 100644 --- a/src/views/inspection/runTask/index.vue +++ b/src/views/inspection/runTask/index.vue @@ -6,18 +6,20 @@ 添加任务
-
+
{{ task.taskName }}
+ @click.stop="pauseTask(task)" /> + :size="24" color="#00FF88" @click.stop="startTask(task)" /> + @click.stop="stopTask(task)" /> + @click.stop="removeTask(task)" />
主要机器人:{{ task.robotName || '执行时安排' }}
@@ -35,38 +37,38 @@
- -
+ +
-
{{ runTask.taskName }}
-
ID: {{ runTask.taskId }}
+
{{ selectedRunTask.taskName }}
+
ID: {{ selectedRunTask.taskId }}
-
主要机器人:{{ runTask.robotName || '按流程角色安排' }}
-
开始时间: {{ formatDate(runTask.startTime) }}
+
主要机器人:{{ selectedRunTask.robotName || '按流程角色安排' }}
+
开始时间: {{ formatDate(selectedRunTask.startTime) }}
- - {{ taskStatusMap[runTask.status] || '未知状态' }} + + {{ taskStatusMap[selectedRunTask.status] || '未知状态' }}
执行进度
- + :percentage="parseFloat(taskRunningInfo[selectedRunTask.id]?.progress?.toFixed(2)) || 0" /> +
执行日志
- +
+
@@ -170,7 +172,7 @@ import taskSteps from "./task-steps.vue"; import taskLog from "./task-log.vue"; import { useContainerHeight } from "@/hooks/tableHeight"; import { getTaskList, getWaypointByTaskId } from "@/api/inspection/task"; -import { onMounted, onUnmounted } from "vue"; +import { computed, onMounted, onUnmounted } from "vue"; import { addRunTask, getRunTaskList, startRunTask, rerunRunTask, pauseRunTask, stopRunTask, resumeRunTask, deleteRunTask, getTaskLogListApi } from "@/api/inspection/runTask"; import { ElMessage, ElMessageBox } from "element-plus"; import { formatDate } from "@/utils/index"; @@ -220,6 +222,23 @@ const rules = reactive({ const taskList = ref([]); const runTaskList = ref([]); +// 接口和 WebSocket 可能分别以数字、字符串返回任务实例 ID,统一转换后再判断是否为选中任务。 +const isSelectedTask = (task) => String(task?.id ?? '') === String(selectedTaskId.value) + +// 当前任务详情直接从完整任务队列中取得,因此未执行、执行中和已暂停任务都可以被选中查看。 +const selectedRunTask = computed(() => runTaskList.value.find(isSelectedTask) || null) + +/** + * 点击左侧任务卡片时切换右侧当前任务详情,并从历史记录面板返回当前任务面板。 + * 卡片内的启动、暂停、停止和删除图标均使用 .stop 阻止冒泡,执行操作时不会意外改变当前选择。 + * + * @param {Object} task 左侧任务队列中被点击的任务实例 + */ +const selectTask = (task) => { + selectedTaskId.value = task.id + activePanel.value = 'current' +} + const normalizeTaskStatus = (tasks = []) => tasks.map(item => ({ ...item, status: String(item.status), @@ -264,9 +283,12 @@ const cancelTaskDialog = () => { } -const runingTaskList = ref([]) /** - * 获取任务队列 + * 获取任务队列并维护当前选中的任务: + * 1. 页面首次加载时默认选中队列第一条任务; + * 2. 队列刷新后,如果原任务仍存在,则保留用户当前选择; + * 3. 如果原任务已经结束或被删除,则选择刷新后队列中的第一条任务; + * 4. 如果任务队列为空,则清空选择并由模板展示空状态。 */ const getList = () => { return getRunTaskList({ @@ -275,7 +297,9 @@ const getList = () => { if (res.code === 200) { const tasks = normalizeTaskStatus(res.rows) runTaskList.value = tasks; - runingTaskList.value = tasks.filter(item => item.status !== '5') + if (!tasks.some(isSelectedTask)) { + selectedTaskId.value = tasks[0]?.id ?? '' + } for (let i = 0; i < runTaskList.value.length; i++) { getPointByTaskId(runTaskList.value[i].taskId) getTaskLogList(runTaskList.value[i].id) @@ -618,6 +642,17 @@ onUnmounted(() => { box-shadow: inset 0 0 0 1px #eee; border-radius: 8px; margin-bottom: 16px; + cursor: pointer; + transition: background-color 0.2s ease, box-shadow 0.2s ease; + + &:hover { + background: var(--el-fill-color-light); + } + + &.is-selected { + background: var(--el-color-primary-light-9); + box-shadow: inset 0 0 0 2px var(--el-color-primary); + } .task-content { display: flex; @@ -684,10 +719,6 @@ onUnmounted(() => { border-radius: 20px; margin-bottom: 12px; - &--selected { - box-shadow: inset 0 0 0 2px var(--el-color-primary); - } - .task-header { display: flex; justify-content: space-between; diff --git a/src/views/intelligenceTest/runningTask/index.vue b/src/views/intelligenceTest/runningTask/index.vue index cdd5794..ab3e0de 100644 --- a/src/views/intelligenceTest/runningTask/index.vue +++ b/src/views/intelligenceTest/runningTask/index.vue @@ -6,18 +6,20 @@ 添加任务
-
+
{{ task.taskName }}
+ @click.stop="pauseTask(task)" /> + :size="24" color="#00FF88" @click.stop="startTask(task)" /> + @click.stop="stopTask(task)" /> + @click.stop="removeTask(task)" />
手机:{{ task.phoneName }}
@@ -36,44 +38,44 @@
- -
+ +
-
{{ runTask.taskName }}
-
ID: {{ runTask.taskId }}
+
{{ selectedRunTask.taskName }}
+
ID: {{ selectedRunTask.taskId }}
-
手机:{{ runTask.phoneName }}
-
车辆:{{ runTask.vehicleName }}
-
开始时间: {{ formatDate(runTask.startTime) }}
+
手机:{{ selectedRunTask.phoneName }}
+
车辆:{{ selectedRunTask.vehicleName }}
+
开始时间: {{ formatDate(selectedRunTask.startTime) }}
- - {{ taskStatusMap[runTask.status] || '未知状态' }} + + {{ taskStatusMap[selectedRunTask.status] || '未知状态' }}
执行进度
- + :percentage="parseFloat(taskRunningInfo[selectedRunTask.id]?.progress?.toFixed(2)) || 0" /> +
执行日志
- +
+
@@ -191,7 +193,7 @@ import { useContainerHeight } from "@/hooks/tableHeight"; import { getTaskList, getTestCaseByTaskId } from "@/api/intelligenceTest/taskManage"; import { getPhoneList } from "@/api/intelligenceTest/mobilePhone"; import { getVehicleList } from "@/api/intelligenceTest/car"; -import { onMounted, onUnmounted } from "vue"; +import { computed, onMounted, onUnmounted } from "vue"; import { addTaskinstance, getTaskinstanceList, @@ -253,6 +255,21 @@ const phoneList = ref([]); const runTaskList = ref([]); +// 任务实例 ID 在接口和 WebSocket 中可能分别是数字或字符串,统一按字符串比较选中状态。 +const isSelectedTask = (task) => String(task?.id ?? '') === String(selectedTaskId.value) + +// 右侧当前任务始终从完整任务队列中取选中的一条,包括尚未执行、执行中和已暂停任务。 +const selectedRunTask = computed(() => runTaskList.value.find(isSelectedTask) || null) + +/** + * 点击左侧任务卡片时切换右侧详情,并自动回到“当前任务”面板。 + * 卡片内部操作按钮使用 .stop 阻止冒泡,因此执行暂停/启动等命令时不会意外切换选择。 + */ +const selectTask = (task) => { + selectedTaskId.value = task.id + activePanel.value = 'current' +} + const normalizeTaskStatus = (tasks = []) => tasks.map(item => ({ ...item, status: String(item.status), @@ -317,9 +334,11 @@ const cancelTaskDialog = () => { } -const runingTaskList = ref([]) /** - * 获取任务队列 + * 获取任务队列,并维护当前选中任务: + * 1. 首次加载默认选择队列第一条; + * 2. 刷新后原任务仍在队列中则保持选择; + * 3. 原任务已结束或被删除时回退到新的第一条,队列为空时清空选择。 */ const getList = () => { return getTaskinstanceList({ @@ -328,7 +347,9 @@ const getList = () => { if (res.code === 200) { const tasks = normalizeTaskStatus(res.rows) runTaskList.value = tasks; - runingTaskList.value = tasks.filter(item => item.status !== '5') + if (!tasks.some(isSelectedTask)) { + selectedTaskId.value = tasks[0]?.id ?? '' + } for (let i = 0; i < runTaskList.value.length; i++) { getCaseByTaskId(runTaskList.value[i].taskId) getTaskLogList(runTaskList.value[i].id) @@ -684,6 +705,17 @@ onUnmounted(() => { box-shadow: inset 0 0 0 1px #eee; border-radius: 8px; margin-bottom: 16px; + cursor: pointer; + transition: background-color 0.2s ease, box-shadow 0.2s ease; + + &:hover { + background: var(--el-fill-color-light); + } + + &.is-selected { + background: var(--el-color-primary-light-9); + box-shadow: inset 0 0 0 2px var(--el-color-primary); + } .task-content { display: flex; @@ -750,10 +782,6 @@ onUnmounted(() => { border-radius: 20px; margin-bottom: 12px; - &--selected { - box-shadow: inset 0 0 0 2px var(--el-color-primary); - } - .task-header { display: flex; justify-content: space-between;