refactor(schedule): 暂时下线查询日志详情功能(Snail Job 日志详情 API 变更为 WebSocket 模式)

This commit is contained in:
2025-07-27 14:37:49 +08:00
parent f3dea886ad
commit 5050126892
4 changed files with 1 additions and 250 deletions

View File

@@ -24,13 +24,3 @@ export function stopJob(id: number) {
export function retryJob(id: number) {
return http.post(`${BASE_URL}/retry/${id}`)
}
/** @desc 查询任务实例列表 */
export function listJobInstance(query: T.JobInstanceQuery) {
return http.get<T.JobInstanceResp[]>(`${BASE_URL}/instance`, query)
}
/** @desc 查询任务实例日志列表 */
export function listJobInstanceLog(query: T.JobInstanceLogQuery) {
return http.get<T.JobInstanceLogResp>(`${BASE_URL}/instance/log`, query)
}

View File

@@ -50,36 +50,3 @@ export interface JobLogQuery {
datetimeRange?: Array<string>
}
export interface JobLogPageQuery extends JobLogQuery, PageQuery {}
/** 任务实例类型 */
export interface JobInstanceResp {
id: number
groupName: string
jobId: number
taskBatchId: number
taskStatus: number
retryCount: number
resultMessage: string
clientInfo: string
}
export interface JobInstanceQuery {
jobId?: string | number
taskBatchId?: number | string
}
/** 任务实例日志类型 */
export interface JobInstanceLogResp {
id: number
message: any[]
finished: number
fromIndex: number
nextStartId: number
}
export interface JobInstanceLogQuery {
taskBatchId: number
jobId: number
taskId: number
startId: number
fromIndex: number
size: number
}

View File

@@ -1,196 +0,0 @@
<template>
<a-drawer
v-model:visible="visible"
title="任务日志详情"
:width="width >= 1300 ? 1300 : '100%'"
:footer="false"
@close="closed"
>
<div style="display: flex;">
<div style="padding: 10px 10px;">
<div class="job_list">
<div
v-for="item in dataList"
:key="item.id"
:class="`job_list_item ${item.id === activeId ? 'active' : ''}`"
@click="onStartInfo(item)"
>
<div class="content">
<span class="title">{{ item.clientInfo.split('@')[1] }}</span>
<span class="status">
<a-tag bordered :color="statusList[item.taskStatus].color">{{ statusList[item.taskStatus].title }}</a-tag>
</span>
</div>
</div>
</div>
</div>
<div class="code_view">
<GiCodeView :code-json="content" />
</div>
</div>
</a-drawer>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { useWindowSize } from '@vueuse/core'
import { type JobInstanceQuery, type JobInstanceResp, type JobLogResp, listJobInstance, listJobInstanceLog } from '@/apis/schedule'
const { width } = useWindowSize()
const queryForm = reactive<JobInstanceQuery>({})
const dataList = ref<JobInstanceResp[]>([])
const visible = ref(false)
const loading = ref(false)
const activeId = ref<string | number>('')
const statusList = {
1: {
title: '待处理',
color: 'gray',
isRun: false,
},
2: {
title: '运行中',
color: 'cyan',
isRun: true,
},
3: {
title: '成功',
color: 'green',
isRun: false,
},
4: {
title: '已失败',
color: 'red',
isRun: false,
},
5: {
title: '已停止',
color: 'purple',
isRun: false,
},
6: {
title: '已取消',
color: 'orange',
isRun: false,
},
}
// 格式化日志
const formatLog = (log: any) => {
const date = new Date(Number.parseInt(log.time_stamp))
let formatLog = `${dayjs(date).format('YYYY-MM-DD HH:mm:ss')} ${log.level} [${log.thread}] ${log.location} - ${log.message}`
// 增加堆栈信息显示
if (log.throwable) {
formatLog += `\n ${log.throwable}`
}
return formatLog
}
const content = ref('')
const setIntervalNode = ref<NodeJS.Timeout>()
// 日志输出
const onLogDetail = async (record: JobInstanceResp) => {
activeId.value = record?.id
try {
// todo startId根据第一次查询 如果有返回!=0则需要在查一次
const res = await listJobInstanceLog({
taskBatchId: record.taskBatchId,
jobId: record.jobId,
taskId: record.id,
startId: 0,
fromIndex: 0,
size: 50,
})
if (res.data?.finished) {
clearInterval(setIntervalNode.value)
}
content.value = res.data.message.map(formatLog).join('\n')
} catch (error) {
content.value = ''
}
}
const onStartInfo = (record: JobInstanceResp) => {
content.value = ''
clearInterval(setIntervalNode.value)
const isRun = statusList[record.taskStatus].isRun
if (isRun) {
setIntervalNode.value = setInterval(() => {
onLogDetail(record)
}, 1000)
} else {
onLogDetail(record)
}
}
// 查询列表数据
const getInstanceList = async (query: JobInstanceQuery = { ...queryForm }) => {
try {
loading.value = true
const res = await listJobInstance(query)
dataList.value = res.data
onStartInfo(dataList.value[0])
} finally {
loading.value = false
}
}
const closed = () => {
clearInterval(setIntervalNode.value)
}
onUnmounted(() => {
clearInterval(setIntervalNode.value)
})
// 打开
const onOpen = async (record: JobLogResp) => {
// 更新 queryForm
queryForm.jobId = record.jobId
queryForm.taskBatchId = record.id
visible.value = true
await getInstanceList()
}
defineExpose({ onOpen })
</script>
<style scoped lang="scss">
.job_list {
position: relative;
width: 100%;
border: 1px solid var(--color-neutral-3);
.job_list_item {
padding: 8px 10px;
cursor: pointer;
&:not(:last-child) {
border-bottom: 2px dashed var(--color-neutral-3);
}
&:hover {
background-color: var(--color-neutral-2);
}
.content {
display: flex;
justify-content: space-between;
justify-items: center;
.title {
margin-right: 20px;
}
}
}
.active {
border-bottom: 2px solid $color-theme !important;
background-color: var(--color-neutral-3) !important;
}
}
.code_view {
position: relative;
overflow: auto;
}
</style>

View File

@@ -41,7 +41,6 @@
</template>
<template #action="{ record }">
<a-space>
<a-link v-permission="['schedule:log:get']" title="详情" @click="onDetail(record)">详情</a-link>
<a-popconfirm content="是否确定停止本次执行?" type="warning" @ok="onStop(record)">
<a-link v-if="record.taskBatchStatus === 2" v-permission="['schedule:log:stop']" status="danger" title="停止">停止</a-link>
</a-popconfirm>
@@ -58,8 +57,6 @@
</a-space>
</template>
</GiTable>
<LogDetailDrawer ref="LogDetailDrawerRef" />
</GiPageLayout>
</template>
@@ -68,7 +65,6 @@ import type { TableInstance } from '@arco-design/web-vue'
import { Message } from '@arco-design/web-vue'
import { useRoute } from 'vue-router'
import dayjs from 'dayjs'
import LogDetailDrawer from './LogDetailDrawer.vue'
import { type JobLogQuery, type JobLogResp, listGroup, listJobLog, retryJob, stopJob } from '@/apis/schedule'
import { useTable } from '@/hooks'
import { useDict } from '@/hooks/app'
@@ -111,7 +107,7 @@ const columns: TableInstance['columns'] = [
width: 130,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['schedule:log:get', 'schedule:log:stop', 'schedule:log:retry']),
show: has.hasPermOr(['schedule:log:stop', 'schedule:log:retry']),
},
]
@@ -149,12 +145,6 @@ const onRetry = (record: JobLogResp) => {
})
}
const LogDetailDrawerRef = ref<InstanceType<typeof LogDetailDrawer>>()
// 详情
const onDetail = (record: JobLogResp) => {
LogDetailDrawerRef.value?.onOpen(record)
}
const route = useRoute()
onMounted(() => {
if (route.query) {