From 082abbb60ac86dadc78426f9ff365c3e1a552ef2 Mon Sep 17 00:00:00 2001 From: yuhawu <15545526+yuhawu@user.noreply.gitee.com> Date: Tue, 22 Jul 2025 10:00:01 +0800 Subject: [PATCH] task --- src/api/modules/task.js | 12 + src/views/Task/List.vue | 387 +++++++++++++++++++++++++++++---- src/views/Tools/Cards/List.vue | 7 +- src/views/User/Edit.vue | 9 - 4 files changed, 359 insertions(+), 56 deletions(-) delete mode 100644 src/views/User/Edit.vue diff --git a/src/api/modules/task.js b/src/api/modules/task.js index 0fdd0f1..9d9d9b2 100644 --- a/src/api/modules/task.js +++ b/src/api/modules/task.js @@ -8,6 +8,18 @@ const taskApi = { // 停止指定任务 stopTask: (taskId) => instance.get(`/task/stopTask?taskId=${taskId}`), + + // 获取任务日志列表 + getLogsList: (id) => instance.get(`/task/logsList?id=${id}`), + + // 获取任务日志消息 + getLogsMsg: (id) => instance.get(`/task/logsMsg?id=${id}`), + + // 获取任务详细日志列表 + getLogsDetailList: (taskId, shopId) => instance.get(`/task/logsDetailList/${taskId}/${shopId}`), + + // 下载日志文件 + downloadLogs: (fileName) => instance.get(`/task/downloadLogs/${fileName}`, { responseType: 'blob' }), }; // 导出模块 diff --git a/src/views/Task/List.vue b/src/views/Task/List.vue index e8eecc8..dbca112 100644 --- a/src/views/Task/List.vue +++ b/src/views/Task/List.vue @@ -13,15 +13,8 @@
暂无运行中的任务
- + @@ -34,35 +27,39 @@ - + - +
- +
- + {{ currentTask.id }} @@ -71,16 +68,76 @@ {{ currentTask.dataNum }} {{ currentTask.createTime }} - +
{{ currentTask.msg }}
+ + + +
+ +
+
+
加载中...
+
+
+ {{ line }} +
+
+
+
+ + 刷新 + +
+
+ + +
+ + + + + + + + + + + + +
+
+ + +
@@ -88,6 +145,7 @@ import { ref, onMounted } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { taskApi } from '@/api/modules/task' +import { Document, VideoPause, View, Download, Refresh } from '@element-plus/icons-vue' // 任务列表数据 const taskList = ref([]) @@ -101,16 +159,23 @@ const total = ref(0) const currentPage = ref(1) // 界面显示的当前页,从1开始 const pageSize = ref(10) // 每页条数 +// 日志相关数据 +const logsVisible = ref(false) +const logsLoading = ref(false) +const logsList = ref([]) +const logsMessage = ref('') +const currentTaskId = ref('') + // 获取任务列表 const fetchTaskList = async () => { loading.value = true try { // 将currentPage转换为后端需要的pageSize(0表示第一页) const pageIndex = currentPage.value - 1 - + const res = await taskApi.getRunningTasks(pageIndex, pageSize.value) console.log('API响应数据:', res) - + if (res.code === 200) { // 适应后端返回的数据结构 if (res.data) { @@ -175,7 +240,7 @@ const refreshTasks = () => { // 停止任务 const handleStopTask = async (taskId) => { - console.log("taskId",taskId) + console.log("taskId", taskId) try { await ElMessageBox.confirm( `确定要停止任务吗?`, @@ -186,10 +251,10 @@ const handleStopTask = async (taskId) => { type: 'warning', } ) - + stoppingTasks.value.push(taskId) const res = await taskApi.stopTask(taskId) - + if (res.code === 200) { ElMessage.success('任务已成功停止') // 停止成功后刷新列表 @@ -239,27 +304,151 @@ const showTaskDetail = (task) => { // 计算进度 const calculateProgress = (task) => { if (!task || !task.msg) return 0 - + try { // 尝试从消息中提取进度信息 const totalMatch = task.msg.match(/总执行数据:(\d+)条/) const executedMatch = task.msg.match(/已执行条数:(\d+)条/) - + if (totalMatch && executedMatch) { const total = parseInt(totalMatch[1]) const executed = parseInt(executedMatch[1]) - + if (total > 0) { return Math.floor((executed / total) * 100) } } - + return 0 } catch (e) { return 0 } } +// 查看日志 +const handleViewLogs = async (taskId) => { + currentTaskId.value = taskId + logsVisible.value = true + await fetchLogs() +} + +// 获取日志数据 +const fetchLogs = async () => { + logsLoading.value = true + try { + // 并行调用两个接口 + const [logsListRes, logsMsgRes] = await Promise.all([ + taskApi.getLogsList(currentTaskId.value), + taskApi.getLogsMsg(currentTaskId.value) + ]) + + console.log('日志列表响应:', logsListRes) + console.log('日志消息响应:', logsMsgRes) + + // 处理日志列表数据 + if (logsListRes.code === 200) { + if (Array.isArray(logsListRes.data)) { + logsList.value = logsListRes.data + } else if (logsListRes.data && Array.isArray(logsListRes.data.data)) { + logsList.value = logsListRes.data.data + } else { + logsList.value = [] + } + } else { + logsList.value = [] + ElMessage.error('获取日志列表失败: ' + (logsListRes.message || '未知错误')) + } + + // 处理日志消息数据 + if (logsMsgRes.code === 200) { + // 如果返回的是字符串,直接使用 + if (typeof logsMsgRes.data === 'string') { + logsMessage.value = logsMsgRes.data + } + // 如果返回的是对象,尝试获取消息字段 + else if (logsMsgRes.data && typeof logsMsgRes.data === 'object') { + logsMessage.value = logsMsgRes.data.message || logsMsgRes.data.msg || JSON.stringify(logsMsgRes.data) + } else { + logsMessage.value = '暂无日志消息' + } + } else { + logsMessage.value = '获取日志消息失败' + ElMessage.error('获取日志消息失败: ' + (logsMsgRes.message || '未知错误')) + } + + } catch (error) { + console.error('获取日志数据出错:', error) + ElMessage.error('获取日志数据失败: ' + (error.message || '未知错误')) + logsList.value = [] + logsMessage.value = '获取日志数据失败' + } finally { + logsLoading.value = false + } +} + +// 刷新日志 +const refreshLogs = () => { + fetchLogs() +} + +// 查看详细日志 +const handleViewDetail = async (row) => { + try { + const res = await taskApi.getLogsDetailList(row.taskId, row.shopId) + console.log('详细日志响应:', res) + + if (res.code === 200) { + // 这里可以打开一个新的弹窗显示详细日志,或者跳转到详细页面 + ElMessage.success('查看详细日志功能待实现') + } else { + ElMessage.error('获取详细日志失败: ' + (res.message || '未知错误')) + } + } catch (error) { + console.error('获取详细日志出错:', error) + ElMessage.error('获取详细日志失败: ' + (error.message || '未知错误')) + } +} + +// 下载日志 +const handleDownload = async (row) => { + try { + // 构建文件名,根据后端逻辑应该是 taskId + shopId + ".txt" + const fileName = `${row.taskId}${row.shopId}.txt` + + const response = await taskApi.downloadLogs(fileName) + + // 创建下载链接 + const blob = new Blob([response.data]) + const url = window.URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = fileName + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + window.URL.revokeObjectURL(url) + + ElMessage.success('文件下载成功') + } catch (error) { + console.error('下载日志文件出错:', error) + ElMessage.error('下载日志文件失败: ' + (error.message || '未知错误')) + } +} + +// 格式化日志消息 +const formatLogMessage = (message) => { + if (!message) return ['暂无日志消息'] + + // 将日志消息按行分割,处理各种可能的换行符 + const lines = message.split(/\r?\n|\r/).filter(line => line.trim() !== '') + + if (lines.length === 0) { + return ['暂无日志消息'] + } + + return lines +} + // 组件挂载时获取任务列表 onMounted(() => { fetchTaskList() @@ -270,18 +459,22 @@ onMounted(() => { .task-list-container { padding: 20px; } + .card-header { display: flex; justify-content: space-between; align-items: center; } -.empty-content, .loading-content { + +.empty-content, +.loading-content { min-height: 300px; display: flex; justify-content: center; align-items: center; color: #909399; } + .task-msg { white-space: pre-line; max-height: 150px; @@ -290,6 +483,7 @@ onMounted(() => { background-color: #f8f8f8; border-radius: 4px; } + .pagination-container { margin-top: 15px; background-color: #fff; @@ -300,6 +494,21 @@ onMounted(() => { justify-content: flex-end; } +.operation-buttons { + display: flex; + justify-content: center; + gap: 10px; +} + +.operation-buttons .el-button { + margin: 0; + transition: transform 0.2s; +} + +.operation-buttons .el-button:hover { + transform: scale(1.1); +} + /* 表格样式 */ :deep(.el-table) { border-radius: 4px; @@ -341,4 +550,92 @@ onMounted(() => { padding: 8px; height: 50px; } - \ No newline at end of file + +/* 日志弹窗样式 */ +.logs-container { + display: flex; + flex-direction: column; + gap: 20px; +} + +.logs-message-section { + background-color: #f5f7fa; + border-radius: 8px; + padding: 16px; + position: relative; +} + +.logs-message-content { + margin-bottom: 10px; +} + +.logs-text { + color: #606266; + line-height: 1.6; + white-space: pre-line; + font-size: 14px; + min-height: 120px; + padding: 12px; + background-color: #fff; + border-radius: 4px; + border: 1px solid #e4e7ed; +} + +.log-line { + margin-bottom: 4px; + color: #606266; + font-size: 14px; +} + +.loading-text { + color: #909399; + text-align: center; + padding: 40px; + font-size: 14px; +} + +.refresh-btn-container { + display: flex; + justify-content: flex-end; +} + +.logs-table-section { + margin-top: 10px; +} + +/* 日志弹窗表格样式 */ +.logs-table-section :deep(.el-table) { + border-radius: 8px; +} + +.logs-table-section :deep(.el-table th) { + background-color: #f5f7fa !important; + color: #606266; + font-weight: 500; +} + +.logs-table-section :deep(.el-button) { + margin-right: 4px; +} + +.logs-table-section :deep(.el-button:last-child) { + margin-right: 0; +} + +/* 弹窗底部样式 */ +.dialog-footer { + text-align: right; +} + +/* 日志弹窗标题样式 */ +:deep(.el-dialog__header) { + padding: 20px 20px 10px; + border-bottom: 1px solid #e4e7ed; +} + +:deep(.el-dialog__title) { + font-size: 18px; + font-weight: 500; + color: #303133; +} + \ No newline at end of file diff --git a/src/views/Tools/Cards/List.vue b/src/views/Tools/Cards/List.vue index cdddda7..5af6b9e 100644 --- a/src/views/Tools/Cards/List.vue +++ b/src/views/Tools/Cards/List.vue @@ -368,7 +368,7 @@ const submitCardSecretRequest = async () => { }; const res = await cardsApi.createCardSecret(cardData) // 由于createCardSecret方法已经处理了响应,所以直接使用res - console.log("res",res) + console.log("res",res) if (res.code === 200) { cardSecretValue.value = res.data @@ -380,7 +380,10 @@ const submitCardSecretRequest = async () => { } } catch (error) { console.error('获取卡密失败:', error) - ElMessage.error('获取卡密失败: ' + (error.message || '未知错误')) + // if(error.status === 400){ + // ElMessage.error('获取卡密失败: ' + (error.message || '未知错误')) + // } + ElMessage.error('获取卡密失败: ' + (error.response.data.message || '未知错误')) } } diff --git a/src/views/User/Edit.vue b/src/views/User/Edit.vue deleted file mode 100644 index 263a3d7..0000000 --- a/src/views/User/Edit.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file