mirror of
				https://github.com/tiny-craft/tiny-rdm.git
				synced 2025-10-31 10:36:22 +08:00 
			
		
		
		
	feat: add display of content length and size info
This commit is contained in:
		| @@ -825,17 +825,19 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var value any | 	var value any | ||||||
| 	var size int64 | 	var size, length int64 | ||||||
| 	var cursor uint64 | 	var cursor uint64 | ||||||
| 	switch strings.ToLower(keyType) { | 	switch strings.ToLower(keyType) { | ||||||
| 	case "string": | 	case "string": | ||||||
| 		var str string | 		var str string | ||||||
| 		str, err = client.Get(ctx, key).Result() | 		str, err = client.Get(ctx, key).Result() | ||||||
| 		value, decodeType, viewAs = strutil.ConvertTo(str, decodeType, viewAs) | 		value, decodeType, viewAs = strutil.ConvertTo(str, decodeType, viewAs) | ||||||
| 		size, _ = client.StrLen(ctx, key).Result() | 		length, _ = client.StrLen(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	case "list": | 	case "list": | ||||||
| 		value, err = client.LRange(ctx, key, 0, -1).Result() | 		value, err = client.LRange(ctx, key, 0, -1).Result() | ||||||
| 		size, _ = client.LLen(ctx, key).Result() | 		length, _ = client.LLen(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	case "hash": | 	case "hash": | ||||||
| 		//value, err = client.HGetAll(ctx, key).Result() | 		//value, err = client.HGetAll(ctx, key).Result() | ||||||
| 		items := map[string]string{} | 		items := map[string]string{} | ||||||
| @@ -855,7 +857,8 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		value = items | 		value = items | ||||||
| 		size, _ = client.HLen(ctx, key).Result() | 		length, _ = client.HLen(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	case "set": | 	case "set": | ||||||
| 		//value, err = client.SMembers(ctx, key).Result() | 		//value, err = client.SMembers(ctx, key).Result() | ||||||
| 		items := []string{} | 		items := []string{} | ||||||
| @@ -873,7 +876,8 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		value = items | 		value = items | ||||||
| 		size, _ = client.SCard(ctx, key).Result() | 		length, _ = client.SCard(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	case "zset": | 	case "zset": | ||||||
| 		//value, err = client.ZRangeWithScores(ctx, key, 0, -1).Result() | 		//value, err = client.ZRangeWithScores(ctx, key, 0, -1).Result() | ||||||
| 		var items []types.ZSetItem | 		var items []types.ZSetItem | ||||||
| @@ -899,7 +903,8 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		value = items | 		value = items | ||||||
| 		size, _ = client.ZCard(ctx, key).Result() | 		length, _ = client.ZCard(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	case "stream": | 	case "stream": | ||||||
| 		var msgs []redis.XMessage | 		var msgs []redis.XMessage | ||||||
| 		items := []types.StreamItem{} | 		items := []types.StreamItem{} | ||||||
| @@ -915,7 +920,8 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 			}) | 			}) | ||||||
| 		} | 		} | ||||||
| 		value = items | 		value = items | ||||||
| 		size, _ = client.XLen(ctx, key).Result() | 		length, _ = client.XLen(ctx, key).Result() | ||||||
|  | 		size, _ = client.MemoryUsage(ctx, key, 0).Result() | ||||||
| 	} | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		resp.Msg = err.Error() | 		resp.Msg = err.Error() | ||||||
| @@ -927,6 +933,7 @@ func (c *connectionService) GetKeyValue(connName string, db int, k any, viewAs, | |||||||
| 		"ttl":    ttl, | 		"ttl":    ttl, | ||||||
| 		"value":  value, | 		"value":  value, | ||||||
| 		"size":   size, | 		"size":   size, | ||||||
|  | 		"length": length, | ||||||
| 		"viewAs": viewAs, | 		"viewAs": viewAs, | ||||||
| 		"decode": decodeType, | 		"decode": decodeType, | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ const tabContent = computed(() => { | |||||||
|         ttl: tab.ttl, |         ttl: tab.ttl, | ||||||
|         value: tab.value, |         value: tab.value, | ||||||
|         size: tab.size || 0, |         size: tab.size || 0, | ||||||
|  |         length: tab.length || 0, | ||||||
|         viewAs: tab.viewAs, |         viewAs: tab.viewAs, | ||||||
|         decode: tab.decode, |         decode: tab.decode, | ||||||
|     } |     } | ||||||
| @@ -131,6 +132,7 @@ watch( | |||||||
|                     :decode="tabContent.decode" |                     :decode="tabContent.decode" | ||||||
|                     :key-code="tabContent.keyCode" |                     :key-code="tabContent.keyCode" | ||||||
|                     :key-path="tabContent.keyPath" |                     :key-path="tabContent.keyPath" | ||||||
|  |                     :length="tabContent.length" | ||||||
|                     :name="tabContent.name" |                     :name="tabContent.name" | ||||||
|                     :size="tabContent.size" |                     :size="tabContent.size" | ||||||
|                     :ttl="tabContent.ttl" |                     :ttl="tabContent.ttl" | ||||||
|   | |||||||
| @@ -3,14 +3,17 @@ import { computed, h, reactive, ref } from 'vue' | |||||||
| import { useI18n } from 'vue-i18n' | import { useI18n } from 'vue-i18n' | ||||||
| import ContentToolbar from './ContentToolbar.vue' | import ContentToolbar from './ContentToolbar.vue' | ||||||
| import AddLink from '@/components/icons/AddLink.vue' | import AddLink from '@/components/icons/AddLink.vue' | ||||||
| import { NButton, NCode, NIcon, NInput } from 'naive-ui' | import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui' | ||||||
| import { types, types as redisTypes } from '@/consts/support_redis_type.js' | import { types, types as redisTypes } from '@/consts/support_redis_type.js' | ||||||
| import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | ||||||
| import useDialogStore from 'stores/dialog.js' | import useDialogStore from 'stores/dialog.js' | ||||||
| import useConnectionStore from 'stores/connections.js' | import useConnectionStore from 'stores/connections.js' | ||||||
| import { isEmpty } from 'lodash' | import { isEmpty } from 'lodash' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
|  | const themeVars = useThemeVars() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|     name: String, |     name: String, | ||||||
|     db: Number, |     db: Number, | ||||||
| @@ -25,6 +28,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: Object, |     value: Object, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -259,8 +263,9 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|             :key-type="keyType" |             :key-type="keyType" | ||||||
|             :server="props.name" |             :server="props.name" | ||||||
|             :ttl="ttl" /> |             :ttl="ttl" | ||||||
|         <div class="tb2 flex-box-h"> |             class="value-item-part" /> | ||||||
|  |         <div class="tb2 value-item-part flex-box-h"> | ||||||
|             <div class="flex-box-h"> |             <div class="flex-box-h"> | ||||||
|                 <n-input-group> |                 <n-input-group> | ||||||
|                     <n-select |                     <n-select | ||||||
| @@ -277,9 +282,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                         @update:value="onFilterInput" /> |                         @update:value="onFilterInput" /> | ||||||
|                 </n-input-group> |                 </n-input-group> | ||||||
|             </div> |             </div> | ||||||
|             <div class="tb2-extra-info flex-item-expand"> |             <div class="flex-item-expand"></div> | ||||||
|                 <n-tag size="large">{{ $t('interface.total', { size: props.size }) }}</n-tag> |  | ||||||
|             </div> |  | ||||||
|             <n-button :focusable="false" plain @click="onAddRow"> |             <n-button :focusable="false" plain @click="onAddRow"> | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|                     <n-icon :component="AddLink" size="18" /> |                     <n-icon :component="AddLink" size="18" /> | ||||||
| @@ -287,7 +290,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 {{ $t('interface.add_row') }} |                 {{ $t('interface.add_row') }} | ||||||
|             </n-button> |             </n-button> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-wrapper fill-height flex-box-h"> |         <div class="value-wrapper value-item-part fill-height flex-box-h"> | ||||||
|             <n-data-table |             <n-data-table | ||||||
|                 :key="(row) => row.no" |                 :key="(row) => row.no" | ||||||
|                 :bordered="false" |                 :bordered="false" | ||||||
| @@ -303,7 +306,18 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 virtual-scroll |                 virtual-scroll | ||||||
|                 @update:filters="onUpdateFilter" /> |                 @update:filters="onUpdateFilter" /> | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|  |             <div class="flex-item-expand"></div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .value-footer { | ||||||
|  |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|  |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|   | |||||||
| @@ -3,14 +3,17 @@ import { computed, h, reactive, ref } from 'vue' | |||||||
| import { useI18n } from 'vue-i18n' | import { useI18n } from 'vue-i18n' | ||||||
| import ContentToolbar from './ContentToolbar.vue' | import ContentToolbar from './ContentToolbar.vue' | ||||||
| import AddLink from '@/components/icons/AddLink.vue' | import AddLink from '@/components/icons/AddLink.vue' | ||||||
| import { NButton, NCode, NIcon, NInput } from 'naive-ui' | import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui' | ||||||
| import { isEmpty, size } from 'lodash' | import { isEmpty, size } from 'lodash' | ||||||
| import { types, types as redisTypes } from '@/consts/support_redis_type.js' | import { types, types as redisTypes } from '@/consts/support_redis_type.js' | ||||||
| import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | ||||||
| import useDialogStore from 'stores/dialog.js' | import useDialogStore from 'stores/dialog.js' | ||||||
| import useConnectionStore from 'stores/connections.js' | import useConnectionStore from 'stores/connections.js' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
|  | const themeVars = useThemeVars() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|     name: String, |     name: String, | ||||||
|     db: Number, |     db: Number, | ||||||
| @@ -25,6 +28,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: Object, |     value: Object, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -191,8 +195,9 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|             :key-type="keyType" |             :key-type="keyType" | ||||||
|             :server="props.name" |             :server="props.name" | ||||||
|             :ttl="ttl" /> |             :ttl="ttl" | ||||||
|         <div class="tb2 flex-box-h"> |             class="value-item-part" /> | ||||||
|  |         <div class="tb2 value-item-part flex-box-h"> | ||||||
|             <div class="flex-box-h"> |             <div class="flex-box-h"> | ||||||
|                 <n-input |                 <n-input | ||||||
|                     v-model:value="filterValue" |                     v-model:value="filterValue" | ||||||
| @@ -201,9 +206,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                     @clear="clearFilter" |                     @clear="clearFilter" | ||||||
|                     @update:value="onFilterInput" /> |                     @update:value="onFilterInput" /> | ||||||
|             </div> |             </div> | ||||||
|             <div class="tb2-extra-info flex-item-expand"> |             <div class="flex-item-expand"></div> | ||||||
|                 <n-tag size="large">{{ $t('interface.total', { size: props.size }) }}</n-tag> |  | ||||||
|             </div> |  | ||||||
|             <n-button :focusable="false" plain @click="onAddValue"> |             <n-button :focusable="false" plain @click="onAddValue"> | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|                     <n-icon :component="AddLink" size="18" /> |                     <n-icon :component="AddLink" size="18" /> | ||||||
| @@ -211,7 +214,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 {{ $t('interface.add_row') }} |                 {{ $t('interface.add_row') }} | ||||||
|             </n-button> |             </n-button> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-wrapper fill-height flex-box-h"> |         <div class="value-wrapper value-item-part fill-height flex-box-h"> | ||||||
|             <n-data-table |             <n-data-table | ||||||
|                 :key="(row) => row.no" |                 :key="(row) => row.no" | ||||||
|                 :bordered="false" |                 :bordered="false" | ||||||
| @@ -227,7 +230,18 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 virtual-scroll |                 virtual-scroll | ||||||
|                 @update:filters="onUpdateFilter" /> |                 @update:filters="onUpdateFilter" /> | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|  |             <div class="flex-item-expand"></div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .value-footer { | ||||||
|  |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|  |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|   | |||||||
| @@ -3,14 +3,17 @@ import { computed, h, reactive, ref } from 'vue' | |||||||
| import { useI18n } from 'vue-i18n' | import { useI18n } from 'vue-i18n' | ||||||
| import ContentToolbar from './ContentToolbar.vue' | import ContentToolbar from './ContentToolbar.vue' | ||||||
| import AddLink from '@/components/icons/AddLink.vue' | import AddLink from '@/components/icons/AddLink.vue' | ||||||
| import { NButton, NCode, NIcon, NInput } from 'naive-ui' | import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui' | ||||||
| import { isEmpty, size } from 'lodash' | import { isEmpty, size } from 'lodash' | ||||||
| import useDialogStore from 'stores/dialog.js' | import useDialogStore from 'stores/dialog.js' | ||||||
| import { types, types as redisTypes } from '@/consts/support_redis_type.js' | import { types, types as redisTypes } from '@/consts/support_redis_type.js' | ||||||
| import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | ||||||
| import useConnectionStore from 'stores/connections.js' | import useConnectionStore from 'stores/connections.js' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
|  | const themeVars = useThemeVars() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|     name: String, |     name: String, | ||||||
|     db: Number, |     db: Number, | ||||||
| @@ -25,6 +28,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: Array, |     value: Array, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -186,8 +190,9 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|             :key-type="keyType" |             :key-type="keyType" | ||||||
|             :server="props.name" |             :server="props.name" | ||||||
|             :ttl="ttl" /> |             :ttl="ttl" | ||||||
|         <div class="tb2 flex-box-h"> |             class="value-item-part" /> | ||||||
|  |         <div class="tb2 value-item-part flex-box-h"> | ||||||
|             <div class="flex-box-h"> |             <div class="flex-box-h"> | ||||||
|                 <n-input |                 <n-input | ||||||
|                     v-model:value="filterValue" |                     v-model:value="filterValue" | ||||||
| @@ -196,9 +201,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                     @clear="clearFilter" |                     @clear="clearFilter" | ||||||
|                     @update:value="onFilterInput" /> |                     @update:value="onFilterInput" /> | ||||||
|             </div> |             </div> | ||||||
|             <div class="tb2-extra-info flex-item-expand"> |             <div class="flex-item-expand"></div> | ||||||
|                 <n-tag size="large">{{ $t('interface.total', { size: props.size }) }}</n-tag> |  | ||||||
|             </div> |  | ||||||
|             <n-button :focusable="false" plain @click="onAddValue"> |             <n-button :focusable="false" plain @click="onAddValue"> | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|                     <n-icon :component="AddLink" size="18" /> |                     <n-icon :component="AddLink" size="18" /> | ||||||
| @@ -206,7 +209,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 {{ $t('interface.add_row') }} |                 {{ $t('interface.add_row') }} | ||||||
|             </n-button> |             </n-button> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-wrapper fill-height flex-box-h"> |         <div class="value-wrapper value-item-part fill-height flex-box-h"> | ||||||
|             <n-data-table |             <n-data-table | ||||||
|                 :key="(row) => row.no" |                 :key="(row) => row.no" | ||||||
|                 :bordered="false" |                 :bordered="false" | ||||||
| @@ -222,7 +225,18 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 virtual-scroll |                 virtual-scroll | ||||||
|                 @update:filters="onUpdateFilter" /> |                 @update:filters="onUpdateFilter" /> | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|  |             <div class="flex-item-expand"></div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .value-footer { | ||||||
|  |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|  |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|   | |||||||
| @@ -3,14 +3,17 @@ import { computed, h, reactive, ref } from 'vue' | |||||||
| import { useI18n } from 'vue-i18n' | import { useI18n } from 'vue-i18n' | ||||||
| import ContentToolbar from './ContentToolbar.vue' | import ContentToolbar from './ContentToolbar.vue' | ||||||
| import AddLink from '@/components/icons/AddLink.vue' | import AddLink from '@/components/icons/AddLink.vue' | ||||||
| import { NButton, NCode, NIcon, NInput } from 'naive-ui' | import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui' | ||||||
| import { types, types as redisTypes } from '@/consts/support_redis_type.js' | import { types, types as redisTypes } from '@/consts/support_redis_type.js' | ||||||
| import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | ||||||
| import useDialogStore from 'stores/dialog.js' | import useDialogStore from 'stores/dialog.js' | ||||||
| import useConnectionStore from 'stores/connections.js' | import useConnectionStore from 'stores/connections.js' | ||||||
| import { includes, isEmpty, keys, some, values } from 'lodash' | import { includes, isEmpty, keys, some, values } from 'lodash' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
|  | const themeVars = useThemeVars() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|     name: String, |     name: String, | ||||||
|     db: Number, |     db: Number, | ||||||
| @@ -25,6 +28,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: Object, |     value: Object, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -171,8 +175,9 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|             :key-type="keyType" |             :key-type="keyType" | ||||||
|             :server="props.name" |             :server="props.name" | ||||||
|             :ttl="ttl" /> |             :ttl="ttl" | ||||||
|         <div class="tb2 flex-box-h"> |             class="value-item-part" /> | ||||||
|  |         <div class="tb2 value-item-part flex-box-h"> | ||||||
|             <div class="flex-box-h"> |             <div class="flex-box-h"> | ||||||
|                 <n-input-group> |                 <n-input-group> | ||||||
|                     <n-select |                     <n-select | ||||||
| @@ -189,9 +194,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                         @update:value="onFilterInput" /> |                         @update:value="onFilterInput" /> | ||||||
|                 </n-input-group> |                 </n-input-group> | ||||||
|             </div> |             </div> | ||||||
|             <div class="tb2-extra-info flex-item-expand"> |             <div class="flex-item-expand"></div> | ||||||
|                 <n-tag size="large">{{ $t('interface.total', { size: props.size }) }}</n-tag> |  | ||||||
|             </div> |  | ||||||
|             <n-button :focusable="false" plain @click="onAddRow"> |             <n-button :focusable="false" plain @click="onAddRow"> | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|                     <n-icon :component="AddLink" size="18" /> |                     <n-icon :component="AddLink" size="18" /> | ||||||
| @@ -199,7 +202,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 {{ $t('interface.add_row') }} |                 {{ $t('interface.add_row') }} | ||||||
|             </n-button> |             </n-button> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-wrapper fill-height flex-box-h"> |         <div class="value-wrapper value-item-part fill-height flex-box-h"> | ||||||
|             <n-data-table |             <n-data-table | ||||||
|                 :key="(row) => row.id" |                 :key="(row) => row.id" | ||||||
|                 :bordered="false" |                 :bordered="false" | ||||||
| @@ -215,7 +218,19 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 virtual-scroll |                 virtual-scroll | ||||||
|                 @update:filters="onUpdateFilter" /> |                 @update:filters="onUpdateFilter" /> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|  |             <div class="flex-item-expand"></div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .value-footer { | ||||||
|  |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|  |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ import DropdownSelector from '@/components/content_value/DropdownSelector.vue' | |||||||
| import Code from '@/components/icons/Code.vue' | import Code from '@/components/icons/Code.vue' | ||||||
| import Conversion from '@/components/icons/Conversion.vue' | import Conversion from '@/components/icons/Conversion.vue' | ||||||
| import EditFile from '@/components/icons/EditFile.vue' | import EditFile from '@/components/icons/EditFile.vue' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
| const themeVars = useThemeVars() | const themeVars = useThemeVars() | ||||||
| @@ -33,6 +34,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: String, |     value: String, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
|     viewAs: { |     viewAs: { | ||||||
|         type: String, |         type: String, | ||||||
|         default: formatTypes.PLAIN_TEXT, |         default: formatTypes.PLAIN_TEXT, | ||||||
| @@ -192,6 +194,9 @@ const onSaveValue = async () => { | |||||||
|                 type="textarea" /> |                 type="textarea" /> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-footer flex-box-h"> |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.length') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|             <div class="flex-item-expand"></div> |             <div class="flex-item-expand"></div> | ||||||
|             <dropdown-selector |             <dropdown-selector | ||||||
|                 :icon="Code" |                 :icon="Code" | ||||||
| @@ -199,9 +204,7 @@ const onSaveValue = async () => { | |||||||
|                 :tooltip="$t('interface.view_as')" |                 :tooltip="$t('interface.view_as')" | ||||||
|                 :value="props.viewAs" |                 :value="props.viewAs" | ||||||
|                 @update:value="onViewTypeUpdate" /> |                 @update:value="onViewTypeUpdate" /> | ||||||
|  |  | ||||||
|             <n-divider vertical /> |             <n-divider vertical /> | ||||||
|  |  | ||||||
|             <dropdown-selector |             <dropdown-selector | ||||||
|                 :icon="Conversion" |                 :icon="Conversion" | ||||||
|                 :options="decodeTypes" |                 :options="decodeTypes" | ||||||
| @@ -221,6 +224,6 @@ const onSaveValue = async () => { | |||||||
|  |  | ||||||
| .value-footer { | .value-footer { | ||||||
|     border-top: v-bind('themeVars.borderColor') 1px solid; |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|     background-color: v-bind('themeVars.bodyColor'); |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: [String, Object], |     value: [String, Object], | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
|     viewAs: { |     viewAs: { | ||||||
|         type: String, |         type: String, | ||||||
|         default: formatTypes.PLAIN_TEXT, |         default: formatTypes.PLAIN_TEXT, | ||||||
| @@ -70,6 +71,7 @@ const onReloadKey = async () => { | |||||||
|             :decode="props.decode" |             :decode="props.decode" | ||||||
|             :key-code="props.keyCode" |             :key-code="props.keyCode" | ||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|  |             :length="props.length" | ||||||
|             :name="props.name" |             :name="props.name" | ||||||
|             :size="props.size" |             :size="props.size" | ||||||
|             :ttl="props.ttl" |             :ttl="props.ttl" | ||||||
|   | |||||||
| @@ -3,14 +3,17 @@ import { computed, h, reactive, ref } from 'vue' | |||||||
| import { useI18n } from 'vue-i18n' | import { useI18n } from 'vue-i18n' | ||||||
| import ContentToolbar from './ContentToolbar.vue' | import ContentToolbar from './ContentToolbar.vue' | ||||||
| import AddLink from '@/components/icons/AddLink.vue' | import AddLink from '@/components/icons/AddLink.vue' | ||||||
| import { NButton, NCode, NIcon, NInput, NInputNumber } from 'naive-ui' | import { NButton, NCode, NIcon, NInput, NInputNumber, useThemeVars } from 'naive-ui' | ||||||
| import { types, types as redisTypes } from '@/consts/support_redis_type.js' | import { types, types as redisTypes } from '@/consts/support_redis_type.js' | ||||||
| import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | import EditableTableColumn from '@/components/common/EditableTableColumn.vue' | ||||||
| import { isEmpty } from 'lodash' | import { isEmpty } from 'lodash' | ||||||
| import useDialogStore from 'stores/dialog.js' | import useDialogStore from 'stores/dialog.js' | ||||||
| import useConnectionStore from 'stores/connections.js' | import useConnectionStore from 'stores/connections.js' | ||||||
|  | import bytes from 'bytes' | ||||||
|  |  | ||||||
| const i18n = useI18n() | const i18n = useI18n() | ||||||
|  | const themeVars = useThemeVars() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|     name: String, |     name: String, | ||||||
|     db: Number, |     db: Number, | ||||||
| @@ -25,6 +28,7 @@ const props = defineProps({ | |||||||
|     }, |     }, | ||||||
|     value: Object, |     value: Object, | ||||||
|     size: Number, |     size: Number, | ||||||
|  |     length: Number, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -284,8 +288,9 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|             :key-path="props.keyPath" |             :key-path="props.keyPath" | ||||||
|             :key-type="keyType" |             :key-type="keyType" | ||||||
|             :server="props.name" |             :server="props.name" | ||||||
|             :ttl="ttl" /> |             :ttl="ttl" | ||||||
|         <div class="tb2 flex-box-h"> |             class="value-item-part" /> | ||||||
|  |         <div class="tb2 value-item-part flex-box-h"> | ||||||
|             <div class="flex-box-h"> |             <div class="flex-box-h"> | ||||||
|                 <n-input-group> |                 <n-input-group> | ||||||
|                     <n-select |                     <n-select | ||||||
| @@ -307,9 +312,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                     </n-tooltip> |                     </n-tooltip> | ||||||
|                 </n-input-group> |                 </n-input-group> | ||||||
|             </div> |             </div> | ||||||
|             <div class="tb2-extra-info flex-item-expand"> |             <div class="flex-item-expand"></div> | ||||||
|                 <n-tag size="large">{{ $t('interface.total', { size: props.size }) }}</n-tag> |  | ||||||
|             </div> |  | ||||||
|             <n-button :focusable="false" plain @click="onAddRow"> |             <n-button :focusable="false" plain @click="onAddRow"> | ||||||
|                 <template #icon> |                 <template #icon> | ||||||
|                     <n-icon :component="AddLink" size="18" /> |                     <n-icon :component="AddLink" size="18" /> | ||||||
| @@ -317,7 +320,7 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 {{ $t('interface.add_row') }} |                 {{ $t('interface.add_row') }} | ||||||
|             </n-button> |             </n-button> | ||||||
|         </div> |         </div> | ||||||
|         <div class="value-wrapper fill-height flex-box-h"> |         <div class="value-wrapper value-item-part fill-height flex-box-h"> | ||||||
|             <n-data-table |             <n-data-table | ||||||
|                 :key="(row) => row.no" |                 :key="(row) => row.no" | ||||||
|                 :bordered="false" |                 :bordered="false" | ||||||
| @@ -333,7 +336,18 @@ const onUpdateFilter = (filters, sourceColumn) => { | |||||||
|                 virtual-scroll |                 virtual-scroll | ||||||
|                 @update:filters="onUpdateFilter" /> |                 @update:filters="onUpdateFilter" /> | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="value-footer flex-box-h"> | ||||||
|  |             <n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text> | ||||||
|  |             <n-divider v-if="!isNaN(props.length)" vertical /> | ||||||
|  |             <n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text> | ||||||
|  |             <div class="flex-item-expand"></div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .value-footer { | ||||||
|  |     border-top: v-bind('themeVars.borderColor') 1px solid; | ||||||
|  |     background-color: v-bind('themeVars.tableHeaderColor'); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|   | |||||||
| @@ -75,6 +75,9 @@ | |||||||
|     "search": "Search", |     "search": "Search", | ||||||
|     "filter_field": "Filter Field", |     "filter_field": "Filter Field", | ||||||
|     "filter_value": "Filter Value", |     "filter_value": "Filter Value", | ||||||
|  |     "length": "Length", | ||||||
|  |     "entries": "Entries", | ||||||
|  |     "memory_usage": "Memory Usage", | ||||||
|     "view_as": "View As", |     "view_as": "View As", | ||||||
|     "decode_with": "Decode/Decompress Type", |     "decode_with": "Decode/Decompress Type", | ||||||
|     "reload": "Reload", |     "reload": "Reload", | ||||||
| @@ -94,7 +97,6 @@ | |||||||
|     "action": "Action", |     "action": "Action", | ||||||
|     "type": "Type", |     "type": "Type", | ||||||
|     "score": "Score", |     "score": "Score", | ||||||
|     "total": "Length: {size}", |  | ||||||
|     "cli_welcome": "Welcome to Tiny RDM Redis Console", |     "cli_welcome": "Welcome to Tiny RDM Redis Console", | ||||||
|     "sub_tab": { |     "sub_tab": { | ||||||
|       "status": "Status", |       "status": "Status", | ||||||
|   | |||||||
| @@ -75,6 +75,9 @@ | |||||||
|     "search": "搜索", |     "search": "搜索", | ||||||
|     "filter_field": "筛选字段", |     "filter_field": "筛选字段", | ||||||
|     "filter_value": "筛选值", |     "filter_value": "筛选值", | ||||||
|  |     "length": "长度", | ||||||
|  |     "entries": "条目", | ||||||
|  |     "memory_usage": "内存占用", | ||||||
|     "view_as": "查看方式", |     "view_as": "查看方式", | ||||||
|     "decode_with": "解码/解压方式", |     "decode_with": "解码/解压方式", | ||||||
|     "reload": "重新载入", |     "reload": "重新载入", | ||||||
| @@ -94,7 +97,6 @@ | |||||||
|     "action": "操作", |     "action": "操作", | ||||||
|     "type": "类型", |     "type": "类型", | ||||||
|     "score": "分值", |     "score": "分值", | ||||||
|     "total": "总数:{size}", |  | ||||||
|     "cli_welcome": "欢迎使用Tiny RDM的Redis命令行控制台", |     "cli_welcome": "欢迎使用Tiny RDM的Redis命令行控制台", | ||||||
|     "sub_tab": { |     "sub_tab": { | ||||||
|       "status": "状态", |       "status": "状态", | ||||||
|   | |||||||
| @@ -665,7 +665,7 @@ const useConnectionStore = defineStore('connections', { | |||||||
|                 if (!isEmpty(key)) { |                 if (!isEmpty(key)) { | ||||||
|                     const { data, success, msg } = await GetKeyValue(server, db, key, viewType, decodeType) |                     const { data, success, msg } = await GetKeyValue(server, db, key, viewType, decodeType) | ||||||
|                     if (success) { |                     if (success) { | ||||||
|                         const { type, ttl, value, size, viewAs, decode } = data |                         const { type, ttl, value, size, length, viewAs, decode } = data | ||||||
|                         const k = decodeRedisKey(key) |                         const k = decodeRedisKey(key) | ||||||
|                         const binaryKey = k !== key |                         const binaryKey = k !== key | ||||||
|                         tab.upsertTab({ |                         tab.upsertTab({ | ||||||
| @@ -678,6 +678,7 @@ const useConnectionStore = defineStore('connections', { | |||||||
|                             key: k, |                             key: k, | ||||||
|                             value, |                             value, | ||||||
|                             size, |                             size, | ||||||
|  |                             length, | ||||||
|                             viewAs, |                             viewAs, | ||||||
|                             decode, |                             decode, | ||||||
|                         }) |                         }) | ||||||
| @@ -702,6 +703,7 @@ const useConnectionStore = defineStore('connections', { | |||||||
|                     keyCode: null, |                     keyCode: null, | ||||||
|                     value: null, |                     value: null, | ||||||
|                     size: 0, |                     size: 0, | ||||||
|  |                     length: 0, | ||||||
|                 }) |                 }) | ||||||
|             } finally { |             } finally { | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -92,11 +92,12 @@ const useTabStore = defineStore('tab', { | |||||||
|          * @param {string} [key] |          * @param {string} [key] | ||||||
|          * @param {string} [keyCode] |          * @param {string} [keyCode] | ||||||
|          * @param {number} [size] |          * @param {number} [size] | ||||||
|  |          * @param {number} [length] | ||||||
|          * @param {*} [value] |          * @param {*} [value] | ||||||
|          * @param {string} [viewAs] |          * @param {string} [viewAs] | ||||||
|          * @param {string} [decode] |          * @param {string} [decode] | ||||||
|          */ |          */ | ||||||
|         upsertTab({ subTab, server, db, type, ttl, key, keyCode, size, value, viewAs, decode }) { |         upsertTab({ subTab, server, db, type, ttl, key, keyCode, size, length, value, viewAs, decode }) { | ||||||
|             let tabIndex = findIndex(this.tabList, { name: server }) |             let tabIndex = findIndex(this.tabList, { name: server }) | ||||||
|             if (tabIndex === -1) { |             if (tabIndex === -1) { | ||||||
|                 this.tabList.push({ |                 this.tabList.push({ | ||||||
| @@ -110,6 +111,7 @@ const useTabStore = defineStore('tab', { | |||||||
|                     key, |                     key, | ||||||
|                     keyCode, |                     keyCode, | ||||||
|                     size, |                     size, | ||||||
|  |                     length, | ||||||
|                     value, |                     value, | ||||||
|                     viewAs, |                     viewAs, | ||||||
|                     decode, |                     decode, | ||||||
| @@ -128,6 +130,7 @@ const useTabStore = defineStore('tab', { | |||||||
|                 tab.key = key |                 tab.key = key | ||||||
|                 tab.keyCode = keyCode |                 tab.keyCode = keyCode | ||||||
|                 tab.size = size |                 tab.size = size | ||||||
|  |                 tab.length = length | ||||||
|                 tab.value = value |                 tab.value = value | ||||||
|                 tab.viewAs = viewAs |                 tab.viewAs = viewAs | ||||||
|                 tab.decode = decode |                 tab.decode = decode | ||||||
|   | |||||||
| @@ -87,10 +87,6 @@ body { | |||||||
|     gap: 5px; |     gap: 5px; | ||||||
|     justify-content: flex-end; |     justify-content: flex-end; | ||||||
|     align-items: center; |     align-items: center; | ||||||
|  |  | ||||||
|     .tb2-extra-info { |  | ||||||
|       padding: 0 5px; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .value-wrapper { |   .value-wrapper { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 tiny-craft
					tiny-craft