Files
weflow-new/src/pages/AnnualReportPage.tsx
T
2026-02-01 02:26:00 +08:00

178 lines
6.0 KiB
TypeScript

import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { Calendar, Loader2, Sparkles, Users } from 'lucide-react'
import './AnnualReportPage.scss'
type YearOption = number | 'all'
function AnnualReportPage() {
const navigate = useNavigate()
const [availableYears, setAvailableYears] = useState<number[]>([])
const [selectedYear, setSelectedYear] = useState<YearOption | null>(null)
const [selectedPairYear, setSelectedPairYear] = useState<YearOption | null>(null)
const [isLoading, setIsLoading] = useState(true)
const [isGenerating, setIsGenerating] = useState(false)
const [loadError, setLoadError] = useState<string | null>(null)
useEffect(() => {
loadAvailableYears()
}, [])
const loadAvailableYears = async () => {
setIsLoading(true)
setLoadError(null)
try {
const result = await window.electronAPI.annualReport.getAvailableYears()
if (result.success && result.data && result.data.length > 0) {
setAvailableYears(result.data)
setSelectedYear((prev) => prev ?? result.data[0])
setSelectedPairYear((prev) => prev ?? result.data[0])
} else if (!result.success) {
setLoadError(result.error || '加载年度数据失败')
}
} catch (e) {
console.error(e)
setLoadError(String(e))
} finally {
setIsLoading(false)
}
}
const handleGenerateReport = async () => {
if (selectedYear === null) return
setIsGenerating(true)
try {
const yearParam = selectedYear === 'all' ? 0 : selectedYear
navigate(`/annual-report/view?year=${yearParam}`)
} catch (e) {
console.error('生成报告失败:', e)
} finally {
setIsGenerating(false)
}
}
const handleGenerateDualReport = () => {
if (selectedPairYear === null) return
const yearParam = selectedPairYear === 'all' ? 0 : selectedPairYear
navigate(`/dual-report?year=${yearParam}`)
}
if (isLoading) {
return (
<div className="annual-report-page">
<Loader2 size={32} className="spin" style={{ color: 'var(--text-tertiary)' }} />
<p style={{ color: 'var(--text-tertiary)', marginTop: 16 }}>正在加载年份数据...</p>
</div>
)
}
if (availableYears.length === 0) {
return (
<div className="annual-report-page">
<Calendar size={64} style={{ color: 'var(--text-tertiary)', opacity: 0.5 }} />
<h2 style={{ fontSize: 20, fontWeight: 600, color: 'var(--text-primary)', margin: '16px 0 8px' }}>暂无聊天记录</h2>
<p style={{ color: 'var(--text-tertiary)', margin: 0 }}>
{loadError || '请先解密数据库后再生成年度报告'}
</p>
</div>
)
}
const yearOptions: YearOption[] = availableYears.length > 0
? ['all', ...availableYears]
: []
const getYearLabel = (value: YearOption | null) => {
if (!value) return ''
return value === 'all' ? '全部时间' : `${value} 年`
}
return (
<div className="annual-report-page">
<Sparkles size={32} className="header-icon" />
<h1 className="page-title">年度报告</h1>
<p className="page-desc">选择年份,生成你的微信聊天年度回顾</p>
<div className="report-sections">
<section className="report-section">
<div className="section-header">
<div>
<h2 className="section-title">总年度报告</h2>
<p className="section-desc">包含所有会话与消息</p>
</div>
</div>
<div className="year-grid">
{yearOptions.map(option => (
<div
key={option}
className={`year-card ${option === 'all' ? 'all-time' : ''} ${selectedYear === option ? 'selected' : ''}`}
onClick={() => setSelectedYear(option)}
>
<span className="year-number">{option === 'all' ? '全部' : option}</span>
<span className="year-label">{option === 'all' ? '时间' : '年'}</span>
</div>
))}
</div>
<button
className="generate-btn"
onClick={handleGenerateReport}
disabled={!selectedYear || isGenerating}
>
{isGenerating ? (
<>
<Loader2 size={20} className="spin" />
<span>正在生成...</span>
</>
) : (
<>
<Sparkles size={20} />
<span>生成 {getYearLabel(selectedYear)} 年度报告</span>
</>
)}
</button>
</section>
<section className="report-section">
<div className="section-header">
<div>
<h2 className="section-title">双人年度报告</h2>
<p className="section-desc">选择一位好友,只看你们的私聊</p>
</div>
<div className="section-badge">
<Users size={16} />
<span>私聊</span>
</div>
</div>
<div className="year-grid">
{yearOptions.map(option => (
<div
key={`pair-${option}`}
className={`year-card ${option === 'all' ? 'all-time' : ''} ${selectedPairYear === option ? 'selected' : ''}`}
onClick={() => setSelectedPairYear(option)}
>
<span className="year-number">{option === 'all' ? '全部' : option}</span>
<span className="year-label">{option === 'all' ? '时间' : '年'}</span>
</div>
))}
</div>
<button
className="generate-btn secondary"
onClick={handleGenerateDualReport}
disabled={!selectedPairYear}
>
<Users size={20} />
<span>选择好友并生成报告</span>
</button>
<p className="section-hint">从聊天排行中选择好友生成双人报告</p>
</section>
</div>
</div>
)
}
export default AnnualReportPage