import { useState, useEffect } from "react"; import { useNavigate, useParams } from "react-router"; import { motion, AnimatePresence } from "motion/react"; import { ChevronLeft, Heart, TrendingUp, AlertCircle, CheckCircle2, Info, Calendar, Share2, Download, Sparkles, Activity, Baby, MessageCircle, FileText, X, Link2, Check, AlertTriangle, ShieldAlert, Loader2, Image as ImageIcon, } from "lucide-react"; import { Button } from "../components/ui/button"; import { Card } from "../components/ui/card"; import { Badge } from "../components/ui/badge"; import { generateAnalysis, type AnalysisResponse } from "../services/api"; export function AIAnalysisPage() { const navigate = useNavigate(); const { reportId } = useParams(); const [showShareSheet, setShowShareSheet] = useState(false); const [linkCopied, setLinkCopied] = useState(false); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [analysisData, setAnalysisData] = useState(null); useEffect(() => { if (!reportId) return; setLoading(true); generateAnalysis(reportId) .then((data) => setAnalysisData(data)) .catch((err) => setError(err instanceof Error ? err.message : "加载失败")) .finally(() => setLoading(false)); }, [reportId]); const handleCopyLink = async () => { try { const shareUrl = `${window.location.origin}/share/${reportId}`; await navigator.clipboard.writeText(shareUrl); setLinkCopied(true); setTimeout(() => setLinkCopied(false), 2000); } catch (error) { console.error('复制失败:', error); // 降级方案:使用旧的复制方法 const textArea = document.createElement('textarea'); textArea.value = `${window.location.origin}/share/${reportId}`; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); setLinkCopied(true); setTimeout(() => setLinkCopied(false), 2000); } catch (err) { alert('复制失败,请手动复制链接'); } document.body.removeChild(textArea); } }; if (loading) { return (

AI 正在解读您的报告...

这可能需要几秒钟

); } if (error || !analysisData) { return (

解读失败

{error || "未知错误"}

); } const getStatusColor = (status: string) => { switch (status) { case "normal": return { bg: "bg-morandi-sage-100", border: "border-morandi-sage-200", text: "text-morandi-sage-600", badge: "bg-morandi-sage-100 text-morandi-sage-600", icon: "text-morandi-sage-400", }; case "attention": return { bg: "bg-morandi-rose-100", border: "border-morandi-200", text: "text-morandi-600", badge: "bg-morandi-rose-100 text-morandi-600", icon: "text-morandi-rose-400", }; case "high": return { bg: "bg-red-50", border: "border-red-200", text: "text-red-700", badge: "bg-red-100 text-red-700", icon: "text-red-500", }; default: return { bg: "bg-gray-50", border: "border-gray-200", text: "text-gray-700", badge: "bg-gray-100 text-gray-700", icon: "text-gray-500", }; } }; const statusColors = getStatusColor(analysisData.overall_status); // 指标状态颜色(紫色系色温区分:冷调sage→中性purple→暖调rose) const getIndicatorColor = (indicatorStatus: string) => { switch (indicatorStatus) { case "normal": return { bg: "bg-morandi-sage-100", border: "border-morandi-sage-200", text: "text-morandi-sage-600", badge: "bg-morandi-sage-100 text-morandi-sage-600", barBg: "bg-morandi-sage-200", barFill: "bg-morandi-sage-400", }; case "borderline": return { bg: "bg-morandi-100", border: "border-morandi-200", text: "text-morandi-600", badge: "bg-morandi-200 text-morandi-700", barBg: "bg-morandi-200", barFill: "bg-morandi-400", }; case "abnormal": return { bg: "bg-morandi-rose-100", border: "border-morandi-rose-300", text: "text-morandi-700", badge: "bg-morandi-rose-100 text-morandi-rose-400", barBg: "bg-morandi-rose-100", barFill: "bg-morandi-rose-400", }; default: return { bg: "bg-gray-50", border: "border-gray-200", text: "text-gray-700", badge: "bg-gray-100 text-gray-700", barBg: "bg-gray-100", barFill: "bg-gray-400", }; } }; const getRiskLabel = (riskLevel: string) => { switch (riskLevel) { case "low": return { label: "低风险", color: "bg-morandi-100 text-morandi-600" }; case "medium": return { label: "中风险", color: "bg-morandi-rose-100 text-morandi-rose-400" }; case "high": return { label: "高风险", color: "bg-morandi-rose-100 text-morandi-700" }; default: return { label: "", color: "" }; } }; return (
{/* 顶部导航 */}

AI 智能解读

{/* AI 解读标识 */} AI 深度解读 · 个性化定制 {/* 整体评估卡片 */}

整体评估

{analysisData.overall_status === "normal" ? "一切正常" : analysisData.overall_status === "attention" ? "需要关注" : "需要重视"}

{analysisData.emotional_summary || analysisData.overall_summary}

{new Date(analysisData.created_at).toLocaleDateString("zh-CN")}
{/* 风险等级指示器 */}
综合风险评级 {analysisData.risk_level === "low" ? "低风险" : analysisData.risk_level === "medium" ? "中风险" : "高风险"}
{/* 分类详情 */}

详细解读

{analysisData.categories.map((category, index) => { const colors = getStatusColor(category.status); return ( {/* 分类头部 */}

{category.category}

{category.status === "normal" ? "正常" : category.status === "attention" ? "需关注" : "异常"}
{/* 指标详情 */}
{category.indicators.map((item, itemIdx) => { const indicatorStatus = item.status === "normal" ? "normal" : item.status === "low" || item.status === "high" ? "abnormal" : "borderline"; const indColors = getIndicatorColor(indicatorStatus); return (
{/* 指标名称和数值 */}

{item.name}

{item.nickname && (

{item.nickname}

)}
{item.value} {item.unit}
{item.reference_range && (

参考范围:{item.reference_range}

)}
{indicatorStatus === "normal" ? ( ) : ( )} {item.status === "normal" ? "正常" : item.status === "high" ? "偏高" : "偏低"}
{/* 状态指示条 */}
{/* 白话解释 */}
{item.what_is_it && (

这是什么?

{item.what_is_it}

)} {item.baby_impact && (

对宝宝的影响

{item.baby_impact}

)} {item.suggestion && (

建议措施

{item.suggestion}

)} {item.follow_up && (
{item.follow_up}
)}
); })}
); })}
{/* 行动建议 */}

接下来该做什么?

{analysisData.action_items.map((rec, index) => (

{rec.title}

{rec.priority === "high" && ( 重要 )}

{rec.description}

{rec.timeframe && (
{rec.timeframe}
)}
))}
{/* 深度服务 - 新增 */}

🎯 获取更多帮助

navigate(`/chat/${reportId}`)} className="bg-morandi-100 rounded-2xl p-4 border-0 cursor-pointer hover:scale-105 transition-transform" >

AI对话追问

针对报告提问

navigate(`/doctor-questions/${reportId}`)} className="bg-gradient-to-br from-morandi-slate-100 to-morandi-slate-50 rounded-2xl p-4 border-0 cursor-pointer hover:scale-105 transition-transform" >

问诊清单

就医沟通话术

{/* 温馨提示 */}

温馨提示

以上解读仅供参考,不能替代医生的专业诊断。如有任何疑问或不适,请及时就医咨询专业医生。保持好心情,宝宝能感受到妈妈的情绪哦 💕

{/* 底部操作栏 */}
{/* 分享弹窗 */} {showShareSheet && ( <> setShowShareSheet(false)} className="fixed inset-0 bg-black/40 z-40" />
{/* 拖拽指示器 */}

分享报告

{/* 分享方式 */}
{/* 生成分享长图 */} {/* 复制链接 */}
{/* 分享预览卡片 */}

{analysisData.categories[0]?.category || "检查报告"} · AI解读

{analysisData.overall_summary}

{new Date(analysisData.created_at).toLocaleDateString("zh-CN")}
{/* 隐私提示 */}
分享时将自动隐藏个人敏感信息,保护您的隐私
)}
); }