mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-23 00:17:16 +08:00
Update On Mon Feb 16 19:58:17 CET 2026
This commit is contained in:
@@ -7,38 +7,63 @@
|
||||
</p>
|
||||
</header>
|
||||
<section ref="section" :class="{ 'modal-card-body': true }">
|
||||
<b-field :label="$tc('log.refreshInterval')">
|
||||
<b-select v-model="intervalTime" @input="changeInterval">
|
||||
<option
|
||||
v-for="candidate in intervalCandidate"
|
||||
:key="candidate"
|
||||
:value="candidate"
|
||||
>
|
||||
{{ `${candidate} ${$tc("log.seconds")}` }}
|
||||
</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
<b-field label="Logs" style="margin-bottom: 2rem">
|
||||
<div class="log-title">{{ $t("log.logsLabel") }}</div>
|
||||
<div class="log-content" tabindex="0" @keydown="handleLogKeydown">
|
||||
<RecycleScroller
|
||||
ref="logScroller"
|
||||
v-slot="{ item }"
|
||||
v-slot="{ item, index }"
|
||||
class="log-scroller"
|
||||
:items="items"
|
||||
:items="filteredItems"
|
||||
:item-size="itemSize"
|
||||
:grid-items="1"
|
||||
:buffer="1000"
|
||||
>
|
||||
<hightlight-log class="text" :text="item.text"></hightlight-log>
|
||||
<div class="log-row">
|
||||
<span class="log-line-number">{{ index + 1 }}</span>
|
||||
<hightlight-log class="text" :text="item.text"></hightlight-log>
|
||||
</div>
|
||||
</RecycleScroller>
|
||||
</b-field>
|
||||
<b-field>
|
||||
<b-switch v-model="autoScoll" @input="changeScoll">
|
||||
{{ $tc("log.autoScoll") }}
|
||||
</b-switch>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="log-footer">
|
||||
<div class="log-footer-item">
|
||||
<div class="log-footer-label">{{ $tc("log.refreshInterval") }}</div>
|
||||
<div class="log-footer-control">
|
||||
<b-select v-model="intervalTime" @input="changeInterval">
|
||||
<option
|
||||
v-for="candidate in intervalCandidate"
|
||||
:key="candidate"
|
||||
:value="candidate"
|
||||
>
|
||||
{{ `${candidate} ${$tc("log.seconds")}` }}
|
||||
</option>
|
||||
</b-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="log-footer-item">
|
||||
<div class="log-footer-label">{{ $tc("log.category") }}</div>
|
||||
<div class="log-footer-control">
|
||||
<b-select v-model="levelFilter">
|
||||
<option
|
||||
v-for="option in levelOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ $t(option.label) }}
|
||||
</option>
|
||||
</b-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="log-footer-item">
|
||||
<div class="log-footer-label">{{ $tc("log.autoScoll") }}</div>
|
||||
<div class="log-footer-control">
|
||||
<b-switch v-model="autoScoll" @input="changeScoll" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HightlightLog from "@/components/highlightLog";
|
||||
export default {
|
||||
@@ -53,8 +78,26 @@ export default {
|
||||
intervalCandidate: [2, 5, 10, 15],
|
||||
itemSize: 28,
|
||||
autoScoll: true,
|
||||
levelFilter: "all",
|
||||
levelOptions: [
|
||||
{ value: "all", label: "log.categories.all" },
|
||||
{ value: "error", label: "log.categories.error" },
|
||||
{ value: "warn", label: "log.categories.warn" },
|
||||
{ value: "info", label: "log.categories.info" },
|
||||
{ value: "debug", label: "log.categories.debug" },
|
||||
{ value: "trace", label: "log.categories.trace" },
|
||||
{ value: "other", label: "log.categories.other" },
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filteredItems() {
|
||||
if (this.levelFilter === "all") {
|
||||
return this.items;
|
||||
}
|
||||
return this.items.filter((item) => item.level === this.levelFilter);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.autoScoll = !(localStorage.getItem("log.autoScoll") === "false");
|
||||
|
||||
@@ -74,12 +117,63 @@ export default {
|
||||
clearInterval(this.intervalId);
|
||||
},
|
||||
methods: {
|
||||
handleLogKeydown(event) {
|
||||
const scroller = this.$refs.logScroller;
|
||||
const el = scroller && scroller.$el ? scroller.$el : null;
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
const pageStep = Math.max(1, Math.floor(el.clientHeight * 0.9));
|
||||
switch (event.key) {
|
||||
case "Home":
|
||||
el.scrollTop = 0;
|
||||
event.preventDefault();
|
||||
break;
|
||||
case "End":
|
||||
el.scrollTop = el.scrollHeight;
|
||||
event.preventDefault();
|
||||
break;
|
||||
case "PageUp":
|
||||
el.scrollTop = Math.max(0, el.scrollTop - pageStep);
|
||||
event.preventDefault();
|
||||
break;
|
||||
case "PageDown":
|
||||
el.scrollTop = Math.min(el.scrollHeight, el.scrollTop + pageStep);
|
||||
event.preventDefault();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
detectLevel(text) {
|
||||
const lower = text.toLowerCase();
|
||||
if (lower.includes("[e]") || lower.includes(" error ")) {
|
||||
return "error";
|
||||
}
|
||||
if (lower.includes("[w]") || lower.includes(" warn")) {
|
||||
return "warn";
|
||||
}
|
||||
if (lower.includes("[d]") || lower.includes(" debug")) {
|
||||
return "debug";
|
||||
}
|
||||
if (lower.includes("[t]") || lower.includes(" trace")) {
|
||||
return "trace";
|
||||
}
|
||||
if (lower.includes("[i]") || lower.includes(" info")) {
|
||||
return "info";
|
||||
}
|
||||
return "other";
|
||||
},
|
||||
updateLog(logs) {
|
||||
if (logs.data.length && logs.data.length !== 0) {
|
||||
const baseIndex = this.items.length;
|
||||
const items = logs.data
|
||||
.split("\n")
|
||||
.map((x, i) => ({ text: x, id: baseIndex + i }));
|
||||
.map((x, i) => ({
|
||||
text: x,
|
||||
id: baseIndex + i,
|
||||
level: this.detectLevel(x),
|
||||
}));
|
||||
if (this.endOfLine) {
|
||||
this.items = this.items.concat(items);
|
||||
} else {
|
||||
@@ -88,8 +182,8 @@ export default {
|
||||
}
|
||||
this.endOfLine = items[items.length - 1].text.endsWith("\n");
|
||||
this.currentSkip += new Blob([logs.data]).size;
|
||||
if (this.autoScoll) {
|
||||
this.$refs.logScroller.scrollToItem(this.items.length - 1);
|
||||
if (this.autoScoll && this.filteredItems.length > 0) {
|
||||
this.$refs.logScroller.scrollToItem(this.filteredItems.length - 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -109,13 +203,70 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.text {
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.log-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.log-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.log-line-number {
|
||||
min-width: 3.5rem;
|
||||
text-align: right;
|
||||
color: #9aa4b2;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.log-footer {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.log-footer-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
.log-footer-label {
|
||||
font-weight: 600;
|
||||
min-height: 1.5rem;
|
||||
}
|
||||
|
||||
.log-footer-control ::v-deep .control,
|
||||
.log-footer-control ::v-deep .select,
|
||||
.log-footer-control ::v-deep select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.log-footer-control ::v-deep .control {
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.log-scroller {
|
||||
height: 50vh;
|
||||
|
||||
Reference in New Issue
Block a user