2024-04-26 16:43:25 +08:00
|
|
|
<script setup lang="tsx">
|
|
|
|
import { NCollapse, NCollapseItem } from 'naive-ui';
|
2024-05-07 14:51:19 +08:00
|
|
|
import { defineComponent, watch } from 'vue';
|
2024-06-24 15:55:40 +08:00
|
|
|
import { useRouter } from 'vue-router';
|
2024-05-07 14:51:19 +08:00
|
|
|
import { $t } from '@/locales';
|
2024-06-24 15:55:40 +08:00
|
|
|
import { useLogStore } from '@/store/modules/log';
|
2024-04-26 16:43:25 +08:00
|
|
|
|
|
|
|
defineOptions({
|
|
|
|
name: 'LogDrawer'
|
|
|
|
});
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
title?: string;
|
|
|
|
show?: boolean;
|
2024-05-07 15:19:49 +08:00
|
|
|
drawer?: boolean;
|
2024-05-07 14:51:19 +08:00
|
|
|
modelValue?: Api.JobLog.JobMessage[];
|
2024-04-26 16:43:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
2024-05-07 14:51:19 +08:00
|
|
|
title: $t('page.log.title'),
|
|
|
|
show: false,
|
2024-05-07 15:19:49 +08:00
|
|
|
drawer: true,
|
2024-05-07 14:51:19 +08:00
|
|
|
modelValue: () => []
|
2024-04-26 16:43:25 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
interface Emits {
|
|
|
|
(e: 'update:show', show: boolean): void;
|
|
|
|
}
|
|
|
|
|
|
|
|
const emit = defineEmits<Emits>();
|
|
|
|
const visible = defineModel<boolean>('visible', {
|
|
|
|
default: true
|
|
|
|
});
|
|
|
|
|
|
|
|
const ThrowableComponent = defineComponent({
|
|
|
|
props: {
|
2024-06-18 17:05:56 +08:00
|
|
|
throwable: {
|
|
|
|
type: String,
|
|
|
|
default: ''
|
|
|
|
}
|
2024-04-26 16:43:25 +08:00
|
|
|
},
|
|
|
|
setup(thProps) {
|
|
|
|
return () => {
|
|
|
|
if (!thProps.throwable) {
|
|
|
|
return <></>;
|
|
|
|
}
|
|
|
|
const firstLine = thProps.throwable.match(/^.+/m);
|
|
|
|
if (!firstLine) {
|
|
|
|
return <></>;
|
|
|
|
}
|
|
|
|
const restOfText = thProps.throwable.replace(/^.+(\n|$)/m, '');
|
|
|
|
return (
|
|
|
|
<NCollapse>
|
|
|
|
<NCollapseItem title={firstLine[0]} name="1">
|
|
|
|
{`${restOfText}`}
|
|
|
|
</NCollapseItem>
|
|
|
|
</NCollapse>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
watch(
|
|
|
|
() => props.show,
|
|
|
|
val => {
|
|
|
|
visible.value = val;
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
);
|
|
|
|
|
2024-06-24 15:55:40 +08:00
|
|
|
const store = useLogStore();
|
|
|
|
|
2024-04-26 16:43:25 +08:00
|
|
|
const onUpdateShow = (value: boolean) => {
|
2024-06-24 15:55:40 +08:00
|
|
|
if (!value) {
|
|
|
|
store.clear();
|
|
|
|
}
|
2024-04-26 16:43:25 +08:00
|
|
|
emit('update:show', value);
|
|
|
|
};
|
|
|
|
|
|
|
|
function timestampToDate(timestamp: string): string {
|
2024-06-15 10:39:12 +08:00
|
|
|
const date = new Date(Number.parseInt(timestamp?.toString(), 10));
|
2024-04-26 16:43:25 +08:00
|
|
|
const year = date.getFullYear();
|
|
|
|
const month =
|
2024-06-15 10:39:12 +08:00
|
|
|
(date.getMonth() + 1)?.toString().length === 1 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1)?.toString();
|
|
|
|
const day = date.getDate()?.toString().length === 1 ? `0${date.getDate()}` : date.getDate()?.toString();
|
|
|
|
const hours = date.getHours()?.toString().length === 1 ? `0${date.getHours()}` : date.getHours()?.toString();
|
|
|
|
const minutes = date.getMinutes()?.toString().length === 1 ? `0${date.getMinutes()}` : date.getMinutes()?.toString();
|
|
|
|
const seconds = date.getSeconds()?.toString().length === 1 ? `0${date.getSeconds()}` : date.getSeconds()?.toString();
|
2024-04-26 16:43:25 +08:00
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${date.getMilliseconds()}`;
|
|
|
|
}
|
2024-06-24 15:55:40 +08:00
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
function openNewTab() {
|
|
|
|
const url = router.resolve('/log');
|
|
|
|
store.setData(props.modelValue);
|
|
|
|
window.open(url.href);
|
|
|
|
}
|
2024-04-26 16:43:25 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2024-06-25 17:53:44 +08:00
|
|
|
<NDrawer v-if="drawer" v-model:show="visible" width="100%" display-directive="if" @update:show="onUpdateShow">
|
2024-06-24 15:55:40 +08:00
|
|
|
<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>
|
2024-05-08 20:08:37 +08:00
|
|
|
<div class="snail-log bg-#fafafc p-16px dark:bg-#000">
|
2024-04-26 16:43:25 +08:00
|
|
|
<div class="snail-log-scrollbar">
|
|
|
|
<code>
|
2024-06-25 17:53:44 +08:00
|
|
|
<NVirtualList class="virtual-list" :item-size="42" :items="modelValue">
|
|
|
|
<template #default="{ item: message, index }">
|
|
|
|
<pre><NDivider v-if="index !== 0" /><span class="log-hljs-time inline-block">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`" class="ml-12px mr-12px inline-block">{{`${message.level}`}}</span><span class="log-hljs-thread mr-12px inline-block">{{ `[${message.host}:${message.port}]` }}</span><span class="log-hljs-thread mr-12px inline-block">{{`[${message.thread}]`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
|
|
|
|
</template>
|
|
|
|
</NVirtualList>
|
2024-04-26 16:43:25 +08:00
|
|
|
</code>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</NDrawerContent>
|
|
|
|
</NDrawer>
|
2024-06-25 17:53:44 +08:00
|
|
|
<div v-if="!drawer" class="snail-log">
|
2024-05-07 15:19:49 +08:00
|
|
|
<div class="snail-log-scrollbar">
|
|
|
|
<code>
|
2024-06-25 17:53:44 +08:00
|
|
|
<NVirtualList class="virtual-list" :item-size="42" :items="modelValue">
|
|
|
|
<template #default="{ item: message, index }">
|
|
|
|
<pre><NDivider v-if="index !== 0" /><span class="log-hljs-time inline-block">{{timestampToDate(message.time_stamp)}}</span><span :class="`log-hljs-level-${message.level}`" class="ml-12px mr-12px inline-block">{{`${message.level}`}}</span><span class="log-hljs-thread mr-12px inline-block">{{ `[${message.host}:${message.port}]` }}</span><span class="log-hljs-thread mr-12px inline-block">{{`[${message.thread}]`}}</span><span class="log-hljs-location">{{`${message.location}: \n`}}</span> -<span class="pl-6px">{{`${message.message}`}}</span><ThrowableComponent :throwable="message.throwable" /></pre>
|
|
|
|
</template>
|
|
|
|
</NVirtualList>
|
2024-05-07 15:19:49 +08:00
|
|
|
</code>
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-04-26 16:43:25 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.snail-log {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
|
2024-06-25 17:53:44 +08:00
|
|
|
.virtual-list {
|
|
|
|
max-height: calc(100vh - 101px);
|
|
|
|
}
|
|
|
|
|
2024-04-26 16:43:25 +08:00
|
|
|
&-scrollbar {
|
|
|
|
padding: 0;
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
overflow: auto;
|
|
|
|
@include scrollbar();
|
|
|
|
|
|
|
|
.n-divider:not(.n-divider--vertical) {
|
|
|
|
margin-top: 6px;
|
|
|
|
margin-bottom: 6px;
|
|
|
|
}
|
|
|
|
|
|
|
|
pre {
|
|
|
|
white-space: pre-wrap;
|
|
|
|
word-break: break-word;
|
|
|
|
margin: 0;
|
|
|
|
font-size: 16px;
|
|
|
|
color: #333639;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.dark {
|
|
|
|
.snail-log {
|
|
|
|
background-color: #1e1f22;
|
|
|
|
|
|
|
|
pre {
|
|
|
|
color: #ffffffe6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.log-hljs {
|
|
|
|
&-time {
|
|
|
|
color: #2db7f5;
|
|
|
|
}
|
|
|
|
|
|
|
|
&-level {
|
|
|
|
&-DEBUG {
|
|
|
|
color: #2647cc;
|
|
|
|
}
|
|
|
|
|
|
|
|
&-INFO {
|
|
|
|
color: #5c962c;
|
|
|
|
}
|
|
|
|
|
|
|
|
&-WARN {
|
|
|
|
color: #da9816;
|
|
|
|
}
|
|
|
|
|
|
|
|
&-ERROR {
|
|
|
|
color: #dc3f41;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
&-thread {
|
|
|
|
color: #00a3a3;
|
|
|
|
}
|
|
|
|
|
|
|
|
&-location {
|
|
|
|
color: #a771bf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|