feat(sj_map_reduce): 执行批次新增日志按钮,并优化日志显示
This commit is contained in:
parent
090763eec9
commit
61cc8252a7
12
public/iconify/hugeicons.json
Normal file
12
public/iconify/hugeicons.json
Normal 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>"
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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',
|
||||
|
@ -302,6 +302,7 @@ const local: App.I18n.Schema = {
|
||||
404: '页面不存在',
|
||||
500: '服务器错误',
|
||||
'iframe-page': '外链页面',
|
||||
log: '日志',
|
||||
home: '首页',
|
||||
about: '关于',
|
||||
pods: '在线机器',
|
||||
|
@ -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"),
|
||||
|
@ -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)?',
|
||||
|
40
src/store/modules/log/index.ts
Normal file
40
src/store/modules/log/index.ts
Normal 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
|
||||
};
|
||||
});
|
5
src/typings/storage.d.ts
vendored
5
src/typings/storage.d.ts
vendored
@ -44,5 +44,10 @@ declare namespace StorageType {
|
||||
layout: UnionKey.ThemeLayoutMode;
|
||||
siderCollapse: boolean;
|
||||
};
|
||||
log: {
|
||||
taskName: string;
|
||||
taskBatchId: string;
|
||||
data: Api.JobLog.JobMessage[];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
26
src/views/_builtin/log/index.vue
Normal file
26
src/views/_builtin/log/index.vue
Normal 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>
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user