Files
n8n_Demo/web_frontend/exhibition-demo/src/components/ResultModal.tsx
Yep_Q b50d700a2e feat: 添加交通物流、智能制造、智能开发终端模拟并优化食品订单班
主要更新:
- 新增3个订单班终端模拟数据 (交通物流、智能制造、智能开发)
- 交通物流: 图片重命名(9张UUID图片→描述性中文名)
- 智能制造: 图片重命名(7张UUID图片→描述性中文名)
- 食品订单班: 完成React应用架构和设计系统
- 新增4个Serena记忆文档 (终端模拟开发指南、订单班命名规范等)
- 优化模态框和工作流页面交互逻辑

文件变更:
- 新增: transportation.ts, intelligentManufacturing.ts, developer.ts
- 新增: 食品订单班完整React应用 (Vite + TypeScript + Tailwind)
- 修改: RequirementModal.tsx, ResultModal.tsx, WorkflowPageV4.tsx
- 图片: 交通物流9张 + 智能制造7张重命名为中文描述性名称
2025-10-02 20:29:01 +08:00

175 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, Eye, CheckCircle, FileText, TrendingUp, Calendar } from 'lucide-react';
interface ResultModalProps {
isOpen: boolean;
onClose: () => void;
onViewDetails?: () => void;
projectTitle?: string;
projectSubtitle?: string;
orderClassName?: string;
}
const ResultModal: React.FC<ResultModalProps> = ({
isOpen,
onClose,
onViewDetails,
projectTitle = '项目方案',
projectSubtitle = '包含完整的分析、设计、预算、执行计划等内容',
orderClassName = '通用'
}) => {
const stats = [
{ label: '生成时间', value: '3分钟', icon: <Calendar className="w-5 h-5" /> },
{ label: '文档页数', value: '68页', icon: <FileText className="w-5 h-5" /> },
{ label: '预期ROI', value: '30%', icon: <TrendingUp className="w-5 h-5" /> },
];
const sections = [
{ name: '策划案概述', status: 'completed', pages: 8 },
{ name: '展会介绍', status: 'completed', pages: 12 },
{ name: '营销方案', status: 'completed', pages: 15 },
{ name: '现场运营', status: 'completed', pages: 10 },
{ name: '预算分析', status: 'completed', pages: 13 },
{ name: '风险评估', status: 'completed', pages: 10 },
];
return (
<AnimatePresence>
{isOpen && (
<>
{/* 背景遮罩 */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50"
onClick={onClose}
/>
{/* 弹窗内容 */}
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
className="fixed inset-0 flex items-center justify-center z-50 p-4"
onClick={onClose}
>
<div
className="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-hidden flex flex-col"
onClick={(e) => e.stopPropagation()}
>
{/* 头部 */}
<div className="relative bg-gradient-to-br from-green-500 to-emerald-600 p-8 text-white flex-shrink-0">
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 hover:bg-white/20 rounded-lg transition-colors"
>
<X className="w-6 h-6" />
</button>
<div className="flex items-center justify-center mb-4">
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ delay: 0.2, type: 'spring', stiffness: 200 }}
className="p-4 bg-white/20 rounded-full"
>
<CheckCircle className="w-12 h-12" />
</motion.div>
</div>
<h2 className="text-3xl font-bold text-center mb-2"></h2>
<p className="text-center text-green-100">
AI已成功为您生成完整的{orderClassName}
</p>
</div>
<div className="p-6 overflow-y-auto flex-1">
{/* 统计信息 */}
<div className="grid grid-cols-3 gap-4 mb-6">
{stats.map((stat, index) => (
<motion.div
key={stat.label}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 + index * 0.1 }}
className="bg-gray-50 rounded-xl p-4"
>
<div className="flex items-center gap-3 mb-2">
<div className="p-2 bg-white rounded-lg text-gray-600">
{stat.icon}
</div>
<div>
<p className="text-2xl font-bold text-gray-900">{stat.value}</p>
<p className="text-xs text-gray-500">{stat.label}</p>
</div>
</div>
</motion.div>
))}
</div>
{/* 内容章节 */}
<div className="mb-6">
<h3 className="text-sm font-semibold text-gray-700 mb-3"></h3>
<div className="space-y-2">
{sections.map((section, index) => (
<motion.div
key={section.name}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.4 + index * 0.05 }}
className="flex items-center justify-between p-3 bg-gray-50 rounded-lg"
>
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-green-100 text-green-600 rounded-full flex items-center justify-center">
<CheckCircle className="w-5 h-5" />
</div>
<span className="font-medium text-gray-900">{section.name}</span>
</div>
<span className="text-sm text-gray-500">{section.pages}</span>
</motion.div>
))}
</div>
</div>
{/* 生成信息 */}
<div className="p-4 bg-blue-50 rounded-xl mb-6">
<div className="flex items-start gap-3">
<div className="p-2 bg-blue-100 rounded-lg">
<FileText className="w-5 h-5 text-blue-600" />
</div>
<div className="flex-1">
<h4 className="font-semibold text-gray-900 mb-1">
{projectTitle}
</h4>
<p className="text-sm text-gray-600">
{projectSubtitle}
</p>
</div>
</div>
</div>
</div>
{/* 操作按钮 - 固定在底部 */}
<div className="p-6 bg-gray-50 border-t border-gray-200 flex-shrink-0">
<div className="flex justify-center">
<button
onClick={onViewDetails}
className="px-8 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-xl font-medium hover:shadow-lg transform hover:scale-105 transition-all flex items-center justify-center gap-2"
>
<Eye className="w-5 h-5" />
</button>
</div>
</div>
</div>
</motion.div>
</>
)}
</AnimatePresence>
);
};
export default ResultModal;