feat: 任务批次新增日志详情
This commit is contained in:
parent
790e4a71be
commit
713c643544
101
src/components/common/detail-drawer.vue
Normal file
101
src/components/common/detail-drawer.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onUnmounted, reactive, ref } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
|
||||
defineOptions({
|
||||
name: 'DetailDrawer'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
width?: [string, string];
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', modelValue: boolean): void;
|
||||
}
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<boolean>({ default: false });
|
||||
|
||||
const slots = defineSlots();
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
const state = reactive({ width: 0 });
|
||||
const isFullscreen = ref(false);
|
||||
const drawerWidth = computed(() => {
|
||||
if (props.width) {
|
||||
return isFullscreen.value ? props.width[1] : props.width[0];
|
||||
}
|
||||
const maxMinWidth = 360;
|
||||
const maxMaxWidth = 600;
|
||||
if (appStore.isMobile) {
|
||||
return state.width * 0.9 >= maxMinWidth ? `${maxMinWidth}px` : '90%';
|
||||
}
|
||||
let minWidth = state.width * 0.3 >= maxMinWidth ? `${maxMinWidth}px` : '30%';
|
||||
minWidth = state.width <= 420 ? '90%' : minWidth;
|
||||
let maxWidth = state.width * 0.5 >= maxMaxWidth ? `${maxMaxWidth}px` : '50%';
|
||||
maxWidth = state.width <= 420 ? '90%' : maxWidth;
|
||||
return isFullscreen.value ? maxWidth : minWidth;
|
||||
});
|
||||
|
||||
const getState = () => {
|
||||
state.width = document.documentElement.clientWidth;
|
||||
};
|
||||
|
||||
nextTick(() => {
|
||||
getState();
|
||||
window.addEventListener('resize', getState);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 移除监听事件
|
||||
window.removeEventListener('resize', getState);
|
||||
});
|
||||
|
||||
const onUpdateShow = (value: boolean) => {
|
||||
emit('update:modelValue', value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="model" display-directive="if" :width="drawerWidth" @update:show="onUpdateShow">
|
||||
<NDrawerContent :title="props.title" :native-scrollbar="false" closable header-class="operate-dawer-header">
|
||||
<template #header>
|
||||
{{ props.title }}
|
||||
<div
|
||||
v-if="!appStore.isMobile && (!props.width || (props.width && props.width[0] !== props.width[1]))"
|
||||
quaternary
|
||||
class="fullscreen text-18px color-#6a6a6a"
|
||||
@click="isFullscreen = !isFullscreen"
|
||||
>
|
||||
<icon-material-symbols:close-fullscreen-rounded v-if="isFullscreen" />
|
||||
<icon-material-symbols:open-in-full-rounded v-else />
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<template v-if="slots.footer" #footer>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
</NDrawerContent>
|
||||
</NDrawer>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.fullscreen {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fullscreen:hover {
|
||||
background-color: #e8e8e8;
|
||||
color: #696969;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,7 @@
|
||||
<script setup lang="tsx">
|
||||
import { NCollapse, NCollapseItem } from 'naive-ui';
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
name: 'LogDrawer'
|
||||
@ -9,11 +10,13 @@ defineOptions({
|
||||
interface Props {
|
||||
title?: string;
|
||||
show?: boolean;
|
||||
modelValue?: Api.JobLog.JobMessage[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: '日志详情',
|
||||
show: false
|
||||
title: $t('page.log.title'),
|
||||
show: false,
|
||||
modelValue: () => []
|
||||
});
|
||||
|
||||
interface Emits {
|
||||
@ -25,38 +28,6 @@ const visible = defineModel<boolean>('visible', {
|
||||
default: true
|
||||
});
|
||||
|
||||
const messageList = ref([
|
||||
{
|
||||
time_stamp: '1712021845601',
|
||||
level: 'ERROR',
|
||||
port: '8018',
|
||||
throwable:
|
||||
'java.lang.ArithmeticException: / by zero\n\tat com.example.easy.retry.service.impl.RemoteRetryServiceImpl.remoteSync(RemoteRetryServiceImpl.java:46)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:568)\n\tat org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n\tat org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)\n\tat com.aizuda.easy.retry.client.core.intercepter.EasyRetryInterceptor.invoke(EasyRetryInterceptor.java:92)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)\n\tat org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)\n\tat com.example.easy.retry.service.impl.RemoteRetryServiceImpl$$SpringCGLIB$$0.remoteSync(<generated>)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:568)\n\tat org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:281)\n\tat com.aizuda.easy.retry.client.core.strategy.ExecutorAnnotationMethod.doExecute(ExecutorAnnotationMethod.java:28)\n\tat com.aizuda.easy.retry.client.core.executor.AbstractRetryExecutor.doExecute(AbstractRetryExecutor.java:32)\n\tat com.aizuda.easy.retry.client.core.executor.AbstractRetryExecutor.execute(AbstractRetryExecutor.java:23)\n\tat com.aizuda.easy.retry.client.core.strategy.RemoteRetryStrategies.lambda$doGetCallable$2(RemoteRetryStrategies.java:89)\n\tat com.github.rholder.retry.AttemptTimeLimiters$NoAttemptTimeLimit.call(AttemptTimeLimiters.java:78)\n\tat com.github.rholder.retry.Retryer.call(Retryer.java:160)\n\tat com.aizuda.easy.retry.client.core.executor.GuavaRetryExecutor.call(GuavaRetryExecutor.java:56)\n\tat com.aizuda.easy.retry.client.core.strategy.AbstractRetryStrategies.openRetry(AbstractRetryStrategies.java:88)\n\tat com.aizuda.easy.retry.client.core.client.RetryEndPoint.dispatch(RetryEndPoint.java:99)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)',
|
||||
host: '127.0.0.1',
|
||||
location: 'com.aizuda.easy.retry.client.core.client.RetryEndPoint.dispatch(RetryEndPoint.java:124)',
|
||||
thread: 'http-nio-8018-exec-5',
|
||||
message: 'remote retry complete. count:[1] '
|
||||
},
|
||||
{
|
||||
time_stamp: '1712021875512',
|
||||
level: 'INFO',
|
||||
port: '8018',
|
||||
host: '127.0.0.1',
|
||||
location: 'com.aizuda.easy.retry.client.core.client.RetryEndPoint.dispatch(RetryEndPoint.java:117)',
|
||||
thread: 'http-nio-8018-exec-2',
|
||||
message: 'remote retry complete. count:[4] result:[null]'
|
||||
},
|
||||
{
|
||||
time_stamp: '1712021875512',
|
||||
level: 'ERROR',
|
||||
port: '8018',
|
||||
host: '127.0.0.1',
|
||||
location: 'com.aizuda.easy.retry.client.core.client.RetryEndPoint.dispatch(RetryEndPoint.java:124)',
|
||||
thread: 'http-nio-8018-exec-2',
|
||||
message: 'remote retry complete. count:[4] '
|
||||
}
|
||||
]);
|
||||
|
||||
const ThrowableComponent = defineComponent({
|
||||
props: {
|
||||
throwable: String
|
||||
@ -109,12 +80,12 @@ function timestampToDate(timestamp: string): string {
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="visible" width="100%" display-directive="if" @update:show="onUpdateShow">
|
||||
<NDrawerContent title="日志详情" closable>
|
||||
<NDrawerContent :title="title" closable>
|
||||
<div class="snail-log">
|
||||
<div class="snail-log-scrollbar">
|
||||
<code>
|
||||
<pre
|
||||
v-for="(message, index) in messageList"
|
||||
v-for="(message, index) in modelValue"
|
||||
:key="index"
|
||||
><NDivider v-if="index !== 0" /><span class="log-hljs-time">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`">{{`\t${message.level}\t`}}</span><span class="log-hljs-thread">{{`[${message.thread}]\t`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}\n`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
|
||||
</code>
|
||||
|
@ -976,7 +976,17 @@ const local: App.I18n.Schema = {
|
||||
jobName: 'Please enter job name',
|
||||
taskBatchStatus: 'Please enter state'
|
||||
},
|
||||
detail: 'Job Batch Detail'
|
||||
detail: 'Job Batch Detail',
|
||||
jobTask: {
|
||||
title: 'JobTask 列表',
|
||||
id: 'ID',
|
||||
groupName: '组名称',
|
||||
clientInfo: '地址',
|
||||
argsStr: '参数',
|
||||
resultMessage: '结果',
|
||||
retryCount: '重试次数',
|
||||
createDt: '开始执行时间'
|
||||
}
|
||||
},
|
||||
userManager: {
|
||||
title: 'UserCenter List',
|
||||
@ -1001,6 +1011,11 @@ const local: App.I18n.Schema = {
|
||||
user: 'User',
|
||||
admin: 'Admin'
|
||||
}
|
||||
},
|
||||
log: {
|
||||
title: 'Log Detail',
|
||||
view: 'View Log',
|
||||
info: 'Info'
|
||||
}
|
||||
},
|
||||
form: {
|
||||
|
@ -971,7 +971,17 @@ const local: App.I18n.Schema = {
|
||||
jobName: '请输入任务名称',
|
||||
taskBatchStatus: '请输入状态'
|
||||
},
|
||||
detail: '执行批次详情'
|
||||
detail: '执行批次详情',
|
||||
jobTask: {
|
||||
title: 'JobTask 列表',
|
||||
id: 'ID',
|
||||
groupName: '组名称',
|
||||
clientInfo: '地址',
|
||||
argsStr: '参数',
|
||||
resultMessage: '结果',
|
||||
retryCount: '重试次数',
|
||||
createDt: '开始执行时间'
|
||||
}
|
||||
},
|
||||
userManager: {
|
||||
title: '用户列表',
|
||||
@ -996,6 +1006,11 @@ const local: App.I18n.Schema = {
|
||||
user: '普通用户',
|
||||
admin: '管理员'
|
||||
}
|
||||
},
|
||||
log: {
|
||||
title: '日志详情',
|
||||
view: '查看日志',
|
||||
info: '基本信息'
|
||||
}
|
||||
},
|
||||
form: {
|
||||
|
@ -18,6 +18,15 @@ export function fetchGetJobList(params?: Api.Job.JobSearchParams) {
|
||||
});
|
||||
}
|
||||
|
||||
/** get Job Task list */
|
||||
export function fetchGetJobTaskList(params?: Api.Job.jobTaskSearchParams) {
|
||||
return request<Api.Job.JobTaskList>({
|
||||
url: '/job/task/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/** add Job */
|
||||
export function fetchAddJob(data: Api.Job.Job) {
|
||||
return request<boolean>({
|
||||
|
19
src/service/api/log.ts
Normal file
19
src/service/api/log.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/** get Job Log List */
|
||||
export function fetchJobLogList(params?: Api.JobLog.JobLogSearchParams) {
|
||||
return request<Api.JobLog.JobLogList>({
|
||||
url: '/job/log/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/** get Retry Log List */
|
||||
export function fetchRetryLogList(params?: Api.JobLog.JobLogSearchParams) {
|
||||
return request<Api.JobLog.JobLogList>({
|
||||
url: '/retry-task-log/message/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
64
src/typings/api.d.ts
vendored
64
src/typings/api.d.ts
vendored
@ -986,6 +986,36 @@ declare namespace Api {
|
||||
jobId?: number;
|
||||
keywords?: string;
|
||||
}>;
|
||||
|
||||
/** jobTask */
|
||||
type JobTask = Common.CommonRecord<{
|
||||
/** ID */
|
||||
id: string;
|
||||
/** 任务 ID */
|
||||
jobId: string;
|
||||
/** 组名称 */
|
||||
groupName: string;
|
||||
/** 地址 */
|
||||
clientInfo: string;
|
||||
/** 参数 */
|
||||
argsStr: string;
|
||||
/** 结果 */
|
||||
resultMessage: string;
|
||||
/** 重试次数 */
|
||||
retryCount: string;
|
||||
/** 开始执行时间 */
|
||||
createDt: string;
|
||||
/** 任务批次 ID */
|
||||
taskBatchId: string;
|
||||
}>;
|
||||
|
||||
/** jobTask search params */
|
||||
type jobTaskSearchParams = CommonType.RecordNullable<
|
||||
Pick<Api.Job.JobTask, 'groupName' | 'taskBatchId'> & CommonSearchParams & { startId: number; fromIndex: number }
|
||||
>;
|
||||
|
||||
/** jobTask list */
|
||||
type JobTaskList = Common.PaginatingQueryRecord<JobTask>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1159,4 +1189,38 @@ declare namespace Api {
|
||||
/** 1、user 2、admin */
|
||||
type Role = 1 | 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* namespace JobLog
|
||||
*
|
||||
* backend api module: "JobLog"
|
||||
*/
|
||||
namespace JobLog {
|
||||
type JobLevel = 'INFO' | 'WARN' | 'ERROR' | 'DEBUG';
|
||||
|
||||
type JobLogSearchParams = {
|
||||
taskBatchId: string;
|
||||
jobId: string;
|
||||
taskId: string;
|
||||
startId: string;
|
||||
fromIndex: number;
|
||||
size: number;
|
||||
};
|
||||
|
||||
type JobLogList = {
|
||||
finished: boolean;
|
||||
fromIndex: number;
|
||||
message: JobMessage[];
|
||||
nextStartId: string;
|
||||
};
|
||||
|
||||
type JobMessage = {
|
||||
level: JobLevel;
|
||||
location: string;
|
||||
message: string;
|
||||
thread: string;
|
||||
['time_stamp']: string;
|
||||
throwable: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
15
src/typings/app.d.ts
vendored
15
src/typings/app.d.ts
vendored
@ -1119,6 +1119,16 @@ declare namespace App {
|
||||
taskBatchStatus: string;
|
||||
};
|
||||
detail: string;
|
||||
jobTask: {
|
||||
title: string;
|
||||
id: string;
|
||||
groupName: string;
|
||||
clientInfo: string;
|
||||
argsStr: string;
|
||||
resultMessage: string;
|
||||
retryCount: string;
|
||||
createDt: string;
|
||||
};
|
||||
};
|
||||
userManager: {
|
||||
title: string;
|
||||
@ -1144,6 +1154,11 @@ declare namespace App {
|
||||
admin: string;
|
||||
};
|
||||
};
|
||||
log: {
|
||||
title: string;
|
||||
view: string;
|
||||
info: string;
|
||||
};
|
||||
};
|
||||
form: {
|
||||
required: string;
|
||||
|
@ -151,7 +151,7 @@ watch(
|
||||
class="sm:h-full"
|
||||
/>
|
||||
</NCard>
|
||||
<JobBatchDetailDrawer v-model:visible="detailVisible" :row-data="detailData" />
|
||||
<JobBatchDetailDrawer v-if="detailVisible" v-model:visible="detailVisible" :row-data="detailData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { watch } from 'vue';
|
||||
<script setup lang="tsx">
|
||||
import { NButton } from 'naive-ui';
|
||||
import { onBeforeUnmount, ref } from 'vue';
|
||||
import { executorTypeRecord, operationReasonRecord, taskBatchStatusRecord } from '@/constants/business';
|
||||
import { $t } from '@/locales';
|
||||
// import { fetchGetJobBatchDetail } from '@/service/api';
|
||||
import { tagColor } from '@/utils/common';
|
||||
import { useTable } from '@/hooks/common/table';
|
||||
import { fetchGetJobTaskList } from '@/service/api';
|
||||
import { fetchJobLogList } from '@/service/api/log';
|
||||
|
||||
defineOptions({
|
||||
name: 'JobBatchDetailDrawer'
|
||||
@ -13,50 +17,187 @@ interface Props {
|
||||
/** row data */
|
||||
rowData?: Api.JobBatch.JobBatch | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const taskData = ref<Api.Job.JobTask>();
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
const logShow = defineModel<boolean>('logShow', {
|
||||
default: false
|
||||
});
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
async val => {
|
||||
if (val === true) {
|
||||
console.log(props.rowData?.id);
|
||||
}
|
||||
const { columns, data, loading, mobilePagination } = useTable({
|
||||
apiFn: fetchGetJobTaskList,
|
||||
apiParams: {
|
||||
page: 1,
|
||||
size: 10,
|
||||
groupName: props.rowData?.groupName,
|
||||
taskBatchId: props.rowData?.id,
|
||||
startId: 0,
|
||||
fromIndex: 0
|
||||
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
|
||||
// the value can not be undefined, otherwise the property in Form will not be reactive
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
columns: () => [
|
||||
{
|
||||
key: 'index',
|
||||
title: $t('common.index'),
|
||||
align: 'center',
|
||||
width: 64,
|
||||
render: row => {
|
||||
async function openLog() {
|
||||
logShow.value = true;
|
||||
taskData.value = row;
|
||||
await getLogList();
|
||||
}
|
||||
return (
|
||||
<NButton type="info" text onClick={openLog}>
|
||||
<span class="w-28px ws-break-spaces">{$t('page.log.view')}</span>
|
||||
</NButton>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: $t('page.jobBatch.jobTask.id'),
|
||||
align: 'left',
|
||||
minWidth: 64
|
||||
},
|
||||
{
|
||||
key: 'groupName',
|
||||
title: $t('page.jobBatch.jobTask.groupName'),
|
||||
align: 'left',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'clientInfo',
|
||||
title: $t('page.jobBatch.jobTask.clientInfo'),
|
||||
align: 'left',
|
||||
minWidth: 120,
|
||||
render: row => {
|
||||
if (row.clientInfo) {
|
||||
const parts = row.clientInfo?.split('@');
|
||||
const result = parts.length > 1 ? parts[1] : '';
|
||||
return <div>{result}</div>;
|
||||
}
|
||||
return <div>{row.clientInfo}</div>;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'argsStr',
|
||||
title: $t('page.jobBatch.jobTask.argsStr'),
|
||||
align: 'left',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'resultMessage',
|
||||
title: $t('page.jobBatch.jobTask.resultMessage'),
|
||||
align: 'left',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
key: 'retryCount',
|
||||
title: $t('page.jobBatch.jobTask.retryCount'),
|
||||
align: 'left',
|
||||
minWidth: 64
|
||||
},
|
||||
{
|
||||
key: 'createDt',
|
||||
title: $t('page.jobBatch.jobTask.createDt'),
|
||||
align: 'left',
|
||||
minWidth: 120
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const logList = ref<Api.JobLog.JobMessage[]>([]);
|
||||
const interval = ref<NodeJS.Timeout>();
|
||||
const controller = new AbortController();
|
||||
const finished = ref<boolean>(false);
|
||||
let startId = '0';
|
||||
let fromIndex: number = 0;
|
||||
|
||||
async function getLogList() {
|
||||
const { data: logData, error } = await fetchJobLogList({
|
||||
taskBatchId: taskData.value!.taskBatchId,
|
||||
jobId: taskData.value!.jobId,
|
||||
taskId: taskData.value!.id,
|
||||
startId,
|
||||
fromIndex,
|
||||
size: 50
|
||||
});
|
||||
if (!error) {
|
||||
finished.value = logData.finished;
|
||||
startId = logData.nextStartId;
|
||||
fromIndex = logData.fromIndex;
|
||||
if (logData.message) {
|
||||
logList.value.push(...logData.message);
|
||||
logList.value.sort((a, b) => Number.parseInt(a.time_stamp, 10) - Number.parseInt(b.time_stamp, 10));
|
||||
}
|
||||
if (!finished.value) {
|
||||
clearTimeout(interval.value);
|
||||
interval.value = setTimeout(getLogList, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const stopLog = () => {
|
||||
finished.value = true;
|
||||
controller.abort();
|
||||
clearTimeout(interval.value);
|
||||
interval.value = undefined;
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopLog();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OperateDrawer v-model="visible" :title="$t('page.jobBatch.detail')">
|
||||
<NDescriptions label-placement="top" bordered :column="2">
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.groupName')">{{ rowData?.groupName }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.jobName')">{{ rowData?.jobName }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.taskBatchStatus')">
|
||||
<NTag :type="tagColor(rowData?.taskBatchStatus!)">
|
||||
{{ $t(taskBatchStatusRecord[rowData?.taskBatchStatus!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executionAt')">{{ rowData?.executionAt }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.operationReason')">
|
||||
<NTag :type="tagColor(rowData?.operationReason!)">
|
||||
{{ $t(operationReasonRecord[rowData?.operationReason!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executorType')">
|
||||
<NTag :type="tagColor(rowData?.executorType!)">
|
||||
{{ $t(executorTypeRecord[rowData?.executorType!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executorInfo')" :span="2">
|
||||
{{ rowData?.executorInfo }}
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('common.createDt')" :span="2">{{ rowData?.createDt }}</NDescriptionsItem>
|
||||
</NDescriptions>
|
||||
</OperateDrawer>
|
||||
<DetailDrawer v-model="visible" :title="$t('page.jobBatch.detail')" :width="['50%', '90%']">
|
||||
<NTabs type="segment" animated>
|
||||
<NTabPane :name="0" :tab="$t('page.log.info')">
|
||||
<NDescriptions label-placement="top" bordered :column="2">
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.groupName')">{{ rowData?.groupName }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.jobName')">{{ rowData?.jobName }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.taskBatchStatus')">
|
||||
<NTag :type="tagColor(rowData?.taskBatchStatus!)">
|
||||
{{ $t(taskBatchStatusRecord[rowData?.taskBatchStatus!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executionAt')">{{ rowData?.executionAt }}</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.operationReason')">
|
||||
<NTag :type="tagColor(rowData?.operationReason!)">
|
||||
{{ $t(operationReasonRecord[rowData?.operationReason!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executorType')">
|
||||
<NTag :type="tagColor(rowData?.executorType!)">
|
||||
{{ $t(executorTypeRecord[rowData?.executorType!]) }}
|
||||
</NTag>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('page.jobBatch.executorInfo')" :span="2">
|
||||
{{ rowData?.executorInfo }}
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem :label="$t('common.createDt')" :span="2">{{ rowData?.createDt }}</NDescriptionsItem>
|
||||
</NDescriptions>
|
||||
</NTabPane>
|
||||
<NTabPane :name="1" :tab="$t('page.log.title')" display-directive="if">
|
||||
<NDataTable
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:loading="loading"
|
||||
remote
|
||||
:row-key="row => row.id"
|
||||
:pagination="mobilePagination"
|
||||
class="sm:h-full"
|
||||
/>
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
<LogDrawer v-model="logList" v-model:show="logShow" title="日志" />
|
||||
</DetailDrawer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
Loading…
Reference in New Issue
Block a user