Commit Graph

148 Commits

Author SHA1 Message Date
Jokul afe2894c35 docs: restructure review report - remove fixed defects, focus on architecture analysis and roadmap
- Remove section 一 (all 54 defects fixed and committed)
- Deepen section 二: each architecture problem now shows '已解决' vs '仍存在' vs '架构级方案'
- Update section 三: mark 7 completed needs (N1/N2/N6/N15/N16/N17/N25), refine remaining 19
- Update roadmap: 4 phases with architecture improvement suggestions per phase
2026-07-12 14:55:12 +08:00
Jokul bf0bccb19f refactor: patch all P3 code quality issues, complete full audit
- string.ts: remove dead rejsonDel function (P3#38)
- AGENTS.md: add batchMemoryUsage and executeUnsafe to IPC channels table (P3#41)
- connection.ts: add console.warn to silent TLS/SSH catch blocks (P3#44)
- i18n: replace hardcoded strings in KeyDetail/TitleBar/Sidebar with t() (P3#37)
- composables/useTypeColor.ts: extract shared typeColor, replace in 7 editors (P3#39)
- CliView: extract formatRedisResult function to deduplicate (P3#39)
- SetEditor/ZsetEditor/CommandLog: watch+ref -> computed (P3#40)
- preload/index.d.ts: replace 15+ any types with concrete types (P3#36, P3#42)
- store.ts: add ConnectionConfig version field + migrateConnections() (P3#43)
- docs: update PROJECT_REVIEW.md - all 54 issues processed
2026-07-12 14:42:17 +08:00
Jokul 1a5e4dd706 fix: patch all P2 quality/performance issues from project review
- ipc-handlers: withLog extracts actual connection ID from args[0] (P2#20)
- updater: add initialized guard to prevent duplicate IPC registration (P2#25)
- win-state: log writeFile errors instead of empty callback (P2#26)
- format: detectFormat samples up to 4096 chars instead of 100 (P2#28)
- commandLogger: add 30+ missing write commands to WRITE_COMMANDS (P2#32)
- ReJsonEditor: bind Monaco theme to monacoTheme computed (P2#19)
- keys: normalize empty SCAN pattern to '*' (P2#21)
- SlowLogView: remove duplicate <style scoped> block (P2#29)
- CliView: deduplicate XGROUP in writeCommands Set (P2#33)
- key store: use connectionStore instead of IPC for separator (P2#22)
- NewConnectionDialog: add visible guard after async watch (P2#30)
- KeyList: remove dangerouslyUseHTMLString, use plain text + i18n (P2#31)
- KeyList: batch DUMP export with Promise.allSettled (batch=20) (P2#23)
- HashEditor: lazy load field TTL on click instead of bulk HTTL (P2#24)
- P2#27 already fixed in P0#2; P2#34 is feature (N4); P2#35 not a bug
- docs: update PROJECT_REVIEW.md with P2 fix status
2026-07-12 14:30:18 +08:00
Jokul 70db25b337 fix: patch all P1 bugs from project review
- pubsub: add sender.isDestroyed() checks + destroyed event auto-cleanup (P1#10)
- pubsub: add .catch() to monitor() promise + isDestroyed check (P1#11)
- connection: move server.on('error') before server.listen() (P1#12)
- preload: onSubscribeMessage/onMonitorMessage return cleanup functions (P1#9)
- CliView: save and call IPC listener cleanup in onUnmounted (P1#9)
- KeyDetail: move setInterval into onMounted, cleanup in onUnmounted (P1#8)
- key store: add loadKeyVersion guard to prevent race condition (P1#13)
- ListEditor: LSET sentinel + LREM for index-based deletion (P1#14)
- ipc-handlers: remove non-null assertion, add null guard in reorderConnections (P1#16)
- StreamEditor: add Confirm/Cancel buttons to Trim dialog (P1#17)
- KeyBrowser: remove { immediate: true } to prevent double scan (P1#18)
- P1#7 MULTI/EXEC: investigated, not a bug (Redis server handles queuing)
- docs: update PROJECT_REVIEW.md with P1 fix status
2026-07-12 14:18:48 +08:00
Jokul 9d73ff019c fix(security): patch all P0 vulnerabilities from project review
- credential: encrypt/decrypt now throw when safeStorage unavailable instead of base64 fallback
- ipc-handlers: encrypt auth/sshPassword/sshPassphrase before storing, decrypt on read (avoid mutation)
- ipc-handlers: block FLUSHALL/FLUSHDB/SHUTDOWN/DEBUG in redis:execute, add redis:executeUnsafe for CLI
- format: whitelist allowed external formatters (xxd/jq/python3/python/php/column), clean up tmpDir
- connection: clearTimeout on ready/error paths to fix timeout race in Sentinel/Cluster/normal modes
- index: add app.on('will-quit') to disconnectAll + stopAllPubSubClients on exit
- pubsub: add stopAllPubSubClients() to clean up all sub/monitor connections
- docs: add PROJECT_REVIEW.md with full audit report and fix status
2026-07-12 14:13:44 +08:00
Jokul 4d0e0b75aa 删除无用文档 2026-07-12 12:44:34 +08:00
Jokul 73976bc37a fix(settings): dropdown hover color, editor layout alignment, add about card 2026-07-12 12:21:47 +08:00
Jokul bf46cb160a feat(key-detail): live TTL countdown with expiry check and i18n 2026-07-12 11:54:15 +08:00
Jokul 775b66054a refactor: move type-badge from KeyDetail header to editors with colored border style 2026-07-12 11:25:13 +08:00
Jokul 9848d97b4c fix(key-list): add horizontal scroll for deeply nested keys 2026-07-12 11:09:42 +08:00
Jokul 0a5ceeaf4d style: reorganize key list layout — actions to bottom, fix footer wrap
Layout restructure:
- Move Import Keys button from toolbar to footer (left side)
- Move batch action bar (select-all + export/delete) to bottom,
  above the footer, below the tree view
- Toolbar now only contains filter input + refresh/toggle buttons

Footer fix:
- Add min-width:0 + overflow:hidden on left side to truncate long counts
- Add flex-shrink:0 + white-space:nowrap on right side to keep buttons
  from wrapping when key count is large
2026-07-12 10:59:23 +08:00
Jokul e39ec7afce fix: add visual selected state for active key in key tree
The active/selected classes were already applied via :class binding
but had no CSS styles defined. Add:
- .active: indigo background tint + 3px left accent border (box-shadow
  inset to avoid layout shift) + bold accent-colored key name
- .selected: subtle indigo background for multi-select checked items
2026-07-12 10:46:34 +08:00
Jokul 8340630dd4 i18n: replace hardcoded strings in all editor components
Fix 36 hardcoded UI strings across 7 editor files:
- ReJsonEditor.vue: add useI18n import (was entirely missing i18n)
- StringEditor.vue: Edit/Save/Cancel/Saved buttons
- HashEditor.vue: delete confirm dialog, Deleted/Added toasts
- SetEditor.vue: remove confirm dialog, Added/Removed toasts
- ZsetEditor.vue: same pattern as SetEditor
- ListEditor.vue: Prev/Next pagination, Saved/Added/Removed toasts
- StreamEditor.vue: 8 strings (group destroy, entry delete, trim,
  add field warning, entries count)

New i18n keys added to all 5 locales (en, zh-CN, ja, ko, de):
- common.prev, common.next
- editor.deleted, deleteFieldConfirm, removeElementConfirm,
  removeMemberConfirm, destroyGroupConfirm, deleteEntryConfirm,
  trimConfirmDetail, trimmed, entries, addFieldWarning
2026-07-12 10:27:29 +08:00
Jokul d2c1f50f87 feat: replace min size filter with key name + type filter
Remove the minSizeKB number input (rarely useful). Add:
- Key name search input (case-insensitive substring match)
- Type dropdown filter (string/hash/list/set/zset/stream)

Updated i18n for all 5 locales (en, zh-CN, ja, ko, de).
2026-07-12 10:16:45 +08:00
Jokul bb3adeb688 perf: increase SCAN_COUNT to 1000 for faster memory scan
Virtual scroll now handles large batches without lag, so we can
increase the per-iteration key count from 200 to 1000. This reduces
the number of SCAN iterations and IPC round-trips by 5x.
2026-07-12 10:11:58 +08:00
Jokul 9c16dbdb15 perf: replace el-table with virtual scroll for memory analysis
- Replace el-table (renders all DOM rows) with lightweight virtual scroll
  (only renders visible rows + buffer). This is the key fix for scan lag.
- Reduce flush interval from 300ms to 100ms (matches legacy setTimeout(100))
- Virtual list uses fixed 36px row height, calculates visible range from
  scrollTop, and translates only the rendered window.
- Stripe rows via CSS alt class instead of Element Plus stripe prop.
- Column layout: flex-based with key (flex:1), type (80px), size (100px).
2026-07-12 10:07:03 +08:00
Jokul c8eeb7c0b9 fix: memory analysis dark mode stripe, scan speed, and NaN total size
- Dark mode: add --el-fill-color-lighter and --el-table-current-row-bg-color
  to .el-table overrides so striped rows render with proper contrast
- Scan speed: add batchKeyMemoryUsage pipeline (TYPE + MEMORY USAGE in one
  Redis round-trip instead of 2×N sequential IPC calls)
- Scan speed: decouple scan loop from UI via 300ms flush buffer, keeping
  el-table re-render frequency capped at ~3/s
- Scan speed: use shallowRef for entries to skip deep reactive proxies
- NaN fix: handle ioredis stringNumbers:true by converting via Number()
  instead of typeof === 'number'
- formatSize: guard against non-finite input, add TB/PB units
2026-07-12 10:01:30 +08:00
Jokul 72967c45e9 更新版本号 2026-07-12 00:42:49 +08:00
Jokul c6265fdaf5 fix: 模板中通过变量引用 __APP_VERSION__ 全局常量 2026-07-12 00:40:49 +08:00
Jokul faedfd7fa3 fix: StatusBar 版本号改为从 package.json 动态注入
- electron.vite.config.ts 读取 package.json 注入 __APP_VERSION__ 全局常量
- StatusBar.vue 使用 __APP_VERSION__ 替代硬编码 v2.0
- env.d.ts 添加 __APP_VERSION__ 类型声明
2026-07-12 00:37:06 +08:00
Jokul 19672045d6 fix: StatusBar 版本号改为从 package.json 动态读取 2026-07-12 00:31:57 +08:00
Jokul 83159151b9 fix: DbSelector 连接后自动选择第一个有数据的 DB,切换 DB 时重新加载键树
- 新增 getDefaultDb(): 优先恢复 lastDbMap > 第一个有数据的 DB > DB0
- onMounted 执行 DB 选择(覆盖首次连接和右键重连场景)
- activeId watcher 改为完整 DB 选择流程(不再硬编码 DB0)
- isConnected watcher 精简为仅加载自定义名称(避免竞态重复调用)
- switchDb() 新增 scanKeys 重新加载键树
2026-07-12 00:28:14 +08:00
Jokul 76c9758f0a 更改切换redis连接操作方式 2026-07-12 00:01:01 +08:00
Jokul b4aab76141 fix: DbSelector 数据库 key 数量使用 INFO keyspace 直接获取
- 改用 INFO keyspace 命令替代解析完整 INFO 输出,避免正则匹配 Keyspace 段失败
- activeId 变化时重新获取 DB 数量和 key 计数
- expose refreshDbCounts 方法供父组件调用
2026-07-11 23:03:53 +08:00
Jokul b7e9c80022 fix: 连接断开后 IPC handler 不再报 Client null / Connection closed
- connection.ts: 新增 requireClient(id),状态非 ready 时抛明确错误
- connection.ts: Redis client 监听 close 事件自动从 Map 清理
- 8 个 redis 模块: getClient + null check 统一替换为 requireClient
- sentinel/cluster/普通连接三种模式均添加 close 自动清理
2026-07-11 22:31:55 +08:00
Jokul 0ffe3ae83f feat: 连接相关提示信息国际化
- 右键连接: 成功/失败弹出 ElMessage 提示
- 测试连接: testSuccess/testFailed 替换硬编码
- 保存连接: created/updated/saveFailed 替换硬编码
- 导入/导出: exported/imported/importTitle 替换硬编码
- connection store: serverInfoUnavailable/connectFailed 国际化
- 新增 11 个 i18n key (5 语言): hostRequired, nameHostRequired,
  connectSuccess, connectFailed, created, updated, saveFailed,
  exported, importTitle, imported, serverInfoUnavailable
2026-07-11 22:15:56 +08:00
Jokul 19b5a3d1d0 fix: key 类型为 none 时显示过期提示并自动移除失效 key
- KeyDetail: 新增 'none' 类型专用视图,显示过期提示 + 刷新按钮
- key store: TYPE 返回 none 时自动从列表移除失效 key 并重建 tree
- 新增 i18n keyExpired 多语言 (zh-CN/en/ja/ko/de)
2026-07-11 21:44:08 +08:00
Jokul 3dea59f703 refactor: 组件按功能分组到子目录
components/ 拆分为 5 个子目录:
- layout/       TitleBar, StatusBar, Sidebar, MainArea
- connection/   ConnectionList, ConnectionCard, NewConnectionDialog
- key/          KeyBrowser, KeyList, KeyDetail, DbSelector
- editors/      String/Hash/List/Set/Zset/Stream/ReJson Editor
- views/        StatusView, CliView, SlowLogView, MemoryAnalysis, CommandLog, SettingsView

更新 4 个文件的跨目录引用 (App.vue, Sidebar, MainArea, KeyDetail)
AGENTS.md 架构树同步更新
2026-07-11 21:21:47 +08:00
Jokul 12134ec896 fix: tooltip 浅色模式不可见 - 覆盖 Element Plus CSS 变量
根因: .el-popper 全局规则覆盖了 tooltip 背景为浅色, 但 is-dark 类
仍将文字设为白色。现在同时覆盖 --el-text-color-primary 和
--el-bg-color 变量, 确保 tooltip 背景和文字都有对比度。
2026-07-11 21:15:44 +08:00
Jokul 3142f84334 fix: tooltip 文字颜色与背景同色 - 精确匹配 is-dark/is-light 选择器 2026-07-11 21:10:07 +08:00
Jokul ee619589ac ux: 优化 Key 搜索区布局和操作逻辑
- 去掉 MATCH 前缀标签, 改为搜索图标 (Search icon prefix)
- Go 按钮改为搜索图标按钮, 带 tooltip 说明通配符用法
- Filter 输入框加 Filter 图标前缀, 与扫描区分
- placeholder 更新: '扫描 Key (如 user:*, 支持 * ?)'
- 新增 scanHint i18n (5 语言): 说明 * ? 通配符和回车扫描
2026-07-11 21:03:04 +08:00
Jokul f3af1e415a fix: MATCH 前缀背景色跟随深色/浅色主题切换 2026-07-11 20:50:55 +08:00
Jokul 464a40840a 紧凑布局 2026-07-11 17:54:51 +08:00
Jokul 0b7b512094 调整连接信息弹框样式以及国际化 2026-07-11 17:38:23 +08:00
Jokul a49d088540 中文名称 2026-07-11 17:10:07 +08:00
Jokul 9188829eae 调整redis连接展开收缩按钮样式 2026-07-11 17:01:10 +08:00
Jokul ca10707fbf fix: 加载更多按钮浅色模式文字不可见 - 去掉 text 属性 2026-07-11 16:34:42 +08:00
Jokul 1831acc7f0 fix: 树状视图深层级节点支持水平滚动 2026-07-11 16:32:27 +08:00
Jokul 392c64fc4a fix: WRONGTYPE 根因 - selectedKey 在类型加载前设置导致竞争
KeyList.selectKey 在调用 loadKeyData 之前设置了 selectedKey,
触发编辑器 watch 时 selectedType 还是上一个 key 的类型。
如果上一个 key 是 set 而新 key 不是, SetEditor 会对新 key
调用 SMEMBERS 导致 WRONGTYPE。

loadKeyData 内部已在校验类型后设置 selectedKey,
KeyList 中的提前设置是多余且有害的, 移除即可。
2026-07-11 16:30:07 +08:00
Jokul a20730f1e5 feat: 键 tab 自动打开, 去掉右上角键按钮
- keys tab 和 status tab 一样不可关闭 (closable: false)
- 连接成功时自动打开 status + keys 两个 tab
- 右上角按钮组移除键按钮
2026-07-11 16:23:12 +08:00
Jokul 8dfd3aecad hash的保存和删除按钮宽度修改 2026-07-11 16:13:44 +08:00
Jokul ff83315b64 style: HashEditor 按钮一排显示 + 颜色对比 + TTL 内联编辑
- 去掉设置 TTL 按钮, TTL 列改为 el-input-number 内联编辑
- saveField 保存时一并提交 TTL (HEXPIRE)
- 保存和删除按钮改为一排显示 (列宽 120px)
- 按钮从 text 改为 outline 样式, 确保浅色模式下文字可见
- 移除 setFieldTtl 函数和 .field-ttl 样式
2026-07-11 16:06:17 +08:00
Jokul 53ffa1043c style: HashEditor 表格高度适配 + 文字颜色对比
- max-height=400 改为 height=100%, 表格填满剩余空间
- hash-table-wrap overflow hidden + min-height:0 配合 flex 布局
- 表格正文文字用 --text-primary (深色模式下白色)
- 表头用 --text-secondary + --bg-tertiary 背景
- 行悬停用 --bg-hover
- 输入框文字用 --text-primary 确保可读性
2026-07-11 15:58:37 +08:00
Jokul 78695c0b7f fix: WRONGTYPE 错误处理 - key 类型变更时不崩溃
- loadKeyData: 类型特定命令 (SCARD/LLEN 等) 失败时重新获取 key 类型,
  避免显示错误的编辑器
- SetEditor.loadMembers: 添加 catch 块, WRONGTYPE 时清空成员列表而非
  抛出未捕获异常
2026-07-11 15:52:33 +08:00
Jokul 99f8a8b250 fix: keyStore.selectedType (string | null) 传参类型不匹配 2026-07-11 15:44:13 +08:00
Jokul 54350b152e fix: 移除空 CSS 规则 .leaf-item 2026-07-11 15:42:31 +08:00
Jokul a782180dd3 Revert "feat: 树状视图路径压缩 - 单子节点文件夹自动合并"
This reverts commit ccb91731fc.
2026-07-11 15:37:33 +08:00
Jokul ccb91731fc feat: 树状视图路径压缩 - 单子节点文件夹自动合并
文件夹只有 1 个子节点时合并名称, 避免不必要的层级展开:
- a:b:c:d (单个 key) 直接显示为 a:b:c:d 而非 4 层嵌套
- a:b:c + a:b:d 仍展开为 a > b > {c, d} (b 有 2 个子节点)
- a:b:c + a:d:e 显示为 a > {b:c, d:e} (b/d 各 1 子节点, 合并)
2026-07-11 15:35:06 +08:00
Jokul 4305773f0d refactor: KeyList 移除列表模式, 只保留树状模式
- 移除 viewMode、虚拟滚动 (useVirtualizer)、scrollRef
- 移除列表视图模板和样式 (.key-flat-list, .key-item 等)
- 移除工具栏的列表/树状切换按钮
- 树状叶子节点新增多选 checkbox (原先只有列表模式有)
- 保留 .key-checkbox 样式供树状多选使用
2026-07-11 15:30:56 +08:00
Jokul 5a479d416e refactor: Scan Count 从全局设置移到连接配置
- ConnectionConfig 新增 scanCount 字段 (默认 100)
- NewConnectionDialog 基本信息区新增 Scan Count 输入框
- key.ts 改为从 activeConnection.scanCount 读取
- SettingsView 移除 Scan Count 设置项
- app store 移除 scanCount 和 setScanCount
- 主进程 store ConnectionConfig 同步新增字段
2026-07-11 15:22:58 +08:00