feat: support comparison operator to filter ordered set by score
This commit is contained in:
parent
62d6924541
commit
6a54183d91
|
@ -11,18 +11,6 @@ import useConnectionStore from '../../stores/connections.js'
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
|
|
||||||
const filterOption = [
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
label: i18n.t('field'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 2,
|
|
||||||
label: i18n.t('value'),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const filterType = ref(1)
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
name: String,
|
name: String,
|
||||||
db: Number,
|
db: Number,
|
||||||
|
@ -34,6 +22,18 @@ const props = defineProps({
|
||||||
value: Object,
|
value: Object,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const filterOption = computed(() => [
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: i18n.t('field'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: i18n.t('value'),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const filterType = ref(1)
|
||||||
|
|
||||||
const connectionStore = useConnectionStore()
|
const connectionStore = useConnectionStore()
|
||||||
const dialogStore = useDialogStore()
|
const dialogStore = useDialogStore()
|
||||||
const keyType = redisTypes.HASH
|
const keyType = redisTypes.HASH
|
||||||
|
@ -206,10 +206,12 @@ const filterValue = ref('')
|
||||||
const onFilterInput = (val) => {
|
const onFilterInput = (val) => {
|
||||||
switch (filterType.value) {
|
switch (filterType.value) {
|
||||||
case filterOption[0].value:
|
case filterOption[0].value:
|
||||||
|
// filter field
|
||||||
valueColumn.filterOptionValue = null
|
valueColumn.filterOptionValue = null
|
||||||
fieldColumn.filterOptionValue = val
|
fieldColumn.filterOptionValue = val
|
||||||
break
|
break
|
||||||
case filterOption[1].value:
|
case filterOption[1].value:
|
||||||
|
// filter value
|
||||||
fieldColumn.filterOptionValue = null
|
fieldColumn.filterOptionValue = null
|
||||||
valueColumn.filterOptionValue = val
|
valueColumn.filterOptionValue = val
|
||||||
break
|
break
|
||||||
|
|
|
@ -6,11 +6,12 @@ import AddLink from '../icons/AddLink.vue'
|
||||||
import { NButton, NCode, NIcon, NInput, NInputNumber, useMessage } from 'naive-ui'
|
import { NButton, NCode, NIcon, NInput, NInputNumber, useMessage } 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 '../common/EditableTableColumn.vue'
|
import EditableTableColumn from '../common/EditableTableColumn.vue'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty, replace } 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'
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
name: String,
|
name: String,
|
||||||
db: Number,
|
db: Number,
|
||||||
|
@ -22,6 +23,18 @@ const props = defineProps({
|
||||||
value: Object,
|
value: Object,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const filterOption = computed(() => [
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: i18n.t('value'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: i18n.t('score'),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const filterType = ref(1)
|
||||||
|
|
||||||
const connectionStore = useConnectionStore()
|
const connectionStore = useConnectionStore()
|
||||||
const dialogStore = useDialogStore()
|
const dialogStore = useDialogStore()
|
||||||
const keyType = redisTypes.ZSET
|
const keyType = redisTypes.ZSET
|
||||||
|
@ -36,6 +49,40 @@ const scoreColumn = reactive({
|
||||||
align: 'center',
|
align: 'center',
|
||||||
titleAlign: 'center',
|
titleAlign: 'center',
|
||||||
resizable: true,
|
resizable: true,
|
||||||
|
filterOptionValue: null,
|
||||||
|
filter(value, row) {
|
||||||
|
const score = parseFloat(row.score)
|
||||||
|
if (isNaN(score)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /^(>=|<=|>|<|=|!=)?(\d+(\.\d*)?)?$/
|
||||||
|
const matches = value.match(regex)
|
||||||
|
if (matches) {
|
||||||
|
const operator = matches[1] || ''
|
||||||
|
const filterScore = parseFloat(matches[2] || '')
|
||||||
|
if (!isNaN(filterScore)) {
|
||||||
|
switch (operator) {
|
||||||
|
case '>=':
|
||||||
|
return score >= filterScore
|
||||||
|
case '<=':
|
||||||
|
return score <= filterScore
|
||||||
|
case '>':
|
||||||
|
return score > filterScore
|
||||||
|
case '<':
|
||||||
|
return score < filterScore
|
||||||
|
case '=':
|
||||||
|
return score === filterScore
|
||||||
|
case '!=':
|
||||||
|
return score !== filterScore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return !!~row.value.indexOf(value.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
render: (row) => {
|
render: (row) => {
|
||||||
const isEdit = currentEditRow.value.no === row.no
|
const isEdit = currentEditRow.value.no === row.no
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
|
@ -180,7 +227,18 @@ const onAddRow = () => {
|
||||||
|
|
||||||
const filterValue = ref('')
|
const filterValue = ref('')
|
||||||
const onFilterInput = (val) => {
|
const onFilterInput = (val) => {
|
||||||
|
switch (filterType.value) {
|
||||||
|
case filterOption[0].value:
|
||||||
|
// filter value
|
||||||
|
scoreColumn.filterOptionValue = null
|
||||||
valueColumn.filterOptionValue = val
|
valueColumn.filterOptionValue = val
|
||||||
|
break
|
||||||
|
case filterOption[1].value:
|
||||||
|
// filter score
|
||||||
|
valueColumn.filterOptionValue = null
|
||||||
|
scoreColumn.filterOptionValue = val
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChangeFilterType = (type) => {
|
const onChangeFilterType = (type) => {
|
||||||
|
@ -189,10 +247,20 @@ const onChangeFilterType = (type) => {
|
||||||
|
|
||||||
const clearFilter = () => {
|
const clearFilter = () => {
|
||||||
valueColumn.filterOptionValue = null
|
valueColumn.filterOptionValue = null
|
||||||
|
scoreColumn.filterOptionValue = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUpdateFilter = (filters, sourceColumn) => {
|
const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
|
switch (filterType.value) {
|
||||||
|
case filterOption[0].value:
|
||||||
|
// filter value
|
||||||
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
||||||
|
break
|
||||||
|
case filterOption[1].value:
|
||||||
|
// filter score
|
||||||
|
scoreColumn.filterOptionValue = filters[sourceColumn.key]
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -201,6 +269,16 @@ const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
<content-toolbar :db="props.db" :key-path="props.keyPath" :key-type="keyType" :server="props.name" :ttl="ttl" />
|
<content-toolbar :db="props.db" :key-path="props.keyPath" :key-type="keyType" :server="props.name" :ttl="ttl" />
|
||||||
<div class="tb2 flex-box-h">
|
<div class="tb2 flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
|
<n-input-group>
|
||||||
|
<n-select
|
||||||
|
v-model:value="filterType"
|
||||||
|
:consistent-menu-width="false"
|
||||||
|
:options="filterOption"
|
||||||
|
style="width: 120px"
|
||||||
|
@update:value="onChangeFilterType"
|
||||||
|
/>
|
||||||
|
<n-tooltip :disabled="filterType !== 2" :delay="500">
|
||||||
|
<template #trigger>
|
||||||
<n-input
|
<n-input
|
||||||
v-model:value="filterValue"
|
v-model:value="filterValue"
|
||||||
:placeholder="$t('search')"
|
:placeholder="$t('search')"
|
||||||
|
@ -208,6 +286,10 @@ const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
@clear="clearFilter"
|
@clear="clearFilter"
|
||||||
@update:value="onFilterInput"
|
@update:value="onFilterInput"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
|
<div class="text-block">{{ $t('score_filter_tip') }}</div>
|
||||||
|
</n-tooltip>
|
||||||
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button plain @click="onAddRow">
|
<n-button plain @click="onAddRow">
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"edit_value": "Edit Value",
|
"edit_value": "Edit Value",
|
||||||
"save_update": "Save Update",
|
"save_update": "Save Update",
|
||||||
"cancel_update": "Cancel Update",
|
"cancel_update": "Cancel Update",
|
||||||
|
"score_filter_tip": "Support operator list below:\n= equal\n!= not equal\n> greater than\n>= greater than or equal to\n< less than\n<= less than or equal to\nfor example you want to filter results which greater than 3, input: >3",
|
||||||
"add_row": "Add Row",
|
"add_row": "Add Row",
|
||||||
"edit_row": "Edit Row",
|
"edit_row": "Edit Row",
|
||||||
"delete_row": "Delete Row",
|
"delete_row": "Delete Row",
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"edit_value": "修改值",
|
"edit_value": "修改值",
|
||||||
"save_update": "保存修改",
|
"save_update": "保存修改",
|
||||||
"cancel_update": "取消修改",
|
"cancel_update": "取消修改",
|
||||||
|
"score_filter_tip": "支持如下运算符比较匹配范围\n=:等于\n!=:不等于\n>:大于\n<:小于\n>=:大于等于\n<=:小于等于\n如查询分值大于3的结果,则输入:>3",
|
||||||
"add_row": "插入行",
|
"add_row": "插入行",
|
||||||
"edit_row": "编辑行",
|
"edit_row": "编辑行",
|
||||||
"delete_row": "删除行",
|
"delete_row": "删除行",
|
||||||
|
|
|
@ -77,6 +77,10 @@ body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-block {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
Loading…
Reference in New Issue