refactor: tighten private analytics header

This commit is contained in:
aits2026
2026-03-10 12:24:42 +08:00
parent 6911132c95
commit 74e974177c
4 changed files with 43 additions and 40 deletions

View File

@@ -2,6 +2,8 @@
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
gap: 16px;
min-height: 28px; min-height: 28px;
padding: 4px 0; padding: 4px 0;
background: transparent; background: transparent;
@@ -107,9 +109,28 @@
} }
} }
.chat-analysis-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
margin-left: auto;
flex-wrap: wrap;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.chat-analysis-header {
align-items: flex-start;
flex-wrap: wrap;
}
.chat-analysis-breadcrumb { .chat-analysis-breadcrumb {
flex-wrap: wrap; flex-wrap: wrap;
row-gap: 4px; row-gap: 4px;
} }
.chat-analysis-actions {
width: 100%;
justify-content: flex-start;
}
} }

View File

@@ -1,5 +1,5 @@
import { ChevronDown, ChevronLeft } from 'lucide-react' import { ChevronDown, ChevronLeft } from 'lucide-react'
import { useEffect, useMemo, useRef, useState } from 'react' import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import './ChatAnalysisHeader.scss' import './ChatAnalysisHeader.scss'
@@ -7,6 +7,7 @@ export type ChatAnalysisMode = 'private' | 'group'
interface ChatAnalysisHeaderProps { interface ChatAnalysisHeaderProps {
currentMode: ChatAnalysisMode currentMode: ChatAnalysisMode
actions?: ReactNode
} }
const MODE_CONFIG: Record<ChatAnalysisMode, { label: string; path: string }> = { const MODE_CONFIG: Record<ChatAnalysisMode, { label: string; path: string }> = {
@@ -20,7 +21,7 @@ const MODE_CONFIG: Record<ChatAnalysisMode, { label: string; path: string }> = {
} }
} }
function ChatAnalysisHeader({ currentMode }: ChatAnalysisHeaderProps) { function ChatAnalysisHeader({ currentMode, actions }: ChatAnalysisHeaderProps) {
const navigate = useNavigate() const navigate = useNavigate()
const currentLabel = MODE_CONFIG[currentMode].label const currentLabel = MODE_CONFIG[currentMode].label
const [menuOpen, setMenuOpen] = useState(false) const [menuOpen, setMenuOpen] = useState(false)
@@ -95,6 +96,8 @@ function ChatAnalysisHeader({ currentMode }: ChatAnalysisHeaderProps) {
)} )}
</div> </div>
</div> </div>
{actions ? <div className="chat-analysis-actions">{actions}</div> : null}
</div> </div>
) )
} }

View File

@@ -8,10 +8,6 @@
.error-container { .error-container {
flex: 1; flex: 1;
} }
.page-header {
margin-bottom: 16px;
}
} }
// 加载和错误状态 // 加载和错误状态
@@ -69,24 +65,6 @@
} }
} }
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 16px;
h1 {
margin: 0;
}
.header-actions {
display: flex;
align-items: center;
gap: 8px;
}
}
@keyframes spin { @keyframes spin {
from { from {
transform: rotate(0deg); transform: rotate(0deg);

View File

@@ -424,6 +424,19 @@ function AnalyticsPage() {
</div> </div>
) )
const analyticsHeaderActions = (
<>
<button className="btn btn-secondary" onClick={handleRefresh} disabled={isLoading}>
<RefreshCw size={16} className={isLoading ? 'spin' : ''} />
{isLoading ? '刷新中...' : '刷新'}
</button>
<button className="btn btn-secondary" onClick={openExcludeDialog}>
<UserMinus size={16} />
{excludedUsernames.size > 0 ? ` (${excludedUsernames.size})` : ''}
</button>
</>
)
if (isLoading && !isLoaded) { if (isLoading && !isLoaded) {
return renderPageShell( return renderPageShell(
<div className="loading-container"> <div className="loading-container">
@@ -463,21 +476,9 @@ function AnalyticsPage() {
} }
return renderPageShell( return (
<> <div className="analytics-page-shell">
<div className="page-header"> <ChatAnalysisHeader currentMode="private" actions={analyticsHeaderActions} />
<h1></h1>
<div className="header-actions">
<button className="btn btn-secondary" onClick={handleRefresh} disabled={isLoading}>
<RefreshCw size={16} className={isLoading ? 'spin' : ''} />
{isLoading ? '刷新中...' : '刷新'}
</button>
<button className="btn btn-secondary" onClick={openExcludeDialog}>
<UserMinus size={16} />
{excludedUsernames.size > 0 ? ` (${excludedUsernames.size})` : ''}
</button>
</div>
</div>
<div className="page-scroll"> <div className="page-scroll">
<section className="page-section"> <section className="page-section">
<div className="stats-overview"> <div className="stats-overview">
@@ -625,7 +626,7 @@ function AnalyticsPage() {
</div> </div>
</div> </div>
)} )}
</> </div>
) )
} }