mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-12 00:16:37 +08:00
fix: Fix missing line breaks in copied logs on the log page (#9283)
This commit is contained in:
parent
763df5606b
commit
4f377c04b8
3 changed files with 23 additions and 121 deletions
|
@ -25,15 +25,7 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<div class="log-container" :style="styleVars" ref="logContainer">
|
||||
<div class="log-spacer" :style="{ height: `${totalHeight}px` }"></div>
|
||||
<div
|
||||
v-for="(log, index) in visibleLogs"
|
||||
:key="startIndex + index"
|
||||
class="log-item"
|
||||
:style="{ top: `${(startIndex + index) * logHeight}px` }"
|
||||
>
|
||||
<hightlight :log="log" type="container"></hightlight>
|
||||
</div>
|
||||
<CodemirrorPro v-model="logInfo" :lineWrapping="true" :heightDiff="230" :disabled="true"></CodemirrorPro>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -44,7 +36,6 @@ import { dateFormatForName } from '@/utils/util';
|
|||
import { onUnmounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import hightlight from '@/components/log/custom-hightlight/index.vue';
|
||||
import { GlobalStore } from '@/store';
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
|
@ -72,8 +63,6 @@ const styleVars = computed(() => ({
|
|||
}));
|
||||
|
||||
const logVisible = ref(false);
|
||||
const logContainer = ref<HTMLElement | null>(null);
|
||||
const logs = ref<string[]>([]);
|
||||
let eventSource: EventSource | null = null;
|
||||
const logSearch = reactive({
|
||||
isWatch: true,
|
||||
|
@ -82,17 +71,7 @@ const logSearch = reactive({
|
|||
tail: 100,
|
||||
compose: '',
|
||||
});
|
||||
const logHeight = 20;
|
||||
const logCount = computed(() => logs.value.length);
|
||||
const totalHeight = computed(() => logHeight * logCount.value);
|
||||
const startIndex = ref(0);
|
||||
const containerHeight = ref(500);
|
||||
const visibleCount = computed(() => Math.ceil(containerHeight.value / logHeight) + 2);
|
||||
const visibleLogs = computed(() => {
|
||||
const start = Math.max(0, startIndex.value - 1);
|
||||
const end = startIndex.value + visibleCount.value + 1;
|
||||
return logs.value.slice(start, end);
|
||||
});
|
||||
const logInfo = ref<string>('');
|
||||
|
||||
const timeOptions = ref([
|
||||
{ label: i18n.global.t('commons.table.all'), value: 'all' },
|
||||
|
@ -135,7 +114,7 @@ const searchLogs = async () => {
|
|||
if (!logSearch.isWatch) {
|
||||
return;
|
||||
}
|
||||
logs.value = [];
|
||||
logInfo.value = '';
|
||||
let currentNode = globalStore.currentNode;
|
||||
let url = `/api/v2/containers/search/log?container=${logSearch.container}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}&operateNode=${currentNode}`;
|
||||
if (logSearch.compose !== '') {
|
||||
|
@ -143,13 +122,7 @@ const searchLogs = async () => {
|
|||
}
|
||||
eventSource = new EventSource(url);
|
||||
eventSource.onmessage = (event: MessageEvent) => {
|
||||
const data = event.data;
|
||||
logs.value.push(data);
|
||||
nextTick(() => {
|
||||
if (logContainer.value) {
|
||||
logContainer.value.scrollTop = logContainer.value.scrollHeight;
|
||||
}
|
||||
});
|
||||
logInfo.value += event.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '') + '\n';
|
||||
};
|
||||
eventSource.onerror = (event: MessageEvent) => {
|
||||
stopListening();
|
||||
|
@ -199,49 +172,23 @@ const onClean = async () => {
|
|||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
type: 'info',
|
||||
}).then(async () => {
|
||||
console.log(logSearch);
|
||||
await cleanContainerLog(logSearch.container);
|
||||
searchLogs();
|
||||
await searchLogs();
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
});
|
||||
};
|
||||
|
||||
const handleScroll = () => {
|
||||
if (logContainer.value) {
|
||||
const scrollTop = logContainer.value.scrollTop;
|
||||
startIndex.value = Math.max(0, Math.floor(scrollTop / logHeight) - 1);
|
||||
}
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
handleClose();
|
||||
if (logContainer.value) {
|
||||
logContainer.value.removeEventListener('scroll', handleScroll);
|
||||
}
|
||||
});
|
||||
|
||||
const resizeObserver = ref<ResizeObserver | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
logSearch.container = props.container;
|
||||
logSearch.compose = props.compose;
|
||||
|
||||
logVisible.value = true;
|
||||
logSearch.tail = 100;
|
||||
logSearch.mode = 'all';
|
||||
logSearch.isWatch = true;
|
||||
|
||||
nextTick(() => {
|
||||
if (logContainer.value) {
|
||||
containerHeight.value = logContainer.value.clientHeight;
|
||||
logContainer.value.addEventListener('scroll', handleScroll);
|
||||
resizeObserver.value = new ResizeObserver((entries) => {
|
||||
containerHeight.value = entries[0].contentRect.height;
|
||||
});
|
||||
resizeObserver.value.observe(logContainer.value);
|
||||
}
|
||||
});
|
||||
|
||||
searchLogs();
|
||||
});
|
||||
</script>
|
||||
|
@ -264,8 +211,7 @@ onMounted(() => {
|
|||
}
|
||||
|
||||
.log-container {
|
||||
height: calc(100vh - var(--custom-height, 320px));
|
||||
overflow-y: auto;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
background-color: #1e1e1e;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div v-loading="firstLoading">
|
||||
<div v-if="defaultButton">
|
||||
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail(false)" v-if="showTail">
|
||||
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail()" v-if="showTail">
|
||||
{{ $t('commons.button.watch') }}
|
||||
</el-checkbox>
|
||||
<el-button
|
||||
|
@ -17,26 +17,23 @@
|
|||
<slot name="button"></slot>
|
||||
</span>
|
||||
</div>
|
||||
<div class="log-container" ref="logContainer" @scroll="onScroll" :style="containerStyle">
|
||||
<div class="log-spacer" :style="{ height: `${totalHeight}px` }"></div>
|
||||
<div
|
||||
v-for="(log, index) in visibleLogs"
|
||||
:key="startIndex + index"
|
||||
class="log-item"
|
||||
:style="{ top: `${(startIndex + index) * logHeight}px` }"
|
||||
>
|
||||
<hightlight :log="log" :type="config.colorMode ?? 'nginx'"></hightlight>
|
||||
</div>
|
||||
<div class="log-container" ref="logContainer" :style="containerStyle">
|
||||
<CodemirrorPro
|
||||
v-if="true"
|
||||
v-model="logInfo"
|
||||
:lineWrapping="true"
|
||||
:heightDiff="330"
|
||||
:disabled="true"
|
||||
></CodemirrorPro>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { downloadFile } from '@/utils/util';
|
||||
import { readByLine } from '@/api/modules/files';
|
||||
import { GlobalStore } from '@/store';
|
||||
import bus from '@/global/bus';
|
||||
import hightlight from '@/components/log/custom-hightlight/index.vue';
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
interface LogProps {
|
||||
|
@ -129,34 +126,10 @@ const minPage = ref(0);
|
|||
let timer: NodeJS.Timer | null = null;
|
||||
const logPath = ref('');
|
||||
|
||||
const logInfo = ref<string>('');
|
||||
const firstLoading = ref(false);
|
||||
const logs = ref<string[]>([]);
|
||||
const logContainer = ref<HTMLElement | null>(null);
|
||||
const logHeight = 20;
|
||||
const logCount = ref(0);
|
||||
const totalHeight = computed(() => logHeight * logCount.value);
|
||||
const containerHeight = ref(500);
|
||||
const visibleCount = computed(() => Math.ceil(containerHeight.value / logHeight));
|
||||
const startIndex = ref(0);
|
||||
|
||||
const visibleLogs = computed(() => {
|
||||
return logs.value.slice(startIndex.value, startIndex.value + visibleCount.value);
|
||||
});
|
||||
|
||||
const onScroll = () => {
|
||||
if (logContainer.value) {
|
||||
const scrollTop = logContainer.value.scrollTop;
|
||||
if (scrollTop == 0) {
|
||||
readReq.page = minPage.value - 1;
|
||||
if (readReq.page < 1) {
|
||||
return;
|
||||
}
|
||||
minPage.value = readReq.page;
|
||||
getContent(true);
|
||||
}
|
||||
startIndex.value = Math.floor(scrollTop / logHeight);
|
||||
}
|
||||
};
|
||||
|
||||
const changeLoading = () => {
|
||||
loading.value = !loading.value;
|
||||
|
@ -169,10 +142,8 @@ const onDownload = async () => {
|
|||
changeLoading();
|
||||
};
|
||||
|
||||
const changeTail = (fromOutSide: boolean) => {
|
||||
if (fromOutSide) {
|
||||
const changeTail = () => {
|
||||
tailLog.value = !tailLog.value;
|
||||
}
|
||||
if (tailLog.value) {
|
||||
timer = setInterval(() => {
|
||||
getContent(false);
|
||||
|
@ -212,7 +183,7 @@ const getContent = async (pre: boolean) => {
|
|||
isLoading.value = false;
|
||||
firstLoading.value = false;
|
||||
}
|
||||
|
||||
logInfo.value = res.data.content;
|
||||
logPath.value = res.data.path;
|
||||
firstLoading.value = false;
|
||||
|
||||
|
@ -255,15 +226,6 @@ const getContent = async (pre: boolean) => {
|
|||
logs.value = pre ? [...newLogs, ...logs.value] : [...logs.value, ...newLogs];
|
||||
}
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
if (pre) {
|
||||
logContainer.value.scrollTop = 2000;
|
||||
} else {
|
||||
logContainer.value.scrollTop = totalHeight.value;
|
||||
containerHeight.value = logContainer.value.getBoundingClientRect().height;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logCount.value = logs.value.length;
|
||||
|
@ -317,7 +279,7 @@ const init = async () => {
|
|||
tailLog.value = false;
|
||||
}
|
||||
if (tailLog.value) {
|
||||
changeTail(false);
|
||||
changeTail();
|
||||
}
|
||||
readReq.latest = true;
|
||||
await getContent(false);
|
||||
|
@ -331,12 +293,6 @@ onMounted(async () => {
|
|||
logs.value = [];
|
||||
firstLoading.value = true;
|
||||
await init();
|
||||
nextTick(() => {
|
||||
if (logContainer.value) {
|
||||
logContainer.value.scrollTop = totalHeight.value;
|
||||
containerHeight.value = logContainer.value.getBoundingClientRect().height;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
@ -347,7 +303,7 @@ defineExpose({ changeTail, onDownload, clearLog });
|
|||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.log-container {
|
||||
overflow-y: auto;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
background-color: var(--panel-logs-bg-color);
|
||||
|
|
|
@ -351,7 +351,7 @@
|
|||
<PruneDialog @search="search" ref="dialogPruneRef" />
|
||||
|
||||
<RenameDialog @search="search" ref="dialogRenameRef" />
|
||||
<ContainerLogDialog ref="dialogContainerLogRef" :highlightDiff="235" />
|
||||
<ContainerLogDialog ref="dialogContainerLogRef" :highlightDiff="210" />
|
||||
<UpgradeDialog @search="search" ref="dialogUpgradeRef" />
|
||||
<CommitDialog @search="search" ref="dialogCommitRef" />
|
||||
<MonitorDialog ref="dialogMonitorRef" />
|
||||
|
|
Loading…
Add table
Reference in a new issue