|
@@ -1,7 +1,8 @@
|
|
<template>
|
|
<template>
|
|
- <div class="magic-log-wrapper" @contextmenu.prevent="e=> onContextMenu(e)">
|
|
|
|
|
|
+ <div class="magic-log-wrapper">
|
|
|
|
+ <magic-panel-toolbar :toolbars="toolbars"/>
|
|
<magic-empty v-if="!logs ||logs.length === 0" :text="$i('message.empty', $i('message.log'))"/>
|
|
<magic-empty v-if="!logs ||logs.length === 0" :text="$i('message.empty', $i('message.log'))"/>
|
|
- <div v-else class="magic-log" ref="element">
|
|
|
|
|
|
+ <div v-show="logs && logs.length > 0" class="magic-log" ref="element" @contextmenu.prevent="e=> onContextMenu(e)">
|
|
<div v-for="(item, key) in logs" :class="{ multiple: item.multiple, more: item.showMore }" :key="'run_log_' + key">
|
|
<div v-for="(item, key) in logs" :class="{ multiple: item.multiple, more: item.showMore }" :key="'run_log_' + key">
|
|
<pre v-html="item.html"></pre>
|
|
<pre v-html="item.html"></pre>
|
|
<span v-if="item.multiple" class="multiple" @click="item.showMore = !item.showMore">
|
|
<span v-if="item.multiple" class="multiple" @click="item.showMore = !item.showMore">
|
|
@@ -12,13 +13,44 @@
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
<script setup>
|
|
<script setup>
|
|
-import { getCurrentInstance, nextTick, ref } from 'vue'
|
|
|
|
|
|
+import { getCurrentInstance, nextTick, onMounted, ref } from 'vue'
|
|
import bus from '../../../scripts/bus.js'
|
|
import bus from '../../../scripts/bus.js'
|
|
import $i from '../../../scripts/i18n.js'
|
|
import $i from '../../../scripts/i18n.js'
|
|
import Socket from '../../../scripts/constants/socket.js'
|
|
import Socket from '../../../scripts/constants/socket.js'
|
|
const logs = ref([])
|
|
const logs = ref([])
|
|
|
|
+const keepScroll = ref(false)
|
|
|
|
+const toolbars = ref([{
|
|
|
|
+ icon: 'expand-all',
|
|
|
|
+ title: $i('resource.header.expand'),
|
|
|
|
+ onClick: ()=> logs.value.forEach(it => it.showMore = true)
|
|
|
|
+}, {
|
|
|
|
+ icon: 'collapse-all',
|
|
|
|
+ title: $i('resource.header.collapse'),
|
|
|
|
+ onClick: ()=> logs.value.forEach(it => it.showMore = false)
|
|
|
|
+}, {
|
|
|
|
+ icon: 'delete',
|
|
|
|
+ title: $i('message.clear'),
|
|
|
|
+ onClick: ()=> logs.value.splice(0)
|
|
|
|
+}, {
|
|
|
|
+ icon: 'scroll-down',
|
|
|
|
+ title: $i('log.scrollEnd'),
|
|
|
|
+ selectable: true,
|
|
|
|
+ onSelect: (val)=> {
|
|
|
|
+ keepScroll.value = val
|
|
|
|
+ updateScroll()
|
|
|
|
+ }
|
|
|
|
+}])
|
|
const element = ref(null)
|
|
const element = ref(null)
|
|
const { proxy } = getCurrentInstance()
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
+const updateScroll = () => {
|
|
|
|
+ if(keepScroll.value){
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ if(element.value){
|
|
|
|
+ element.value.scrollTop = element.value.scrollHeight
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|
|
const onContextMenu = event => {
|
|
const onContextMenu = event => {
|
|
proxy.$contextmenu({
|
|
proxy.$contextmenu({
|
|
event,
|
|
event,
|
|
@@ -58,30 +90,37 @@ const _pushLog = items => {
|
|
})
|
|
})
|
|
if(messages){
|
|
if(messages){
|
|
logs.value.push(...messages)
|
|
logs.value.push(...messages)
|
|
- nextTick(() => {
|
|
|
|
- if(element.value){
|
|
|
|
- element.value.scrollTop = element.value.scrollHeight
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
|
|
+ updateScroll()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bus.$event(Socket.LOGS, ([ rows ]) => _pushLog(rows))
|
|
bus.$event(Socket.LOGS, ([ rows ]) => _pushLog(rows))
|
|
bus.$event(Socket.LOG, ([ row ]) => _pushLog(row))
|
|
bus.$event(Socket.LOG, ([ row ]) => _pushLog(row))
|
|
|
|
+const observer = new IntersectionObserver(() => {
|
|
|
|
+ updateScroll()
|
|
|
|
+})
|
|
|
|
+onMounted(() => {
|
|
|
|
+ observer.observe(element.value)
|
|
|
|
+})
|
|
|
|
|
|
</script>
|
|
</script>
|
|
<style>
|
|
<style>
|
|
.magic-log-wrapper{
|
|
.magic-log-wrapper{
|
|
- position: relative;
|
|
|
|
- overflow: auto;
|
|
|
|
- width: 100%;
|
|
|
|
|
|
+ display: flex;
|
|
|
|
+ flex: 1;
|
|
height: 100%;
|
|
height: 100%;
|
|
- background: var(--run-log-background-color);
|
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ position: relative;
|
|
}
|
|
}
|
|
.magic-log {
|
|
.magic-log {
|
|
- position: absolute;
|
|
|
|
font-size: 13.5px;
|
|
font-size: 13.5px;
|
|
- height: 100%;
|
|
|
|
padding: 5px;
|
|
padding: 5px;
|
|
|
|
+ flex: 1;
|
|
|
|
+ overflow: auto;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 0;
|
|
|
|
+ right: 0;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ left: 24px;
|
|
}
|
|
}
|
|
.magic-log > div{
|
|
.magic-log > div{
|
|
width: 100%;
|
|
width: 100%;
|