🔨 修改日志查看逻辑.

This commit is contained in:
lijiahang
2025-02-10 09:51:53 +08:00
parent a9ac9d0f79
commit de9a921c49
4 changed files with 111 additions and 90 deletions

View File

@@ -65,17 +65,18 @@ export const LogAppenderOptions: ITerminalOptions & ITerminalInitOnlyOptions = {
fontFamily: defaultFontFamily,
};
// dom 引用
export interface LogDomRef {
// append 配置
export interface LogAppenderConfig {
id: number;
el: HTMLElement;
openSearch: () => {};
type: ExecType;
scrollLines: number;
}
// appender 配置
export interface LogAppenderConf {
// appender 视口
export interface LogAppenderView {
id: number;
el: HTMLElement;
opened: boolean;
openSearch: () => {};
terminal: Terminal;
addons: XtermAddons;
@@ -84,7 +85,10 @@ export interface LogAppenderConf {
// 执行日志 appender 定义
export interface ILogAppender {
// 初始化
init(refs: Array<LogDomRef>): Promise<void>;
init(refs: Array<LogAppenderView>): Promise<void>;
// 打开日志
openLog(id: number): void;
// 设置当前元素
setCurrent(id: number): void;

View File

@@ -4,7 +4,7 @@
<exec-host class="exec-host-container"
:visibleBack="visibleBack"
:current="currentHostExecId"
:hosts="execLog.hosts"
:hosts="execLog.hosts as any"
@selected="selectedHost"
@back="emits('back')" />
<!-- 日志容器 -->
@@ -13,7 +13,8 @@
:type="type"
:current="currentHostExecId"
:exec-log="execLog"
:appender="appender" />
:appender="appender"
@ready="openLog(currentHostExecId)" />
</div>
</template>
@@ -30,7 +31,8 @@
import { getExecCommandLogStatus } from '@/api/exec/exec-command-log';
import { getExecJobLogStatus } from '@/api/exec/exec-job-log';
import { dictKeys, ExecHostStatus, ExecStatus } from '../const';
import { useDictStore } from '@/store';
import { useCacheStore, useDictStore } from '@/store';
import { toAnonymousNumber } from '@/utils';
import ExecHost from './exec-host.vue';
import LogView from './log-view.vue';
import LogAppender from './log-appender';
@@ -43,16 +45,24 @@
const emits = defineEmits(['back']);
const logViewRef = ref();
const currentHostExecId = ref();
const currentHostExecId = ref(0);
const pullIntervalId = ref();
const execLog = ref<ExecLogQueryResponse>();
const appender = ref<ILogAppender>();
// 打开
const open = (record: ExecLogQueryResponse) => {
appender.value = new LogAppender(props.type, { execId: record.id });
execLog.value = record;
const open = async (record: ExecLogQueryResponse) => {
execLog.value = { ...record };
currentHostExecId.value = record.hosts[0].id;
// 获取最大显示行数
const { log_webScrollLines } = await useCacheStore().loadSystemSetting();
const scrollLines = toAnonymousNumber(log_webScrollLines) || 1000;
// 创建 appender
appender.value = new LogAppender({
id: record.id,
type: props.type,
scrollLines,
});
// 定时查询执行状态
if (record.status === ExecStatus.WAITING ||
record.status === ExecStatus.RUNNING) {
@@ -88,55 +98,45 @@
execLog.value.finishTime = logList[0].finishTime;
}
// 设置主机状态
for (let host of execLog.value.hosts) {
const hostStatus = hostList.find(s => s.id === host.id);
if (hostStatus) {
host.status = hostStatus.status;
host.startTime = hostStatus.startTime;
for (let hostRow of hostList) {
const execLogHost = execLog.value.hosts.find(s => s.id === hostRow.id);
if (execLogHost) {
execLogHost.status = hostRow.status;
execLogHost.startTime = hostRow.startTime;
// 结束时间绑定了使用时间 如果未完成则使用当前时间
host.finishTime = hostStatus.finishTime || Date.now();
host.exitCode = hostStatus.exitCode;
host.errorMessage = hostStatus.errorMessage;
execLogHost.finishTime = hostRow.finishTime || Date.now();
execLogHost.exitCode = hostRow.exitCode;
execLogHost.errorMessage = hostRow.errorMessage;
}
// 当前选中主机非等待状态则打开日志
if (hostRow.id === currentHostExecId.value) {
openLog(hostRow.id);
}
}
// 已完成跳过
// 已完成关闭轮询
if (execLog.value.status === ExecStatus.COMPLETED ||
execLog.value.status === ExecStatus.FAILED) {
closeClient();
clearAllInterval();
}
};
// 设置完成时间
const setTaskFinishTime = () => {
const hosts = execLog.value?.hosts;
if (!hosts) {
return;
}
hosts.forEach(s => {
// 未完成自动设置完成时间为当前时间 用于展示使用时间
if (s.status === ExecHostStatus.WAITING ||
s.status === ExecHostStatus.RUNNING) {
if (!s.startTime) {
s.startTime = Date.now();
}
s.finishTime = Date.now();
}
});
};
defineExpose({ open });
// 选中主机
const selectedHost = (hostId: number) => {
currentHostExecId.value = hostId;
const selectedHost = (id: number) => {
currentHostExecId.value = id;
// 打开日志
openLog(id);
};
// 关闭连接
const closeClient = () => {
// 清理轮询
clearAllInterval();
// 关闭 client
appender.value?.closeClient();
// 打开日志
const openLog = (id: number) => {
// 获取状态
const status = execLog.value?.hosts.find(s => s.id === id)?.status;
if (status && status !== ExecHostStatus.WAITING) {
// 打开日志
appender.value?.openLog(id);
}
};
// 清理并且关闭

View File

@@ -1,7 +1,6 @@
import type { ExecType, ILogAppender, LogAppenderConf, LogDomRef } from '../const';
import type { ILogAppender, LogAppenderConfig, LogAppenderView } from '../const';
import { LogAppenderOptions } from '../const';
import type { XtermAddons } from '@/types/xterm';
import type { ExecLogTailRequest } from '@/api/exec/exec-log';
import { openExecLogChannel } from '@/api/exec/exec-log';
import { getExecCommandLogTailToken } from '@/api/exec/exec-command-log';
import { getExecJobLogTailToken } from '@/api/exec/exec-job-log';
@@ -19,58 +18,58 @@ import { Unicode11Addon } from '@xterm/addon-unicode11';
// 执行日志 appender 实现
export default class LogAppender implements ILogAppender {
private current: LogAppenderConf;
private current: LogAppenderView;
private client?: WebSocket;
private readonly config: ExecLogTailRequest;
private readonly appenderViews: Record<string, LogAppenderView>;
private readonly appenderRel: Record<string, LogAppenderConf>;
private readonly config: LogAppenderConfig;
private keepAliveTask?: number;
private readonly fitAllFn: () => {};
private readonly fitAllFn: () => void;
private readonly type: ExecType;
constructor(type: ExecType, config: ExecLogTailRequest) {
this.current = undefined as unknown as LogAppenderConf;
this.type = type;
constructor(config: LogAppenderConfig) {
this.config = config;
this.appenderRel = {};
this.current = undefined as unknown as LogAppenderView;
this.appenderViews = {};
this.fitAllFn = useDebounceFn(this.fitAll).bind(this);
}
// 初始化
async init(logDomRefs: Array<LogDomRef>) {
async init(configs: Array<LogAppenderView>) {
// 初始化 appender
await this.initAppender(logDomRefs);
await this.initAppender(configs);
// 初始化 client
await this.openClient();
}
// 初始化 appender
async initAppender(logDomRefs: Array<LogDomRef>) {
async initAppender(configs: Array<LogAppenderView>) {
// 打开 log-view
for (let logDomRef of logDomRefs) {
for (let config of configs) {
// 初始化 terminal
const terminal = new Terminal(LogAppenderOptions);
const terminal = new Terminal({
...LogAppenderOptions,
scrollback: this.config.scrollLines,
});
// 初始化快捷键
this.initCustomKey(terminal);
// 初始化插件
const addons = this.initAddons(terminal);
// 打开终端
terminal.open(logDomRef.el);
terminal.open(config.el);
// 自适应
addons.fit.fit();
this.appenderRel[logDomRef.id] = {
...logDomRef,
this.appenderViews[config.id] = {
...config,
terminal,
addons
};
}
// 设置当前对象
this.current = this.appenderRel[logDomRefs[0].id];
this.current = this.appenderViews[configs[0].id];
// 注册自适应事件
addEventListen(window, 'resize', this.fitAllFn);
}
@@ -152,12 +151,12 @@ export default class LogAppender implements ILogAppender {
async openClient() {
let tokenMaker;
// 获取 token
if (this.type === 'BATCH') {
if (this.config.type === 'BATCH') {
// 获取批量执行日志 token
tokenMaker = getExecCommandLogTailToken(this.config);
tokenMaker = getExecCommandLogTailToken(this.config.id);
} else {
// 获取计划任务日志 token
tokenMaker = getExecJobLogTailToken(this.config);
tokenMaker = getExecJobLogTailToken(this.config.id);
}
const { data } = await tokenMaker;
// 打开会话
@@ -180,15 +179,26 @@ export default class LogAppender implements ILogAppender {
}, 15000) as unknown as number;
}
// 设置当前元素
setCurrent(id: number): void {
const rel = this.appenderRel[id];
if (!rel) {
// 打开日志
openLog(id: number): void {
const view = this.appenderViews[id];
if (!view || view.opened || this.client?.readyState !== WebSocket.OPEN) {
return;
}
this.current = rel;
// 发送打开日志
this.client?.send(id.toString());
view.opened = true;
}
// 设置当前元素
setCurrent(id: number): void {
const view = this.appenderViews[id];
if (!view) {
return;
}
this.current = view;
// 自适应
rel.addons.fit.fit();
view.addons.fit.fit();
this.focus();
}
@@ -259,7 +269,7 @@ export default class LogAppender implements ILogAppender {
// 自适应全部
fitAll(): void {
Object.values(this.appenderRel).forEach(s => {
Object.values(this.appenderViews).forEach(s => {
s.addons.fit.fit();
});
}
@@ -282,7 +292,7 @@ export default class LogAppender implements ILogAppender {
// 移除自适应事件
removeEventListen(window, 'resize', this.fitAllFn);
// 关闭 terminal
Object.values(this.appenderRel).forEach(s => {
Object.values(this.appenderViews).forEach(s => {
try {
// 卸载插件
Object.values(s.addons)
@@ -313,12 +323,12 @@ export default class LogAppender implements ILogAppender {
const separatorIndex = data.indexOf('|');
const id = data.substring(0, separatorIndex);
const text = data.substring(separatorIndex + 1, data.length);
// 获取 appender
const appender = this.appenderRel[id];
if (!appender) {
// 获取 view
const view = this.appenderViews[id];
if (!view) {
return;
}
appender.terminal.write(text);
view.terminal.write(text);
}
}

View File

@@ -1,8 +1,8 @@
<template>
<div class="container">
<log-item class="log-item"
v-show="current === host.id"
v-for="host in execLog.hosts"
v-show="current === host.id"
:key="host.id"
:ref="addRef as unknown as VNodeRef"
:type="type"
@@ -20,7 +20,7 @@
<script lang="ts" setup>
import type { VNodeRef } from 'vue';
import type { LogDomRef, ILogAppender } from '../const';
import type { ILogAppender, LogAppenderView } from '../const';
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
import type { ExecType } from '../const';
import { nextTick, ref, watch } from 'vue';
@@ -33,7 +33,9 @@
type: ExecType;
}>();
const logRefs = ref<Array<LogDomRef>>([]);
const emits = defineEmits(['ready']);
const logRefs = ref<Array<LogAppenderView>>([]);
// 切换标签
watch(() => props.current, (val) => {
@@ -50,6 +52,7 @@
if (props.appender) {
// 初始化
await props.appender.init(logRefs.value);
emits('ready');
}
});
};
@@ -61,12 +64,16 @@
if (!ref) {
return;
}
if (logRefs.value.find(s => s.id === ref.id)) {
return;
}
nextTick(() => {
logRefs.value.push({
id: ref.id,
el: ref.appenderRef,
opened: false,
openSearch: ref.openSearch,
});
} as LogAppenderView);
});
};