feat(sj_map_reduce): 执行批次新增日志按钮,并优化日志显示

This commit is contained in:
xlsea 2024-06-24 15:55:40 +08:00
parent 090763eec9
commit 61cc8252a7
12 changed files with 146 additions and 8 deletions

View File

@ -0,0 +1,12 @@
{
"prefix": "hugeicons",
"lastModified": 1715671861,
"aliases": {},
"width": 24,
"height": 24,
"icons": {
"share-01": {
"body": "<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" color=\"currentColor\"><path d=\"m20.393 8.032l-1.747-1.517c-1.259-1.093-1.752-1.681-2.434-1.474c-.85.26-.57 1.895-.57 2.447c-1.321 0-2.695-.101-3.998.11c-4.3.7-5.644 3.759-5.644 7.055c1.217-.747 2.433-1.578 3.895-1.924c1.826-.432 3.865-.226 5.747-.226c0 .552-.28 2.188.57 2.447c.772.236 1.175-.38 2.434-1.473l1.747-1.517C21.464 11.03 22 10.564 22 9.996s-.536-1.034-1.607-1.964\"/><path d=\"M10.568 3c-3.86.007-5.882.102-7.174 1.39C2 5.783 2 8.022 2 12.5s0 6.717 1.394 8.109C4.788 22 7.032 22 11.52 22s6.73 0 8.125-1.391C20.615 19.64 20.91 18.26 21 16\"/></g>"
}
}
}

View File

@ -1,7 +1,9 @@
<script setup lang="tsx">
import { NCollapse, NCollapseItem } from 'naive-ui';
import { defineComponent, watch } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@/locales';
import { useLogStore } from '@/store/modules/log';
defineOptions({
name: 'LogDrawer'
@ -66,7 +68,12 @@ watch(
{ immediate: true }
);
const store = useLogStore();
const onUpdateShow = (value: boolean) => {
if (!value) {
store.clear();
}
emit('update:show', value);
};
@ -81,6 +88,14 @@ function timestampToDate(timestamp: string): string {
const seconds = date.getSeconds().toString().length === 1 ? `0${date.getSeconds()}` : date.getSeconds().toString();
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${date.getMilliseconds()}`;
}
const router = useRouter();
function openNewTab() {
const url = router.resolve('/log');
store.setData(props.modelValue);
window.open(url.href);
}
</script>
<template>
@ -91,7 +106,13 @@ function timestampToDate(timestamp: string): string {
display-directive="if"
@update:show="onUpdateShow"
>
<NDrawerContent :title="title" closable>
<NDrawerContent closable>
<template #header>
<div class="flex-center">
<span>{{ title }}</span>
<ButtonIcon icon="hugeicons:share-01" tooltip-content="在新标签页打开" class="ml-3px" @click="openNewTab" />
</div>
</template>
<div class="snail-log bg-#fafafc p-16px dark:bg-#000">
<div class="snail-log-scrollbar">
<code>

View File

@ -302,6 +302,7 @@ const local: App.I18n.Schema = {
404: 'Page Not Found',
500: 'Server Error',
'iframe-page': 'Iframe',
log: 'Log',
home: 'Home',
about: 'About',
pods: 'Online Machine',

View File

@ -302,6 +302,7 @@ const local: App.I18n.Schema = {
404: '页面不存在',
500: '服务器错误',
'iframe-page': '外链页面',
log: '日志',
home: '首页',
about: '关于',
pods: '在线机器',

View File

@ -19,6 +19,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
404: () => import("@/views/_builtin/404/index.vue"),
500: () => import("@/views/_builtin/500/index.vue"),
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
log: () => import("@/views/_builtin/log/index.vue"),
login: () => import("@/views/_builtin/login/index.vue"),
about: () => import("@/views/about/index.vue"),
group: () => import("@/views/group/index.vue"),

View File

@ -120,6 +120,17 @@ export const generatedRoutes: GeneratedRoute[] = [
}
]
},
{
name: 'log',
path: '/log',
component: 'layout.blank$view.log',
meta: {
title: 'log',
i18nKey: 'route.log',
icon: 'carbon:batch-job',
hideInMenu: true
}
},
{
name: 'login',
path: '/login/:module(pwd-login)?',

View File

@ -0,0 +1,40 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { localStg } from '@/utils/storage';
export const useLogStore = defineStore('log', () => {
const taskName = ref<string>();
const taskBatchId = ref<string>();
const data = ref<Api.JobLog.JobMessage[]>([]);
function setTaskInfo(name: string, id: string) {
taskName.value = name;
taskBatchId.value = id;
}
function setData(value: Api.JobLog.JobMessage[]) {
data.value = value;
localStg.set('log', { taskName: taskName.value!, taskBatchId: taskBatchId.value!, data: data.value });
}
function clear() {
taskName.value = undefined;
taskBatchId.value = undefined;
data.value = [];
localStg.remove('log');
}
function getLogStg() {
return localStg.get('log');
}
return {
taskName,
taskBatchId,
data,
clear,
setTaskInfo,
setData,
getLogStg
};
});

View File

@ -44,5 +44,10 @@ declare namespace StorageType {
layout: UnionKey.ThemeLayoutMode;
siderCollapse: boolean;
};
log: {
taskName: string;
taskBatchId: string;
data: Api.JobLog.JobMessage[];
};
}
}

View File

@ -0,0 +1,26 @@
<script setup lang="ts">
import { onUnmounted, ref } from 'vue';
import { useLogStore } from '@/store/modules/log';
const store = useLogStore();
const data = ref(store.getLogStg());
onUnmounted(() => {
store.clear();
});
</script>
<template>
<NCard
:title="`${$t('page.log.title')} ------ ${$t('page.jobBatch.jobName')}: ${data?.taskName}, ${$t('common.batchList')} ID: ${data?.taskBatchId}`"
:bordered="false"
size="small"
class="h-full sm:flex-1-hidden card-wrapper"
header-class="view-card-header"
>
<LogDrawer :model-value="data?.data" :drawer="false" />
</NCard>
</template>
<style scoped></style>

View File

@ -20,6 +20,7 @@ const route = useRoute();
const detailData = ref<Api.JobBatch.JobBatch | null>();
/** 详情页可见状态 */
const { bool: detailVisible, setTrue: openDetail } = useBoolean(false);
const { bool: detailLog, setBool: setDetailLog } = useBoolean(false);
const { columnChecks, columns, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
apiFn: fetchGetJobBatchList,
@ -55,6 +56,7 @@ const { columnChecks, columns, data, getData, loading, mobilePagination, searchP
render: row => {
function showDetailDrawer() {
detailData.value = row;
setDetailLog(false);
openDetail();
}
@ -152,6 +154,9 @@ const { columnChecks, columns, data, getData, loading, mobilePagination, searchP
width: 130,
render: row => (
<div class="flex-center gap-8px">
<NButton type="primary" text ghost size="small" onClick={handleLog}>
{$t('common.log')}
</NButton>
{row.taskBatchStatus === 1 || row.taskBatchStatus === 2 ? (
<NPopconfirm onPositiveClick={() => handleStopJob(row.id!)}>
{{
@ -186,6 +191,11 @@ const { columnChecks, columns, data, getData, loading, mobilePagination, searchP
]
});
function handleLog() {
setDetailLog(true);
openDetail();
}
async function handleRetryJob(id: string) {
const { error } = await fetchJobBatchRetry(id);
if (!error) {
@ -269,7 +279,12 @@ initParams();
class="sm:h-full"
/>
</NCard>
<JobBatchDetailDrawer v-if="detailVisible" v-model:visible="detailVisible" :row-data="detailData" />
<JobBatchDetailDrawer
v-if="detailVisible"
v-model:visible="detailVisible"
v-model:log="detailLog"
:row-data="detailData"
/>
</div>
</template>

View File

@ -4,6 +4,7 @@ import { executorTypeRecord, operationReasonRecord, taskBatchStatusRecord } from
import { $t } from '@/locales';
import { tagColor } from '@/utils/common';
import { fetchJobLogList } from '@/service/api/log';
import { useLogStore } from '@/store/modules/log';
import JobTaskListTable from './job-task-list-table.vue';
defineOptions({
@ -13,20 +14,24 @@ defineOptions({
interface Props {
/** row data */
rowData?: Api.JobBatch.JobBatch | null;
log?: boolean;
}
defineProps<Props>();
const props = withDefaults(defineProps<Props>(), {
log: false,
rowData: null
});
const visible = defineModel<boolean>('visible', {
default: false
});
const taskData = ref<Api.Job.JobTask>();
const logShow = defineModel<boolean>('logShow', {
default: false
});
const logShow = ref(false);
const store = useLogStore();
async function openLog(row: Api.Job.JobTask) {
store.setTaskInfo(props.rowData!.jobName, row.taskBatchId);
logShow.value = true;
taskData.value = row;
await getLogList();
@ -77,7 +82,7 @@ onBeforeUnmount(() => {
<template>
<DetailDrawer v-model="visible" :title="$t('page.jobBatch.detail')" :width="['50%', '90%']">
<NTabs type="segment" animated>
<NTabs type="segment" animated :default-value="log ? 1 : 0">
<NTabPane :name="0" :tab="$t('page.log.info')">
<NDescriptions label-placement="top" bordered :column="2">
<NDescriptionsItem :label="$t('page.jobBatch.groupName')">{{ rowData?.groupName }}</NDescriptionsItem>

View File

@ -48,7 +48,7 @@ const { columns, data, loading, mobilePagination } = useTable({
key: 'id',
title: $t('page.jobBatch.jobTask.id'),
align: 'left',
minWidth: 100,
width: 100,
ellipsis: {
tooltip: true
}