From 072c49a037a29d9e103e227aeb27d7e6f457bba5 Mon Sep 17 00:00:00 2001 From: xuncha <1658671838@qq.com> Date: Mon, 16 Mar 2026 18:23:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E5=90=8D=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/GroupAnalyticsPage.scss | 87 +++++++++++++++++++++++++++++++ src/pages/GroupAnalyticsPage.tsx | 71 +++++++++++++++++++++---- 2 files changed, 149 insertions(+), 9 deletions(-) diff --git a/src/pages/GroupAnalyticsPage.scss b/src/pages/GroupAnalyticsPage.scss index 95c71e6..b1b0eab 100644 --- a/src/pages/GroupAnalyticsPage.scss +++ b/src/pages/GroupAnalyticsPage.scss @@ -1606,6 +1606,11 @@ background: rgba(30, 30, 30, 0.95); border: 1px solid rgba(255, 255, 255, 0.1); } + + .member-result-modal { + background: rgba(30, 30, 30, 0.95); + border: 1px solid rgba(255, 255, 255, 0.1); + } } // 成员详情弹框 @@ -1822,3 +1827,85 @@ gap: 18px; } } + +.member-result-modal { + background: rgba(255, 255, 255, 0.97); + border-radius: 20px; + padding: 28px; + width: min(420px, calc(100vw - 32px)); + position: relative; + backdrop-filter: blur(20px); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + + &.success { + border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border-color)); + } + + &.error { + border: 1px solid color-mix(in srgb, #ef4444 38%, var(--border-color)); + } + + .modal-close { + position: absolute; + top: 16px; + right: 16px; + background: var(--bg-tertiary); + border: none; + width: 32px; + height: 32px; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + transition: all 0.15s; + + &:hover { + background: var(--bg-hover); + color: var(--text-primary); + } + } +} + +.member-result-modal-body { + padding-right: 40px; + + h3 { + margin: 0; + font-size: 20px; + font-weight: 600; + color: var(--text-primary); + } + + p { + margin: 10px 0 0; + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary); + word-break: break-word; + } +} + +.member-result-modal-actions { + margin-top: 24px; + display: flex; + justify-content: flex-end; +} + +.member-result-modal-btn { + min-width: 96px; + border: none; + border-radius: 12px; + background: var(--primary); + color: #fff; + padding: 10px 18px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: opacity 0.2s; + + &:hover { + opacity: 0.92; + } +} diff --git a/src/pages/GroupAnalyticsPage.tsx b/src/pages/GroupAnalyticsPage.tsx index 84aaf89..db14c4d 100644 --- a/src/pages/GroupAnalyticsPage.tsx +++ b/src/pages/GroupAnalyticsPage.tsx @@ -188,6 +188,11 @@ function GroupAnalyticsPage() { const [selectedMember, setSelectedMember] = useState(null) const [copiedField, setCopiedField] = useState(null) const [showMemberExportModal, setShowMemberExportModal] = useState(false) + const [exportResultDialog, setExportResultDialog] = useState<{ + title: string + message: string + tone: 'success' | 'error' + } | null>(null) const [showMessageMemberSelect, setShowMessageMemberSelect] = useState(false) const [showFormatSelect, setShowFormatSelect] = useState(false) const [showDisplayNameSelect, setShowDisplayNameSelect] = useState(false) @@ -783,13 +788,25 @@ function GroupAnalyticsPage() { const result = await window.electronAPI.groupAnalytics.exportGroupMembers(selectedGroup.username, saveResult.filePath) if (result.success) { - alert(`导出成功,共 ${result.count ?? members.length} 人`) + setExportResultDialog({ + title: '导出成功', + message: `共导出 ${result.count ?? members.length} 人`, + tone: 'success' + }) } else { - alert(`导出失败:${result.error || '未知错误'}`) + setExportResultDialog({ + title: '导出失败', + message: result.error || '未知错误', + tone: 'error' + }) } } catch (e) { console.error('导出群成员失败:', e) - alert(`导出失败:${String(e)}`) + setExportResultDialog({ + title: '导出失败', + message: String(e), + tone: 'error' + }) } finally { setIsExportingMembers(false) } @@ -864,13 +881,25 @@ function GroupAnalyticsPage() { ) if (result.success && (result.successCount ?? 0) > 0) { setShowMemberExportModal(false) - alert(`导出成功:${member.displayName || member.username}`) + setExportResultDialog({ + title: '导出成功', + message: `已导出 ${member.displayName || member.username}`, + tone: 'success' + }) } else { - alert(`导出失败:${result.error || '未知错误'}`) + setExportResultDialog({ + title: '导出失败', + message: result.error || '未知错误', + tone: 'error' + }) } } catch (e) { console.error('导出成员消息失败:', e) - alert(`导出失败:${String(e)}`) + setExportResultDialog({ + title: '导出失败', + message: String(e), + tone: 'error' + }) } finally { setIsExportingMemberMessages(false) } @@ -1048,8 +1077,8 @@ function GroupAnalyticsPage() {
handleFunctionSelect('memberMessages')}> - 成员消息查看 - 按成员筛选并分页查看群聊消息 + 成员消息筛选与导出 + 按成员查看群聊消息,并支持导出当前成员记录
handleFunctionSelect('ranking')}> @@ -1074,7 +1103,7 @@ function GroupAnalyticsPage() { const getFunctionTitle = () => { switch (selectedFunction) { case 'members': return '群成员查看' - case 'memberMessages': return '成员消息查看' + case 'memberMessages': return '成员消息筛选与导出' case 'ranking': return '群聊发言排行' case 'activeHours': return '群聊活跃时段' case 'mediaStats': return '媒体内容统计' @@ -1513,6 +1542,29 @@ function GroupAnalyticsPage() { ) } + const renderExportResultDialog = () => { + if (!exportResultDialog) return null + + return ( +
setExportResultDialog(null)}> +
e.stopPropagation()}> + +
+

{exportResultDialog.title}

+

{exportResultDialog.message}

+
+
+ +
+
+
+ ) + } + return (
@@ -1525,6 +1577,7 @@ function GroupAnalyticsPage() {
{renderMemberModal()} {renderMemberExportModal()} + {renderExportResultDialog()}
) }