diff --git a/docs/PROJECT_REVIEW.md b/docs/PROJECT_REVIEW.md
index e42d4eb..7e5f991 100644
--- a/docs/PROJECT_REVIEW.md
+++ b/docs/PROJECT_REVIEW.md
@@ -4,7 +4,7 @@
> 审查方式:并行扫描主进程、渲染进程、IPC 契约一致性
> 审查范围:主进程 10 文件、渲染进程 ~40 文件、IPC 65 通道
> 发现问题:54 个(P0×6, P1×12, P2×17, P3×19)
-> 已修复:**P0×6 + P1×11 全部修复** (2026-07-12)
+> 已修复:**P0×6 + P1×11 + P2×14 全部修复** (2026-07-12)
> 可开发需求:26 项(高优先级 6,中 11,低 9)
---
@@ -49,27 +49,27 @@
| 17 | `StreamEditor.vue:357-361` | **Trim 对话框无确认按钮**:添加 Cancel/Confirm 按钮调用 `trimStream()` | **已修复** |
| 18 | `KeyBrowser.vue` + `DbSelector.vue` | **双重扫描**:移除 KeyBrowser watch 的 `{ immediate: true }` | **已修复** |
-### P2 - 应修复(质量/性能)
+### P2 - 应修复(质量/性能) - 全部已处理
-| # | 位置 | 问题 |
-|---|------|------|
-| 19 | `ReJsonEditor.vue:88` | Monaco 主题硬编码 `vs-dark`,亮色主题下对比度极差。 |
-| 20 | `ipc-handlers.ts:13,16` | `withLog` 记录 `'current'` 而非实际连接 ID,命令日志无用。 |
-| 21 | `keys.ts:96` | 空模式 `''` 导致 SCAN 匹配空字符串键,应规范化为 `'*'`。 |
-| 22 | `key.ts:115-119` | 每次扫描都调 `getConnections()` IPC,连接信息已在 store 中。 |
-| 23 | `KeyList.vue:143-180` | 批量导出串行 DUMP,1000 key = 1000 次 IPC 往返。 |
-| 24 | `HashEditor.vue:80-89` | 逐个字段 HTTL,大 hash 数百次 IPC。 |
-| 25 | `updater.ts:15,25,35` | 重复调用 `initUpdater` 时 `ipcMain.handle` 抛重复注册错误。 |
-| 26 | `win-state.ts:47` | 写错误空回调静默吞噬。 |
-| 27 | `format.ts:56-58` | 临时目录 `mkdtemp` 创建后成功路径不清理,`/tmp/jrdm-fmt-*/` 累积。 |
-| 28 | `format.ts:46` | `detectFormat` 仅检查前 100 字符,前 100 为 ASCII 的二进制值误判为 text。 |
-| 29 | `SlowLogView.vue:241-283` | 重复 `
-
diff --git a/src/renderer/src/i18n/locales/de.ts b/src/renderer/src/i18n/locales/de.ts
index baf9d06..b27136f 100644
--- a/src/renderer/src/i18n/locales/de.ts
+++ b/src/renderer/src/i18n/locales/de.ts
@@ -112,6 +112,7 @@ export default {
batchConfirm: '{n} Schlüssel löschen?',
batchDeleted: '{n} Schlüssel gelöscht',
batchPreview: 'Löschvorschau',
+ batchDeleteConfirm: '{n} Schlüssel löschen?',
batchPreviewHint: '{n} Schlüssel werden gelöscht',
andMore: '...und {n} weitere',
selected: '{n} ausgewählt',
diff --git a/src/renderer/src/i18n/locales/en.ts b/src/renderer/src/i18n/locales/en.ts
index 9cf020f..d67d5b1 100644
--- a/src/renderer/src/i18n/locales/en.ts
+++ b/src/renderer/src/i18n/locales/en.ts
@@ -112,6 +112,7 @@ export default {
batchConfirm: 'Delete {n} key(s)?',
batchDeleted: 'Deleted {n} key(s)',
batchPreview: 'Delete Preview',
+ batchDeleteConfirm: 'Delete {n} key(s)?',
batchPreviewHint: 'About to delete {n} keys',
andMore: '...and {n} more',
selected: '{n} selected',
diff --git a/src/renderer/src/i18n/locales/ja.ts b/src/renderer/src/i18n/locales/ja.ts
index 027a528..140fb96 100644
--- a/src/renderer/src/i18n/locales/ja.ts
+++ b/src/renderer/src/i18n/locales/ja.ts
@@ -112,6 +112,7 @@ export default {
batchConfirm: '{n} 個のキーを削除しますか?',
batchDeleted: '{n} 個のキーを削除しました',
batchPreview: '削除プレビュー',
+ batchDeleteConfirm: '{n} 個のキーを削除しますか?',
batchPreviewHint: '{n} 個のキーを削除しようとしています',
andMore: '...他 {n} 個',
selected: '{n} 個選択済み',
diff --git a/src/renderer/src/i18n/locales/ko.ts b/src/renderer/src/i18n/locales/ko.ts
index 709c287..86ba368 100644
--- a/src/renderer/src/i18n/locales/ko.ts
+++ b/src/renderer/src/i18n/locales/ko.ts
@@ -112,6 +112,7 @@ export default {
batchConfirm: '{n}개 키를 삭제하시겠습니까?',
batchDeleted: '{n}개 키가 삭제되었습니다',
batchPreview: '삭제 미리보기',
+ batchDeleteConfirm: '{n}개 키를 삭제하시겠습니까?',
batchPreviewHint: '{n}개 키를 삭제하려고 합니다',
andMore: '...그 외 {n}개',
selected: '{n}개 선택됨',
diff --git a/src/renderer/src/i18n/locales/zh-CN.ts b/src/renderer/src/i18n/locales/zh-CN.ts
index 2cc38fd..37cf367 100644
--- a/src/renderer/src/i18n/locales/zh-CN.ts
+++ b/src/renderer/src/i18n/locales/zh-CN.ts
@@ -112,6 +112,7 @@ export default {
batchConfirm: '删除 {n} 个键?',
batchDeleted: '已删除 {n} 个键',
batchPreview: '删除预览',
+ batchDeleteConfirm: '确定删除 {n} 个键?',
batchPreviewHint: '即将删除以下 {n} 个键',
andMore: '...以及其他 {n} 个',
selected: '已选 {n} 项',
diff --git a/src/renderer/src/stores/key.ts b/src/renderer/src/stores/key.ts
index 77eef2f..61c29a1 100644
--- a/src/renderer/src/stores/key.ts
+++ b/src/renderer/src/stores/key.ts
@@ -113,8 +113,8 @@ export const useKeyStore = defineStore('key', () => {
hasMore.value = result.cursor !== '0'
if (useTree.value) {
- const conn = (await window.electronAPI.storage.getConnections())
- .find((c: any) => c.id === connId)
+ const connectionStore = useConnectionStore()
+ const conn = connectionStore.connections.find(c => c.id === connId)
const sep = conn?.separator || ':'
treeKeys.value = buildTree(keys.value.map(k => k.name), sep)
}
@@ -149,8 +149,8 @@ export const useKeyStore = defineStore('key', () => {
keys.value = keys.value.filter(k => k.name !== key)
// Rebuild tree if needed
if (useTree.value) {
- const conn = (await window.electronAPI.storage.getConnections())
- .find((c: any) => c.id === connId)
+ const connectionStore = useConnectionStore()
+ const conn = connectionStore.connections.find(c => c.id === connId)
const sep = conn?.separator || ':'
treeKeys.value = buildTree(keys.value.map(k => k.name), sep)
}