Files
n8n_Demo/web_frontend/exhibition-demo/src/pages/ResultPage.tsx

261 lines
8.5 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
FileText,
Target,
TrendingUp,
Calendar,
DollarSign,
AlertTriangle,
ChevronLeft,
ChevronRight,
RotateCcw,
Download
} from 'lucide-react';
import { useDemoStore } from '../store/demoStore';
interface ResultPageProps {
onRestart: () => void;
}
const sections = [
{ id: 'overview', title: '策划案概述', icon: FileText },
{ id: 'introduction', title: '展会介绍与预期效果', icon: Target },
{ id: 'marketing', title: '营销方案', icon: TrendingUp },
{ id: 'operation', title: '现场运营方案', icon: Calendar },
{ id: 'budget', title: '预算与收益分析', icon: DollarSign },
{ id: 'risk', title: '风险评估与应急预案', icon: AlertTriangle },
];
const ResultPage: React.FC<ResultPageProps> = ({ onRestart }) => {
const [currentSection, setCurrentSection] = useState(0);
const { generatedContent } = useDemoStore();
const handlePrevious = () => {
if (currentSection > 0) {
setCurrentSection(currentSection - 1);
}
};
const handleNext = () => {
if (currentSection < sections.length - 1) {
setCurrentSection(currentSection + 1);
}
};
// Mock content for demonstration
const getSectionContent = (sectionId: string) => {
const mockContent = {
overview: {
title: '2024长三角国际新能源汽车与智能交通产业博览会',
content: `
##
##
-
- 3008亿
-
- 广绿
`,
images: ['/api/placeholder/600/400', '/api/placeholder/600/400']
},
introduction: {
title: '展会规模与预期',
content: `
##
绿
##
- 50,000
- 1,2009/
- 20,000
- 350
- 50,000
##
- 10亿
- 30亿
- 1亿
`,
images: []
},
// Add more sections...
};
return mockContent[sectionId] || generatedContent[sectionId] || mockContent.overview;
};
const currentSectionData = getSectionContent(sections[currentSection].id);
return (
<div className="min-h-screen p-6">
<div className="max-w-7xl mx-auto">
{/* Header */}
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
className="mb-8"
>
<div className="flex items-center justify-between">
<h1 className="text-4xl font-bold text-gradient">
</h1>
<div className="flex items-center gap-4">
<button
onClick={() => {}}
className="px-4 py-2 glass-morphism rounded-xl hover:scale-105 transition-transform flex items-center gap-2"
>
<Download className="w-4 h-4" />
</button>
<button
onClick={onRestart}
className="px-4 py-2 glass-morphism rounded-xl hover:scale-105 transition-transform flex items-center gap-2"
>
<RotateCcw className="w-4 h-4" />
</button>
</div>
</div>
</motion.div>
{/* Section Tabs */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.2 }}
className="mb-8"
>
<div className="flex items-center gap-2 overflow-x-auto scrollbar-thin pb-2">
{sections.map((section, index) => {
const Icon = section.icon;
return (
<button
key={section.id}
onClick={() => setCurrentSection(index)}
className={`
flex items-center gap-2 px-4 py-2 rounded-xl transition-all whitespace-nowrap
${currentSection === index
? 'bg-gradient-to-r from-blue-500 to-purple-500 text-white shadow-lg'
: 'glass-morphism hover:scale-105'
}
`}
>
<Icon className="w-4 h-4" />
<span className="font-medium">{section.title}</span>
</button>
);
})}
</div>
</motion.div>
{/* Content Area */}
<AnimatePresence mode="wait">
<motion.div
key={currentSection}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
className="glass-morphism rounded-2xl p-8"
>
{/* Section Header */}
<div className="mb-6">
<h2 className="text-3xl font-bold mb-2">
{currentSectionData.title}
</h2>
<div className="h-1 w-20 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full" />
</div>
{/* Section Content */}
<div className="prose prose-neutral dark:prose-invert max-w-none">
<div className="whitespace-pre-wrap text-neutral-700 dark:text-neutral-300">
{currentSectionData.content}
</div>
</div>
{/* Images */}
{currentSectionData.images && currentSectionData.images.length > 0 && (
<div className="mt-8 grid grid-cols-2 gap-4">
{currentSectionData.images.map((src, index) => (
<motion.div
key={index}
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: index * 0.1 }}
className="rounded-xl overflow-hidden shadow-lg"
>
<img
src={src}
alt={`Section image ${index + 1}`}
className="w-full h-full object-cover"
/>
</motion.div>
))}
</div>
)}
</motion.div>
</AnimatePresence>
{/* Navigation */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
className="mt-8 flex items-center justify-between"
>
<button
onClick={handlePrevious}
disabled={currentSection === 0}
className={`
px-4 py-2 rounded-xl flex items-center gap-2 transition-all
${currentSection === 0
? 'opacity-50 cursor-not-allowed glass-morphism'
: 'glass-morphism hover:scale-105'
}
`}
>
<ChevronLeft className="w-4 h-4" />
</button>
{/* Page Indicators */}
<div className="flex items-center gap-2">
{sections.map((_, index) => (
<div
key={index}
className={`
w-2 h-2 rounded-full transition-all
${currentSection === index
? 'w-8 bg-gradient-to-r from-blue-500 to-purple-500'
: 'bg-neutral-400'
}
`}
/>
))}
</div>
<button
onClick={handleNext}
disabled={currentSection === sections.length - 1}
className={`
px-4 py-2 rounded-xl flex items-center gap-2 transition-all
${currentSection === sections.length - 1
? 'opacity-50 cursor-not-allowed glass-morphism'
: 'glass-morphism hover:scale-105'
}
`}
>
<ChevronRight className="w-4 h-4" />
</button>
</motion.div>
</div>
</div>
);
};
export default ResultPage;