From 13f343977ab90ced82fafdf25af101e146ff189b Mon Sep 17 00:00:00 2001
From: Lykin <137850705+tiny-craft@users.noreply.github.com>
Date: Fri, 17 Nov 2023 23:50:10 +0800
Subject: [PATCH] chore: refine ui details
---
backend/utils/string/convert.go | 2 +-
.../src/components/content/ContentLogPane.vue | 181 +++++++++---------
.../content_value/ContentEntryEditor.vue | 2 +
.../components/content_value/ContentSlog.vue | 166 ++++++++--------
.../content_value/ContentValueHash.vue | 4 +
.../content_value/ContentValueList.vue | 4 +
.../content_value/ContentValueZSet.vue | 10 +-
.../src/components/new_value/AddHashValue.vue | 4 +-
.../src/components/new_value/AddZSetValue.vue | 7 +-
frontend/src/langs/en-us.json | 2 +-
frontend/src/langs/pt-br.json | 2 +-
frontend/src/langs/zh-cn.json | 2 +-
12 files changed, 204 insertions(+), 182 deletions(-)
diff --git a/backend/utils/string/convert.go b/backend/utils/string/convert.go
index e8c3e2f..12ebd8c 100644
--- a/backend/utils/string/convert.go
+++ b/backend/utils/string/convert.go
@@ -109,7 +109,7 @@ func autoDecode(str string) (value, resultDecode string) {
// pure digit content may incorrect regard as some encoded type, skip decode
if match, _ := regexp.MatchString(`^\d+$`, str); !match {
var ok bool
- if len(str)%4 == 0 && !isSameChar(str) {
+ if len(str)%4 == 0 && len(str) >= 12 && !isSameChar(str) {
if value, ok = decodeBase64(str); ok {
resultDecode = types.DECODE_BASE64
return
diff --git a/frontend/src/components/content/ContentLogPane.vue b/frontend/src/components/content/ContentLogPane.vue
index fc4c79e..27493d2 100644
--- a/frontend/src/components/content/ContentLogPane.vue
+++ b/frontend/src/components/content/ContentLogPane.vue
@@ -34,39 +34,101 @@ const filterServerOption = computed(() => {
const tableRef = ref(null)
-const loadHistory = () => {
- data.loading = true
- browserStore
- .getCmdHistory()
- .then((list) => {
- data.history = list || []
- })
- .finally(() => {
- data.loading = false
- tableRef.value?.scrollTo({ top: 999999 })
- })
+const columns = computed(() => [
+ {
+ title: i18n.t('log.exec_time'),
+ key: 'timestamp',
+ defaultSortOrder: 'ascend',
+ sorter: 'default',
+ width: 180,
+ align: 'center',
+ titleAlign: 'center',
+ render: ({ timestamp }, index) => {
+ return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
+ },
+ },
+ {
+ title: i18n.t('log.server'),
+ key: 'server',
+ filterOptionValue: data.server,
+ filter: (value, row) => {
+ return value === '' || row.server === value.toString()
+ },
+ width: 150,
+ align: 'center',
+ titleAlign: 'center',
+ ellipsis: {
+ tooltip: true,
+ },
+ },
+ {
+ title: i18n.t('log.cmd'),
+ key: 'cmd',
+ titleAlign: 'center',
+ filterOptionValue: data.keyword,
+ resizable: true,
+ filter: (value, row) => {
+ return value === '' || !!~row.cmd.indexOf(value.toString())
+ },
+ render: ({ cmd }, index) => {
+ const cmdList = split(cmd, '\n')
+ if (size(cmdList) > 1) {
+ return h(
+ 'div',
+ null,
+ map(cmdList, (c) => h('div', null, c)),
+ )
+ }
+ return cmd
+ },
+ },
+ {
+ title: i18n.t('log.cost_time'),
+ key: 'cost',
+ width: 100,
+ align: 'center',
+ titleAlign: 'center',
+ render: ({ cost }, index) => {
+ const ms = dayjs.duration(cost).asMilliseconds()
+ if (ms < 1000) {
+ return `${ms} ms`
+ } else {
+ return `${Math.floor(ms / 1000)} s`
+ }
+ },
+ },
+])
+
+const loadHistory = async () => {
+ try {
+ await nextTick()
+ data.loading = true
+ const list = await browserStore.getCmdHistory()
+ data.history = list || []
+ } finally {
+ data.loading = false
+ tableRef.value?.scrollTo({ top: 999999 })
+ }
}
const cleanHistory = async () => {
- $dialog.warning(i18n.t('log.confirm_clean_log'), () => {
- data.loading = true
- browserStore
- .cleanCmdHistory()
- .then((success) => {
- if (success) {
- data.history = []
- tableRef.value?.scrollTo({ top: 0 })
- $message.success(i18n.t('common.success'))
- }
- })
- .finally(() => {
- data.loading = false
- })
+ $dialog.warning(i18n.t('log.confirm_clean_log'), async () => {
+ try {
+ data.loading = true
+ const success = await browserStore.cleanCmdHistory()
+ if (success) {
+ data.history = []
+ tableRef.value?.scrollTo({ top: 0 })
+ $message.success(i18n.t('common.success'))
+ }
+ } finally {
+ data.loading = false
+ }
})
}
defineExpose({
- refresh: () => nextTick().then(loadHistory),
+ refresh: loadHistory,
})
@@ -98,71 +160,12 @@ defineExpose({
+ flex-height
+ virtual-scroll />
diff --git a/frontend/src/components/content_value/ContentEntryEditor.vue b/frontend/src/components/content_value/ContentEntryEditor.vue
index 789387c..31711a5 100644
--- a/frontend/src/components/content_value/ContentEntryEditor.vue
+++ b/frontend/src/components/content_value/ContentEntryEditor.vue
@@ -151,6 +151,7 @@ const onSave = () => {
{{ props.fieldLabel }}
@@ -160,6 +161,7 @@ const onSave = () => {
{{ props.valueLabel }}
-import { h, onMounted, onUnmounted, reactive, ref } from 'vue'
+import { computed, h, onMounted, onUnmounted, reactive, ref } from 'vue'
import Refresh from '@/components/icons/Refresh.vue'
import { debounce, isEmpty, map, size, split } from 'lodash'
import { useI18n } from 'vue-i18n'
@@ -33,6 +33,85 @@ const data = reactive({
const tableRef = ref(null)
+const columns = computed(() => [
+ {
+ title: i18n.t('slog.exec_time'),
+ key: 'timestamp',
+ sortOrder: data.sortOrder,
+ sorter: 'default',
+ width: 180,
+ align: 'center',
+ titleAlign: 'center',
+ render: ({ timestamp }, index) => {
+ return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
+ },
+ },
+ {
+ title: i18n.t('slog.client'),
+ key: 'client',
+ filterOptionValue: data.client,
+ resizable: true,
+ filter: (value, row) => {
+ return value === '' || row.client === value.toString() || row.addr === value.toString()
+ },
+ width: 200,
+ align: 'center',
+ titleAlign: 'center',
+ ellipsis: {
+ tooltip: true,
+ },
+ render: ({ client, addr }, index) => {
+ let content = ''
+ if (!isEmpty(client)) {
+ content += client
+ }
+ if (!isEmpty(addr)) {
+ if (!isEmpty(content)) {
+ content += ' - '
+ }
+ content += addr
+ }
+ return content
+ },
+ },
+ {
+ title: i18n.t('slog.cmd'),
+ key: 'cmd',
+ titleAlign: 'center',
+ filterOptionValue: data.keyword,
+ resizable: true,
+ filter: (value, row) => {
+ return value === '' || !!~row.cmd.indexOf(value.toString())
+ },
+ render: ({ cmd }, index) => {
+ const cmdList = split(cmd, '\n')
+ if (size(cmdList) > 1) {
+ return h(
+ 'div',
+ null,
+ map(cmdList, (c) => h('div', null, c)),
+ )
+ }
+ return cmd
+ },
+ },
+ {
+ title: i18n.t('slog.cost_time'),
+ key: 'cost',
+ width: 100,
+ align: 'center',
+ titleAlign: 'center',
+ render: ({ cost }, index) => {
+ const ms = dayjs.duration(cost).asMilliseconds()
+ if (ms < 1000) {
+ return `${ms} ms`
+ } else {
+ return `${Math.floor(ms / 1000)} s`
+ }
+ },
+ },
+])
+
const _loadSlowLog = () => {
data.loading = true
browserStore
@@ -103,86 +182,12 @@ const onListLimitChanged = (limit) => {
(data.sortOrder = order)" />
@@ -190,9 +195,4 @@ const onListLimitChanged = (limit) => {
diff --git a/frontend/src/components/content_value/ContentValueHash.vue b/frontend/src/components/content_value/ContentValueHash.vue
index fd56f00..98be334 100644
--- a/frontend/src/components/content_value/ContentValueHash.vue
+++ b/frontend/src/components/content_value/ContentValueHash.vue
@@ -158,6 +158,10 @@ const saveEdit = async (field, value, decode, format) => {
throw new Error('row not exists')
}
+ if (isEmpty(field)) {
+ field = currentEditRow.key
+ }
+
const { success, msg } = await browserStore.setHash({
server: props.name,
db: props.db,
diff --git a/frontend/src/components/content_value/ContentValueList.vue b/frontend/src/components/content_value/ContentValueList.vue
index fe1717f..1be0501 100644
--- a/frontend/src/components/content_value/ContentValueList.vue
+++ b/frontend/src/components/content_value/ContentValueList.vue
@@ -130,6 +130,10 @@ const saveEdit = async (pos, value, decode, format) => {
throw new Error('row not exists')
}
+ if (isEmpty(value)) {
+ value = currentEditRow.value
+ }
+
const { success, msg } = await browserStore.updateListItem({
server: props.name,
db: props.db,
diff --git a/frontend/src/components/content_value/ContentValueZSet.vue b/frontend/src/components/content_value/ContentValueZSet.vue
index c27f041..838944a 100644
--- a/frontend/src/components/content_value/ContentValueZSet.vue
+++ b/frontend/src/components/content_value/ContentValueZSet.vue
@@ -68,7 +68,7 @@ const filterOption = [
},
{
value: 2,
- label: i18n.t('interface.score'),
+ label: i18n.t('common.score'),
},
]
const filterType = ref(1)
@@ -95,7 +95,7 @@ const inFullEdit = computed(() => {
const scoreFilterOption = ref(null)
const scoreColumn = computed(() => ({
key: 'score',
- title: i18n.t('interface.score'),
+ title: i18n.t('common.score'),
align: 'center',
titleAlign: 'center',
resizable: true,
@@ -183,6 +183,10 @@ const saveEdit = async (field, value, decode, format) => {
throw new Error('row not exists')
}
+ if (isEmpty(value)) {
+ value = currentEditRow.value
+ }
+
const { success, msg } = await browserStore.updateZSetItem({
server: props.name,
db: props.db,
@@ -429,7 +433,7 @@ defineExpose({
v-model:fullscreen="fullEdit"
:decode="currentEditRow.decode"
:field="currentEditRow.score"
- :field-label="$t('interface.score')"
+ :field-label="$t('common.score')"
:format="currentEditRow.format"
:value="currentEditRow.value"
:value-label="$t('common.value')"
diff --git a/frontend/src/components/new_value/AddHashValue.vue b/frontend/src/components/new_value/AddHashValue.vue
index c3e3b97..5803039 100644
--- a/frontend/src/components/new_value/AddHashValue.vue
+++ b/frontend/src/components/new_value/AddHashValue.vue
@@ -50,7 +50,9 @@ const onUpdate = (val) => {
-
+
{
-
+
+ :