From 1347136b54ad733643b6d06df7cb9a053e3dd0f8 Mon Sep 17 00:00:00 2001 From: tisonhuang Date: Mon, 2 Mar 2026 13:52:54 +0800 Subject: [PATCH] feat(export): use window-level detail drawer overlay --- electron/services/snsService.ts | 10 +++++++--- src/pages/ExportPage.scss | 31 +++++++++++++++---------------- src/pages/ExportPage.tsx | 28 +++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/electron/services/snsService.ts b/electron/services/snsService.ts index d22c853..e6e144c 100644 --- a/electron/services/snsService.ts +++ b/electron/services/snsService.ts @@ -417,13 +417,13 @@ class SnsService { ) let rows = primary.rows - if (!primary.success || !rows) { + if (!primary.success || !rows || rows.length === 0) { const fallback = await wcdbService.execQuery( 'sns', null, "SELECT userName AS username, COUNT(1) AS total FROM SnsTimeLine WHERE userName IS NOT NULL AND userName <> '' GROUP BY userName" ) - if (!fallback.success || !fallback.rows) { + if (!fallback.success || !fallback.rows || fallback.rows.length === 0) { return { success: false, error: primary.error || fallback.error || '获取朋友圈联系人条数失败' } } rows = fallback.rows @@ -433,7 +433,11 @@ class SnsService { const usernameRaw = row?.username ?? row?.user_name ?? row?.userName ?? '' const username = typeof usernameRaw === 'string' ? usernameRaw.trim() : String(usernameRaw || '').trim() if (!username) continue - counts[username] = this.parseCountValue(row) + const countRaw = row?.total ?? row?.count ?? row?.cnt + const parsedCount = Number(countRaw) + counts[username] = Number.isFinite(parsedCount) && parsedCount > 0 + ? Math.floor(parsedCount) + : this.parseCountValue(row) } return { success: true, data: counts } } catch (e) { diff --git a/src/pages/ExportPage.scss b/src/pages/ExportPage.scss index eaad4bc..08a8183 100644 --- a/src/pages/ExportPage.scss +++ b/src/pages/ExportPage.scss @@ -573,7 +573,6 @@ display: flex; flex: 1; min-height: 0; - gap: 10px; .table-wrap { flex: 1; @@ -1015,15 +1014,25 @@ } } +.export-session-detail-overlay { + position: fixed; + inset: 0; + z-index: 1100; + display: flex; + justify-content: flex-end; + background: rgba(15, 23, 42, 0.24); +} + .export-session-detail-panel { - width: 300px; - min-width: 300px; - border: 1px solid var(--border-color); - border-radius: 10px; + width: min(360px, calc(100vw - 16px)); + height: 100vh; + border-left: 1px solid var(--border-color); + border-radius: 0; background: var(--card-bg); display: flex; flex-direction: column; overflow: hidden; + box-shadow: -12px 0 30px rgba(0, 0, 0, 0.18); .detail-header { display: flex; @@ -1615,16 +1624,6 @@ .media-check-grid { grid-template-columns: repeat(2, minmax(120px, 1fr)); } - - .session-table-layout.with-detail { - flex-direction: column; - } - - .export-session-detail-panel { - width: 100%; - min-width: 0; - max-height: 360px; - } } @media (max-width: 720px) { @@ -1647,6 +1646,6 @@ } .export-session-detail-panel { - max-height: 320px; + width: calc(100vw - 12px); } } diff --git a/src/pages/ExportPage.tsx b/src/pages/ExportPage.tsx index 5051bea..e783995 100644 --- a/src/pages/ExportPage.tsx +++ b/src/pages/ExportPage.tsx @@ -2096,6 +2096,17 @@ function ExportPage() { void loadSessionDetail(sessionId) }, [loadSessionDetail]) + useEffect(() => { + if (!showSessionDetailPanel) return + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setShowSessionDetailPanel(false) + } + } + window.addEventListener('keydown', handleKeyDown) + return () => window.removeEventListener('keydown', handleKeyDown) + }, [showSessionDetailPanel]) + const handleCopyDetailField = useCallback(async (text: string, field: string) => { try { await navigator.clipboard.writeText(text) @@ -2581,7 +2592,7 @@ function ExportPage() { )} -
+
{contactsList.length === 0 && contactsLoadIssue ? (
@@ -2698,7 +2709,17 @@ function ExportPage() {
{showSessionDetailPanel && ( - +
)}