tiny-rdm/frontend/src/components/dialogs/DeleteKeyDialog.vue

200 lines
6.4 KiB
Vue

<script setup>
import { computed, nextTick, reactive, ref, watchEffect } from 'vue'
import useDialog from 'stores/dialog'
import { isEmpty, map, size } from 'lodash'
import useBrowserStore from 'stores/browser.js'
import { decodeRedisKey } from '@/utils/key_convert.js'
const deleteForm = reactive({
server: '',
db: 0,
key: '',
showAffected: false,
loadingAffected: false,
affectedKeys: [],
async: true,
direct: false,
})
const dialogStore = useDialog()
const browserStore = useBrowserStore()
watchEffect(() => {
if (dialogStore.deleteKeyDialogVisible) {
const { server, db, key } = dialogStore.deleteKeyParam
deleteForm.server = server
deleteForm.db = db
deleteForm.key = key
deleteForm.loadingAffected = false
// deleteForm.async = true
loading.value = false
deleting.value = false
if (key instanceof Array) {
deleteForm.showAffected = true
deleteForm.affectedKeys = key
} else {
deleteForm.showAffected = false
deleteForm.affectedKeys = []
}
}
})
const loading = ref(false)
const deleting = ref(false)
const scanAffectedKey = async () => {
try {
loading.value = true
deleteForm.loadingAffected = true
const { keys = [] } = await browserStore.scanKeys({
server: deleteForm.server,
db: deleteForm.db,
match: deleteForm.key,
loadType: 2,
})
deleteForm.affectedKeys = keys || []
deleteForm.showAffected = true
} finally {
deleteForm.loadingAffected = false
loading.value = false
}
}
const resetAffected = () => {
deleteForm.showAffected = false
deleteForm.affectedKeys = []
}
const keyLines = computed(() => {
return map(deleteForm.affectedKeys, (k) => decodeRedisKey(k))
})
const onConfirmDelete = async () => {
try {
deleting.value = true
const { server, db, key, affectedKeys } = deleteForm
await nextTick()
browserStore.deleteKeys(server, db, affectedKeys).catch((e) => {})
} catch (e) {
$message.error(e.message)
return
} finally {
deleting.value = false
}
dialogStore.closeDeleteKeyDialog()
}
const onConfirmDirectDelete = async () => {
try {
deleting.value = true
const { server, db, key } = deleteForm
await nextTick()
browserStore.deleteByPattern(server, db, key).catch((e) => {})
} catch (e) {
$message.error(e.message)
return
} finally {
deleting.value = false
}
dialogStore.closeDeleteKeyDialog()
}
const onClose = () => {
dialogStore.closeDeleteKeyDialog()
}
</script>
<template>
<n-modal
v-model:show="dialogStore.deleteKeyDialogVisible"
:closable="false"
:mask-closable="false"
:show-icon="false"
:title="$t('interface.batch_delete_key')"
close-on-esc
preset="dialog"
transform-origin="center"
@esc="onClose">
<n-spin :show="loading">
<n-form :model="deleteForm" :show-require-mark="false" label-placement="top">
<n-grid :x-gap="10">
<n-form-item-gi :label="$t('dialogue.key.server')" :span="12">
<n-input :autofocus="false" :value="deleteForm.server" readonly />
</n-form-item-gi>
<n-form-item-gi :label="$t('dialogue.key.db_index')" :span="12">
<n-input :autofocus="false" :value="deleteForm.db.toString()" readonly />
</n-form-item-gi>
</n-grid>
<n-form-item
v-if="!(deleteForm.key instanceof Array)"
:label="$t('dialogue.key.key_expression')"
required>
<n-input v-model:value="deleteForm.key" placeholder="" @input="resetAffected" />
</n-form-item>
<n-checkbox v-if="!deleteForm.showAffected" v-model:checked="deleteForm.direct">
{{ $t('dialogue.key.direct_delete') }}
</n-checkbox>
<n-card
v-if="deleteForm.showAffected"
:title="$t('dialogue.key.affected_key') + `(${size(deleteForm.affectedKeys)})`"
embedded
size="small">
<n-skeleton v-if="deleteForm.loadingAffected" :repeat="10" text />
<n-virtual-list v-else :item-size="25" :items="keyLines" class="list-wrapper">
<template #default="{ item }">
<div class="line-item content-value">
{{ item }}
</div>
</template>
</n-virtual-list>
</n-card>
</n-form>
</n-spin>
<template #action>
<div class="flex-item n-dialog__action">
<n-button :disabled="loading" :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
<n-button
v-if="deleteForm.direct"
:focusable="false"
:loading="loading"
type="primary"
@click="onConfirmDirectDelete">
{{ $t('dialogue.key.confirm_delete') }}
</n-button>
<template v-else>
<n-button
v-if="!deleteForm.showAffected"
:focusable="false"
:loading="loading"
type="primary"
@click="scanAffectedKey">
{{ $t('dialogue.key.show_affected_key') }}
</n-button>
<n-button
v-else
:disabled="isEmpty(deleteForm.affectedKeys)"
:focusable="false"
:loading="loading"
type="primary"
@click="onConfirmDelete">
{{ $t('dialogue.key.confirm_delete_key', { num: size(deleteForm.affectedKeys) }) }}
</n-button>
</template>
</div>
</template>
</n-modal>
</template>
<style lang="scss" scoped>
.line-item {
line-height: 1.6;
}
.list-wrapper {
box-sizing: border-box;
max-height: 180px;
user-select: text;
cursor: text;
}
</style>