Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/components/client/virtual/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const props = defineProps({
activeKey: { default: '' },
threshold: { default: 0 },
maxHeight: String,
follow: { type: Boolean, default: true },
activate: {
type: String as PropType<'top' | 'bottom' | 'current'>,
default: 'bottom',
Expand All @@ -47,7 +48,7 @@ const root = ref<typeof ElScrollbar>()

watch(() => props.data.length, () => {
const { scrollTop, clientHeight, scrollHeight } = root.value.wrapRef
if (!props.pinned || Math.abs(scrollTop + clientHeight - scrollHeight) < 1) {
if (props.follow && (!props.pinned || Math.abs(scrollTop + clientHeight - scrollHeight) < 1)) {
nextTick(scrollToBottom)
}
virtual.updateUids(getUids())
Expand Down Expand Up @@ -93,6 +94,10 @@ onMounted(() => {
}
})

watch(() => props.follow, (value) => {
if (value) nextTick(scrollToBottom)
})

function scrollToOffset(offset: number, smooth = false) {
if (smooth) {
root.value.wrapRef.scrollTo({ top: offset, behavior: 'smooth' })
Expand Down
87 changes: 86 additions & 1 deletion plugins/logger/client/index.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,97 @@
<template>
<k-layout>
<logs class="layout-logger" :logs="store.logs" show-link></logs>
<div class="logger-toolbar">
<el-input
v-model="keyword"
class="logger-search"
placeholder="输入关键词以过滤日志,使用空格分隔多个关键词"
clearable
size="small"
>
<template #suffix>
<k-icon name="search" />
</template>
</el-input>
<el-switch
v-model="wrap"
size="small"
active-text="自动换行"
inactive-text="单行显示"
/>
<el-button size="small" @click="toggleScroll">
{{ autoScroll ? '停止滚动' : '恢复滚动' }}
</el-button>
<span class="logger-toolbar__stat" v-if="keywordList.length">
匹配 {{ filteredLogs.length }} / {{ totalLogs }}
</span>
</div>
<logs
class="layout-logger"
:logs="filteredLogs"
show-link
:wrap="wrap"
:follow="autoScroll"
pinned
></logs>
</k-layout>
</template>

<script lang="ts" setup>

import { store } from '@koishijs/client'
import { computed, ref } from 'vue'
import Logs from './logs.vue'

const keyword = ref('')
const wrap = ref(true)
const autoScroll = ref(true)

const normalizedKeyword = computed(() => keyword.value.trim().toLowerCase())
const keywordList = computed(() => normalizedKeyword.value.split(/\s+/).filter(Boolean))
const totalLogs = computed(() => store.logs?.length || 0)

const filteredLogs = computed(() => {
const logs = store.logs || []
if (!keywordList.value.length) return logs
return logs.filter((record) => {
const target = [
record.name,
record.type,
record.content,
record.meta?.paths?.join(' '),
].filter(Boolean).join(' ').toLowerCase()
return keywordList.value.every((word) => target.includes(word))
})
})

function toggleScroll() {
autoScroll.value = !autoScroll.value
}

</script>

<style lang="scss" scoped>

.logger-toolbar {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
align-items: center;
margin-bottom: 0.75rem;

:deep(.el-switch__label) {
font-size: 12px;
}
}

.logger-search {
flex: 1;
min-width: 240px;
}

.logger-toolbar__stat {
font-size: 12px;
color: var(--k-text-secondary);
}

</style>
42 changes: 37 additions & 5 deletions plugins/logger/client/logs.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<template>
<virtual-list class="log-list k-text-selectable" :data="logs" :count="300" :max-height="maxHeight">
<virtual-list
:class="['log-list k-text-selectable', { 'nowrap-enabled': !wrap }]"
:data="logs"
:count="300"
:max-height="maxHeight"
:pinned="pinned"
:follow="follow"
>
<template #="record">
<div :class="{ line: true, start: isStart(record) }">
<div :class="{ line: true, start: isStart(record), nowrap: !wrap }">
<code v-html="renderLine(record)"></code>
<router-link
class="log-link inline-flex items-center justify-center absolute w-20px h-20px bottom-0 right-0"
Expand All @@ -22,11 +29,19 @@ import {} from '@koishijs/plugin-config'
import Logger from 'reggol'
import ansi from 'ansi_up'

const props = defineProps<{
const props = withDefaults(defineProps<{
logs: Logger.Record[],
showLink?: boolean,
maxHeight?: string,
}>()
pinned?: boolean,
follow?: boolean,
wrap?: boolean,
}>(), {
showLink: false,
pinned: false,
follow: true,
wrap: true,
})

// this package does not have consistent exports in different environments
const converter = new (ansi['default'] || ansi)()
Expand All @@ -38,7 +53,9 @@ function renderColor(code: number, value: any, decoration = '') {
const showTime = 'yyyy-MM-dd hh:mm:ss'

function isStart(record: Logger.Record & { index: number }) {
return record.index && props.logs[record.index - 1].id > record.id && record.name === 'app'
if (!record?.index || !store.logs?.length) return false
const previous = store.logs[record.index - 1]
return !!previous && previous.id > record.id && record.name === 'app'
}

function renderLine(record: Logger.Record) {
Expand Down Expand Up @@ -106,6 +123,21 @@ function renderLine(record: Logger.Record) {
background-color: var(--terminal-bg-selection);
}
}

&.nowrap-enabled {
:deep(.el-scrollbar__wrap) {
overflow-x: auto;
}

:deep(.el-scrollbar__view) {
min-width: fit-content;
}

.line.nowrap {
white-space: pre;
word-break: normal;
}
}
}

</style>
17 changes: 12 additions & 5 deletions yakumo.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- name: yakumo
- id: csdja9
name: yakumo
config:
pipeline:
build:
Expand All @@ -7,7 +8,13 @@
- client
clean:
- tsc --clean
- name: yakumo-esbuild
- name: yakumo-mocha
- name: yakumo-tsc
- name: '@koishijs/client/lib'
- id: im28qa
name: yakumo-esbuild
- id: xze1p8
name: yakumo-mocha
- id: w2p6rr
name: yakumo-tsc
- id: ixt9c8
name: '@koishijs/client/lib'
- id: hk5mez
name: yakumo/run