mirror of
https://github.com/tiny-craft/tiny-rdm.git
synced 2025-04-13 01:58:05 +08:00
200 lines
6.4 KiB
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>
|