perf: add refresh interval option for server status page

This commit is contained in:
Lykin 2024-01-12 15:36:30 +08:00
parent a3f9c62f4e
commit a663ecdeb5
7 changed files with 119 additions and 41 deletions

View File

@ -0,0 +1,69 @@
<script setup>
import { isNumber } from 'lodash'
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
on: {
type: Boolean,
default: false,
},
defaultValue: {
type: Number,
default: 2,
},
interval: {
type: Number,
default: 2,
},
onRefresh: {
type: Function,
default: () => {},
},
})
const emit = defineEmits(['toggle', 'update:on', 'update:interval'])
const onToggle = (on) => {
emit('update:on', on === true)
if (on) {
let interval = props.interval
if (!isNumber(interval)) {
interval = props.defaultValue
}
interval = Math.max(1, interval)
emit('update:interval', interval)
emit('toggle', true)
} else {
emit('toggle', false)
}
}
</script>
<template>
<n-form :show-feedback="false" label-align="right" label-placement="left" label-width="auto" size="small">
<n-form-item :label="$t('interface.auto_refresh')">
<n-switch :loading="props.loading" :value="props.on" @update:value="onToggle" />
</n-form-item>
<n-form-item :label="$t('interface.refresh_interval')">
<n-input-number
:autofocus="false"
:default-value="props.defaultValue"
:disabled="props.on"
:max="9999"
:min="1"
:show-button="false"
:value="props.interval"
style="max-width: 100px"
@update:value="(val) => emit('update:interval', val)">
<template #suffix>
{{ $t('common.unit_second') }}
</template>
</n-input-number>
</n-form-item>
</n-form>
</template>
<style lang="scss" scoped></style>

View File

@ -6,16 +6,19 @@ import Filter from '@/components/icons/Filter.vue'
import Refresh from '@/components/icons/Refresh.vue' import Refresh from '@/components/icons/Refresh.vue'
import useBrowserStore from 'stores/browser.js' import useBrowserStore from 'stores/browser.js'
import { timeout } from '@/utils/promise.js' import { timeout } from '@/utils/promise.js'
import AutoRefreshForm from '@/components/common/AutoRefreshForm.vue'
import { NIcon, useThemeVars } from 'naive-ui'
const props = defineProps({ const props = defineProps({
server: String, server: String,
}) })
const browserStore = useBrowserStore() const browserStore = useBrowserStore()
const themeVars = useThemeVars()
const serverInfo = ref({}) const serverInfo = ref({})
const pageState = reactive({ const pageState = reactive({
autoRefresh: false, autoRefresh: false,
refreshInterval: 1, refreshInterval: 5,
loading: false, // loading status for refresh loading: false, // loading status for refresh
autoLoading: false, // loading status for auto refresh autoLoading: false, // loading status for auto refresh
}) })
@ -41,15 +44,11 @@ const refreshInfo = async (force) => {
} }
} }
const isLoading = computed(() => {
return pageState.loading || pageState.autoLoading
})
const startAutoRefresh = async () => { const startAutoRefresh = async () => {
if (pageState.autoRefresh) {
return
}
pageState.autoRefresh = true
if (!isNaN(pageState.refreshInterval)) {
pageState.refreshInterval = 5
}
pageState.refreshInterval = Math.min(pageState.refreshInterval, 1)
let lastExec = Date.now() let lastExec = Date.now()
do { do {
if (!pageState.autoRefresh) { if (!pageState.autoRefresh) {
@ -171,28 +170,34 @@ const infoFilter = ref('')
</n-space> </n-space>
</template> </template>
<template #header-extra> <template #header-extra>
<n-space align="center" inline> <n-popover keep-alive-on-hover placement="bottom-end" trigger="hover">
{{ $t('status.auto_refresh') }} <template #trigger>
<n-switch <n-button
:loading="pageState.loading"
:type="isLoading ? 'primary' : 'default'"
circle
size="small"
tertiary
@click="refreshInfo(true)">
<template #icon>
<n-icon :size="props.size">
<refresh
:class="{
'auto-rotate': pageState.autoRefresh || isLoading,
}"
:color="pageState.autoRefresh ? themeVars.primaryColor : undefined"
:stroke-width="pageState.autoRefresh ? 6 : 3" />
</n-icon>
</template>
</n-button>
</template>
<auto-refresh-form
v-model:interval="pageState.refreshInterval"
v-model:on="pageState.autoRefresh"
:default-value="5"
:loading="pageState.autoLoading" :loading="pageState.autoLoading"
:value="pageState.autoRefresh" @toggle="onToggleRefresh" />
@update:value="onToggleRefresh" /> </n-popover>
<n-tooltip>
{{ $t('status.refresh') }}
<template #trigger>
<n-button
:loading="pageState.autoLoading"
circle
size="small"
tertiary
@click="refreshInfo(true)">
<template #icon>
<n-icon :component="Refresh" />
</template>
</n-button>
</template>
</n-tooltip>
</n-space>
</template> </template>
<n-spin :show="pageState.loading"> <n-spin :show="pageState.loading">
<n-grid style="min-width: 500px" x-gap="5"> <n-grid style="min-width: 500px" x-gap="5">

View File

@ -16,14 +16,14 @@ const props = defineProps({
<path <path
:stroke-width="props.strokeWidth" :stroke-width="props.strokeWidth"
d="M36.7279 36.7279C33.4706 39.9853 28.9706 42 24 42C14.0589 42 6 33.9411 6 24C6 14.0589 14.0589 6 24 6C28.9706 6 33.4706 8.01472 36.7279 11.2721C38.3859 12.9301 42 17 42 17" d="M36.7279 36.7279C33.4706 39.9853 28.9706 42 24 42C14.0589 42 6 33.9411 6 24C6 14.0589 14.0589 6 24 6C28.9706 6 33.4706 8.01472 36.7279 11.2721C38.3859 12.9301 42 17 42 17"
stroke="currentColor" :stroke="color"
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" /> stroke-linejoin="round" />
<path <path
:stroke-width="props.strokeWidth" :stroke-width="props.strokeWidth"
class="default-stroke" class="default-stroke"
d="M42 8V17H33" d="M42 8V17H33"
stroke="currentColor" :stroke="color"
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" /> stroke-linejoin="round" />
</svg> </svg>

View File

@ -359,9 +359,7 @@
"connected_clients": "Clients", "connected_clients": "Clients",
"total_keys": "Keys", "total_keys": "Keys",
"memory_used": "Memory", "memory_used": "Memory",
"all_info": "Information", "all_info": "Information"
"refresh": "Refresh",
"auto_refresh": "Auto Refresh"
}, },
"slog": { "slog": {
"title": "Slow Log", "title": "Slow Log",

View File

@ -291,9 +291,7 @@
"connected_clients": "Clientes Conectados", "connected_clients": "Clientes Conectados",
"total_keys": "Chaves Totais", "total_keys": "Chaves Totais",
"memory_used": "Memória Usada", "memory_used": "Memória Usada",
"all_info": "Informações", "all_info": "Informações"
"refresh": "Atualizar",
"auto_refresh": "Atualização Automática"
}, },
"slog": { "slog": {
"title": "Registro de Operações Lentas", "title": "Registro de Operações Lentas",

View File

@ -359,9 +359,7 @@
"connected_clients": "已连客户端", "connected_clients": "已连客户端",
"total_keys": "键总数", "total_keys": "键总数",
"memory_used": "内存使用", "memory_used": "内存使用",
"all_info": "全部信息", "all_info": "全部信息"
"refresh": "立即刷新",
"auto_refresh": "自动刷新"
}, },
"slog": { "slog": {
"title": "慢日志", "title": "慢日志",

View File

@ -168,3 +168,13 @@ body {
.fade-leave-to { .fade-leave-to {
opacity: 0; opacity: 0;
} }
.auto-rotate {
animation: rotate 2s linear infinite;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}