diff --git a/README_zh.md b/README_zh.md index 2c8c658..a3c4b49 100644 --- a/README_zh.md +++ b/README_zh.md @@ -41,7 +41,6 @@ ## 未来版本规划 - [ ] 命令实时监控 - [ ] 发布/订阅支持 -- [ ] 引入Monaco Editor - [ ] 连接配置导入/导出 - [ ] 数据导入/导出 diff --git a/backend/services/browser_service.go b/backend/services/browser_service.go index 2dab58a..a10dd2c 100644 --- a/backend/services/browser_service.go +++ b/backend/services/browser_service.go @@ -504,8 +504,8 @@ func (b *browserService) LoadNextKeys(connName string, db int, match, keyType st return } -// LoadAllKeys load all keys -func (b *browserService) LoadAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) { +// LoadNextAllKeys load next all keys +func (b *browserService) LoadNextAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) { item, err := b.getRedisClient(connName, db) if err != nil { resp.Msg = err.Error() @@ -530,6 +530,28 @@ func (b *browserService) LoadAllKeys(connName string, db int, match, keyType str return } +// LoadAllKeys load all keys +func (b *browserService) LoadAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) { + item, err := b.getRedisClient(connName, db) + if err != nil { + resp.Msg = err.Error() + return + } + + client, ctx := item.client, item.ctx + keys, _, err := b.scanKeys(ctx, client, match, keyType, 0, 0) + if err != nil { + resp.Msg = err.Error() + return + } + + resp.Success = true + resp.Data = map[string]any{ + "keys": keys, + } + return +} + func (b *browserService) GetKeyType(param types.KeySummaryParam) (resp types.JSResp) { item, err := b.getRedisClient(param.Server, param.DB) if err != nil { diff --git a/frontend/src/components/dialogs/DeleteKeyDialog.vue b/frontend/src/components/dialogs/DeleteKeyDialog.vue index 209e634..9c04cf9 100644 --- a/frontend/src/components/dialogs/DeleteKeyDialog.vue +++ b/frontend/src/components/dialogs/DeleteKeyDialog.vue @@ -47,7 +47,12 @@ const scanAffectedKey = async () => { try { loading.value = true deleteForm.loadingAffected = true - const { keys = [] } = await browserStore.scanKeys(deleteForm.server, deleteForm.db, deleteForm.key) + const { keys = [] } = await browserStore.scanKeys({ + server: deleteForm.server, + db: deleteForm.db, + match: deleteForm.key, + loadType: 2, + }) deleteForm.affectedKeys = keys || [] deleteForm.showAffected = true } finally { diff --git a/frontend/src/objects/redisNodeItem.js b/frontend/src/objects/redisNodeItem.js index 50a15c7..3297f41 100644 --- a/frontend/src/objects/redisNodeItem.js +++ b/frontend/src/objects/redisNodeItem.js @@ -1,4 +1,4 @@ -import { isEmpty, remove, sortedIndexBy, sumBy } from 'lodash' +import { isEmpty, remove, sortBy, sortedIndexBy, sumBy } from 'lodash' import { ConnectionType } from '@/consts/connection_type.js' /** @@ -74,29 +74,55 @@ export class RedisNodeItem { * @returns {boolean} return whether key count changed */ tidy(skipSort) { - let count = 0 - if (!isEmpty(this.children)) { - if (skipSort !== true) { - this._sortNodes(this.children) - } - - for (const elem of this.children) { - elem.tidy(skipSort) - count += elem.keyCount - } - } else { - if (this.type === ConnectionType.RedisValue) { - count += 1 + if (this.type === ConnectionType.RedisValue) { + this.keyCount = 1 + } else if (this.type === ConnectionType.RedisKey || this.type === ConnectionType.RedisDB) { + let keyCount = 0 + if (!isEmpty(this.children)) { + if (skipSort !== true) { + this.sortChildren() + } + for (const child of this.children) { + child.tidy(skipSort) + keyCount += child.keyCount + } } else { - // no children in db node or layer node, set count to 0 - count = 0 + keyCount = 0 + } + if (this.keyCount !== keyCount) { + this.keyCount = keyCount + return true } - } - if (this.keyCount !== count) { - this.keyCount = count - return true } return false + + // let count = 0 + // if (!isEmpty(this.children)) { + // if (skipSort !== true) { + // this.sortChildren() + // } + // + // for (const elem of this.children) { + // elem.tidy(skipSort) + // count += elem.keyCount + // } + // } else { + // if (this.type === ConnectionType.RedisValue) { + // count += 1 + // } else { + // // no children in db node or layer node, set count to 0 + // count = 0 + // } + // } + // if (this.keyCount !== count) { + // this.keyCount = count + // return true + // } + // return false + } + + sortChildren() { + sortBy(this.children, (item) => item.key) } /** @@ -123,7 +149,7 @@ export class RedisNodeItem { } const removed = remove(this.children, predicate) if (this.children.length <= 0) { - // remove from parent if no children + // TODO: remove from parent if no children } } @@ -131,10 +157,11 @@ export class RedisNodeItem { return this.children } - calcKeyCount() { + reCalcKeyCount() { if (this.type === ConnectionType.RedisValue) { - return 1 + this.keyCount = 1 } - return sumBy(this.children, (c) => c.keyCount) + this.keyCount = sumBy(this.children, (c) => c.keyCount) + return this.keyCount } } diff --git a/frontend/src/objects/redisServerState.js b/frontend/src/objects/redisServerState.js index 88276fd..c90e86a 100644 --- a/frontend/src/objects/redisServerState.js +++ b/frontend/src/objects/redisServerState.js @@ -1,4 +1,4 @@ -import { initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, sumBy, toUpper } from 'lodash' +import { initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, toUpper } from 'lodash' import useConnectionStore from 'stores/connections.js' import { ConnectionType } from '@/consts/connection_type.js' import { RedisDatabaseItem } from '@/objects/redisDatabaseItem.js' @@ -79,7 +79,7 @@ export class RedisServerState { /** * update max key by increase/decrease value - * @param {string} db + * @param {number} db * @param {number} updateVal */ updateDBKeyCount(db, updateVal) { @@ -309,26 +309,26 @@ export class RedisServerState { redisKey: key, }) - // check and remove empty layer node - let i = totalParts - 1 - for (; i >= 0; i--) { - const anceKey = join(slice(keyParts, 0, i), this.separator) - if (i > 0) { - const anceNode = this.nodeMap.get(`${ConnectionType.RedisKey}/${anceKey}`) - const redisKey = join(slice(keyParts, 0, i + 1), this.separator) - anceNode.removeChild({ type: ConnectionType.RedisKey, redisKey }) - - if (isEmpty(anceNode.children)) { - this.nodeMap.delete(`${ConnectionType.RedisKey}/${anceKey}`) - } else { - break - } - } else { - // last one, remove from db node - dbRoot.removeChild({ type: ConnectionType.RedisKey, redisKey: keyParts[0] }) - this.nodeMap.delete(`${ConnectionType.RedisValue}/${keyParts[0]}`) - } - } + // // check and remove empty layer node + // let i = totalParts - 1 + // for (; i >= 0; i--) { + // const anceKey = join(slice(keyParts, 0, i), this.separator) + // if (i > 0) { + // const anceNode = this.nodeMap.get(`${ConnectionType.RedisKey}/${anceKey}`) + // const redisKey = join(slice(keyParts, 0, i + 1), this.separator) + // anceNode.removeChild({ type: ConnectionType.RedisKey, redisKey }) + // + // if (isEmpty(anceNode.children)) { + // this.nodeMap.delete(`${ConnectionType.RedisKey}/${anceKey}`) + // } else { + // break + // } + // } else { + // // last one, remove from db node + // dbRoot.removeChild({ type: ConnectionType.RedisKey, redisKey: keyParts[0] }) + // this.nodeMap.delete(`${ConnectionType.RedisValue}/${keyParts[0]}`) + // } + // } } return true @@ -358,7 +358,6 @@ export class RedisServerState { node = dbNode } const keyCountUpdated = node.tidy(skipResort) - if (keyCountUpdated) { // update key count of parent and above for (; i > 0; i--) { @@ -367,16 +366,14 @@ export class RedisServerState { if (parentNode == null) { break } - parentNode.keyCount = parentNode.calcKeyCount() + parentNode.reCalcKeyCount() } // update key count of db - // dbNode.keyCount = sumBy(dbNode.children, 'keyCount') const dbInst = this.databases[this.db] if (dbInst != null) { - dbInst.keyCount = sumBy(dbNode.children, (c) => c.keyCount) + dbInst.keyCount = dbNode.reCalcKeyCount() } } - return true } /** diff --git a/frontend/src/stores/browser.js b/frontend/src/stores/browser.js index 53c1106..e839fa3 100644 --- a/frontend/src/stores/browser.js +++ b/frontend/src/stores/browser.js @@ -18,6 +18,7 @@ import { GetKeyType, GetSlowLogs, LoadAllKeys, + LoadNextAllKeys, LoadNextKeys, OpenConnection, OpenDatabase, @@ -537,15 +538,22 @@ const useBrowserStore = defineStore('browser', { * @param {number} db * @param {string} match * @param {string} [matchType] - * @param {boolean} [full] + * @param {number} [loadType] 0.load next; 1.load next full; 2.reload load all * @returns {Promise<{keys: string[], maxKeys: number, end: boolean}>} */ - async scanKeys(server, db, match, matchType, full) { + async scanKeys({ server, db, match = '*', matchType = '', loadType = 0 }) { let resp - if (full) { - resp = await LoadAllKeys(server, db, match || '*', matchType) - } else { - resp = await LoadNextKeys(server, db, match || '*', matchType) + switch (loadType) { + case 0: + default: + resp = await LoadNextKeys(server, db, match, matchType) + break + case 1: + resp = await LoadNextAllKeys(server, db, match, matchType) + break + case 2: + resp = await LoadAllKeys(server, db, match, matchType) + break } const { data, success, msg } = resp || {} if (!success) { @@ -575,7 +583,7 @@ const useBrowserStore = defineStore('browser', { match = prefix + separator + '*' } } - return this.scanKeys(server, db, match, matchType, all) + return this.scanKeys({ server, db, match, matchType, loadType: all ? 1 : 0 }) }, /** @@ -1583,25 +1591,6 @@ const useBrowserStore = defineStore('browser', { // some fail $message.warn(i18nGlobal.t('dialogue.delete_completed', { success: deletedCount, fail: failCount })) } - - // FIXME: update tree view - // if (!isEmpty(deleted)) { - // let updateDeleted = [] - // let count = size(deleted) - // for (const k of deleted) { - // updateDeleted.push(k) - // console.log(count) - // count -= 1 - // if (size(updateDeleted) > 100 || count <= 0) { - // for (const dk of updateDeleted) { - // this._deleteKeyNode(server, db, dk, false) - // await nextTick() - // } - // updateDeleted = [] - // console.warn('updateDeleted:', updateDeleted) - // } - // } - // } }, /**