import React, { useState, useEffect, useMemo } from 'react'; import { useAuth } from '../contexts/AuthContext'; import { localApi } from '../lib/localApi'; import { ChineseButton } from '../components/ui/ChineseButton'; import { ChineseInput } from '../components/ui/ChineseInput'; import { ChineseSelect } from '../components/ui/ChineseSelect'; import { ChineseCard, ChineseCardContent, ChineseCardHeader, ChineseCardTitle } from '../components/ui/ChineseCard'; import AnalysisResultDisplay from '../components/AnalysisResultDisplay'; import { toast } from 'sonner'; import { Sparkles, Star, Compass, Calendar, MapPin, User, Loader2 } from 'lucide-react'; import { UserProfile, AnalysisRequest, NumerologyReading } from '../types'; import { cn } from '../lib/utils'; type AnalysisType = 'bazi' | 'ziwei' | 'yijing'; const AnalysisPage: React.FC = () => { const { user } = useAuth(); const [profile, setProfile] = useState(null); const [analysisType, setAnalysisType] = useState('bazi'); const [formData, setFormData] = useState({ name: '', birth_date: '', birth_time: '', gender: 'male' as 'male' | 'female', birth_place: '', question: '财运' }); const [loading, setLoading] = useState(false); const [analysisResult, setAnalysisResult] = useState(null); // 使用useMemo缓存birthDate对象,避免重复渲染导致useEffect重复执行 const memoizedBirthDate = useMemo(() => { if (analysisType === 'bazi' || analysisType === 'ziwei') { return { date: formData.birth_date, time: formData.birth_time, name: formData.name, gender: formData.gender }; } return undefined; }, [analysisType, formData.birth_date, formData.birth_time, formData.name, formData.gender]); useEffect(() => { loadProfile(); }, [user]); // 切换分析类型时清空分析结果 useEffect(() => { setAnalysisResult(null); }, [analysisType]); const loadProfile = async () => { if (!user) return; try { const response = await localApi.profiles.get(); if (response.data && response.data.profile) { const data = response.data.profile; setProfile(data); setFormData({ name: data.full_name || '', birth_date: data.birth_date || '', birth_time: data.birth_time || '', gender: data.gender || 'male', birth_place: data.birth_location || '', question: '财运' }); } } catch (error) { console.error('加载档案失败:', error); } }; const handleAnalysis = async () => { if (!user) return; // 根据分析类型验证必要参数 if (analysisType === 'yijing') { if (!formData.question) { toast.error('请填写占卜问题'); return; } } else { if (!formData.name || !formData.birth_date) { toast.error('请填写姓名和出生日期'); return; } } setLoading(true); setAnalysisResult(null); try { const birthData = { name: formData.name, birth_date: formData.birth_date, birth_time: formData.birth_time, gender: formData.gender, birth_place: formData.birth_place }; let response; // 根据分析类型调用相应的API switch (analysisType) { case 'bazi': response = await localApi.analysis.bazi(birthData); break; case 'ziwei': response = await localApi.analysis.ziwei(birthData); break; case 'yijing': const yijingData = { question: formData.question, user_id: user.id, divination_method: 'time' }; response = await localApi.analysis.yijing(yijingData); break; default: throw new Error(`不支持的分析类型: ${analysisType}`); } const { data, error } = response; if (error) { throw error; } if (data?.error) { throw new Error(data.error.message); } // 后端返回格式: { data: { analysis } } const analysisData = data.analysis; setAnalysisResult({ type: analysisType, data: analysisData }); // 分析完成后,保存历史记录 try { const inputData = analysisType === 'yijing' ? { question: formData.question, divination_method: 'time' } : { name: formData.name, birth_date: formData.birth_date, birth_time: formData.birth_time, birth_place: formData.birth_place, gender: formData.gender }; await localApi.analysis.saveHistory(analysisType, analysisData, inputData); console.log('历史记录保存成功'); } catch (historyError: any) { console.error('保存历史记录失败:', historyError); // 历史记录保存失败不影响分析结果显示 } toast.success('分析完成!'); } catch (error: any) { console.error('分析失败:', error); toast.error('分析失败:' + (error.message || '未知错误')); } finally { setLoading(false); } }; const analysisTypes = [ { type: 'bazi' as AnalysisType, title: '八字命理', description: '基于传统八字学说,分析五行平衡、格局特点、四柱信息', icon: Sparkles, color: 'text-red-600', bgColor: 'bg-red-50', borderColor: 'border-red-300' }, { type: 'ziwei' as AnalysisType, title: '紫微斗数', description: '通过星曜排布和十二宫位分析性格命运', icon: Star, color: 'text-yellow-600', bgColor: 'bg-yellow-50', borderColor: 'border-yellow-300' }, { type: 'yijing' as AnalysisType, title: '易经占卜', description: '运用梅花易数起卦法,解读卦象含义,指导人生决策', icon: Compass, color: 'text-orange-600', bgColor: 'bg-orange-50', borderColor: 'border-orange-300' } ]; return (
{/* 页面标题 */}

命理分析

选择分析方式,探索您的命运密码

{/* 分析类型选择 */} 选择分析类型

选择您感兴趣的命理分析方式

{analysisTypes.map((type) => { const Icon = type.icon; const isSelected = analysisType === type.type; return (
setAnalysisType(type.type)} className={cn( 'p-4 md:p-5 rounded-lg border-2 cursor-pointer transition-all duration-200', 'hover:shadow-md active:scale-95', isSelected ? `${type.borderColor} ${type.bgColor} shadow-md` : 'border-gray-200 hover:border-gray-300 bg-white' )} >

{type.title}

{type.description}

); })}
{/* 分析表单 */} 填写分析信息

{profile ? '已从您的档案中自动填充,您可以修改' : '请填写以下信息进行分析'}

{analysisType === 'yijing' ? ( // 易经占卜表单
setFormData(prev => ({ ...prev, question: e.target.value }))} placeholder="请输入您希望占卜的具体问题,如:我的事业发展如何?" required variant="filled" helperText="💡 提示:问题越具体,占卜结果越准确。可以询问事业、感情、财运、健康等方面的问题。" />
) : ( // 八字和紫微表单 <>
setFormData(prev => ({ ...prev, name: e.target.value }))} required placeholder="请输入真实姓名" variant="filled" className="pr-10" />
setFormData(prev => ({ ...prev, gender: e.target.value as 'male' | 'female' }))} options={[ { value: 'male', label: '男性' }, { value: 'female', label: '女性' } ]} required variant="filled" />
{ const value = e.target.value; // 验证日期格式:YYYY-MM-DD,确保年份是4位数字 if (value && !/^\d{4}-\d{2}-\d{2}$/.test(value)) { return; // 不更新状态,保持原值 } setFormData(prev => ({ ...prev, birth_date: value })); }} min="1900-01-01" max="2100-12-31" required variant="filled" className="pr-10" />
setFormData(prev => ({ ...prev, birth_time: e.target.value }))} helperText="选填,但强烈建议填写以提高准确性" variant="filled" />
{analysisType !== 'ziwei' && (
setFormData(prev => ({ ...prev, birth_place: e.target.value }))} placeholder="如:北京市朝阳区(选填)" variant="filled" className="pr-10" helperText="选填,用于更精确的地理位置分析" />
)} )} {loading ? ( <> 分析中... ) : ( <> 开始{analysisTypes.find(t => t.type === analysisType)?.title}分析 )}
{/* 分析结果 */} {analysisResult && ( )}
); }; export default AnalysisPage;