refactor(Scheduler): 优化任务输出和状态更新逻辑

- 改进输出内容的渲染和滚动逻辑
- 优化任务状态和日志的实时更新
- 调整任务对象的处理方式,使用 reactive 数组替换 ref 数组
- 优化 WebSocket 连接的管理
This commit is contained in:
2025-08-13 16:43:12 +08:00
parent 16ede80fd4
commit 9aeda23ade

View File

@@ -39,7 +39,8 @@
<a-tag :color="getTaskStatusColor(task.status)"> <a-tag :color="getTaskStatusColor(task.status)">
{{ task.status }} {{ task.status }}
</a-tag> </a-tag>
<a-button type="text" size="small" danger @click.stop="stopTask(task.websocketId)" :icon="h(StopOutlined)"> <a-button type="text" size="small" danger @click.stop="stopTask(task.websocketId)"
:icon="h(StopOutlined)">
停止 停止
</a-button> </a-button>
</template> </template>
@@ -51,8 +52,10 @@
清空 清空
</a-button> </a-button>
</div> </div>
<div class="output-content" ref="outputRefs"> <div class="output-content" :ref="el => setOutputRef(el as HTMLElement, task.websocketId)"
<div v-for="(log, index) in task.logs" :key="index" :class="['log-line', `log-${log.type}`]"> :key="`output-${task.websocketId}-${task.logs.length}`">
<div v-for="(log, index) in task.logs" :key="`${task.websocketId}-${index}-${log.time}`"
:class="['log-line', `log-${log.type}`]">
<span class="log-time">{{ log.time }}</span> <span class="log-time">{{ log.time }}</span>
<span class="log-message">{{ log.message }}</span> <span class="log-message">{{ log.message }}</span>
</div> </div>
@@ -93,7 +96,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, h, nextTick } from 'vue' import { ref, reactive, onMounted, onUnmounted, h, nextTick, triggerRef } from 'vue'
import { message, notification } from 'ant-design-vue' import { message, notification } from 'ant-design-vue'
import { import {
PlusOutlined, PlusOutlined,
@@ -110,9 +113,8 @@ const addTaskModalVisible = ref(false)
const messageModalVisible = ref(false) const messageModalVisible = ref(false)
const taskOptionsLoading = ref(false) const taskOptionsLoading = ref(false)
const addTaskLoading = ref(false) const addTaskLoading = ref(false)
const selectedTaskId = ref<string>('')
const activeTaskPanels = ref<string[]>([]) const activeTaskPanels = ref<string[]>([])
const outputRefs = ref<HTMLElement[]>([]) const outputRefs = ref<Map<string, HTMLElement>>(new Map())
// 任务选项 // 任务选项
const taskOptions = ref<ComboBoxItem[]>([]) const taskOptions = ref<ComboBoxItem[]>([])
@@ -146,7 +148,7 @@ interface RunningTask {
}> }>
} }
const runningTasks = ref<RunningTask[]>([]) const runningTasks = reactive<RunningTask[]>([])
// 消息处理 // 消息处理
interface TaskMessage { interface TaskMessage {
@@ -160,6 +162,15 @@ interface TaskMessage {
const currentMessage = ref<TaskMessage | null>(null) const currentMessage = ref<TaskMessage | null>(null)
const messageResponse = ref('') const messageResponse = ref('')
// 设置输出容器引用
const setOutputRef = (el: HTMLElement | null, websocketId: string) => {
if (el) {
outputRefs.value.set(websocketId, el)
} else {
outputRefs.value.delete(websocketId)
}
}
// 获取任务选项 // 获取任务选项
const loadTaskOptions = async () => { const loadTaskOptions = async () => {
try { try {
@@ -260,7 +271,7 @@ const startCreatedTask = () => {
} }
// 添加到运行任务列表 // 添加到运行任务列表
runningTasks.value.push(task) runningTasks.push(task)
activeTaskPanels.value.push(task.websocketId) activeTaskPanels.value.push(task.websocketId)
// 连接WebSocket // 连接WebSocket
@@ -379,20 +390,27 @@ const addTaskLog = (task: RunningTask, message: string, type: 'info' | 'error' |
const now = new Date() const now = new Date()
const time = now.toLocaleTimeString() const time = now.toLocaleTimeString()
task.logs.push({ // 找到任务在数组中的索引
time, const taskIndex = runningTasks.findIndex(t => t.websocketId === task.websocketId)
message, if (taskIndex >= 0) {
type // 直接修改 reactive 数组中的任务对象
}) runningTasks[taskIndex].logs.push({
time,
message,
type
})
// 更新任务状态(如果有变化)
if (runningTasks[taskIndex].status !== task.status) {
runningTasks[taskIndex].status = task.status
}
}
// 自动滚动到底部 // 自动滚动到底部
nextTick(() => { nextTick(() => {
const outputElements = outputRefs.value const outputElement = outputRefs.value.get(task.websocketId)
if (outputElements && outputElements.length > 0) { if (outputElement) {
const taskIndex = runningTasks.value.findIndex(t => t.websocketId === task.websocketId) outputElement.scrollTop = outputElement.scrollHeight
if (taskIndex >= 0 && outputElements[taskIndex]) {
outputElements[taskIndex].scrollTop = outputElements[taskIndex].scrollHeight
}
} }
}) })
} }
@@ -403,7 +421,7 @@ const sendMessageResponse = () => {
return return
} }
const task = runningTasks.value.find(t => t.websocketId === currentMessage.value?.taskId) const task = runningTasks.find(t => t.websocketId === currentMessage.value?.taskId)
if (task && task.websocket) { if (task && task.websocket) {
const response = { const response = {
type: 'MessageResponse', type: 'MessageResponse',
@@ -429,9 +447,9 @@ const cancelMessage = () => {
// 停止任务 // 停止任务
const stopTask = (taskId: string) => { const stopTask = (taskId: string) => {
const taskIndex = runningTasks.value.findIndex(t => t.websocketId === taskId) const taskIndex = runningTasks.findIndex(t => t.websocketId === taskId)
if (taskIndex >= 0) { if (taskIndex >= 0) {
const task = runningTasks.value[taskIndex] const task = runningTasks[taskIndex]
// 关闭WebSocket连接 // 关闭WebSocket连接
if (task.websocket) { if (task.websocket) {
@@ -440,7 +458,7 @@ const stopTask = (taskId: string) => {
} }
// 从列表中移除 // 从列表中移除
runningTasks.value.splice(taskIndex, 1) runningTasks.splice(taskIndex, 1)
// 从展开面板中移除 // 从展开面板中移除
const panelIndex = activeTaskPanels.value.indexOf(taskId) const panelIndex = activeTaskPanels.value.indexOf(taskId)
@@ -454,7 +472,7 @@ const stopTask = (taskId: string) => {
// 清空任务输出 // 清空任务输出
const clearTaskOutput = (taskId: string) => { const clearTaskOutput = (taskId: string) => {
const task = runningTasks.value.find(t => t.websocketId === taskId) const task = runningTasks.find(t => t.websocketId === taskId)
if (task) { if (task) {
task.logs = [] task.logs = []
} }
@@ -486,7 +504,7 @@ onMounted(() => {
// 组件卸载时清理WebSocket连接 // 组件卸载时清理WebSocket连接
onUnmounted(() => { onUnmounted(() => {
runningTasks.value.forEach(task => { runningTasks.forEach(task => {
if (task.websocket) { if (task.websocket) {
task.websocket.close() task.websocket.close()
} }